Skip to main content

Platform Gap Register

Loaded by: supervisor, Claude reviewer, sub-agents, daily digest · Updated: weekly review on Mondays + ad-hoc when gaps close This is the living, machine-readable register of known platform gaps. Each entry has: ID, severity, status, owner, target stage, fix mechanism, and source. Agents read this to know what’s open and what to prioritize. Source synthesis: documents/factory/2026-05-11_HOLISTIC_GAP_REVIEW.md (Sauna-side working note).

Conventions

  • Severity: P0 (blocks Stage 1 ship) · P1 (Stage 1-2 must-fix) · P2 (Stage 2-5 fix) · P3 (defer / hygiene)
  • Status: open · in-progress · closed · wontfix
  • Target stage: stage-0 … stage-5 · continuous · out-of-roadmap
  • Owner: @adrper79-dot · @factory-cross-repo[bot] · @sauna (the orchestrator)

P0 — Must close before Stage 1 ships

P1 — Stage 1-2 must-fix

P2 — Stage 2-5 fix

P3 — Hygiene / defer

| G31 | JWT rotation procedure (auth pkg) — no dual-key window for secret rotation | closed | @adrper79-dot + @factory-cross-repo[bot] | stage-4 | verifyToken(token, secret, secretNext?) tries primary first, falls back to secretNext on signature failure only (not expiry). issueToken signs with secretNext when provided. jwtMiddleware(secret, { secretNext? }) threads through. refreshToken re-signs with new key. 9 new dual-key tests; branch coverage 90.24%. Branch claude/dazzling-brahmagupta-RcOz7. | | G32 | Stripe idempotency keys not persisted in DB — retries can double-charge under worker crash | closed | @sauna | stage-3 | stripe_idempotency_keys table added to Neon schema (migration 0106); @lwt/stripe.transferOrIdempotent() helper ships in P2.13h — checks/inserts before Stripe call, updates status on success/failure. Branch claude/dazzling-brahmagupta-RcOz7. | | G33 | No PostgreSQL row-level security templates in @lwt/neon | closed | @sauna | stage-5 | packages/neon/src/rls.ts exports rlsEnable(), rlsViewerPolicy(), rlsCreatorPolicy(), rlsAdminPolicy(), rlsOperatorPolicy(), and rlsPolicies(role, opts). All functions return SQL strings for migration files. Tenant isolation via current_setting('app.tenant_id', TRUE). 100% coverage, 30 tests. Branch claude/dazzling-brahmagupta-RcOz7. | | G34 | No PostHog funnel definitions for monetization paths | closed | @sauna | stage-2 | MONETIZATION_FUNNEL constant + trackFunnelStep() + getFunnelPosition() shipped in @lwt/analytics. 5-step funnel with per-product event overrides. 103 tests, 96.49% branch coverage. Branch claude/dazzling-brahmagupta-RcOz7. | | G35 | No transactional email templates in @lwt/email (currently raw sendEmail() only) | closed | @sauna | stage-5 | packages/email/src/templates.ts exports 6 typed template functions: subscriptionConfirmedTemplate, renewalFailedTemplate, payoutCompletedTemplate, accountReviewRequiredTemplate, magicLinkTemplate, passwordResetTemplate. Each returns { subject, html, text } ready for sendTransactional(). BrandVars interface (productName, supportEmail?, logoUrl?, accentColor?) controls per-product branding. 37 tests; 85.4% branch coverage. Branch claude/dazzling-brahmagupta-RcOz7. | | G36 | No audit logging for payout/admin mutating operations | closed | @sauna | stage-5 | factory_audit_log table (migration 0105) + @lwt/compliance.sendAuditEntry() ships in P2.13g. POST /v1/audit on factory-core-api ingests entries with actor/action/resource/result. AUDIT_INGEST_KEY service auth. Branch claude/dazzling-brahmagupta-RcOz7. | | G37 | CF_API_TOKEN and LATIMERWOODS_SENTRY_AUTH lack scopes for billing/stats endpoints | closed (Sentry fixed, CF pending) | @adrper79-dot | stage-2 | Cost digest run 2026-05-15 returned HTTP 403 on Cloudflare billing/profile and Sentry stats_v2. Sentry fixed: cost-observability.yml + revenue-digest.yml reordered to try FACTORY_SENTRY_API (stats scope) before LATIMERWOODS_SENTRY_AUTH. CF billing 403 tracked separately as G38. | | G38 | GCP billing line in cost digest is a placeholder — needs BQ billing export | open | @adrper79-dot | stage-2 | scripts/cost_digest.py::collect_gcp returns “skipped: missing GCP_BILLING_TOKEN or GCP_BILLING_ACCOUNT_ID” — but the real path is a BigQuery billing export (docs). Until that’s configured + queried, no GCP $ in the digest. | | G39 | Auto-merge bot race: drift PRs from aggregator can sit open and block subsequent runs | closed | @sauna | stage-2 | completion-tracker.yml now re-arms auto-merge (gh pr merge --auto --squash + --admin fallback) when same-day PR has been open >2h. Branch claude/dazzling-brahmagupta-RcOz7. | | G40 | Cross-agent institutional memory has no single entry point | in-progress | @sauna | stage-1 | Memory spreads across CLAUDE.md, ROADMAP.md, FRIDGE.md, GAP_REGISTER.md, decisions/, conformance/, cost/, completion-tracker.json — no agent reads all of them on boot. Fix: docs/STATE.md auto-generated daily (PR landing 2026-05-15). Patterns surface added via docs/architecture/PATTERNS.md. | | G49 | UI fragmentation / orphaned design packages — design-tokens and design-system defined competing token sets with divergent naming; packages/ui shipped but imported by no app; three apps use three CSS strategies and three primary colors | in-progress | @adrper79-dot | stage-6 | Primus consolidation — docs/architecture/PRIMUS.md §6 delivery path (A→E). Phase A in flight: DTCG source + Style Dictionary as the single token source, design-system collapsed to a re-export of design-tokens, Changesets + semver discipline. Later phases de-orphan ui, fill a11y/forms/icons, and drive adoption. | | G50 | USDC creator payouts for Capricast — the narrow web3 option deferred when primusui.com was repurposed to the Primus design-system showcase | open | @adrper79-dot | out-of-roadmap (until Capricast has real payout GMV) | Not built. Deferred per ADR 2026-06-22 Primus decision 1; revisit only when Capricast reaches real payout GMV. |

coh-specific gaps (2026-05-19 sprint)

Opened after a fresh audit of Latimer-Woods-Tech/coh against its shipped reality. See docs/runbooks/coh-world-class-sprint.md for sprint scope and PR links.

Meta-gaps (the framework can’t auto-answer)

How to use this register

  • Agents (supervisor, sub-agents, Claude reviewer): when planning work, check this register for gaps in the milestone’s target stage. Prefer closing register entries over inventing new work.
  • Aggregator workflow: read this file; report open P0 + P1 counts in the daily Pushover digest.
  • Monday review: triage open gaps; promote, demote, or close.
  • Adding gaps: open a PR adding a row; reference the source incident or doc. Severity assigned by the reviewer.
  • Closing gaps: edit status to closed, add a one-line summary of how it closed, link the PR that closed it.

Tracker-aggregator integration

When aggregate_completion.py runs, it tallies:
These four numbers go in the Pushover digest right under the cohesion score. Open P0 > 0 = the system flags itself as not-ready.