Changelog

Changelog

What changed and why it matters. Reverse-chronological, grouped by theme. Internal refactors, dependency bumps, and lint fixes are intentionally omitted.

Changelog

What changed and why it matters. Reverse-chronological. Internal refactors, dependency bumps, and lint fixes are intentionally omitted.

2026-05-01 — Posture and operability hardening

  • Tests stop hitting third-party APIs by default. The pytest -q suite no longer burns Resend, Anthropic, OpenAI, or Stripe quotas on every run. Provider-touching tests are marker-gated and opt-in.
  • lcl-{env} mode hydrates real Secrets Manager values. Running the BE locally against a deployed stage now fetches the same Anthropic, OpenAI, Resend, and invitation-secret values that the deployed Lambda uses, instead of placeholder strings. Fixes a class of silent 404s on token preview / accept paths against lcl-prd.
  • Cognito new-password challenge wired through login. Admin-created accounts (FORCE_CHANGE_PASSWORD) now get a follow-up password-set step instead of throwing a SDK callback error and stranding the user.
  • Resend sender pinned to a verified domain. The from address ships in the gf/prd/resend secret next to the API key; both rotate together. Stops the silent rejection where Resend's sandbox sender refused every recipient except the account owner.

2026-05-01 — AI persona pipeline on its own runtime

  • Persona runs moved to a worker Lambda + SQS queue. Long-running rubric pipelines no longer block the API request lifecycle. The dashboard shows progress and the API returns immediately.
  • Demo card simplified. Three-step header, larger spacing, nine more personas to sample. Closer to what a first-time visitor needs to evaluate the product in 30 seconds.
  • Landing and signed-in copy restructured around the website-feedback loop. The pitch leads with widget feedback paired against AI-persona critique, not with the persona catalog.

2026-05-01 — Auto-fix and resolution evidence

  • Annotations carry an auto_fix flag. When true, the submitter authorised an agent / CI bot / engineering team to apply a change without further discussion. Anonymous submitters always land false — the server coerces, regardless of the client.
  • Stakeholder tokens get an auto_fix_default. Per-row never | optional_off | optional_on controls whether the toggle renders for that reviewer at all and what state it starts in.
  • Resolution rows. A new RESOLUTION entity records what changed to address an annotation: before/after screenshots, a diff_url, an explanation. New endpoints under /api/v1/annotations/{id}/resolutions{,/upload-url}. Multiple resolutions per annotation (fix → revert → re-fix) are supported.
  • Submitter notification. When a resolution lands, the original submitter is notified — Resend email if their address is on file, otherwise a REPLY row appended to the thread that anonymous submitters see when they revisit the page.
  • MCP tools extended. get_resolution_upload_url, attach_resolution, and list_resolutions round out the agent's payday loop end to end.

2026-05-01 — Stakeholder reviews without account creation

  • Stakeholder identity surfaces in the widget and the dashboard. When the loader resolves a stk_* token from the embed attribute or ?gf_st= URL parameter, the reviewer's name lands on the annotation and shows up in the inbox.
  • Stakeholder gating lives on the BE. The roster of named reviewers is enforced server-side; unknown or revoked tokens on submit return 400 instead of being silently downgraded to anonymous.
  • Owner-only share-link controls. Generating and revoking the public share token is now restricted to the workspace owner; member-level callers see the read-only state.

2026-05-01 — IA and route renames

  • /widget/websites/feedback. The site-owner inbox is now /feedback everywhere — left-nav menu, route table, and breadcrumbs. The legacy paths still resolve so existing bookmarks survive.
  • Owners can rename their workspace from /team. Was previously an admin-only operation.

2026-04-30 — Private beta gate and access requests

  • Signup is now a waitlist. /signup collects access requests; agent self-registration at POST /api/v1/agents/register returns 403 with { "reason": "private_beta" } until settings.public_signup_enabled flips.
  • Branded invite emails. Operator-side python -m app.cli grant-access provisions a tier and emails a Resend invite that lands the invitee on a working /join flow.
  • Per-IP signup rate-limit on the agent register route (5/24h) caps abuse without paywalling honest callers.

2026-04-30 — Hero demo, calibrated AI, and abuse defenses

  • Hero demo on the homepage. POST /api/demo/run extracts a URL or ingests pasted text and runs a one-shot Haiku critique. Per-IP daily quota, 24-hour URL-result cache, Cloudflare Turnstile gate, and a demo-scoped WAF rate-limit rule keep the page free of cost runaway.
  • Vision for image and image-only PDF reviews. Real Claude vision instead of the prior text-only stub.
  • Audio and video transcription. OpenAI Whisper API for the first cut; faster-whisper worker on the roadmap.
  • Haiku-by-default routing for the agent tier. Auto-promote to Sonnet on low-confidence runs only, which keeps unit economics positive while preserving rubric quality.

2026-04-30 — Persona marketplace (publish-only) and public showcase

  • Persona marketplace listing at /marketplace. Publish, unpublish, and clone endpoints; cloned personas record clonedFrom so the royalty rail can land later without a data migration.
  • Public showcase pages at /showcase/{slug}. Opt-in only; admin moderation queue at /admin/showcase; anonymous abuse reporting on the public view. Inbound link to the user's landing page (SEO win for them, viral content for us).
  • Per-user usage telemetry at /admin/usage. Pair-data score is computed per user; Top-N tables for reviews, submissions, and ratings drive the future Top-1% comp tier.

2026-04-30 — Agent-discoverable surface

  • /llms.txt, /llms-full.txt, /mcp.json ship as cacheable, anonymous, idempotent endpoints. An LLM agent can discover the API and MCP server in three GETs without auth.
  • POST /api/v1/agents/register wire shape is documented and live behind the private-beta gate. Future contract: a fresh gfat_* token, a prepaid wallet, and a wallet_topup_url come back in one call.
  • gfat_* API tokens with workspace-scoped Bearer auth. Mint via the dashboard or the agent register route; revoke by row id; tokens are clamped at MEMBER role at issuance.
  • MCP server gains write tools. patch_annotation, run_personas, acknowledge, reply, resolve — a Claude Code or Cursor session can drive the inbox without leaving the agent surface.

2026-04-30 — Workspaces, invitations, and soft-delete

  • Workspace as the unit of access. Routes and services authorise on workspace_id; user-id ownership is gone. New /team page for member management; /join page accepts an invitation token.
  • Resend-backed invitations. Invitation tokens are HMAC-signed against gf/prd/invitation-secret; rotation invalidates outstanding invites and is documented in the runbook.
  • Soft-delete with a 30-day grace window. A daily sweeper Lambda cascades the deletion after the window expires. API-token callers see 401, session callers see 403, and the FE renders a "restore" banner.

2026-04-30 — Prd cutover

  • Single-stage repo. dev and stg were decommissioned; the project ships from prd only. Local development still uses lcl (offline JSON store) and lcl-prd (local code, deployed AWS) modes.
  • GHA-driven CDK + Cloudflare Pages deploy. Push to prd → infra, FE, and widget CDN all roll forward in one workflow.
  • bb.md carries the prd infra IDs. The DynamoDB table, media bucket, widget CDN, API Gateway, Lambdas, WAF, and Cognito user pool are public; secrets stay in bb.lcl.md and Secrets Manager.

2026-04-29 — Widget v2 and prd hardening

  • Widget merged into a single bundle. Agent and visitor modes share one runtime; the host site picks the default per page via data-gf-mode.
  • CDN script tag with content-hashed bundle. loader.js reads data-* attributes, fetches a manifest, and injects the immutable bundle. Hosts pick up updates on next page load with no redeploy.
  • Click-with-comment, area select, video reaction, voice memo. The widget captures clicks, text ranges, freeform rectangles, screenshots, and short audio / video reactions, plus the user agent, viewport, and computed styles for the captured element.
  • Loader nonce on every write. POST /api/widget/feedback and POST /api/widget/upload-url require an X-GF-Loader nonce minted by GET /api/widget/sites/by-token/{token}. 30-minute TTL; secret rotates via Secrets Manager.
  • Per-asset payload caps and mime allowlist. Screenshot 2 MB, audio 4 MB, video 8 MB, comment 4 000 chars. Enforced on inline data URLs and on the presigned upload route.
  • DDB-backed sliding-window rate limiter replaces the in-memory deque; 30/min/IP and 600/min/site. WAF is the safety net for storage errors.
  • AWS WAF in front of API Gateway. Per-IP rate-based rule (2 000/5min on prd) plus the Known-Bad-Inputs managed rule set.

2026-04-28 — Persona catalog and IA polish

  • Default persona catalog expanded to 60 across 10 orthogonal lenses. Consumer, domain expert, enterprise buyer, investor, communicator, designer, engineer, skeptic, compliance, educator — six personas each. Edit the catalog by editing markdown files in data/seeds/personas/; review is a normal PR.
  • Sidebar nav matches the most-specific entry on activate so deep links light up the right item instead of the parent.