Skip to content

SSOT sweep 2026-08-02: 15 parallel-registry violations (ranked) #551

Description

@catomean

Full audit of the dual-registry/dual-definition class (the 'Unknown action: forget_memories' bug class). Ranked, most severe first. ✅ = already fixed.

HIGH

  1. Route-surface classification in 3 hand-lists + folder split — ALREADY DRIFTED: /circles /documents render public shell; (authenticated)/collaborate + /home not edge-gated (only page-level useRequireAuth). Fix: derive APP_SURFACES from ENTITY_REGISTRY; middleware imports requiresAuth() from routes.ts.
  2. src/types/database.ts (3.7k lines, self-documented STALE) vs live-schema.json vs unused database.generated.ts. Fix: gen:types writes the real file; CI fails on diff.
  3. isPrivateAddress SSRF guard forked (ssrfGuard vs website-analysis; drifted — ff00::/8 missing in the security module) — fixed in fix(security): single isPrivateAddress SSOT — the SSRF guard was forked #549 via lib/security/private-address.ts.
  4. Notification categories in 5 places + DB columns. Fix: one NOTIFICATION_CATEGORIES array of {id, column, label, description, default}; derive the rest.
  5. ENTITY_STATUS exported twice with different keys (database-constants vs status-config). Fix: delete status-config copy.
  6. getEntityConfig map is Partial<Record> — 16th entity type compiles clean, silently no-ops AI prefill + create wizard. Fix: total Record with explicit null.

HIGH/MED
7. SITE_URL defined twice with different normalization (brand.ts vs env.ts) — trailing-slash breaks OAuth redirect allowlist. Fix: brand re-exports env's.
8. Free/pro daily caps: TS constants vs SQL literals in check_platform_limit(). Fix: migration-parsing equality test.
9. Cat verb chain is actually SEVEN registries (adds action-descriptions.ts switch + MessageBubble ACTION_LABELS). Fix: label + describe() live on CatAction; call sites become lookups.

MED
10. AI provider identity across 4 files + component PROVIDER_LABELS (openai/xai/etc get NO attribution in chat). Fix: wired/runtime/label fields on aiProviders; derive everything.
11. Nav types declared twice (+1 near-copy) with 'mirrors' comment. Fix: src/types/navigation.ts.
12. STORAGE_KEYS config bypassed + shadowed local copy with different literals. Fix: consolidate + ESLint no-restricted-syntax on localStorage string literals.
13. Two disjoint category taxonomies + local iconMap (3 icons already broken). Fix: one taxonomy, icon in config.
14. TS unions vs SQL CHECK constraints un-asserted (timeline subject_type, MODEL_TIERS, CURRENCY_CODES, loan status, GroupVisibility). Fix: extend the entity-registry-live-schema test pattern to enums.
15. Small exact duplicates: OWNER_ACTOR_SLUG ×2, LOAN_OFFER_TYPES ×2, isAiRateLimitError ×2, formatRelativeTime ×2, handleSupabaseError ×2, ViewMode ×3, TaskCategory ×3 (different values!), ConversationSummary ×3, Project ×4.

Class-closing pattern (from the sweep): every failure is a Partial, plain Record<string,…>, or hand-list standing in for a total map over a union. Typing registries as total Record<UnionType, …> converts #1/#6/#9/#10 from runtime failures into compile errors.

Context: #542/#545 (forget verb), #548 (key attribution), #549 (SSRF SSOT) came out of this sweep's trigger incident.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions