Roadmap item #13. Ships the frontend Amplitude SDK behind the v0.13.0
cookie/privacy consent gate. The analytics wrapper lives at
`frontend/src/lib/analytics.js` and exposes `track`, `identify`, and
`anonymize` over a stable nine-event taxonomy (Page Viewed, RFC
Viewed, User Signed In / Signed Out, RFC Proposed, PR Opened, Comment
Posted, Beta Access Requested, Admin Permission Decision). The
wrapper reads consent via `getConsent()` / `onConsentChange()` from
`frontend/src/lib/consent.js` (v0.13.0); the SDK module is
dynamically `import()`-ed only after `consent.analytics === true`,
and a later granted→denied flip calls `setOptOut(true)` so events
stop without a page reload. The Amplitude API key is read from
`VITE_AMPLITUDE_API_KEY` at build time; when unset the wrapper logs
one console warning and no-ops so dev environments keep working.
Wired into App.jsx (route-change Page Viewed + sign-in identify +
sign-out anonymize), Login.jsx (User Signed In with method =
otc/passcode/trust-device, Beta Access Requested on capture-profile
submit), ProposeModal.jsx (RFC Proposed), RFCView.jsx (RFC Viewed),
PRModal.jsx (PR Opened), RFCDiscussionPanel.jsx (Comment Posted with
surface=discussion), PRView.jsx (Comment Posted with surface=pr),
Admin.jsx (Admin Permission Decision with action=grant/revoke).
Event bodies carry only ids and enums — no titles, no comment
bodies, no names, no emails. The user binding passes only
`String(viewer.id)`.
Secret-vs-overlay binding caveat: Amplitude browser API keys are
visible in the shipped bundle via dev tools. Per the roadmap, the
key is still bound through `flotilla secret set` (rather than
`flotilla overlay set`) to keep all-keys-in-Secret-Manager
regularity for the OHM deployment; the CHANGELOG documents the
choice. Operator pre-deploy gesture (in the Upgrade steps block):
`pbpaste | ... ohm-rfc-app-flotilla secret set ohm-rfc-app
AMPLITUDE_API_KEY` — the wave-paused step before this release can
deploy.
No backend events ship in this release (Amplitude SaaS holds the
events); no schema migration; backend is unchanged. Migration slot
015 remains unused and available for the next minor that needs a
schema bump. New dependency: `@amplitude/analytics-browser`.
`VITE_AMPLITUDE_API_KEY` documented in `frontend/.env.example` with
the binding-choice caveat.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Brings the §1 bot wrapper, the §4 cache (webhook + reconciler), the
§5 schema (six numbered migrations), Gitea OAuth + §6 user
provisioning, the §7 catalog left pane, and the propose-to-merge
vertical: propose modal opens an idea PR against the meta repo, an
owner merges from the pending-idea view, the cache picks it up via
webhook or reconciler sweep, and the catalog renders the new
super-draft.
Per §1 the bot is the only Git writer; every commit, branch
creation, and PR merge carries the §6.5 On-behalf-of: trailer and
an `actions` audit row. Per §4 the cache is never written from a
user action — it's webhook+reconciler only.
Covered by `backend/tests/test_propose_vertical.py` against an
in-process Gitea simulator.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>