# Donor / Extraction Language Map

> Generated 2026-06-18. Drives cleanup — missing hit = leak survives. DO NOT edit manually; re-run the survey instead.

---

## Summary

### Totals

| Metric | Count |
|--------|-------|
| Total tracked files with any hit | 157 |
| Total line-hits | 2589 |
| PURE-PROVENANCE files | 18 |
| MIXED files | 78 |
| INCIDENTAL files | 61 |

### Term frequencies (line-level occurrences)

| Term | Hits |
|------|------|
| `multideal` | 817 |
| `donor` | 790 |
| `zync / zync.is` | 526 |
| `census` | 262 |
| `forumzone` | 227 |
| `trance-shop` | 133 |
| `extract / extraction / extracted` | 158 |
| `harvest` | 89 |
| `press.zone / presszone / commentpresszone` | 70 |
| `vibeflare` | 55 |
| `ported / porting` | 44 |
| `verified_by` | 23 |
| `fewtok` | 24 |
| `bestDonor` | 5 |
| `donor-mining` | 1 |
| `tamlil` | 2 |

### Biggest MIXED file

`docs/registry.json` — 118 hits (machine-queryable registry that embeds `"source": "multideal/zync/..."` provenance fields on every capability)

---

## PURE-PROVENANCE files

These files ARE donor/extraction records. Candidate to move wholesale into `.provenance/`.

| File | Hits | What it is |
|------|------|-----------|
| `docs/audits/r5-evidence-batch1.md` | 183 | R5 capability-maturity audit evidence — per-donor capability evidence batch 1 |
| `docs/audits/r5-evidence-batch2.md` | 177 | R5 capability-maturity audit evidence — per-donor capability evidence batch 2 |
| `docs/catalog/2026-06-17-screen-flow-donor-census.md` | 150 | Screen/flow donor census — maps every donor app's UI screens |
| `docs/audits/r5-evidence-ai-pilot.md` | 118 | R5 capability-maturity audit evidence — AI module donor pilot |
| `docs/plans/2026-06-17-affiliate-module-extraction.md` | 85 | Affiliate module extraction build plan — donor-specific wave plan |
| `docs/specs/2026-06-16-donor-capability-inventory.md` | 82 | Pinned donor capability inventory — the master donor census artifact |
| `docs/specs/2026-06-17-wasp-like-template-capability-map.md` | 61 | Wasp-like template capability map referencing donor sources throughout |
| `docs/audits/2026-06-15-r5-capability-maturity-audit.md` | 60 | R5 capability-maturity audit main document — full donor evidence |
| `docs/specs/2026-06-12-module-discovery-census.md` | 34 | Module discovery census — early donor-by-donor capability census |
| `docs/catalog/index.md` | 32 | Catalog index SoT — registry of all donor census artifacts with SHA pins |
| `docs/specs/2026-06-17-affiliate-module-extraction-design.md` | 27 | Affiliate module extraction design spec — donor call-site analysis |
| `docs/specs/2026-06-16-registry-reconciliation-ledger.md` | 26 | Registry reconciliation ledger — donor-sourced disposition decisions awaiting sign-off |
| `docs/catalog/2026-06-17-invoicing-census.md` | 24 | Invoicing donor census artifact |
| `docs/specs/2026-06-17-invoicing-module-extraction-design.md` | 23 | Invoicing module extraction design — donor call-site + seam analysis |
| `docs/catalog/2026-06-16-ui-donor-census.md` | 20 | UI donor census — maps UI capabilities per donor |
| `docs/catalog/2026-06-17-multideal-editorial-census.md` | 12 | Multideal editorial content census |
| `docs/specs/2026-06-17-affiliate-review-verdict.md` | 8 | Affiliate extraction review verdict — donor-specific reviewer output |
| `docs/plans/2026-06-17-mod-www-phase-2-blueprint-extract.md` | 4 | mod-www phase 2 blueprint extraction plan referencing donor sources |

---

## MIXED files

These files contain load-bearing doctrine that must stay public. Donor/extraction references must be surgically extracted (rewritten in public-neutral language) — do NOT move the file wholesale.

### `docs/registry.json` (118 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `"donor_facts": "docs/specs/2026-06-16-donor-capability-inventory.md",` |
| 17 | `"WATCH": "1 donor OR divergent seams — do not build until a 2nd convergent consumer appears",` |
| 21 | `"rule": "@platform-modules/events is DISSOLVED (census x0, 2026-06-14). Cross-module signals use jobs/outbox (transactional) + direct functi` |
| 32 | `"rule": "Every module with a host-injected ADAPTER or STORE seam (network / provider SDK / host primitive) ships an in-memory test double at` |
| 53 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + root smoke + blueprint-transitive (` |
| 54 | `"deps": [], "census": { "count": 6, "donors": ["zync", "multideal", "trance-shop", "ForumZone", "vibeflare", "fewtok"], "note": "leaf-by-lea` |
| 77 | `{ "name": "sanitize-html", "kind": "capability", "build": "WATCH", "note": "promote pending HTML-render census" }` |
| 83 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + root smoke + blueprint-transitive (` |
| 84 | `"deps": [], "census": { "count": 4, "donors": ["multideal", "zync", "ForumZone", "trance-shop"], "converged": true },` |
| 97 | `"verified": true, "verified_at": "2026-06-17", "verified_by": "turbo typecheck+test+build green (record-store + mail + @app/consumer) + tri-` |
| 99 | `"census": {` |
| 100 | `"trigger": "forward-need (expansion mode) — ×1 build, NOT donor-count; shape recurs 3× in-repo (audit.listAudit keyset · jobs.outbox · multi` |
| 101 | `"donors": ["multideal (mock_emails D1 — the capture donor)"]` |
| 104 | `"freeze_criterion": "RecordStore<T> is PROVISIONAL 0.x — freeze to 1.0 ONLY when a NON-donor app confirms the append/list shape (north-star ` |
| 105 | `"contract": "RecordStore<T> = append(record) + keyset-paginated list(filter); sort/cursor on NUMERIC (createdAtMs, seq) NEVER text id (colla` |
| 109 | `{ "name": "d1", "kind": "adapter", "layer": "L1", "peer": ["cloudflare:d1-binding"], "note": "makeD1RecordStore(d1, table) — raw D1 (D1Datab` |
| 118 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + saas-blueprint jobs wiring (this se` |
| 119 | `"deps": ["@platform-modules/db"], "census": { "count": 5, "donors": ["zync", "ForumZone", "multideal", "trance-shop", "vibeflare"], "note": ` |
| 131 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build green (ledger #4)",` |
| 132 | `"deps": [], "census": { "count": 7, "donors": ["zync", "ForumZone", "Press.zone", "multideal", "trance-shop"] },` |
| 145 | `"note": "ForumZone = provider-failover reference"` |
| 149 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + saas/community blueprint fail-close` |
| 152 | `"census": { "count": 4, "donors": ["multideal", "zync", "ForumZone", "trance-shop"], "converged": true },` |
| 167 | `{ "name": "api-keys", "kind": "capability", "build": "designed", "census": { "count": 2, "donors": ["zync", "vibeflare"], "converged": true ` |
| 173 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build green (ledger #4). synthesis-§6 'designed' was sta` |
| 174 | `"deps": ["@platform-modules/db", "@platform-modules/auth"], "census": { "count": 2, "donors": ["zync", "ForumZone"], "converged": true, "als` |
| 178 | `{ "name": "rbac-flat", "kind": "adapter", "note": "ForumZone flat enum" },` |
| 189 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + commerce-blueprint idempotent settl` |
| 191 | `"census": { "count": 3, "donors": ["multideal", "ForumZone", "Press.zone"], "converged": true },` |
| 202 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + commerce-blueprint applyVat funnel ` |
| 204 | `"census": { "count": 2, "donors": ["multideal", "trance-shop"], "converged": true, "note": "rates-table; trance = US-exclusive (Pattern C)" ` |
| 214 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build green (ledger #4)",` |
| 216 | `"census": { "count": 3, "donors": ["zync", "multideal", "ForumZone"], "note": "zync = reference impl" },` |
| 229 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + consumer tests/uploads-authz.test.t` |
| 230 | `"deps": ["@platform-modules/util"], "census": { "count": 6, "donors": ["multideal", "ForumZone", "zync", "trance-shop", "Press.zone"], "note` |
| 244 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + consumer tests/search.test.ts + com` |
| 245 | `"deps": ["@platform-modules/db", "@platform-modules/util"], "census": { "count": 5, "donors": ["zync", "ForumZone", "multideal", "trance-sho` |
| 249 | `"watch": ["algolia/meilisearch adapter (0 donors)", "fewtok SQLite kb-store path"],` |
| 254 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + consumer tests/seo.test.ts (this se` |
| 255 | `"deps": [], "census": { "count": 3, "donors": ["multideal", "ForumZone", "trance-shop"], "note": "pure builders; Press.zone=legacy CMS+SEO s` |
| 269 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + consumer tests/ai.test.ts (this ses` |
| 271 | `"census": { "count": 2, "donors": ["zync", "multideal"], "converged": true, "also": ["ForumZone", "vibeflare", "fewtok"] },` |
| 278 | `{ "name": "usage", "kind": "capability", "build": "harvest", "census": { "count": 2, "donors": ["vibeflare", "Botmaster"] }, "note": "raw to` |
| 279 | `{ "name": "tool-use", "kind": "capability", "build": "harvest" },` |
| 280 | `{ "name": "model-discovery", "kind": "capability", "build": "harvest", "note": "listModels + cache; 1-donor but generic (R5)" },` |
| 284 | `"r5_note": "shipped over-thinned (completion+fallback only); usage/tool-use/model-discovery harvest pending — see synthesis §6 2026-06-15"` |
| 288 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + consumer tests/realtime.test.ts exe` |
| 290 | `"census": { "count": 2, "donors": ["zync", "ForumZone"], "converged": true, "note": "best = ForumZone hibernatable DO" },` |
| 299 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + commerce/saas blueprint money funne` |
| 304 | `"census": { "count": 4, "donors": ["multideal", "ForumZone", "trance-shop", "zync"] },` |
| 307 | `{ "name": "subscriptions", "kind": "capability", "status": "designed", "donors": ["ForumZone", "zync"], "note": "recurring lifecycle — plan ` |
| 312 | `{ "name": "sumit", "kind": "adapter", "note": "IL; trance-shop provider-in-charge" },` |
| 318 | `"status_note": "BUILD-approved (design spec §4, 2026-06-17). Deletion test PASS — delete it → tier/capability gating scatters into every app` |
| 322 | `"census": { "count": 2, "donors": ["zync", "ForumZone"], "note": "zync tier-ordering (plan→feature gates) + ForumZone feature-limits jsonb; ` |
| 329 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build green + consumer tests/marketing.test.ts (complian` |
| 331 | `"census": { "count": 2, "donors": ["trance-shop", "ForumZone"], "note": "self-managed x2; brevo x1 (337 hits), loops x1" },` |
| 339 | `{ "name": "loops", "kind": "adapter", "note": "census-observed ESP (x1); NOT built — no src/loops.ts or package export on disk" }` |
| 344 | `"status_review": "census 2026-06-16 found zync ALSO has standalone invoicing (recurring/AR-aging/credit-notes, hardened) -> x2 donors BUT di` |
| 347 | `"census": { "count": 2, "donors": ["multideal", "zync"], "converged": false },` |
| 356 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + consumer tests/helpdesk.test.ts (th` |
| 357 | `"deps": ["@platform-modules/db"], "census": { "count": 3, "donors": ["zync", "trance-shop", "multideal"], "note": "3-donor shape + multideal` |
| 368 | `"census": { "count": 1, "donors": ["multideal"], "note": "PZ wallet + trance split are DIFFERENT concepts" },` |
| 377 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + consumer tests/audit.test.ts + saas` |
| 378 | `"deps": ["@platform-modules/db"], "census": { "count": 4, "donors": ["zync", "ForumZone", "multideal", "trance-shop"], "note": "core sync-in` |
| 390 | `"deps": [], "census": { "count": 5, "donors": ["multideal", "ForumZone", "trance-shop", "vibeflare", "Press.zone"], "note": "same need, 5 ba` |
| 404 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build+verify green + consumer i18n harness (this session` |
| 406 | `"deps": [], "census": { "count": 1, "donors": ["achiron"], "also": ["trance-shop", "multideal"] },` |
| 408 | `{ "name": ".", "kind": "core", "note": "harvest pending: nested+namespaced keys (R5)" },` |
| 410 | `{ "name": "loader", "kind": "capability", "build": "harvest", "note": "lazy bundle-split" },` |
| 411 | `{ "name": "pick", "kind": "capability", "build": "harvest", "note": "pickLocalized DB-row by locale" },` |
| 412 | `{ "name": "zod", "kind": "capability", "build": "harvest", "peer": ["zod"] }` |
| 434 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build green + jsdom tests + consumer dep (this session, ` |
| 440 | `"verified": true, "verified_at": "2026-06-16", "verified_by": "turbo typecheck+test+build green + 10 jsdom tests (mocked WebSocket) (this se` |
| 446 | `"@platform-modules/events": "census x0 (2026-06-14) -> jobs/outbox + direct calls",` |
| 447 | `"@platform-modules/webhooks": "inbound -> util crypto/idempotency leaves (host recipe); OUTBOUND delivery re-disposition pending (ledger #5,` |
| 452 | `"@platform-modules/risk": "fraud = affiliate/fraud capability; extract on 2nd non-affiliate consumer",` |
| 456 | `"entitlements (prior disposition, REVERSED 2026-06-17)": "was: NOT a module — gate->auth/entitlements; limits->billing; tier->tenancy; cap->` |
| 460 | `"@platform-modules/promotions": "x1 mature (multideal); trance trivial+incompatible",` |
| 462 | `"@platform-modules/community": "x1 (ForumZone-only, all 6 sub-concerns)",` |
| 463 | `"integrations": "NEW class (zync: slack/jira/asana/zapier/make) — x1 WATCH, forward-need for SaaS (ledger #6)",` |
| 464 | `"outbound-webhook-delivery": "x2 now (zync hardened + others) — re-dispose (ledger #5)"` |
| 467 | `"ticketing": "EXCLUDED 2026-06-16 — event ticketing is the PROPRIETARY CORE PRODUCT of trance-shop-israel, not generic substrate. Harvesting` |
| 475 | `{ "stage": "ui-primitives", "owner": "flat @platform-modules/ui-* family (ui-tokens/ui-util/ui-primitives) on the framework/presentation axi` |
| 478 | `{ "stage": "blueprint", "owner": "composed app foundation (THEMELESS, SDK-style dev base)", "status": "speculative", "note": "AMENDED 2026-0` |
| 495 | `"commerce_note": "invoice-on-charge (receipts/tax-invoices emitted when a charge settles) is Pattern-A billing-provider CONFIG — PaymentProv` |
| 508 | `"_note": "a plugin = a bolt-on FEATURE added on top of any base preset (create-mod-app --preset <base> --plugin <name>). Distinct from a pre` |
| 511 | `"subscriptions": { "form": "module", "bundles": ["@platform-modules/billing", "@platform-modules/billing-react", "@platform-modules/entitlem` |
| 512 | `"blog": { "form": "blueprint", "bundles": ["@platform-modules/content", "@platform-modules/content-react"], "requires": ["@platform-modules/` |
| 513 | `"cms": { "form": "blueprint", "bundles": ["@platform-modules/content", "@platform-modules/content-react"], "requires": ["@platform-modules/d` |
| 514 | `"helpdesk": { "form": "module", "bundles": ["@platform-modules/helpdesk", "@platform-modules/helpdesk-react"], "requires": ["@platform-modul` |
| 515 | `"marketing": { "form": "module", "bundles": ["@platform-modules/marketing", "@platform-modules/marketing-react"], "requires": ["@platform-mo` |
| 516 | `"integrations": { "form": "module", "bundles": ["@platform-modules/integrations"], "requires": ["@platform-modules/db", "@platform-modules/a` |
| 517 | `"affiliate": { "form": "module", "bundles": ["@platform-modules/affiliate"], "requires": ["@platform-modules/db", "@platform-modules/ledger"` |
| 518 | `"invoicing": { "form": "module", "bundles": ["@platform-modules/invoicing"], "requires": ["@platform-modules/db", "@platform-modules/billing` |
| 519 | `"_not_plugins": "api-keys + webhooks-outbound are NOT standalone plugins — harvest api-keys into @platform-modules/auth as a subpath (forwar` |
| 522 | `"_note": "DISPOSITION CATALOGUE ONLY — not a backlog. A template is a multi-screen flow (flow-grain; screen-set) assembled by the host over ` |
| 524 | `"_census_gaps_note": "no donor coverage for these screens — build fresh when template gates met",` |
| 526 | `"auth": { "screens": ["sign-in", "sign-up", "reset", "verify-email", "2FA", "social-callback"], "backing": ["@platform-modules/auth", "@plat` |
| 527 | `"account": { "screens": ["profile", "account-settings", "security (sessions/pw)", "api-keys", "delete-account"], "backing": ["@platform-modu` |
| 528 | `"subscription-tiers": { "screens": ["pricing", "plan-picker/compare", "upgrade-downgrade", "checkout", "billing-portal", "usage/quota-meter"` |
| 529 | `"team-org": { "screens": ["members", "invite", "role-assign (RBAC)", "org-switcher", "org-settings"], "backing": ["@platform-modules/tenancy` |
| 530 | `"admin-dashboard": { "screens": ["shell/nav", "metrics-cards", "data-table-CRUD", "detail/edit-drawer", "audit-log-viewer"], "backing": ["@p` |
| 531 | `"content": { "screens": ["post/page-list (admin)", "rich-editor", "publish/schedule", "taxonomy", "media-library", "public-feed", "public-de` |
| 532 | `"notifications": { "screens": ["bell/inbox", "preferences", "web-push-optin"], "backing": ["@platform-modules/notifications", "@platform-mod` |
| 533 | `"onboarding": { "screens": ["welcome-wizard", "empty-states", "setup-checklist"], "backing": ["@platform-modules/ui-primitives"], "owningPlu` |
| 534 | `"marketing": { "screens": ["landing/hero", "features", "newsletter-signup", "blog-index"], "backing": ["@platform-modules/marketing", "@plat` |
| 535 | `"moderation": { "screens": ["report-queue", "user-mgmt", "ban/mute", "flagged-content"], "backing": ["@platform-modules/audit", "@platform-m` |
| 536 | `"search": { "screens": ["search-bar", "results", "filters/facets"], "backing": ["@platform-modules/search", "@platform-modules/search-react"` |
| 537 | `"system": { "screens": ["404/error", "loading/skeleton", "maintenance"], "backing": ["@platform-modules/ui-primitives"], "owningPlugin": nul` |
| 543 | `"saas-admin": { "preset": "saas", "plugins": ["subscriptions"], "templates": ["auth", "account", "team-org", "admin-dashboard", "onboarding"` |
| 544 | `"saas-b2b": { "preset": "saas", "plugins": ["subscriptions"], "templates": ["auth", "account", "team-org (heavy RBAC)", "admin-dashboard", "` |
| 545 | `"commerce-storefront": { "preset": "commerce", "plugins": ["subscriptions"], "templates": ["content (pages)", "admin-dashboard", "subscripti` |
| 546 | `"community-forum": { "preset": "community", "plugins": [], "templates": ["content", "moderation", "notifications", "auth", "onboarding"], "b` |
| 547 | `"blog": { "preset": "core", "plugins": ["blog"], "templates": ["content", "marketing", "auth (minimal)"], "bestDonor": "content net-new; mul` |
| 548 | `"cms": { "preset": "core", "plugins": ["cms"], "templates": ["content (rich)", "admin-dashboard", "team-org (roles)", "search"], "preset_not` |
| 549 | `"ai-saas": { "preset": "saas", "plugins": ["subscriptions"], "templates": ["auth", "account", "subscription-tiers", "admin-dashboard"], "pre` |
| 550 | `"marketing-site": { "preset": "core", "plugins": ["marketing", "blog"], "templates": ["marketing", "content (blog)"], "bestDonor": "zync.is ` |
| 551 | `"helpdesk": { "preset": "core", "plugins": ["helpdesk"], "templates": ["auth", "admin-dashboard", "notifications"], "bestDonor": "multideal ` |

### `docs/specs/2026-06-13-ai-module-boundaries.md` (63 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** Read real LLM-gateway impl + call-sites across 4 census donors (zync, multideal, vibeflare, trance-shop) via parallel read-only ` |
| 11 | `The sharpest finding: **two donors (zync, multideal) independently built the *same* seam** — a provider interface + a retryable-error hierar` |
| 13 | `The second sharpest: **accounting diverges totally** — zync credits, multideal USD, vibeflare "neurons", trance nothing. So the core must **` |
| 17 | `## Census — honest` |
| 19 | `\| Donor \| Provider interface \| Fallback chain \| Accounting \| Verdict \|` |
| 21 | `\| **zync** \| `AIAdapter` (anthropic\\|openai\\|google) + `getAdapter()` factory \| `executeWithFallback` (main→backups, retryable walk, `w` |
| 22 | `\| **multideal** \| `LlmProvider` (`providers/types.ts:56-82`) + `gemini`/`openai-compat`/`mock` \| `ChainedLlmProvider` (`chained.ts:45-115` |
| 23 | `\| **vibeflare** \| OpenAI-compat wire types (`packages/shared/src/openai.ts`, most complete) + CF `env.AI.run()` (`dispatch.ts:15`) \| none` |
| 24 | `\| **trance-shop** \| none — raw `fetch` Gemini REST (`lib/ai/moderation.ts:91-148`) \| none (catch→escalate) \| none \| **NONE (negative co` |
| 26 | `**The honest framing (same discipline as helpdesk):** the **full seam** (interface + error hierarchy + fallback chain) = **2 donors built it` |
| 34 | `- **Vanishes from apps:** the provider-normalization layer (message shape per provider, image-block mapping, error normalization) + the fall` |
| 42 | `Axis = **`anthropic \| openai-compat \| google`** (+ `workers-ai` as a CF-binding backend). `openai-compat` is the common denominator (zync/` |
| 48 | `stream?(req: AIRequest): ReadableStream<string> // optional; zync abstracts it, others don't` |
| 49 | `listModels?(creds, baseUrl?): Promise<ModelOption[]>  // design-forward, 1-donor (multideal spec), UNBUILT — see Model-discovery §` |
| 68 | `- **Error hierarchy** — `RateLimitError \| TransientError \| QuotaExhaustedError \| AuthError \| FatalError`, each with a `retryable` flag. ` |
| 70 | `- **`AIRequest` / `AIResponse` / `AIMessage` / `AIContentBlock`** — provider-agnostic wire shapes. `AIResponse.usage = { promptTokens, compl` |
| 71 | `- **Adapters** (subpaths, peer the SDK): `ai/anthropic`, `ai/openai-compat` (covers OpenAI + most gemini-compat + groq + together), `ai/goog` |
| 76 | `- **DB credential resolution** — host passes creds to `getAdapter`; no DB/secrets inside module (multideal's `buildChainedProvider` DB query` |
| 77 | `- **Prompt assembly / system-prompt layering / use-case taxonomy** — zync's tenant-override stack, trance's moderation matrix, multideal's p` |
| 78 | `- **Job state machine** — multideal's PENDING→RUNNING→COMPLETED (`runner.ts`) = `@platform-modules/jobs` territory + host, not AI core.` |
| 80 | `- **Model registry / pricing tables** — host config (DB-driven in zync/multideal/vibeflare; each different).` |
| 82 | `## WATCH — register nothing (1-donor or host-domain)` |
| 84 | `- **RAG** (zync only — tenant Vectorize namespaces). 1-donor → WATCH.` |
| 85 | `- **Agent-tool-loop** (multideal per-kind agents; vibeflare has `tool_calls` types but no loop). Vocabulary exists, orchestration doesn't re` |
| 86 | `- **Streaming** — zync abstracts via `AIAdapter.stream()`; others bypass. Keep `stream?()` **optional** in the interface; don't force it. (z` |
| 87 | `- **moderation / translate** as named verbs — 1-donor each (trance moderation, none-else). Host use-cases, not module subpaths.` |
| 91 | `## Model-discovery layer — NEW (multideal `2026-06-13-llm-model-dropdown-design.md`, Status: Design, UNBUILT)` |
| 93 | `**Honest headline:** the spec is large for the *donor* (per-instance providers, a cache table, a resolver, two endpoints, a strict-select wi` |
| 97 | `**`fetchProviderModels(type, apiKey, baseUrl) → ModelOption[]` → adapter capability, but FORWARD-TIER.** Hitting a provider's `/models` endp` |
| 99 | `**`llm_model_cache` table + TTL 24h + lazy-fill + serve-stale + GET/refresh endpoints → HOST (confirms).** A per-instance cache of available` |
| 103 | `**Naming seam (build-time reconcile, not core):** discovery keys off stored `type` literals `google\|openai-compat\|mock`; the gateway axis ` |
| 111 | `- `@platform-modules/ai` row: **candidate (census ×4) → designed (thin provider-gateway).** Note: "2-donor independent seam convergence (zyn` |
| 115 | `1. `@platform-modules/ai` core: `AIAdapter` interface + error hierarchy + `AIRequest/Response` types (seed from vibeflare `openai.ts`) + `ex` |
| 123 | `## R5 harvest amendment (2026-06-15) — the gateway was thinned by *dumping mature generic capability to host*` |
| 125 | `> Audience: AI coding agents first. **BLUF:** the original boundary above is a **correct seam drawn too tight**. It routed five *generic, ma` |
| 129 | `\| Capability \| Original call \| R5 call \| Target subpath \| Donors / freeze \| Donor ref \|` |
| 131 | `\| LLM-job runner (`runJob`: load→kind→creds→provider→verdict; `RunResult` ok/retry/fatal; transitions; retry-cap; stale-reap) \| HOST (line` |
| 133 | `\| `JobKind<TInput,TResult,TVerdict>` plugin contract + registry \| (implicit host) \| **NEW → IMPORT** (the contract that makes the runner ` |
| 134 | `\| tool-use agent harness (loop + tool-contract + registry/dispatch + terminal/write classify + autonomy-threshold gate + max-iters + parse-` |
| 135 | `\| generic tool primitives (vision `read-image`, RAG `search-kb`) \| (bundled in the WATCH) \| **OVERTURN → IMPORT per-leaf** (deps diverge ` |
| 136 | `\| cost computation (`computeCost(usage, rateTable)`) \| **HOST** ("hard boundary", 4 currencies) \| **REFINE → IMPORT opt-in** (mechanism o` |
| 138 | `\| PII redactor (`buildRedactionMap`/`redactForPrompt`/`substitutePseudoIds`) — pre-send scrub, post-response de-anon \| (not in spec) \| **` |
| 139 | `\| `google`/Gemini adapter \| planned `ai/google`, UNBUILT \| **BUILD — broken promise** (`getAdapter('google')` throws `FatalError` today) ` |
| 140 | `\| `mock` adapter (simulates 429/quota/auth) \| (test aid) \| **BUILD → IMPORT** (Gate-3 fixture needs it) \| `ai/mock` \| donor has it \| `` |
| 141 | `\| `listModels?()` optional adapter cap \| forward-tier (Model-discovery §) \| **CONFIRM forward-tier** (build with google adapter) \| adapt` |
| 142 | `\| translation kind \| (1 of 4 host kinds) \| **REFINE → IMPORT generic translate mechanism**; fields+persistence HOST \| `ai/kind/translate` |
| 145 | `\| RAG (Vectorize) \| WATCH (1-donor zync) \| **CONFIRM → WATCH** \| — \| 1-donor \| — \|` |
| 148 | `R5 ≠ "harvest everything." The discipline that keeps this from violating *convergence > count*:` |
| 149 | `1. **Harvest the mechanism, NOT the contract-freeze.** Build `ai/job`/`ai/agent`/`ai/kind`/`ai/redact`/`ai/kind/translate` as importable sub` |
| 152 | `4. **Core boundary is untouched** — none of this puts cost or domain logic in `.`; `assertUsageBoundary` still rejects cost. The harvest gro` |
| 154 | `### Post-harvest subpath layout` |
| 171 | `- **Vision** is core, not a tool concern. The image **content path** (`AIRequest`/`AIContentBlock` image variant) was **already in shipped c` |
| 174 | `### Scope (multideal migration)` |
| 175 | `multideal is the donor for all of the above → every harvested subpath is multideal-consumed → **in-scope** for the migration. The contracts ` |
| 178 | `> **BLUF:** the disposition table above is the *durable design surface* (R5 "harvest fully" is a design rule — recording the full mature sur` |
| 180 | `**BUILD NOW — the ai pilot (census-deps: none; clean ports/mechanisms; one fixes a live runtime throw):**` |
| 182 | `\| Subpath \| Why buildable now \| Census deps \|` |
| 187 | `\| `ai/redact` \| `buildRedactionMap`/`redactForPrompt`/`substitutePseudoIds`; security floor; harvest unconditional. \| none \|` |
| 191 | `> **Core seam invariant (reconciles "core unchanged" across this spec):** the core **boundary** — token-only `usage`, no cost field, enforce` |
| 200 | `\| `ai/agent` \| **extraction, not a port** — census shows the harness interwoven with `helpdesk`/`notifications`/`system_config`/app-PII/`i` |
| 201 | `\| `ai/kind` \| same: extraction of the pluggable contract from app-wiring; ×1 donor-only; freeze-blocked. \|` |
| 202 | `\| `ai/kind/translate` \| same: generic translate mechanism is entangled with host field/persistence wiring; ×1 donor-only; freeze-blocked. ` |
| 204 | `**Unblock conditions (when the deferred set becomes buildable):** `read-image` ← after `util/ssrf-guard` ships; `search-kb` ← after `helpdes` |

### `docs/specs/2026-06-13-affiliate-entitlements-invoicing-analytics-tax-module-boundaries.md` (62 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** **haiku-gather / Opus-judge** protocol. 5 haiku agents (ctx-banned, Read/Grep/Glob/Bash only) gathered raw code + `file:line` ac` |
| 11 | `\| Candidate \| Census (real donors) \| Verdict \| One-line \|` |
| 13 | `\| `@platform-modules/affiliate` \| **1** (multideal) \| **WATCH** \| Deep single-donor; Press wallet & trance splits are different concepts` |
| 14 | `\| `@platform-modules/entitlements` \| 3 nominal / **0 convergent** \| **WATCH** \| Only convergent piece already = `uploads/quota`; rest is` |
| 15 | `\| `@platform-modules/invoicing` \| **1** standalone (multideal) \| **WATCH** \| trance folds invoicing into Sumit charge (not a module); ad` |
| 17 | `\| `@platform-modules/tax` \| **2 convergent** (zync, multideal) \| **designed (thin)** \| Same date→rate seam, independently built; storage` |
| 18 | `\| **`@platform-modules/ledger`** *(new, discovered)* \| **3** (multideal, Press.zone, ForumZone) \| **candidate** (register, map next) \| A` |
| 20 | `The tax/entitlements pair is the clean worked example of the **2-donor disposition rule**: tax = same question answered the same way → desig` |
| 24 | `## 1. `@platform-modules/affiliate` → WATCH (1 real donor)` |
| 26 | `- **multideal** = full referral system: `apps/web/src/server/referrals/` (attribution.ts, commission.ts tier-based `resolveAffiliateTierPct`` |
| 27 | `- **Press.zone** = wallet + coin_ledger — virtual-currency economy, **NOT referral/affiliate**. Different concept.` |
| 28 | `- **trance-shop** = platform/vendor payment **splits** (Sumit) — **NOT referral**. Different concept.` |
| 29 | `- zync, ForumZone, vibeflare, Botmaster = NONE.` |
| 31 | `**Gate 1 / census:** 1 genuine affiliate donor. Designing an affiliate module API from one example = the community/ForumZone trap. **WATCH.*` |
| 32 | `**Consumes `@platform-modules/ledger`** when that exists (multideal's credit_ledger + wallet_balances IS a ledger instance — see §6).` |
| 37 | `- **zync** `meetsMinimumTier`/`TIER_ORDER` + `requireTier`→402 (`packages/auth/src/entitlements.ts`) = ranked-access boolean gate. **1 donor` |
| 38 | `- **zync** `checkStorageQuota(used, req, limit)` (`packages/storage/src/quota.ts`) + **ForumZone** per-tier `limits` jsonb (`packages/db/src` |
| 39 | `- **vibeflare** DO daily-budget (`apps/worker/src/quota/do.ts` QuotaCounter, neurons/day, 429) = metered usage. **1 donor** — and a `@platfo` |
| 40 | `- trance, multideal, Press.zone (PlanTier type only), Botmaster = NONE/types.` |
| 42 | `**Gate 1:** pull the convergent piece to its home (`uploads/quota`) and what remains is two 1-donor primitives (`meetsMinimumTier` tier-orde` |
| 45 | `- **enforcement gate** (`meetsMinimumTier(order)` + `requireTier` middleware → 402) → **`@platform-modules/auth`** sub. zync already places ` |
| 47 | `- **which tier this workspace is on** → **`@platform-modules/tenancy`** (zync: tier hangs off the org; B2B = whole workspace on a tier).` |
| 50 | `## 3. `@platform-modules/invoicing` → WATCH (1 standalone donor)` |
| 52 | `- **multideal** = dedicated `src/server/invoicing/`: registry.ts + Morning + iCount adapters, NoopProvider, async job-driven, AES-GCM-encryp` |
| 53 | `- **trance-shop** = Sumit charge **emits** invoice+receipt as a side-effect (`DocumentType:1 InvoiceAndReceipt`, `SendDocumentByEmail`, `pac` |
| 56 | `**Gate 1:** 1 donor built invoicing as a standalone module; the other rides its payment gateway (so for Sumit-class providers, invoicing is ` |
| 61 | `- **vibeflare** = D1 `audit_events` + Cloudflare Analytics Engine `writeDataPoint`; usage charts.` |
| 63 | `- **zync** = webhook-delivery audit log only (no aggregation).` |
| 64 | `- ForumZone, Press.zone, multideal = NONE. No GA/Plausible/PostHog anywhere.` |
| 67 | `**Reusable residue = LLM usage-metering** (vibeflare + Botmaster, 2 donors): record per-call `{model, tokensIn, tokensOut, ts}` + daily roll` |
| 69 | `## 5. `@platform-modules/tax` → designed (thin) — 2-donor convergence` |
| 71 | `- **zync** = IL VAT engine: `vat_rates` table (18 historical rates 1976–2025, `NUMERIC(5,4)`), `getVatRate(country, date)` date-aware (most-` |
| 72 | `- **multideal** = `vat_schedule` in system_config JSON, `findRateInSchedule`/`getVatRateForDate(date)`, integer %, `FALLBACK_RATE=17`; `vatA` |
| 77 | `**Scope caveat (verified, do NOT overclaim):** the gross↔net helpers do **not** unify into one canonical rounding function — zync adds VAT t` |
| 78 | `- `applyVat(netAgorot, rate) → { vat, gross }` (exclusive, zync shape)` |
| 79 | `- `extractVat(grossAgorot, rate) → { net, vat }` (inclusive, multideal shape)` |
| 81 | `Host picks which by pricing model. The value-add = getting integer-agorot rounding right once for **each** direction + the shared IL histori` |
| 83 | `**Money-math representation (amended 2026-06-15 — financial-correctness floor, pinned pre-dispatch).** The donor formulas above (`ROUND(net*` |
| 86 | `- **Rate canonical representation = integer basis points** (1% = 100 bp; 17% = 1700 bp). Losslessly captures zync's `NUMERIC(5,4)` (a 4-deci` |
| 89 | `- **Date contract = host-resolved `YYYY-MM-DD` legal date, NOT a `Date` (amended 2026-06-15, pre-merge).** `resolveVatRate(schedule, date)` ` |
| 90 | `- **Test discipline:** `net + vat === gross` is true *by construction* (gross/net is computed as sum/difference) → it tests nothing about ro` |
| 92 | `**No-fallback is the correct contract — a missing VAT rate MUST fail loud (decided 2026-06-17; supersedes an earlier draft that wrongly prop` |
| 98 | `**What the donors actually built (the only thing that earns `designed`):** zync + multideal both operate on a **single amount** via a **date` |
| 102 | `\| Strategy \| Computes \| Covers \| Donor status \| Lives \|` |
| 104 | `\| **self-compute** (`tax/rates-table`) \| you, from versioned date-effective rate dataset \| jurisdictions w/ simple rate: **IL** national ` |
| 109 | `**Sub-structure & donor tiers:**` |
| 110 | `- **`tax/rates-table`** — **designed, build now (2 donors zync+multideal).** `resolveVatRate(schedule, date)` (the 2-donor convergence) + ra` |
| 114 | `**The `TaxAdapter` envelope is a forward sketch, NOT a decision** — it matches neither tax donor today. It gets decided **against the first ` |
| 116 | `**Sequencing — donor-strength and build-urgency INVERT; sequence by NEED not donor count.** The donor-proven path (`tax/rates-table` IL) may` |
| 118 | `## 6. `@platform-modules/ledger` → NEW candidate (census ×3) — register, do NOT map this turn` |
| 121 | `- **multideal** `credit_ledger` (amount_agorot, entry_type accrual/redemption/adjustment/reversal/clawback, idempotent `(entry_type, source_` |
| 122 | `- **Press.zone** `coin_ledger` (amount, type purchase/spend/refund/reward/tip, `idempotency_key`, reference_id) + `wallets` (balance, lifeti` |
| 123 | `- **ForumZone** `credit_ledger` (delta, reason, balanceAfter inline, periodKey, idempotent allowance grant).` |
| 125 | `**Shared core:** append-only signed-delta entries + idempotency key + materialized balance + typed-reason enum. **Divergent extensions:** ve` |
| 127 | `**Disposition:** register as a **candidate** row. **Do NOT design now** — the locking/materialization contract (multideal's `FOR UPDATE` deb` |
| 133 | `- **affiliate/zync:** the affiliate gather reported zync "no source directories" while the tax & entitlements gathers found zync's `packages` |
| 140 | `- `@platform-modules/affiliate`: candidate → **WATCH (1 donor)**. Note: "multideal full system (referrals/ deep + fraud); Press wallet & tra` |
| 141 | `- `@platform-modules/entitlements`: candidate → **WATCH (no convergent core)**. Note: "convergent piece = `uploads/quota` (zync checkStorage` |
| 142 | `- `@platform-modules/invoicing`: candidate → **WATCH (1 standalone donor)**. Note: "multideal standalone provider-adapter module (Morning/iC` |
| 143 | `- `@platform-modules/analytics`: candidate → **DISSOLVED**. Note: "domain BI = host SQL (search-class); LLM usage-metering (vibeflare+Botmas` |
| 144 | `- `@platform-modules/tax`: candidate → **`tax/rates-table` designed (2 donors); engine axis + `tax/stripe` + `tax/vat-id` forward (0 donors)` |
| 145 | `- **`@platform-modules/ledger`** *(new row)*: **candidate (census ×3: multideal/Press.zone/ForumZone)**. Note: "append-only signed-delta + i` |

### `docs/specs/2026-06-12-module-registry.md` (56 hits)

| Line | Offending substring |
|------|-------------------|
| 9 | `- `docs/registry.json` — machine-readable mirror; per-module **layer** + census live there.` |
| 10 | `- `docs/specs/2026-06-16-donor-capability-inventory.md` — SHA-pinned donor census ("who has X?"). Read it before sending any exploration age` |
| 11 | `- `docs/specs/2026-06-16-registry-reconciliation-ledger.md` — open contradictions + new census signals awaiting sign-off (api-keys promote, ` |
| 13 | `> **`@platform-modules/events` is DISSOLVED** (census ×0, 2026-06-14). Cross-module signals = `@platform-modules/jobs/outbox` (transactional` |
| 27 | `The donor-mining UI stack (headless-module → `-react` sibling → ui-primitive → template → blueprint → distribution → surface-target) is a **` |
| 46 | `Status legend: **shipped** (built+verified) · **designed** (boundary pass done, decisions locked, not built) · **pilot** (committed next bui` |
| 50 | `**Census-verified 2026-06-12** (`2026-06-12-module-discovery-census.md`): 6 mature TS donors scanned (VirtuAc=Python out-of-scope, corrobora` |
| 52 | `**2-donor disposition rule (the discriminator, codified):** census count alone does NOT decide. ×2 promotes to `designed` ONLY when the dono` |
| 54 | `**"designed" is not monolithic — firmness tiers:** STRONG (≥3 donors converging: search 5/5, seo 3/3, uploads 5/6, jobs/cache/audit/auth) vs` |
| 60 | `\| `@platform-modules/util` \| **shipped** (core leaves verified; `result`/`validation` candidate, `sanitize-html` WATCH — opt-in per-subpat` |
| 61 | `\| ~~`@platform-modules/events`~~ \| **DISSOLVED (not a module)** — census ×0 (2026-06-14) \| — \| — \| No in-proc bus. Decoupling = `@platf` |
| 64 | `\| `@platform-modules/record-store` \| **shipped** (2026-06-17 — forward-need ×1, expansion mode — NOT donor count; shape recurs 3× as COUSI` |
| 65 | `\| `@platform-modules/jobs` \| **shipped** \| core = type-discriminated envelope + handler registry + ack/retry convention + pluggable idemp` |
| 66 | `\| `@platform-modules/cache` \| **shipped** (2026-06-16, `7d1cf7f`) \| core = runtime-agnostic seam: `get<T>`/`set<T>`/`del` (JSON+TTL) + `g` |
| 67 | `\| `@platform-modules/audit` \| **shipped** \| core (seam, peer `@platform-modules/db`) = append-only table `(actor_id, actor_type?, actor_l` |
| 76 | `\| `@platform-modules/notifications` \| **shipped** \| core = `notify(event)` router (ZERO channels) + `render` + host-injected `DedupStore`` |
| 77 | `\| `@platform-modules/auth` \| **shipped** (core seam built+verified; methods `/oauth-provider` `/passkey` `/totp` `/otp-sms-firebase` `/adm` |
| 78 | `\| `@platform-modules/tenancy` \| **shipped** \| core = `createTenancy` seam (`scopeQuerier`/`resolveCapabilities` interfaces + tenant/membe` |
| 79 | `\| `@platform-modules/billing` \| **shipped** \| core seam (one-time charge/refund + webhook idempotency); **`/subscriptions` (designed 2026` |
| 80 | `\| `@platform-modules/entitlements` \| **designed** (BUILD-approved 2026-06-17) \| `can(subject, capability): boolean` · `quota(subject, key` |
| 81 | `\| `@platform-modules/search` \| **shipped** (thin seam) \| core = `searchEntities(registry, params)` federation seam: fan-out per-entity pr` |
| 82 | `\| `@platform-modules/webhooks` \| **DISSOLVED (not a module)** \| Census ×5 was direction-split. **Inbound verify** = host-callback (Stripe` |
| 83 | `\| `@platform-modules/ai` \| **shipped** (thin provider-gateway; `usage`/`tool-use`/`model-discovery` harvest-pending, opt-in) \| core = `AI` |
| 84 | `\| `@platform-modules/realtime` \| **shipped** \| core = type-only barrel (`RealtimeEvent`, `ServerFrame` — browser-safe, zero runtime). `/s` |
| 90 | `\| `@platform-modules/invoicing` \| **WATCH** (×2 donors, ×0 convergence — hold) \| core seam; adapters `/morning` `/icount` `/rivhit` `/inv` |
| 91 | `\| `@platform-modules/marketing` \| **shipped** — built + verified: consumer `tests/marketing.test.ts` exercises the compliance seam (legal-` |
| 92 | `\| `@platform-modules/uploads` \| **shipped** (validation leaves + presign adapter) \| leaves `uploads/{magic-bytes [security: strict AVIF b` |
| 93 | `\| ~~`@platform-modules/image`~~ \| **DISSOLVED (not a module)** \| 3 donors, 3 engines (ForumZone jsquash / multideal CF-Images / trance Ph` |
| 94 | `\| `@platform-modules/seo` \| **shipped** (thin scaffolding) \| leaves `seo/jsonld` (serializeJsonLd [**security: escape UNION** of `<>&`+U+` |
| 95 | `\| `@platform-modules/promotions` \| **WATCH** (1 real donor) \| pure `validatePromo`+`applyPromo` (multideal `server/promo/`) \| — \| Censu` |
| 96 | `\| `@platform-modules/inventory` \| **WATCH** (incompatible mechanisms) \| — \| — \| Census ×2 but structurally incompatible: multideal Post` |
| 97 | `\| `@platform-modules/community` \| **WATCH** (1 real donor) \| — \| — \| All 6 sub-concerns (moderation/reputation/reactions/polls/content-` |
| 98 | `\| `@platform-modules/helpdesk` \| **shipped** (built 2026-06-15) \| core (peer `@platform-modules/db`) = polymorphic satellite tables `supp` |
| 100 | `\| ~~`@platform-modules/analytics`~~ (your "bi") \| **DISSOLVED (not a module)** \| domain BI = host SQL (search-class, irreducible per-app ` |
| 101 | `\| `@platform-modules/affiliate` \| **WATCH** (1 real donor) \| referral-tracking, commission-calc, payout; **`/fraud`** (referral-fraud pip` |
| 104 | `\| ~~`@platform-modules/risk`~~ (NOT a module) \| — \| fraud lives as **`@platform-modules/affiliate/fraud`** capability \| — \| — \| **VERI` |
| 106 | `**Not a module (decided):** rate-limit lives at `@platform-modules/util/rate-limit`, not standalone. SMS-as-channel lives at `@platform-modu` |
| 108 | `**New WATCH from 2026-06-16 census** (detail: donor-inventory "New findings" + ledger #5–#7): **`integrations`** (zync `packages/{integratio` |
| 110 | `**EXCLUDED — `ticketing` (NOT a platform candidate, decided 2026-06-16).** Event ticketing (trance `workers/ticketing/` — CF Worker+DO HMAC ` |
| 113 | `- **Scope — in-memory = for TESTS; persistent = the SAME mechanism, different backend (reframed 2026-06-17).** The in-memory fake records to` |
| 122 | `**Materialized 2026-06-16 at `docs/registry.json`** — the full machine-readable mirror (all modules, layers, subpaths, adapters, census, dis` |
| 132 | `"crypto":     { "kind": "capability", "deps": [], "build": "now", "source": "zync/packages/auth/src/crypto.ts" },` |
| 133 | `"tokens":     { "kind": "capability", "deps": [], "build": "now", "source": "zync/packages/auth/src/tokens.ts" },` |
| 134 | `"password":   { "kind": "capability", "deps": [], "build": "now", "source": "zync/packages/auth/src/password.ts", "note": "PBKDF2-SHA-512 10` |
| 139 | `"logger":     { "kind": "capability", "deps": [], "build": "now", "source": "trance-shop/packages/core/logger.ts" },` |
| 140 | `"error-reporter": { "kind": "capability", "deps": [], "build": "now", "source": "trance-shop/packages/core/error-reporter.ts" },` |
| 142 | `"datetime":   { "kind": "capability", "deps": [], "build": "built", "source": "multideal/apps/web/src/lib/datetime.ts + trance-shop/packages` |
| 143 | `"timezone":   { "kind": "capability", "deps": [], "build": "built", "source": "zync/packages/types/src/timezone.ts", "note": "IANA validate/` |
| 153 | `"engine-custom":       { "kind": "adapter", "source": "multideal/server/auth (raw WebCrypto + sv-revocation)", "note": "PBKDF2-SHA-512 + aft` |
| 154 | `"engine-better-auth":  { "kind": "adapter", "peer": ["better-auth"], "source": "ForumZone/packages/auth", "note": "scrypt+own session/jwks t` |
| 156 | `"oauth-provider":      { "kind": "capability", "source": "zync/packages/auth/src/oauth.ts", "note": "BE an authz server; PKCE/consent/scopes` |
| 159 | `"otp-sms-firebase":    { "kind": "adapter", "note": "multideal manual-JWKS RS256, NO firebase-admin" },` |
| 160 | `"totp":                { "kind": "capability", "source": "zync (totp/backup-codes/two-factor)", "note": "Web Crypto reimpl; trance-shop totp` |
| 161 | `"admin-sessions":      { "kind": "capability", "source": "zync signAdminSession/signImpersonationToken" },` |
| 162 | `"portal-sessions":     { "kind": "capability", "source": "zync portal/ + contractor-session" },` |
| 177 | `"_canonical": "docs/registry.json#/templates — 12-template disposition catalogue (added 2026-06-17 from design spec §5). Template = multi-sc` |

### `docs/specs/2026-06-13-helpdesk-module-boundaries.md` (44 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** Read real ticket/case/return/moderation impl + call-sites across 4 census donors (zync, trance-shop, ForumZone, multideal) via p` |
| 9 | `## Headline: `@platform-modules/helpdesk` SURVIVES as a thin **case-substrate** module — but the census is weaker than ×3 looks, and the use` |
| 13 | `1. **"Maybe it shouldn't be a module at all."** It should — but *barely*, and as a thin substrate, not a fat ticketing app. The honest censu` |
| 18 | `## Census — stated honestly (this is the whole ballgame)` |
| 20 | `\| Donor \| What it built \| Substrate? \| Generalized? \|` |
| 22 | `\| **zync** \| `tickets` + `ticket_messages` + `sla_policies` + email-intake + reply-egress + AES creds \| **FULL** (single-entity) \| No — ` |
| 23 | `\| **trance-shop** \| `supportTickets` + `supportMessages` (no attachments, no SLA, no assignment) \| **REAL but light** (single-entity) \| ` |
| 24 | `\| **multideal** \| `supportTickets` + `transactionCases` + `returns` over **polymorphic** `supportMessages`/`supportStateTransitions`/`supp` |
| 25 | `\| **ForumZone** \| `reports` (moderation: open/reviewing/resolved/dismissed, single resolutionNote) \| **NONE** (forum-domain, no threading` |
| 27 | `**The distinction that keeps this honest (it's our own census rule, so name it, don't blur it):**` |
| 28 | `- The **case *shape*** — a ticket entity + threaded messages — is genuinely **3-donor** (zync, trance, multideal).` |
| 29 | `- The **generalized, pluggable, polymorphic substrate** — the thing that makes it a *reusable multi-mode module* — is **multideal alone (1 d` |
| 30 | `- ForumZone contributes **nothing** to the substrate (its `reports` is forum moderation, not a case system) — so the real substrate census i` |
| 32 | `So this is **not** a clean ×3 convergence. It's 3-donor shape + 1-donor generalization, carried over the line by the **user's explicit forwa` |
| 40 | `Unlike `@platform-modules/search` (where federation genuinely *centralizes* and vanishes from N apps), deleting helpdesk **does not simplify` |
| 44 | `**Verdict: SURVIVES as a thin substrate.** A real (modest) module, on 3-donor shape + 1-donor generalization + forward demand. Not rubber-st` |
| 46 | `> vs the dissolves (cron/cache/http/webhooks): those had parts that scattered to leaves or were 1-donor with no recurring orchestration left` |
| 52 | `My earlier sketch — `registerCaseType(def)` + a callback-driven transition-engine — is **my synthesis, not a donor pattern. NO donor built i` |
| 54 | `- **multideal's real pattern:** polymorphic satellite tables (`supportMessages`/`supportStateTransitions`/`supportAttachments` keyed by `par` |
| 55 | `- **zync's real pattern:** transitions hardcoded in the service layer. No registry at all.` |
| 57 | `So a host writing its own state machine directly (as multideal already does) is **not worse off** than a host filling in a `registerCaseType` |
| 61 | `2. A **tiny pure transition-validation helper** — `isValidTransition(adjacencyMap, from, to)` + optional predicate guard — the shape multide` |
| 64 | `This is "soft-coupling seam": **module owns messages/transitions/attachments/SLA-timers/audit; host owns the domain entity + its columns + i` |
| 76 | `- **Threaded messages** — `support_messages (parentType, parentId, authorType: staff\|customer\|system, body, visibility?, createdAt)`. mult` |
| 77 | `- **State-transition audit** — `support_state_transitions (parentType, parentId, fromStatus, toStatus, actorId, reason?, at)`. multideal-pro` |
| 78 | `- **Transition-validation helper** — `isValidTransition(adjacency, from, to)` + optional `(ctx) => boolean` predicate guard. Pure, zero-dep.` |
| 79 | `- **SLA timers** — `sla_policies (scopeKey, target, dueMinutes)` + `computeDue()` + a `breached` flag flip. zync `ticket-sla.ts` + `cron/tic` |
| 82 | `## NOT in core — explicitly excluded (1-donor product/domain, per advisor)` |
| 84 | `The multideal explorer mislabeled several **product features** as substrate. They are **1-donor domain**, kept OUT:` |
| 85 | `- **KB / knowledge-base**, **AI-agent runner**, **escalation rule engine**, **decisions/resolutions registry**, **offer/negotiation loop** (` |
| 86 | `- **Email-intake → reply-egress** (zync `intake/email-routing.ts` + `route-ticket-reply.ts`, `support@{slug}` parse → comms queue) — **zync-` |
| 87 | `- **AES-256-GCM `adapter_credentials`** (zync) — that's `@platform-modules/util/crypto` + channel-config, not helpdesk.` |
| 88 | `- **AI agent** — if a 2nd donor wants auto-reply, it composes `@platform-modules/ai`; not baked into helpdesk core.` |
| 89 | `- **Host-domain (stays in app):** per-entity status enums + their exact values (zync 5-state vs trance 5-state vs multideal per-entity — the` |
| 93 | `The registry currently implies `@platform-modules/returns` as a 2-donor commerce candidate. **Boundary mapping kills it.** Same disposition ` |
| 95 | `- **The domain parts do NOT converge — at all.** multideal `returns` (:1817): liability enum (vendor/buyer), restocking/shipping/cash/credit` |
| 97 | `- **Returns escalates by SPAWNING a case, not by being a case-subtype.** multideal proves it: `returns.caseId` is written at `service.ts:327` |
| 101 | `## Disputes / negotiation — WATCH (1-donor)` |
| 103 | `multideal's `transactionCases` + `caseOffers`/`caseResolutions` vendor-offer/acceptance loop = **1 donor**. Census discipline → WATCH, not i` |
| 109 | `- **"Should helpdesk have modes (RMA vs moderation) as capabilities?"** — Mechanism: **yes to host-registered entity-types over a shared sub` |
| 111 | `- **"Maybe it shouldn't be a module at all / be critical."** — Helpdesk *is* a module, but thin and on weak-but-real census (3-shape + 1-gen` |
| 117 | `- `@platform-modules/helpdesk` row: **candidate (census ×2) → designed (thin case-substrate).** Correct the census note: donors are zync(FUL` |
| 118 | `- `@platform-modules/returns` (currently candidate ×2): **→ DISSOLVED (not a module).** Note: "Domain parts don't converge (multideal liabil` |
| 119 | `- New **WATCH** entries: (a) **support email-intake/reply-egress** (1-donor zync; → `@platform-modules/notifications` inbound-routing when 2` |

### `docs/specs/2026-06-17-mod-cms-feature-gap-analysis.md` (44 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Date:** 2026-06-17. **Scope:** what reference CMS (core + canonical ecosystem) ships that the `mod-cms` line (content module + `cms` bluep` |
| 9 | `**Donor-claim provenance:** EXTRACT dispositions below trace to the SHA-pinned donor inventory + the runsheet/wasp-map (which already flag `` |
| 26 | `**Disposition law (CLAUDE.md §3 — GENERALIZABILITY test, owner directive 2026-06-18):** the question is **"can this be generalized to serve ` |
| 52 | `**Legend.** Source: **EXTRACT** (donor port) · **BUILD** (zero clean donor) · **DESCOPE** (deliberate non-feature, better alternative). Dono` |
| 56 | `\| reference CMS feature \| Bucket \| Disposition \| Source \| Donor \|` |
| 58 | `\| Gutenberg block/rich-text editor \| generic Tiptap **editor primitive** (presentation axis, NOT `content/blocks`/`content-react`-proper) ` |
| 59 | `\| Block patterns / reusable blocks \| ~~`content/blocks`~~ \| **KILL (census 2026-06-18):** NO block model exists in any donor — multideal ` |
| 73 | `\| reference CMS feature \| Bucket \| Disposition \| Source \| Donor \|` |
| 79 | `**Seam decomposition (corrected per donor matrix — do NOT bundle).** Comment thread/store/display = **×1 (FZ only)**; moderation/spam = a **` |
| 81 | `\| reference CMS feature \| Bucket \| Disposition \| Source \| Donor \|` |
| 83 | `\| Threaded comments + thread store/display \| **`@platform-modules/comments`** (L2) — strongest new-module candidate \| ×1-forward-need (FZ` |
| 84 | `\| Moderation queue + spam heuristics (Akismet-class) \| **separable** `comments/moderation` OR composed `moderation` capability (rules+KB) ` |
| 85 | `\| `comments-react` (thread UI, mod tools) \| `-react` sibling \| gated on comments module \| **EXTRACT** \| FZ \|` |
| 89 | `\| reference CMS feature \| Bucket \| Disposition \| Source \| Donor \|` |
| 96 | `\| reference CMS feature \| Bucket \| Disposition \| Source \| Donor \|` |
| 104 | `\| reference CMS feature \| Bucket \| Disposition \| Source \| Donor \|` |
| 113 | `\| reference CMS feature \| Bucket \| Disposition \| Source \| Donor \|` |
| 121 | `\| reference CMS feature \| Bucket \| Disposition \| Source \| Donor \|` |
| 132 | `\| reference CMS feature \| Bucket \| Disposition \| Source \| Donor \|` |
| 134 | `\| Auth/registration screens \| **`auth-react`** sibling \| P1 sibling gap (wasp map) \| **EXTRACT** \| MD, ZY, FZ, TS \|` |
| 140 | `\| reference CMS feature \| Bucket \| Disposition \| Source \| Donor \|` |
| 142 | `\| Media library UI \| **`uploads-react`** sibling (dropzone/progress/presign/grid) \| P2 sibling gap \| **EXTRACT** \| MD media \|` |
| 147 | `\| reference CMS feature \| Bucket \| Disposition \| Source \| Donor \|` |
| 149 | `\| Contact form \| **template** (contact flow) over `helpdesk` \| gated on `helpdesk-react` \| **EXTRACT** \| helpdesk (ZY/TS/MD) \|` |
| 154 | `\| reference CMS feature \| Bucket \| Disposition \| Source \| Donor \|` |
| 156 | `\| Analytics integration \| **adapter** seam (pageview sink) \| WATCH→adapter; `audit` dual-sink precedent \| **EXTRACT** \| VF (D1 + CF Ana` |
| 158 | `\| Zapier/webhooks/integrations \| **plugin** `integrations` \| WATCH ×1 (ZY) — do not build at ×1 \| (EXTRACT later) \| ZY \|` |
| 159 | `\| Membership / subscriptions \| `entitlements` module (BUILD-approved) + billing \| designed ×2 \| **EXTRACT** \| ZY, FZ \|` |
| 167 | `- `@platform-modules/comments` (L2) — thread store/display only; ×1-forward-need (FZ), attaches beyond CMS. EXTRACT (FZ). *Only reference CM` |
| 170 | `- `content-react` (editor/publish — EXTRACT MD), `comments-react` (EXTRACT FZ), `auth-react` (EXTRACT), `uploads-react` (media library — EXT` |
| 173 | `- `content/editor`, `content/blocks` (EXTRACT MD) · `content/revisions`, `content/menus`, `content/settings`, `content/fields`, `content/mig` |
| 182 | `- analytics pageview-sink (EXTRACT VF) · in-admin image transform (provider-side).` |
| 192 | `## 4. EXTRACT vs BUILD split (the sourcing answer)` |
| 194 | `**EXTRACT from donors (port, don't reinvent — run `/platform-extract-modules`):**` |
| 195 | `\| Target \| Donor(s) \|` |
| 199 | `\| generic Tiptap editor primitive + `content-react` (NOT `content/blocks` — KILLED, census 2026-06-18) \| MD `RichTextEditor` (Tiptap HTML)` |
| 200 | `\| `uploads-react` (upload-only; NO media-library in donor) \| MD media — **R2-locked**, needs `StorageAdapter` seam before extraction \|` |
| 206 | `**BUILD from scratch (no clean donor — `/platform-make-modules` scan-gate first, but corpus-class is net-new):**` |
| 207 | `\| Target \| Why no donor \|` |
| 221 | `3. ~~`comments` + `comments-react` + `moderation`~~ — **`comments` core DONE** (pilot, 2026-06-18, merge `9cb3a7f`; ledger #15). `comments-r` |
| 222 | `4. **generic Tiptap editor primitive + `content-react`** — EXTRACT MD `RichTextEditor`; `content/blocks` KILLED (census 2026-06-18, no donor` |
| 224 | `6. **importables on demand** (revisions, menus, settings, migrate, oembed, avatar) — build when a blueprint consumer needs them; freeze ×1 c` |
| 225 | `7. **BUILD-on-owner-ask (generalizability rule 2026-06-18, was WATCH):** general form-builder (right-sized primitive, not Gravity-class), in` |
| 227 | `**Headline:** reference CMS's backend is already covered by shipped modules. The real gaps are (a) ONE new module — `comments`; (b) the `-re` |

### `docs/specs/2026-06-12-auth-util-module-boundaries.md` (38 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** Read real impl + call-sites across 4 reference projects (zync, ForumZone, trance-shop, multideal). Every claim cites `file:line`` |
| 11 | `Verified: every util candidate is **Web Crypto / zero-dep / Workers-safe**. Most-duplicated, most-stable leaf in the platform. zync is the d` |
| 17 | `- **`util/crypto`** — `timingSafeEqual`, `encryptSecret/decryptSecret` (AES-256-GCM, `base64( iv(12B) ‖ ct+tag )` single blob — zync `crypto` |
| 18 | `- **`util/tokens`** — opaque trio only in the pilot: `generateOpaqueToken` (32B base64url), `hashToken` (SHA-256 hex), `verifyToken` (timing` |
| 19 | `- **`util/password`** — PBKDF2-**SHA-512**; stored format `pbkdf2sha512$<iter>$<saltB64>$<hashB64>` — **salt and hash both base64** (`btoa`/` |
| 21 | `Dupes proving leaf-status: trance-shop `payment/encryption.ts` (same AES-GCM, named `encryptVendorKey`), trance-shop `checkout/guest-token.t` |
| 27 | `- **`util/logger`** — port trance-shop `logger.ts`: **custom zero-dep** console-JSON, Workers-safe, single `logger{info,warn,error}`. NOT pi` |
| 28 | `- **`util/error-reporter`** — trance-shop `error-reporter.ts`: pluggable transport (Sentry/Logpush), dep-free. Separate subpath — tiny apps ` |
| 36 | `\| trance-shop `rate-limit.ts` \| CF-KV + in-memory fallback \| generic `rateLimit(key,limit,windowMs,kv?)` + `getClientIP` \|` |
| 37 | `\| multideal \| Neon `rate_limit_buckets`, fixed-window atomic upsert \| policy-registry `applyRateLimitFor(request,scope,subjectKey?)`, SHA` |
| 38 | `\| zync `rate-limit.ts` \| CF-native `RateLimit` binding (wrangler unsafe.binding) \| native edge counter \|` |
| 42 | `**DO dropped (prior-decision reconciliation):** earlier note said DO's sweet-spot = atomic rate-limit counters. Real code: zync's CF-native ` |
| 44 | `multideal's policy set is the donor for `@platform-modules/auth`'s login/OTP throttle hooks.` |
| 48 | `- `util/id` — thin wrapper over `crypto.randomUUID()` (ForumZone `generateId`, trance-shop audit all use it; no ULID seen anywhere). Add ULI` |
| 53 | `Two pure-`Intl` leaves (zero-dep, Workers-safe). **Built on forward-need (CLAUDE.md §3), not donor count alone** — a domain-census of 8 app ` |
| 55 | `- **`util/datetime`** — `civilDateInZone(instant: Date, zone: string): 'YYYY-MM-DD'`. Converged **×2**: multideal `lib/datetime.ts → toIsrae` |
| 56 | `- **`util/timezone`** — `isValidTimezone(tz): tz is IanaTimezone` (trust-boundary narrowing), `listSupportedTimezones()` (memoized + frozen ` |
| 58 | `**Deferred (designed-next, not built):** the **inverse** resolver `zonedTimeToInstant(civilDate, wallTime, zone): Date` — civil wall-time → ` |
| 68 | `**`/engine-custom`** (reference donor: **multideal `server/auth/`** — the audited, zero-dep solid engine; zync `packages/auth/` *informs* it` |
| 73 | `- cookie name is **host-configurable** (not the donor's `zync_session`); cookie parse/serialize helpers in-engine` |
| 75 | `> **Reconciliation (2026-06-14, auth build-readiness):** the 2026-06-12 draft attributed engine-custom to **zync** (jose HS256, 1h TTL, KV b` |
| 77 | `**`/engine-better-auth`** (donor: ForumZone `packages/auth/`, `better-auth ^1.6.13`):` |
| 79 | `- session strategy `'jwt'`, maxAge 30d, jwt plugin 30d, `cookiePrefix: forumzone`` |
| 84 | `**Third reference (not a separate engine — informs the session model):** multideal `server/` — JWT access `multideal_at` (15min, raw Web Cry` |
| 90 | `Reconciliation: zync uses **KV** blocklist; multideal uses **Neon** + `sv`-version + refresh-row delete (no KV). The locked choice = multide` |
| 104 | `\| Subpath \| Kind \| Donor / note \|` |
| 106 | `\| `engine-custom` \| adapter \| **multideal raw-WebCrypto** (audited, zero-dep) + zync-informed — PBKDF2-SHA-512 + after-KDF pepper, Neon r` |
| 107 | `\| `engine-better-auth` \| adapter \| ForumZone — peer `better-auth` \|` |
| 109 | `\| `oauth-provider` \| capability \| zync `oauth.ts` — **be** an OAuth2 authz server (PKCE/consent/scopes/redirect-validation). Distinct fro` |
| 112 | `\| `otp-sms-firebase` \| adapter \| multideal manual-JWKS RS256 verify (NO firebase-admin), extracts phone_number only \|` |
| 113 | `\| `totp` \| capability \| zync totp/backup-codes/two-factor. **Web Crypto reimpl** (trance-shop `totp.ts` uses Node crypto = not Workers-sa` |
| 114 | `\| `admin-sessions` \| capability \| zync `signAdminSession`/`signImpersonationToken` (15min impersonation) \|` |
| 115 | `\| `portal-sessions` \| capability \| zync `portal/` + `contractor-session` — stateful 2nd-audience sessions \|` |
| 116 | `\| `invites` \| capability \| vibeflare pattern: `token_hash`+expiry+revoked \|` |
| 123 | `- **check-primitive** (generic): zync `rbac.ts` `hasPermission`/`isAtLeastRole`; ForumZone `permissions.ts` `hasCapability`/`requireCapabili` |
| 124 | `- **role-DATA** (contextual): ForumZone resolves caps in middleware from per-tenant `PermissionConfig`; roles are tenant-scoped.` |
| 130 | `Auth **consumes `@platform-modules/util/rate-limit`** (login/OTP/refresh throttle hooks, donor policy set = multideal's). Auth **consumes `@` |
| 140 | `3. `@platform-modules/auth` core + `engine-custom` first (**multideal raw-WebCrypto** — audited solid, zero-dep; zync informs), then `engine` |

### `docs/specs/2026-06-13-realtime-module-design.md` (35 hits)

| Line | Offending substring |
|------|-------------------|
| 6 | `**Method:** Designed from the **actual donor source** (read 2026-06-13, every claim cites `file:line`). This corrects two inaccuracies in th` |
| 10 | `## 0. Donor reality (what the source actually says)` |
| 14 | `\| \| **zync** (`zync.is`) \| **ForumZone** \|` |
| 17 | `\| DO \| `apps/zync-api/src/durable-objects/TenantRealtimeDO.ts` — `implements DurableObject`, one per tenant `tenant:{id}` \| `src/conversa` |
| 22 | `\| Presence \| none \| `computeOffline` pure helper, unit-tested (`conversation-room.ts:11-13`) — **1-donor** \|` |
| 25 | `**The genuine 2-donor, line-level convergence is thin** — three things, identical in both:` |
| 27 | `2. **Fan-out loop** — `for (ws of ctx.getWebSockets()) { try { ws.send(payload) } catch { /* closed: ignore */ } }` (zync `TenantRealtimeDO.` |
| 30 | `Everything with domain value **diverges** (tags vs attachment, read-only vs bidirectional) or is **1-donor** (presence, debounce). That fact` |
| 38 | `Naively the convergence is ~13 lines, which looks like a *dissolve into `@platform-modules/util` + a documented pattern* verdict (the one th` |
| 40 | `- **`targetUserId` scoping is a security control, not routing — and it is zync-only (1-donor).** zync tags each socket (`acceptWebSocket(ser` |
| 41 | `- **The internal-broadcast trust gate must be constant-time.** A naive `===` on the service-binding secret is a timing oracle + an unauthent` |
| 56 | `- An abstract base must **pick one** per-socket mechanism. zync uses **tags**, ForumZone uses **serializeAttachment** — different CF APIs. A` |
| 58 | `**Shape: composable helper functions over `DurableObjectState` (`ctx`).** The host writes its own `class XRoom extends DurableObject` (as th` |
| 72 | `**Why two entry points, and why a subpath — not a second package (e.g. unlike `@platform-modules/i18n-react`).** zync *documents* the reason` |
| 74 | `> Two entry points is the proven minimum (zync shipped exactly this). Splitting `/server` further into `/consumer` + `/presence` subpaths is` |
| 78 | `Two **distinct** types, kept separate on purpose (collapsing them bakes zync's coincidence — the same object happens to be both its queue ev` |
| 98 | `* its own `type` union + fields. (ForumZone already versions its frames `v:1`; zync did not` |
| 99 | `* — versioning here adopts the more forward-compatible donor as the seam default.)` |
| 111 | `*  (zync publish.ts:13-22 — exact.) Call via ctx.waitUntil(...) in a route handler. */` |
| 117 | `/** Hibernatable accept. Supports BOTH donor mechanisms — host picks, module forces neither:` |
| 118 | `*  - tags       → ctx.acceptWebSocket(ws, tags)          (zync user-scoping)` |
| 119 | `*  - attachment → ws.serializeAttachment(attachment)     (ForumZone rich per-socket state) */` |
| 126 | `/** getWebSockets → safe send (ignore closed). Combines three donor signals at three` |
| 127 | `*  different confidence levels — stated honestly so nobody reads it as one 2-donor block:` |
| 128 | `*   - the bare loop (no opts)  → the GENUINE 2-donor convergence (zync TenantRealtimeDO.ts:40-46` |
| 129 | `*                                + ForumZone conversation-room.ts:54-62 — identical code).` |
| 131 | `*                                reach others. zync-ONLY (1-donor security primitive).` |
| 132 | `*   - exclude set              → skip that socket (ForumZone typing-relay don't-echo-to-sender,` |
| 133 | `*                                conversation-room.ts:99-102 — also 1-donor).` |
| 147 | `*  Generalizes zync handleRealtimeBatch:17-32. `dispatch` is HOST domain (it owns DO naming/routing). */` |
| 158 | `/** Presence — 1-DONOR (ForumZone only), thin pure helper. Participants minus those currently` |
| 161 | `*  a socket.) Flagged 1-donor; ~3 lines; include because targetUserId/tags already make` |
| 176 | `- **Authenticate at the worker entry, before forwarding to the DO.** Both donors verify tenant + identity (zync session→`X-User-Id`; FZ JWT ` |
| 184 | `A fake DO using the module helpers + a `cloudflare:workers` stub (ForumZone's `test/__stubs__/cloudflare-workers.ts` is the proven 22-line D` |
| 209 | `The boundaries spec (`2026-06-13-realtime-module-boundaries.md`) states zync has `hub.ts:63-89` and a "versioned `{v,…}`" envelope, and prop` |

### `docs/specs/2026-06-17-plugins-templates-blueprints-design.md` (33 hits)

| Line | Offending substring |
|------|-------------------|
| 36 | `- **Harvest/donor map (screen grain) LANDED** — `docs/catalog/2026-06-17-screen-flow-donor-census.md` (registered in catalog index, SHA-pinn` |
| 130 | `- `ForumZone` billing — **H (hardened, webhook-tested)** — Stripe subscription *plans*, checkout/portal, credits/topup, per-tenant cost-conf` |
| 131 | `- `zync` billing — tier-config, payment adapter (Morning), dunning, subscription, usage-metering. + `zync` tenancy — **H** — tier enum, modu` |
| 135 | `\| New surface \| Layer \| What it owns \| Donor \| Why separate \|` |
| 137 | `\| **`entitlements`** (NEW module) \| L2 · deps `{db, util}`, `tenancy` optional, **NO back-edge to billing** \| tier → feature flags + quot` |
| 138 | `\| **`billing/subscriptions`** (subpath, not new module) \| L2 (billing) \| recurring lifecycle: plan catalog, subscribe, portal, proration,` |
| 144 | `**Why subscriptions is a subpath, not a module (single-adapter + R5):** recurring billing is the SAME provider seam billing already owns (St` |
| 152 | `**Rule: a template is a catalogued screen-set, host-assembled over `ui-*` + module `-react` siblings — NOT a package. Build none until its b` |
| 154 | `\| Template \| Screens (multi) \| Backing module(s) + `-react` \| Owning plugin \| Best donor (→ census for paths) \|` |
| 156 | `\| **auth** \| sign-in · sign-up · reset · verify-email · 2FA · social-callback \| `auth` + `auth-react` (missing) \| — (generic, scaffolded` |
| 157 | `\| **account** \| profile · account-settings · security(sessions/pw) · api-keys · delete-account \| `auth` + `auth-react` \| — \| **zync.is*` |
| 158 | `\| **subscription-tiers** \| pricing · plan-picker/compare · upgrade-downgrade · checkout · billing-portal · usage/quota-meter · **admin tie` |
| 159 | `\| **team-org** \| members · invite · role-assign(RBAC) · org-switcher · org-settings \| `tenancy`+`auth` + `-react` \| — (saas/b2b) \| **zy` |
| 160 | `\| **admin-dashboard** \| shell/nav · metrics-cards · data-table-CRUD · detail/edit-drawer · audit-log-viewer \| `audit` + `ui-*` shell \| —` |
| 161 | `\| **content** \| post/page-list(admin) · rich-editor · publish/schedule · taxonomy · media-library · public-feed · public-detail · search-r` |
| 162 | `\| **notifications** \| bell/inbox · preferences · web-push-optin \| `notifications`+`notifications-react`(missing) \| — \| **zync.is** (inb` |
| 163 | `\| **onboarding** \| welcome-wizard · empty-states · setup-checklist \| `ui-*` + host \| — (generic) \| **zync.is** (wizard/progress/resume)` |
| 164 | `\| **marketing** \| landing/hero · features · newsletter-signup · blog-index \| `marketing`+`marketing-react` \| **marketing** \| **zync.is*` |
| 165 | `\| **moderation** \| report-queue · user-mgmt · ban/mute · flagged-content \| `audit`+`notifications` + `-react` \| — (community) \| **multi` |
| 166 | `\| **search** \| search-bar · results · filters/facets \| `search`+`search-react`(missing) \| — \| **multideal** (public) + zync.is (in-app)` |
| 167 | `\| **system** \| 404/error · loading/skeleton · maintenance \| `ui-*` \| — (generic) \| spread: trance (404/500) · zync (status) · multideal` |
| 169 | `**Census gaps (no donor coverage — build fresh):** delete-account · web-push optin · media-library · maintenance page · empty-states · setup` |
| 177 | `\| Blueprint \| Preset \| Plugins \| Templates (host-assembled) \| Best donor (whole-app → census) \|` |
| 179 | `\| **saas-admin** \| `saas` \| subscriptions \| auth · account · team-org · admin-dashboard · onboarding · subscription-tiers \| **zync.is**` |
| 180 | `\| **saas-b2b** (multi-tenant) \| `saas` \| subscriptions \| + team-org (heavy RBAC), org-switcher \| **zync.is** (tenant/roles/switcher) — ` |
| 181 | `\| **commerce-storefront** \| `commerce` \| (catalog/checkout — WATCH) + subscriptions(subscribe&save) \| content(pages) · admin-dashboard ·` |
| 182 | `\| **community-forum** \| `community` \| — \| content · moderation · notifications · auth · onboarding \| **ForumZone** — H \|` |
| 183 | `\| **blog** \| `core` \| **blog** \| content · marketing · auth(minimal) \| content net-new; multideal editor + ForumZone comments \|` |
| 184 | `\| **cms** \| `core`+uploads \| **cms** \| content(rich) · media-library · team-org(roles) · i18n \| net-new; trance content-admin ref (Pres` |
| 185 | `\| **ai-saas** \| `saas`(+ai) \| subscriptions(usage-metered) \| + ai chat/usage screens \| **zync.is** (usage-metered plan) — H \|` |
| 186 | `\| **marketing-site** \| `core` \| **marketing** + blog \| marketing · content(blog) \| **zync.is** (landing) + multideal (landing app) — H ` |
| 187 | `\| **helpdesk** \| `core` \| **helpdesk** \| auth · admin-dashboard · notifications \| **multideal** (admin/support 7-screen subsystem) — H ` |
| 195 | `3. **`content` module** (net-new, make-with-harvest) — gates blog/cms blueprints (already dispositioned in wasp-map §5A).` |

### `docs/specs/2026-06-13-webhooks-module-boundaries.md` (32 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** Read real inbound + outbound webhook impl + call-sites across 5 census donors (zync, ForumZone, multideal, trance-shop, Press.zo` |
| 11 | `Census ×5 was a mirage: it counted "has webhook code", but the code splits hard by **direction**, and neither direction leaves a module-shap` |
| 13 | `- **Inbound verify recurs 5/5 — but the verify step is provider-specific and high-variance** (Svix `id.ts.body`, Slack `v0:ts:body`, Wolt JW` |
| 14 | `- **Outbound deliver = 1 donor (zync only).** Census discipline → WATCH, not extract.` |
| 24 | `**Step 1 — pull the pure leaves to `@platform-modules/util`** (5/5 evidence, clean extract):` |
| 25 | `- `crypto/timing-safe-equal` — constant-time compare. **5/5 hand-roll it** because Node's `crypto.timingSafeEqual` is absent in CF Workers (` |
| 26 | `- `crypto/hmac-sha256` — `crypto.subtle` HMAC sign/verify → hex. Recurs in zync (4 providers), ForumZone email, trance-shop Printful, multid` |
| 27 | `- `ssrf-guard` — **already planned** (zync `packages/utils/src/ssrf-guard.ts`; search spec already references it). https-only + private-IP/I` |
| 30 | `- "claim id once, TTL, reclaim-if-stale, release-on-failure" is **generic at-least-once dedup**. multideal's `claimWebhookEvent`/`releaseWeb` |
| 31 | `- Real **KV-vs-Postgres storage split**: zync KV-TTL vs multideal/ForumZone Postgres `ON CONFLICT (event_id) DO NOTHING/UPDATE … RETURNING`.` |
| 45 | `~12 lines of glue. `verify` is a host callback (the SDK or the hmac leaf — module adds nothing for Stripe, 3/5). `eventId` and `timestamp` e` |
| 64 | `- `crypto/timing-safe-equal` — constant-time hex/string compare. **Security fix** (trance-shop length leak). 5/5 donors.` |
| 66 | `- `ssrf-guard` — already planned; confirmed by zync outbound. https-only + private-IP/IMDS/integer-literal.` |
| 71 | `- `eventId` + `timestamp` extraction (provider-specific JSON/JWT/header shape).` |
| 75 | `### WATCH — register nothing yet (1-donor, census discipline)` |
| 76 | `- **Outbound webhook delivery orchestration** — endpoint registry, HMAC-signed payloads, delivery log, manual retry, encrypted-secret storag` |
| 77 | `- **Refinement:** WATCH covers the *orchestration*. Its primitives — `hmac-sha256`, `ssrf-guard` — DO land as util leaves now. So zync keeps` |
| 83 | `The leaves exist to *fix* recurring donor bugs, same as search's tsquery sanitizer:` |
| 84 | `- **No replay/timestamp window:** Press.zone Stripe (`webhooks.ts:22-29`, parsed-but-unchecked), zync WhatsApp, multideal Brevo, ForumZone e` |
| 85 | `- **No dedup at all (replay = double DB writes):** trance-shop (both), Press.zone (all). → `@platform-modules/util/idempotency`.` |
| 86 | `- **Zero signature auth:** Press.zone SES (`webhooks.ts:201`) + Bunny (`webhooks.ts:277`) — spoofable. → recipe mandates verify-first.` |
| 87 | `- **Length-leaking compare:** trance-shop `subscriptions/webhook.ts:14`. → `crypto/timing-safe-equal`.` |
| 88 | `- **Optional/weak signature + weak fallback event-id:** ForumZone email (`[provider].ts:47,66`). → recipe + idempotency.` |
| 90 | `*(Dropped from value-add: trance-shop's CSRF middleware blocking its own webhook — a host-middleware bug a module would not touch.)*` |
| 92 | `### Donor evidence (condensed)` |
| 93 | `- **zync** — 5 inbound providers, all timing-safe + (mostly) replay-windowed + KV dedup; **the only full outbound system** (registry/sign/SS` |
| 94 | `- **ForumZone** — Stripe SDK (`stripe.ts:15-31`) + custom email HMAC (`webhook/index.ts:5-36`); Postgres `stripe_events`/`email_dedup` `ON C` |
| 95 | `- **multideal** — Stripe SDK + Brevo shared-secret (`brevo.ts:38-43`) + Wolt JWT-HS256 (`wolt-drive.ts:75-103`, 15-min window); Postgres cla` |
| 96 | `- **trance-shop** — Printful HMAC (`printful.ts:9-34`) + subscription shared-secret (length-leak `webhook.ts:14`); **no dedup**; no outbound` |
| 97 | `- **Press.zone** — Stripe HMAC no-replay-check (`webhooks.ts:16-39`) + **zero-auth SES/Bunny**; no dedup; no outbound. Worst inbound hygiene` |
| 103 | `- `@platform-modules/webhooks` row: status **candidate → DISSOLVED (not a module)**. Note: "Census ×5 was direction-split. Inbound verify = ` |
| 105 | `- Add **WATCH** entry: outbound webhook delivery (1-donor zync; extract on consumer #2; primitives already in util).` |

### `docs/standards/coding-standard.md` (32 hits)

| Line | Offending substring |
|------|-------------------|
| 22 | `- The **platform** lives or dies on that second boundary. A `@platform-modules/*` package *is* its seam: a typed contract that must stay sta` |
| 35 | `\| Verdict \| **Reject.** This is exactly what the platform's YAGNI + donor-census governance exists to prevent. \| **Adopt the ladder for i` |
| 46 | `- **Swap survival** — the seam must outlive `tax/rates-table` → `tax/stripe`, `flatpickr` → native, donor-impl → re-port.` |
| 59 | `1. Does this need to exist?        → no: skip it            (YAGNI / donor-census: no 2nd consumer ⇒ don't build)` |
| 79 | ``@platform-modules/i18n` shipped. Reading its source surfaces three defects that are the **exact failure modes** this standard names. They a` |
| 81 | `**Flaw A — donor assumption baked into a seam default.**` |
| 86 | ``'ILS'` is a multideal/zync (Israeli donor app) assumption frozen into a default that 12 apps will inherit silently. A US/EU consumer gets s` |
| 87 | `> **Rule R1 — No donor defaults at a seam.** A reusable export has **no** locale/currency/tenant/region default. Make it required, or resolv` |
| 114 | `- [ ] **No donor defaults (R1).** No home-market/tenant/locale/currency baked into a default.` |
| 120 | `- [ ] **Thin core + importable capabilities (R5).** Harvest the *most mature donor form*: a thin universal core + each generic non-universal` |
| 124 | `- [ ] **Audit-hardened paths carry their conformance test (R4 / §5.1).** If the boundary spec marks the donor path hardened, the ported/carr` |
| 128 | `## 5. Porting from donor apps (the platform's main code source)` |
| 130 | `Most code is *ported*, not written fresh. Porting is where over-engineered ceremony and donor assumptions leak in. The pipeline:` |
| 133 | `donor impl ──▶ run §2 ladder ──▶ strip donor assumptions (R1) ──▶ collapse ceremony (R2) ──▶ design the seam (§4) ──▶ pin with a test` |
| 136 | `- **×1 donor = WATCH, do not build.** Promote to a real module only at the **2nd independent consumer** (per the synthesis governance). One ` |
| 138 | `- **A re-port is a swap.** If the seam was designed right (§4), swapping donor-impl-A for donor-impl-B touches no consumer.` |
| 140 | `### 5.1 Audit-hardened donor code — preserve, don't re-derive` |
| 142 | `Some donor paths already passed a security/UX audit; the fixes are **baked into the donor source** (zync/multideal money · refund · webhook ` |
| 144 | `> **Rule R4 — Preserve the hardened body; design only the seam (Chesterton's Fence).** Where the boundary spec marks a donor path audit-hard` |
| 146 | `- **Carry the donor's executable security tests** (`secaudit-*.spec` and equivalents) in as module conformance tests. With the auditor unava` |
| 147 | `- **A forced change to the hardened body is a kickback, not a quiet rewrite.** If the seam genuinely cannot wrap the donor body unchanged, *` |
| 148 | `- **Knowing it's hardened:** the boundary spec cites an audit or marks the path "preserve". A money/auth/webhook path the spec is *silent* o` |
| 154 | `> **Harvest the most mature donor form, layered — never the laziest form, flattened.** A module is a thin *universal core* + each generic no` |
| 158 | `**R5 — the placement ladder.** First a gate, then for each capability the donor has that is *not* in the universal core, stop at the first r` |
| 161 | `GATE  Does a mature donor implement this today (or is it cross-class forward-needed per synthesis §3)?` |
| 177 | `**Maturity rule.** When a capability exists in several forms (a thin form in the module, a richer form in a donor; or differing donor forms)` |
| 181 | `- **Harvest, don't invent.** R5 promotes capability that exists *mature in a donor* (or is cross-class forward-needed per synthesis §3). It ` |
| 182 | `- **Contract frozen only on non-donor convergence.** The donor is also the first consumer — re-importing into the donor proves swap-survival` |
| 186 | `1. *Should this capability exist at all?* → **YAGNI / the GATE.** No mature donor and not forward-needed ⇒ stop.` |
| 217 | `- **DB access through the `@platform-modules/db` adapter seam — no TCP driver.** Workers have no raw TCP: reach Postgres over an HTTP/fetch ` |
| 227 | `3. **Porting:** strip donor defaults (R1), collapse identity ceremony (R2), memoize natives (R3), design the seam, pin with a test. **Audit-` |
| 228 | `4. **Capability surface (§5A / R5):** harvest the *most mature donor form* — thin core + each generic capability as a tree-shakeable subpath` |

### `docs/specs/2026-06-12-jobs-cron-module-boundaries.md` (29 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** Read real impl + call-sites across 5 donors (zync, ForumZone, multideal, trance-shop, vibeflare) via parallel read-only agents. ` |
| 15 | `\| **multideal** \| CF Queues (fast-path, msg=`{outboxId}`) \| **PRIMARY** (tx outbox + cron backstop) \| `scheduled()` dispatcher (switch o` |
| 16 | `\| **zync** \| CF Queues (1 type-mux bus `zync-jobs`) \| none \| `scheduled()` → HTTP self-fetch to `/api/cron/*` \| none \|` |
| 17 | `\| **ForumZone** \| CF Queues (many named) \| none ("post-commit enqueue discipline") \| `scheduled()` (digest `*/15`) \| none \|` |
| 18 | `\| **trance-shop** \| **none** (Postgres `translation_queue` as bus) \| DB-poll table (status-flip claim) \| HTTP `/api/cron/*` + `CRON_SECR` |
| 19 | `\| **vibeflare** \| none \| none \| `scheduled()` flat (1 daily cron, no router) \| DO-as-counter only (not a runner) \|` |
| 30 | `- **event seam → FAILS:** cron *produces*, queue *consumes*. ForumZone digest cron enqueues to the email queue (`apps/realtime/src/cron/dige` |
| 37 | `- the **DO-alarm self-rescheduler** (DO + `setAlarm` + re-arm-in-`finally` + idempotent `ensureAlarm`) → **the SAME primitive as `jobs/do-ru` |
| 43 | `- `@platform-modules/util/cron` (zero-dep leaf) = scheduler registry + fan-out. Pure-cron projects (vibeflare) need only `@platform-modules/` |
| 47 | `**Outbox stays in `@platform-modules/jobs`** (only 2/5, but): drains *synchronously into the handler registry* — multideal calls `dispatchOu` |
| 55 | `- **Type-discriminated job envelope** — every donor keys dispatch on a `type` string (zync `handleZyncJobsBatch` `index.ts:101`; multideal `` |
| 56 | `- **Handler registry** — `register(type, payloadSchema, handle)` + `dispatch(env, msg)`. multideal's `HANDLER_BY_TYPE` Map + zod `payloadSch` |
| 57 | `- **Ack/retry convention** (identical across zync + ForumZone + multideal): ack-malformed · ack-terminal-domain-error (after writing FAILED ` |
| 59 | `- **Pluggable idempotency seam** — 5 distinct mechanisms found, so this MUST be an injected strategy, not baked: KV-seen-key (zync comms `co` |
| 60 | `- **`QueueMessage<T>` / `QueueBatch<T>` types** — ForumZone re-declares these locally 6× to dodge `@cloudflare/workers-types` global injecti` |
| 61 | `- **`strict` flag** (multideal `outbox/types.ts:56`): missing-secret → throw+Sentry (backstop path) vs log+ack (live path). Generalize as co` |
| 65 | `\| Subpath \| Peer \| Donor \| Shape \|` |
| 67 | `\| `jobs/cf-queues` \| CF `Queue` binding \| zync/ForumZone/multideal \| producer `enqueue(env,name,body)` (ForumZone `queues/index.ts:19`) ` |
| 68 | `\| `jobs/db-poll` \| `@platform-modules/db` \| trance-shop/multideal \| Postgres-as-bus: claim via status-flip `pending→processing` `WHERE s` |
| 69 | `\| `jobs/do-runner` \| CF DO binding \| multideal \| Singleton alarm-driven runner: `nudge()` sets `setAlarm(now)` iff none pending; `alarm(` |
| 73 | `Transactional outbox — multideal is the mature donor; trance-shop `translation_queue` is a lite single-purpose version:` |
| 93 | `- **Schedule registry** — cron-string → ordered handler list. multideal `dispatchCron(cron, env)` switch w/ dynamic `import()` per handler (` |
| 94 | `- **Fan-out runner** — `Promise.allSettled` parallel (multideal `*/30` bundle) or sequential (zync). Per-handler isolation.` |
| 96 | `- Zero deps, Workers-safe → same shelf as `util/csrf`/`util/pagination`. **vibeflare (pure cron, no queue) imports only `@platform-modules/u` |
| 100 | `DO-alarm self-rescheduler — used for periodic firing AND queued-row draining (donors: trance-shop `recs-scheduler-do.ts:28-53` + `do.ts:51-5` |
| 104 | `- wrangler `[triggers] crons` config (per-project; CF free-plan 5-cron cap — zync wrangler comment).` |
| 106 | `- `CRON_SECRET`-guarded cron-trigger route (trance-shop/zync `/api/cron/*`) — a route + `@platform-modules/util/config` bearer check, for ho` |
| 114 | `- multideal: a separate `apps/web-do` worker (`multideal-do-preview`) owns **all** queue consumption + **all** cron triggers; the Astro `app` |
| 115 | `- ForumZone: `apps/web` (Astro) is producer-only; `apps/realtime` is the universal consumer + cron host (`apps/realtime/src/index.ts`).` |

### `docs/specs/2026-06-13-ledger-module-boundaries.md` (29 hits)

| Line | Offending substring |
|------|-------------------|
| 4 | `**Status:** **candidate → PROMOTE to `designed`** (core convergence is structural, not nominal — passes the entitlements test). Idempotency ` |
| 5 | `**Method:** haiku-gather verbatim code from 3 donors (multideal `credit_ledger`+`wallet_balances`, Press.zone `coin_ledger`+`wallets`, Forum` |
| 11 | `The convergence is **real and structural** — append-only signed-delta entries + materialized running-balance + typed-reason converge ×3. DB-` |
| 17 | `\| Property \| multideal \| Press.zone \| ForumZone \| Converges? \|` |
| 32 | `**Pessimistic — lock-then-check (multideal + Press.zone):**` |
| 34 | `// multideal payout-debit.ts:39-57` |
| 41 | `-- Press.zone economy.ts:184-218` |
| 47 | `**Optimistic — guarded conditional UPDATE, single CTE, no explicit lock (ForumZone):**` |
| 49 | `-- ForumZone credit.service.ts:65-81` |
| 60 | `**Judgment.** The contract converges (atomic guarded debit, zero double-spend, no read-then-write window). The mechanism does not. **Recomme` |
| 66 | `**Statement-order constraint (financial-correctness — NOT optional).** The module standardizes idempotent debits (every mutation carries an ` |
| 74 | `\| Donor \| Balance lives \| Shape \|` |
| 76 | `\| multideal \| dedicated `wallet_balances` \| rich multi-bucket: `balance / pending / matured / withdrawable / lifetimeEarned` \|` |
| 77 | `\| Press.zone \| dedicated `wallets` \| simple: `balance (CHECK ≥0) / lifetime_earned / lifetime_spent` \|` |
| 78 | `\| ForumZone \| **`subscriptions.credit_balance`** (existing domain row) + inline `balance_after` per ledger row \| folded onto a foreign ta` |
| 80 | `**ForumZone proves the module cannot own a fixed balance table** — it folds balance onto a pre-existing `subscriptions` row. So:` |
| 82 | `- **Balance projection is host-owned:** module ships an *optional default* `wallet_balances` table, but the host can point the primitive at ` |
| 83 | `- **Multi-bucket vesting (pending/matured/withdrawable) = multideal-only extension, NOT core.** Lives as an opt-in capability (`ledger/vesti` |
| 84 | `- **`balance_after` inline (audit-of-balance-at-entry) = ForumZone-only extension.** Opt-in column, not core.` |
| 85 | `- **lifetime counters (earned/spent) = Press + multideal partial.** Opt-in projection fields.` |
| 91 | `- multideal: **composite natural key** `(entryType, sourceType, sourceId)` — semantic, no caller-generated UUID needed.` |
| 92 | `- Press.zone: **surrogate UUID** `idempotency_key` (client-supplied header) + Redis replay cache at HTTP layer.` |
| 93 | `- ForumZone: **partial-period** `(tenant_id, period_key) WHERE reason='allowance'` — idempotency only on the monthly grant, not consumption.` |
| 95 | `Contract converges: *a unique constraint + `ON CONFLICT DO NOTHING` + detect-inserted-or-not*. The **key itself is caller-defined**. Module ` |
| 108 | `ledger/vesting     (opt-in) pending/matured/withdrawable buckets + maturation sweep (multideal CTE)` |
| 110 | `ledger/balance-after (opt-in) inline balance snapshot per entry (ForumZone audit)` |
| 121 | `- **Gate 2 (adapter minimalism):** the seam exposes the *contract* (atomic idempotent mutation), pushes mechanism choice (optimistic/pessimi` |
| 122 | `- **Gate 3 (consumer-harness):** fixture must exercise BOTH debit shapes + a host-supplied balance target (not just the default table) — els` |
| 128 | `- `@platform-modules/ledger`: **candidate → designed.** Note: "Core = append-only signed-delta + materialized running-balance (NOT SUM-recom` |

### `docs/specs/2026-06-12-cache-module-boundaries.md` (28 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** Read real impl + call-sites across 5 donors (multideal, ForumZone, trance-shop, vibeflare, Press.zone-Node) via parallel read-on` |
| 9 | `## Headline: seam recurs 4×, but almost every backend & "capability" is ONE donor` |
| 11 | `The `get/set/del`+TTL value-cache is real and recurs. Everything fancier (response-cache, epoch, tags, exotic backends) is single-donor. **A` |
| 13 | `**ForumZone is downweighted everywhere** — its cache is aspirational, not working: it `kv.delete()`s keys **nothing ever reads**, the read-t` |
| 21 | `- **`get<T>(key)` / `set<T>(key, val, {ttl?})` / `del(key)`** — JSON (de)serialization + TTL. The recurring shape: trance-shop `MinimalKV`+`` |
| 22 | `- **`getOrSet<T>(key, loader, {ttl?})`** — the read-through **no donor abstracts but all 4 hand-roll inline** (read→miss→load→write). Legit ` |
| 23 | `- **Single-flight coalescing** — the real value-add. multideal hand-rolls `pendingSSR: Map` + `inFlight` to stop thundering-herd on cold mis` |
| 24 | `- **Key-namespace helper** — `tenant:{id}:...` (ForumZone), `printful:...` (trance-shop), `tsi:v1:...` (trance-shop client). Thin prefix/sco` |
| 26 | `Runtime-agnostic: core is just the seam. Backends are runtime-specific (CF bindings vs Node Redis) — that split IS the adapter axis (Press.z` |
| 30 | `Unlike jobs (multideal/outbox was a mature ref), cache has **no mature backend donor** — so nail the seam + clean reference backends, make a` |
| 34 | `\| `cache/memory` \| trance-shop (rate-limit fallback `rate-limit.ts:30-55`) \| **BUILD (default)** \| isolate-local `Map` + `resetAt`/TTL. ` |
| 35 | `\| `cache/kv` \| trance-shop (working) + ForumZone (aspirational) ≈1.5 \| **BUILD (reference)** \| CF KV `get/put/delete` + JSON. peer: CF K` |
| 36 | `\| `cache/redis` \| Press.zone (1) \| **BUILD (Node runtime story)** \| ioredis `^5.3.2` peer-dep. 1 donor but the **only non-CF runtime** —` |
| 37 | `\| `cache/cache-api` \| multideal (domain SSR) + vibeflare (auth challenges) — weak 2 \| **WATCH** \| `caches.default`/`caches.open`, Respon` |
| 38 | `\| `cache/d1` \| vibeflare (1) \| **WATCH** \| D1 table-backed (`response_cache`, SHA-256 key, `expires_at` col + prune cron). \|` |
| 39 | `\| `cache/do` \| multideal (1) \| **WATCH** \| DO-storage-backed authority (the epoch DO). \|` |
| 47 | `Press.zone (`incrementCounter` `redis.ts:90-102`), trance-shop (`rate-limit.ts`), vibeflare (DO `QuotaCounter` `quota/do.ts`) use the cache ` |
| 49 | `**Do NOT extract a shared `@platform-modules/kv-store` base** that both sit on. That's the over-merge trap. The backend resemblance is a ~20` |
| 56 | `- **ETag + `Cache-Control` builders** — vibeflare `withCache` (`lib/cache.ts:22-46`), ForumZone `cacheControlFor`/`applyCacheControl` (`seo/` |
| 58 | `- **Rich Request→key derivation** (strip ~20 tracking params, sort query, `_v=BUILD_ID`, locale-in-header because Vary unhonored) + 304 + SS` |
| 62 | `## WATCH — pin, register nothing (1-donor each, census discipline)` |
| 64 | `- **epoch invalidation** — multideal only: `CacheEpochDO` global authority + monotonic counter + 8s-debounced coalesce + DB-driven route pre` |
| 65 | `- **scope/tag-based purge** — multideal scope types `deal\|category\|vendor\|global` + ForumZone `purgeScope` (aspirational) ≈1.5 donor. WAT` |
| 66 | `- **client/browser localStorage** — trance-shop `client-cache.ts` (SWR, `tsi:v1:` prefix, quota-exceeded bulk-clear). Browser runtime (core ` |
| 67 | `- **DB-materialized aggregates** — multideal denormalized `deals` columns (`domain/variants/cache.ts`). Domain, stays in host. Not a cache b` |
| 68 | `- **open-next framework DOs** — trance-shop `.open-next/` `DOShardedTagCache`/`BucketCachePurge`. Framework-generated, not app-owned. Ignore` |
| 91 | `**D. Single-flight is per-instance / per-isolate ONLY — explicit non-guarantee.** The in-flight `Map` lives in one runtime instance. On a mu` |
| 93 | `**E. `cache/memory` is dev/test/fallback, NOT a production cache.** Isolate-local, unbounded growth (no LRU/size cap in v1 — YAGNI until a d` |

### `docs/specs/2026-06-14-tenancy-module-boundaries.md` (25 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** Tenancy census across the donor set (read-only).` |
| 11 | `> Sections below are rewritten to this resolution; the pre-amendment text is superseded. Only **2 of the donors are genuinely multi-tenant**` |
| 15 | `## Headline: `@platform-modules/tenancy` SURVIVES as a **SEAM** — a `resolveCapabilities` interface + a `Querier<S>` tenant-scoping wrapper ` |
| 21 | `## Disposition (the honest convergence read — census > stale registry)` |
| 23 | `The synthesis registry (`2026-06-13`, §6) tags tenancy **"designed."** This census (`2026-06-14`) is **newer evidence** and refines that tag` |
| 27 | `\| **Tenant exists / lifecycle** (id, slug, status, owner) \| zync ✓ · ForumZone ✓ \| both have a tenant identity \| **designed** (the firm ` |
| 28 | `\| **Tenant-scoping wrapper** (`Querier<S>` → scoped) \| zync (lint-enforced FK) · ForumZone (`ScopedDb` wrapper) \| ×2 *that scoping is nee` |
| 29 | `\| **Capability resolution** (membership → permission strings) \| zync (triad) · ForumZone (flat enum) \| ×2 *that a user's caps are tenant-` |
| 30 | `\| **RBAC storage model** \| zync triad (`roles`/`permissions`/`role_permissions`) · ForumZone flat (`users.role` enum) \| incompatible shap` |
| 31 | `\| **Isolation strategy** \| zync shared-DB+`tenant_id` · ForumZone shared-DB-**or**-`connectionStr` \| incompatible shapes \| **soft** — **` |
| 32 | `\| **Membership cardinality** \| zync M:N (workspace model) · ForumZone effectively 1:N (forum-per-tenant) \| divergent \| core = M:N **supe` |
| 34 | `**Net:** tenancy is **designed on the SEAM** (interface + lifecycle), **soft on every concrete table/strategy**. Only 2/~12 donors multi-ten` |
| 41 | `- **Gate 1 (delete-test) — decisive, on the seam not the shapes:** delete tenancy → every multi-tenant app re-rolls (a) tenant + membership ` |
| 65 | `- **Types:** `Tenant { id; slug; name; status: 'active'\|'suspended'\|'pending'; ownerId; createdAt }`, `Membership { tenantId; userId; role` |
| 80 | `- **`rbac-triad`** (default; zync shape, the **superset**): `roles` · `permissions` · `role_permissions` tables + seeded system roles (`OWNE` |
| 81 | `- **`rbac-flat`** (ForumZone shape, the **degenerate case**): a single role enum (`owner\|admin\|moderator\|member\|guest`, *census-sourced*` |
| 83 | `- **`isolation-rls`** (**default — the structural boundary**, per the 2026-06-15 amendment): Postgres Row-Level Security. Exports `runInTena` |
| 84 | `- **`isolation-fk`** (fail-closed defense-in-depth; the `neon-http`/stateless story): the `scopeQuerier` wrapper above. **Not** the structur` |
| 85 | `- **`isolation-connection`** (**DEFERRED WATCH ×1**; ForumZone's per-tenant `connectionStr` path, `tenant-resolver.ts:34-58`): resolves a te` |
| 117 | `## WATCH / out of scope (census discipline)` |
| 128 | `## Donor evidence (condensed)` |
| 130 | `- **zync.is** — multi-tenant SaaS workspace model. RBAC **triad**: `tenant_memberships` join (M:N) + `roles`/`permissions`/`role_permissions` |
| 131 | `- **ForumZone** — forum-per-tenant model. RBAC **flat**: single `users.role` enum (`owner\|admin\|moderator\|member\|guest\|system`). Isolat` |
| 132 | `- **Other donors** (multideal, trance-shop, …) — **single-org** (no tenant dimension); they are *not* evidence for tenancy and are why adopt` |
| 139 | `2. **`tenant_id` column name convention** — fixed string vs adapter-configurable. Default fixed `tenant_id`; make it a config field on `isol` |

### `docs/specs/2026-06-13-search-module-boundaries.md` (24 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** Read real impl + call-sites across 5 census donors (zync, ForumZone, multideal, Press.zone, trance-shop) via parallel read-only ` |
| 7 | `**Amendment 2026-06-15 (pre-build census, spec-first kickback).** Re-censused zync's actual federation cursor (`packages/db/src/search/{sear` |
| 9 | `**Amendment 2026-06-15b (pre-merge advisor pass — two trust-boundary hardenings).** The advisor flagged that the security floor is partly *s` |
| 17 | `The second sharpest: **no donor has a config-driven searchable-fields registry.** Per-entity SQL, the field list, and visibility gates are h` |
| 19 | `So search is **structurally incapable of being a fat self-contained module** (template Gate 0 / `platform-extract-modules` §1.3: a module "o` |
| 27 | `- **What disappears from N apps:** the federation loop (parallel per-entity query + merge + group + sort + paginate — hand-rolled in all 5: ` |
| 28 | `- **What CANNOT move (stays host):** the per-entity SQL, the searchable-field selection, and visibility/tenancy gates. No donor abstracts th` |
| 31 | `> Note vs cron/cache/http: those DISSOLVED because *all* their parts scattered or were 1-donor. Search is different — the federation seam re` |
| 58 | `- **`@platform-modules/util/fts/sanitize-tsquery`** — the safe tsquery builder. zync `buildTsquery` (`packages/db/src/search/build-tsquery.t` |
| 59 | `- **`@platform-modules/util/fts/safe-headline`** — XSS-safe `ts_headline`→`<mark>` snippet builder. ForumZone `buildSafeHeadlineHtml`: escap` |
| 60 | `- **`@platform-modules/util/fts/rank`** — thin rank-helper choosing `ts_rank` vs `ts_rank_cd` (zync uses `ts_rank_cd`, ForumZone `ts_rank`).` |
| 61 | `- **Cursor pagination = a tiny in-`search` codec, NOT a util leaf.** ~~Reuse `util/pagination`~~ (amended 2026-06-15): no such leaf exists, ` |
| 66 | `- **Provider registry contract** — host registers `entityType -> (query, ctx: Ctx, window: { limit, offset }) => Promise<{ hits: Hit[]; tota` |
| 67 | `- **Params** — `query` (raw user string; module runs it through `@platform-modules/util/fts/sanitize-tsquery` before handing to providers OR` |
| 69 | `### WATCH — register nothing (1-donor or host-domain, census discipline)` |
| 72 | `- **GENERATED tsvector column + GIN + pg_trgm** — ForumZone's mature setup (`search.service.ts`). A *migration recipe* the host adopts, docu` |
| 73 | `- **Per-language search config / dictionaries** — zync hebrew/simple, multideal per-language `search_config`. Host-domain config, passed in ` |
| 74 | `- **Pure ILIKE fallback** — trance-shop `%term%` (no tsvector/GIN/ranking, `apps/web/src/pages/api/search/index.ts`). The naive tier; the pr` |
| 76 | `### Donor evidence (per-donor, condensed)` |
| 78 | `- **zync** — Postgres FTS, 14 entities federated, `ts_rank_cd`, hebrew/simple dicts, `buildTsquery` sanitizes (`packages/db/src/search/build` |
| 79 | `- **ForumZone** — GENERATED ALWAYS STORED tsvector + GIN + pg_trgm, `websearch_to_tsquery` (injection-safe), `ts_rank`, 3 entities (separate` |
| 80 | `- **multideal** — on-the-fly `to_tsvector`/`plainto_tsquery`, **GIN index promised-but-MISSING** (perf gap), per-language `search_config`, I` |
| 81 | `- **Press.zone** — two TS backends: CPZ legacy = ILIKE + inline-tsvector `UNION ALL`, no GIN, **UNSANITIZED** (`.../forum/search.ts`) = the ` |
| 82 | `- **trance-shop** — pure ILIKE `%term%`, no tsvector/trigram/GIN, no ranking (except tracks salesCount), 6 entities `Promise.all`, no saniti` |

### `docs/specs/2026-06-12-i18n-module-pilot-design.md` (22 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Methodology:** `/platform-extract-modules` skill (`.claude/skills/platform-extract-modules/SKILL.md`) — i18n was ported from the multideal` |
| 6 | `**Purpose:** First module extracted — proves the platform plumbing end-to-end (monorepo → build → subpath tree-shaking → host integration co` |
| 21 | `## Extraction sources (read, don't reinvent)` |
| 23 | `- `zync.is/packages/ui/src/i18n` — runtime + RTL + Intl formatting base (most mature).` |
| 24 | `- `trance-shop-israel/.../packages/core/src/i18n` — locale-routing (he/en/ru) reference.` |
| 25 | `- multideal admin translation UI = **domain**, NOT extracted.` |
| 60 | `- **Wave 2 — core:** `@platform-modules/i18n` (registry, `t()`, `resolveLocale`, types) + subpaths `/rtl`, `/format`, `/plural`, `/routing`,` |
| 86 | `## R5 harvest amendment (2026-06-15) — thin core was under-harvested` |
| 88 | `> Audience: AI coding agents first. BLUF: the shipped pilot core (`.` `/rtl` `/format` `/plural` `/routing` + react `.`) is a **correct seam` |
| 90 | `> **Scope:** every item below is consumed by multideal (multideal is the donor) → in-scope for the migration. R5 is a layering rule applied ` |
| 92 | `### Shipped vs harvest (confirmed by reading `packages/i18n/src/*` + `i18n-react/src/index.tsx`, 2026-06-15)` |
| 100 | `\| **nested + namespaced keys** (`t(i18n, loc, 'cart.title')` over nested tables) \| HARVEST → CORE \| `.` (extend `I18n.messages` + `t`) \|` |
| 101 | `\| **lazy bundle-split loader** (load a locale/namespace bundle on demand) \| HARVEST → IMPORT \| `@platform-modules/i18n/loader` \| serves ` |
| 102 | `\| **`pickLocalized`** (pick `title_he`/`title_en` from a DB row by locale) \| HARVEST → IMPORT \| `@platform-modules/i18n/pick` \| field-na` |
| 103 | `\| **`createZodErrorMap`** (localized Zod validation messages) \| HARVEST → IMPORT \| `@platform-modules/i18n/zod` \| `zod` peerDependency; ` |
| 104 | `\| **namespaced + memoized `useT(ns)`** \| HARVEST → -REACT \| i18n-react (extend) \| namespace-scoped; **memoize the translator** by (ns, l` |
| 105 | `\| **shared persist store** (cross-island locale) \| HARVEST → -REACT \| `@platform-modules/i18n-react/store` \| **solves Findings #2 cross-` |
| 106 | `\| **hydration parity (#418 guard)** \| HARVEST → -REACT \| i18n-react `.` \| provider seeds locale from SSR value so first client paint mat` |
| 107 | `\| **`DirectionProvider`** (RTL dir context) \| HARVEST → -REACT \| i18n-react (extend) \| dir context for nested components; complements `/` |
| 111 | `multideal sets locale default **ignoring Accept-Language**. The module's `resolveLocale` (confirmed `packages/i18n/src/index.ts:46`) already` |
| 119 | `### Donor sources (builder re-reads; census not re-run for i18n — surface is small + first-hand)` |
| 120 | `multideal i18n runtime (nested message tables, lazy loader, `pickLocalized`, zod error map) — builder locates under multideal `apps/web/src/` |

### `docs/specs/2026-06-13-monorepo-architecture-synthesis.md` (22 hits)

| Line | Offending substring |
|------|-------------------|
| 11 | `The tier labels (core / bolt-on) were a useful first cut but the **real architecture is a dependency DAG in 4 layers, built strictly bottom-` |
| 23 | `(candidate leaf: sanitize-html — pending HTML-render census)` |
| 25 | `(@platform-modules/events — ⊘ DISSOLVED 2026-06-14, census ×0 — decoupling = jobs/outbox + direct calls; see note ↓)` |
| 57 | `**`@platform-modules/events` — confirmed dissolution (2026-06-14).** Census ×0 for an event-bus contract: greps for `EventBus`/`Emitter`/`Di` |
| 87 | `**Donor status (two tiers — census vs business-intent):**` |
| 88 | `- **`tax/rates-table` (IL) = `designed`** — 2 existing-code donors (zync exclusive `applyVat`, multideal inclusive `extractVat`); proven sha` |
| 89 | `- **engine axis + `tax/stripe` + `tax/vat-id` + EU rates = `designed (forward)`** — **0 donors.** No app routes between tax engines, uses St` |
| 113 | `**Honest reversal note:** two turns earlier I argued "kill the country-axis, tax is IL-only / maybe a util leaf." That was correct **when th` |
| 133 | `- multideal `credit_ledger` + `wallet_balances` (entry_type accrual/redemption/clawback, idempotent `(type,source)`, vesting `mature_at`/`wi` |
| 134 | `- Press.zone `coin_ledger` + `wallets` (idempotency_key, lifetime_earned/spent).` |
| 135 | `- ForumZone `credit_ledger` (delta, reason, balanceAfter, periodKey, idempotent allowance).` |
| 137 | `**Shared core:** append-only signed-delta entries + idempotency key + materialized balance + typed-reason enum. **Divergent extensions:** ve` |
| 141 | `**MAPPED 2026-06-13** (`2026-06-13-ledger-module-boundaries.md`) → **promoted candidate→designed.** Append-only signed-delta + materialized ` |
| 143 | `**Promotion discipline (apply the entitlements lesson):** ×3 census is a *candidate*, not a designed module. The map pass must prove the con` |
| 159 | `\| `@platform-modules/ai`, `@platform-modules/realtime` \| L2 \| designed (2-donor) \|` |
| 163 | `\| `@platform-modules/invoicing` \| L3 \| **WATCH (1 donor)** — owns SHAAM when promoted \|` |
| 164 | `\| `@platform-modules/affiliate` \| L3 \| **WATCH (1 donor)** — consumes ledger \|` |
| 166 | `\| `@platform-modules/events`, `@platform-modules/compliance`, `@platform-modules/image`, `@platform-modules/webhooks`, `@platform-modules/a` |
| 169 | `**2026-06-15 — R5 capability-maturity correction (thin core, importable growth).** The "designed/shipped" status above measures *seam existe` |
| 175 | `1. ~~Map `@platform-modules/ledger`~~ **DONE 2026-06-13** (spec `2026-06-13-ledger-module-boundaries.md`) — promoted candidate→designed. Key` |
| 179 | `5. **Tax build — donor-strength and build-urgency INVERT here; sequence by need, not by donor count.** The donor-proven path (`tax/rates-tab` |
| 180 | `6. WATCH items (affiliate/invoicing/promotions/inventory/community) wait for a 2nd real consumer — do not build on one donor.` |

### `docs/plans/2026-06-14-ai-module.md` (21 hits)

| Line | Offending substring |
|------|-------------------|
| 6 | `**Goal:** Ship `@platform-modules/ai` — a **provider-gateway**: an `AIAdapter` interface + a retryable-error hierarchy + `executeWithFallbac` |
| 8 | `**Layer:** L2 DOMAIN PRIMITIVE (peer provider SDKs per adapter; **NO `db` in core** — host resolves creds). **Hard boundary — never crossed:` |
| 10 | `**Donors:** zync (`AIAdapter`+`executeWithFallback` — reference), multideal (`LlmProvider`+`ChainedLlmProvider` — independent re-impl, the c` |
| 16 | `1. **2-donor independent convergence on the seam** (interface + error hierarchy + fallback chain) = real module, not 1-donor generalization.` |
| 17 | `2. **The seam stops at `usage{tokens}`.** Accounting diverges totally (zync credits / multideal USD / vibeflare neurons / trance none) → cor` |
| 20 | `5. **`listModels?()` stays optional + UNBUILT** (forward-tier, 1-donor, multideal Design-status). Defined in the interface as optional; not ` |
| 26 | `- **Gate 1:** delete ai → the provider-normalization layer + fallback-chain orchestration (zync + multideal each hand-rolled the identical t` |
| 38 | `- `AIRequest`/`AIResponse`/`AIMessage`/`AIContentBlock` — provider-agnostic wire shapes (seed from vibeflare `openai.ts`). **`AIResponse.usa` |
| 80 | `- **`ai/google`** (`/v1beta/openai` or native gemini) · **`ai/workers-ai`** (peer CF `AI` binding, vibeflare's 2nd axis) · **`listModels?()`` |
| 82 | `## Out of scope (census discipline)` |
| 84 | `- **RAG, agent-tool-loops, moderation logic** → WATCH (1-donor each).` |
| 88 | `**Boundary floor in-plan** — the seam stops at `usage{tokens}`; the no-cost-field guard is a required Gate-3 assertion (type + runtime) ✅ · ` |
| 92 | `## Wave 5 — R5 harvest extension (added 2026-06-15) — CLEAN-4 ONLY, the rest deferred by DAG` |
| 94 | `**Goal:** harvest the four **clean** generic capabilities into importable subpaths (spec: `docs/specs/2026-06-13-ai-module-boundaries.md` → ` |
| 96 | `> **DO NOT build `ai/job`, `ai/agent`, `ai/agent/tools/read-image`, `ai/agent/tools/search-kb`, `ai/kind`, `ai/kind/translate` in this wave.` |
| 103 | `**Blocked by:** Task 2 (core, shipped — implements the `AIAdapter` axis + `setAdapterFactories`). **Census deps:** none (pure ports).` |
| 105 | `- [ ] **`src/google.ts` → `ai/google`:** implement `AIAdapter` for Google/Gemini (donor `providers/gemini.ts:169`, `@google/genai` peer). **` |
| 106 | `- [ ] **`src/mock.ts` → `ai/mock`:** `AIAdapter` that simulates 429 / quota / auth / OK on command (donor `providers/mock.ts:1`); the Gate-3` |
| 119 | `**Blocked by:** Task 2 (core, shipped — `AIResponse.usage` token shape is `/pricing`'s input). **Census deps:** none.` |
| 121 | `- [ ] **`src/pricing.ts` → `ai/pricing`:** `computeCost(usage, hostRateTable)` — mechanism only (tokens×rate). **NO baked rates / currency /` |
| 122 | `- [ ] **`src/redact.ts` → `ai/redact`:** `buildRedactionMap` / `redactForPrompt` / `substitutePseudoIds` (donor `agents/support/redactor.ts:` |

### `docs/plans/2026-06-14-util-module.md` (21 hits)

| Line | Offending substring |
|------|-------------------|
| 10 | `**Donors:** zync (crypto/tokens/password), trance-shop (logger/error-reporter/rate-limit/encryption), multideal (tokens, rate-limit policies` |
| 16 | `- **Gate 0 (candidate):** Web-Crypto leaves are zero-dep, Workers-safe, swappable without touching callers. PASS — but disposition is **per-` |
| 51 | `**Seam (spec §crypto; donor zync `crypto.ts`, dupe trance-shop `payment/encryption.ts`):**` |
| 59 | `- [ ] Port from zync `crypto.ts` (CF Web-Crypto, no Node `crypto`). Keep the exact single-blob `base64( iv(12B) ‖ ct+tag )` shape (zync `cry` |
| 61 | `- [ ] **`encryptCredential`/`decryptCredential` are NOT in this pilot** — the donor's 3-field split-column `{ ciphertext, iv, authTag }` for` |
| 67 | `**Seam (spec §tokens; the convergent trio: zync `tokens.ts:21-40` ≡ multideal `tokens.ts:151-161`):**` |
| 73 | `- [ ] Port the opaque trio from zync `tokens.ts`; its `generateOpaqueToken`/`hashToken` pair matches multideal's `generateRefreshToken`/`has` |
| 74 | `- [ ] **`signToken`/`verifySignedToken` are NOT in this pilot.** Census found the signed-token *contract* diverges ×3 (zync = `jose` JWT tha` |
| 80 | `**Seam (spec §password; donor zync `password.ts`):**` |
| 85 | `- [ ] Port from zync `password.ts` (PBKDF2-SHA-512, per-hash 16B random salt, 64B key). Stored format `pbkdf2sha512$<iter>$<saltB64>$<hashB6` |
| 86 | `- [ ] **Iterations = `100_000` (the workerd hard cap, NOT a tuning choice):** workerd rejects PBKDF2 above 100k — `crypto.subtle.deriveBits`` |
| 87 | `- [ ] **`verifyPassword` MUST parse `iter`+`salt` from the stored string** (zync `password.ts:90-96`), never from a module constant — so if ` |
| 104 | `\| Subpath \| Seam \| Donor \| Dep profile \| Build trigger \|` |
| 106 | `\| ~~`util/tokens` (signed)~~ **CLOSED 2026-06-14** \| `signToken`/`verifySignedToken` — **resolved: lands in `auth/engine-custom`, NOT here` |
| 107 | `\| `util/crypto` (credential) \| `encryptCredential`/`decryptCredential` — donor's exact 3-field `{ciphertext,iv,authTag}` split-column form` |
| 108 | `\| `util/password` (argon2id-wasm) \| OWASP-grade KDF **above** the workerd PBKDF2 100k cap — `hashPassword`/`verifyPassword` over an argon2` |
| 109 | `\| `util/logger` \| `logger{info,warn,error}` zero-dep console-JSON \| trance-shop `logger.ts` \| pure \| first module wanting structured lo` |
| 110 | `\| `util/error-reporter` \| pluggable transport (Sentry/Logpush); `logger.error` lazy-imports it \| trance-shop `error-reporter.ts` \| pure ` |
| 111 | `\| `util/id` \| `generateId()` over `crypto.randomUUID()` \| ForumZone `generateId`, trance-shop audit \| pure \| first consumer (ULID only ` |
| 113 | `\| `util/rate-limit` \| low-level `limit(key,max,window)` + policy-registry; backends `memory`(default)/`kv`/`neon`/`cf-native` \| trance-sh` |
| 116 | `\| `util/http-cache-headers`, `util/idempotency`, `util/ssrf-guard`, `util/hmac` \| per synthesis §1 leaf list \| (census at trigger) \| pur` |

### `docs/specs/2026-06-12-audit-module-boundaries.md` (21 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** Read real impl + call-sites across 5 census donors (zync, ForumZone, multideal, trance-shop, vibeflare) via parallel read-only a` |
| 9 | `## Headline: core is tiny and rock-solid; everything fancy is 1 donor (zync)` |
| 11 | `The actor/entity/action record recurs cleanly in **4 donors**. Two census claims are corrected:` |
| 12 | `1. **Census said "async queue fan-in" defines audit. It does NOT — 4/5 write SYNCHRONOUS INLINE.** Only zync does async (CF Queue), and even` |
| 13 | `2. **vibeflare is NOT an audit donor.** Its `audit_events` (`apps/worker/src/db/migrations/0001_init.sql:103`) is an **API request/usage log` |
| 32 | `**Table shape** (open-string, the 4-donor consensus): `id` · `actor_id` (nullable — null/sentinel = system/AI actor) · `actor_type?` (open s` |
| 34 | `**Ship the GOOD indexes** — learn from the donor that got it right, not the one that didn't: `(tenant_id, created_at DESC)` + `(tenant_id, e` |
| 36 | `**`logAudit(db, event)` — synchronous inline insert. Full stop.** 4/5 donors do exactly this (ForumZone tx-inline `admin.service.ts:112`, mu` |
| 38 | `**CONTRACT (not an option): never throw into the business mutation.** Audit failure must not break the operation being logged. trance-shop s` |
| 40 | `**`listAudit(db, filter)` — keyset/cursor pagination is core.** zync's base64url `{created_at,id}` keyset (`audit-list.ts:76`) is the refere` |
| 42 | `### WATCH — register nothing (all 1-donor = zync, census discipline)` |
| 44 | `- **`audit/diff`** — before/after state capture + shallow `computeDiff` → `before_state`/`after_state` jsonb (zync `entity-history.ts:53,94`` |
| 45 | `- **`audit/redact`** — `maskSensitive` blocklist scrubs metadata pre-write (zync `audit.ts:29`). 1 donor. WATCH.` |
| 46 | `- **`audit/retention`** — tier-based prune cron (zync `audit-list.ts:231`; rides `@platform-modules/util/cron` + `@platform-modules/jobs`). ` |
| 47 | `- **`audit/queue-sink`** — async CF-Queue fan-in to decouple write latency (zync `AUDIT_QUEUE` + `audit-log-consumer.ts:19`; peer `@platform` |
| 48 | `- **partitioned compliance table** — zync's 2nd `audit_log` (monthly partitions, raw-SQL DDL). Scale/ops choice → host DDL, not a core featu` |
| 52 | `- **Action/entity catalogs** — the enum/const lists (zync `AUDIT_EVENT_TYPES` 37 strings; multideal strict `pgEnum` `adminActionEnum`/`admin` |
| 53 | `- **Actor-name resolution** — host join (zync users/vendors, ForumZone SYSTEM_USER→`'System'` `moderation.service.ts:718`, multideal `vendor` |
| 61 | `- Distinct from `@platform-modules/util/rate-limit` (counters) and the api-usage/metering track (vibeflare-style request logs) — different c` |
| 89 | `The never-throw contract (swallow → `{ logged: false }`) is the **decoupled, post-commit / fire-and-forget** form — the trance-shop/zync don` |
| 92 | `- **For transaction-atomic audit** (the ForumZone/multideal tx-inline pattern — audit + mutation commit-or-rollback together), the host inse` |

### `docs/specs/2026-06-13-realtime-module-boundaries.md` (21 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** Read real WebSocket/DO/presence/pub-sub impl across 3 census donors (zync, ForumZone, Press.zone) via read-only **sonnet** agent` |
| 9 | `## Headline: `@platform-modules/realtime` SURVIVES as a **Cloudflare-Workers-native** module — 2-donor independent convergence on the SAME s` |
| 11 | `zync (`packages/realtime/`) and ForumZone (`apps/realtime/`) independently built a near-identical substrate: **CF Durable Object + hibernata` |
| 13 | `**Census honest:** 2-donor independent convergence (zync + ForumZone) + Press.zone NONE. Real ≥2 — but **runtime-locked to `cloudflare:worke` |
| 19 | `Delete `@platform-modules/realtime`: the **DO-hub boilerplate** (acceptWebSocket, getWebSockets fan-out, serializeAttachment survival across` |
| 30 | `presenceSet(): string[]                   // compute online from live sockets (ForumZone pattern)` |
| 32 | `publishToQueue(queue, event)                 // producer → CF Queue (zync publish.ts:13-22)` |
| 33 | `broadcastViaServiceBinding(ns, name, frame)  // ForumZone internal POST /broadcast` |
| 47 | `- `RealtimeEnvelope<T>` versioned `{v, type, ...}` frame types (zync `types.ts:25-32`).` |
| 48 | `- `BaseDurableRoom` abstract DO — accept/broadcast/serializeAttachment/close-cleanup (ForumZone `conversation-room.ts:37-75` + zync `hub.ts:` |
| 49 | `- `publishToQueue` producer helper (zync `publish.ts`).` |
| 50 | `- `broadcastViaServiceBinding` + `verifyInternalSecret` (ForumZone `index.ts:37-68`) — **`verifyInternalSecret` reuses `@platform-modules/ut` |
| 51 | `- `makeQueueConsumer(handlers)` ack/retry factory (zync `queues/realtime.ts:17-32`).` |
| 52 | `- `presenceSet()` helper (compute online from live sockets) — **note: 1-donor (ForumZone fully; zync deferred/has the hook).** Include as a ` |
| 57 | `- unread-count accumulation + debounce (zync), typing-indicator relay + participant authz (ForumZone).` |
| 58 | `- The `ForumRoom`/`PresenceTracker` stubs (incomplete, ForumZone-specific).` |
| 61 | ``@platform-modules/realtime` row: **candidate (census ×3) → designed (CF-native module, census ×2).** Note: "2-donor independent substrate c` |
| 74 | `The design spec (`2026-06-13-realtime-module-design.md`) was written from the **actual donor source**, read file-by-file. Three claims above` |
| 76 | `1. **No `zync hub.ts`.** zync's `packages/realtime/` ships **types + `publishRealtimeEvent` only**; its DO is `apps/zync-api/src/durable-obj` |
| 77 | `2. **No `v` in zync's envelope.** zync `RealtimeEvent` (`types.ts:25-32`) has **no version field** — it's `{id,type,tenantId,targetUserId?,p` |
| 78 | `3. **`abstract class BaseDurableRoom` → helper functions.** The two DOs diverge on per-socket identity — zync uses `acceptWebSocket(ws,[user` |

### `.claude/skills/platform-embed-module/references/module-axes.md` (20 hits)

| Line | Offending substring |
|------|-------------------|
| 6 | `> **Risk order — embed low first.** Leaf (no axes) = near-zero risk; **B (db migration) and E (auth/webhook endpoint) riskiest** (live schem` |
| 8 | `\| Module \| Axes \| Peers (A) \| DB schema (B) \| Stores (C) \| Provider (D) \| Endpoint (E) \| Swap-parity target (donor) \|` |
| 10 | `\| **util** \| — \| — \| — \| — \| — \| — \| zync `crypto.ts`/`tokens.ts`, trance `encryption.ts` \|` |
| 11 | `\| **seo** \| — \| — \| — \| — \| — \| — \| ForumZone/multideal jsonld + sitemap escaper \|` |
| 12 | `\| **i18n** \| (E) \| — \| — \| — \| — \| `./routing` locale negotiation (opt) \| donor locale router / `Accept-Language` parse \|` |
| 13 | `\| **i18n-react** \| F \| react \| — \| — \| — \| — \| donor React locale context \|` |
| 14 | `\| **realtime-react** \| F \| react \| — \| — \| — \| — \| donor presence/channel hook \|` |
| 15 | `\| **tax** \| (A) \| db (opt) \| — \| — \| — \| — \| multideal IL-VAT schedule + `resolveVatRate` \|` |
| 16 | `\| **mail** \| D \| — \| — \| — \| resend / ses / postmark / brevo \| — \| donor transactional-email send \|` |
| 17 | `\| **ai** \| D \| — \| — \| — \| openai-compat / anthropic (fetch, no SDK) \| — \| donor LLM-call wrapper + fallback \|` |
| 18 | `\| **uploads** \| D + leaf \| aws4fetch \| — \| — \| r2-binding / presign-s3compat \| — \| multideal image validators (magic-bytes/dims/size` |
| 19 | `\| **search** \| A \| db \| host-owned tables (no own schema) \| — \| — \| — \| multideal/zync FTS query path \|` |
| 20 | `\| **ledger** ★ \| A + B \| db \| `ledgerSchema` \| — \| — \| — \| multideal credit-ledger append/balance \|` |
| 21 | `\| **helpdesk** \| A + B \| db \| `helpdeskSchema` \| — \| — \| — \| donor support-message store \|` |
| 22 | `\| **tenancy** \| A + B + C \| db \| `triadSchema` \| `TenancyStore` \| — \| — \| ForumZone/zync rbac + tenant isolation \|` |
| 23 | `\| **jobs** \| A + B + D \| db \| outbox / poll tables \| `IdempotencyStore` \| cf-queues binding \| — \| donor outbox/queue runner \|` |
| 24 | `\| **notifications** \| A + C + D \| db, mail \| — (host tables) \| `PreferenceStore`, `DedupStore` \| `./email` / `./webpush` channels \| —` |
| 25 | `\| **marketing** \| A + C + D \| db, mail \| — (host tables) \| `ComplianceStore`, `SelfManagedStore` \| `./self-managed` / `./brevo` \| — \` |
| 26 | `\| **billing** \| A + C + D + E \| db, jobs, ledger, tax \| — (uses ledger's) \| `IdempotencyStore` \| stripe / sumit \| webhook `ingestWebh` |
| 27 | `\| **auth** \| A + B + C + D + E \| db, mail, util \| `customAuthSchema` / `betterAuthSchema` \| `OtpStore` \| better-auth (engine-better-au` |

### `.claude/skills/platform-extract-modules/SKILL.md` (18 hits)

| Line | Offending substring |
|------|-------------------|
| 2 | `name: platform-extract-modules` |
| 3 | `description: "Port existing functionality from donor apps (multideal, zync, fewtok, trance-shop, forumzone, press.zone…) into versioned, hea` |
| 6 | `# Extract Modules — Donor-Porting Pipeline` |
| 10 | `Turn functionality rewritten across many donor projects into **versioned, headless, swappable packages**. One `platform/` monorepo builds th` |
| 21 | `**Single source of truth: `docs/standards/coding-standard.md`.** Don't restate rules here — load that doc before writing or migrating any co` |
| 23 | `- **§2 — implementation ladder.** Climb to first rung that holds (YAGNI / donor-census: no 2nd consumer ⇒ don't build). Hard floor never cut` |
| 24 | `- **§3 — R1/R2/R3 porting hazards** — exact things donor code smuggles into seam: **R1** strip donor defaults · **R2** collapse identity cer` |
| 26 | `- **§5 — porting from donors** — donor→ladder→strip→collapse→seam→test pipeline; ×1 = WATCH **unless forward-need fires** (CLAUDE.md §3: fou` |
| 30 | `Score functionality against these. High across all = extract it.` |
| 37 | `6. **High reuse × duplication pain** — rewritten 3+ times. Max token/time savings. **OR forward-need** (CLAUDE.md §3 disposition): *foundati` |
| 131 | `## 6. Extraction process (per module — the checklist)` |
| 138 | `4. **Design interfaces** in **function model** (§3): thin-client shape, capability function signatures, result/error types, Drizzle schema. ` |
| 140 | `6. **Migrate** chosen source impl into packages; strip domain logic back out to host. (→ climb §2 ladder; strip R1 donor defaults; collapse ` |
| 166 | `Deciding *whether* something is a module, what's core vs capability, which deps it has is **upstream** of §6's per-module extraction audit —` |
| 168 | `**The registry is a FILTER, not a backlog.** A row at status `candidate` (census says ≥3 donors) is *hypothesis to be killed or confirmed*, ` |
| 178 | `Prevent: caller importing symbol ≠ coupling. Read what caller DOES with it (what it gates/branches on). One real consumer → keep capability ` |
| 185 | `Assumed logger absent, then assumed wraps pino/consola/winston from name → wrong; trance-shop `packages/core/logger.ts` is CUSTOM zero-dep c` |
| 189 | `Registry pinned rate-limit backends as memory/neon/do; reading real code: trance-shop rate-limit uses CF-KV+in-memory-fallback, multideal us` |

### `CLAUDE.md` (18 hits)

| Line | Offending substring |
|------|-------------------|
| 3 | `Modular boilerplate platform. **Mission, the one line above every disposition: _all the building blocks you need for your project, and for a` |
| 5 | `> **North star — design every public contract for it:** the end state is a **FOSS, host-agnostic application boilerplate** adopted by **thou` |
| 8 | `> Climb the §2 ladder inside a function; satisfy every §4 box at an export. A `@platform-modules/*` package *is* its seam — a typed contract` |
| 18 | `\| `docs/standards/coding-standard.md` \| **how code is written** — §2 ladder · R1/R2/R3 porting hazards · §4 seam checklist · §5.1/R4 prese` |
| 21 | `\| `docs/registry.json` (**machine query surface**) · `docs/specs/2026-06-12-module-registry.md` (**canonical prose source** it mirrors) \| ` |
| 32 | `L0 FOUNDATION (zero/near-zero runtime dep)   @platform-modules/util · @platform-modules/db · @platform-modules/i18n   (i18n reclassified —→L` |
| 45 | `- **Disposition rule (GENERALIZABILITY test — supersedes the donor-count floor; owner directive 2026-06-18):** The decision is **"can this b` |
| 46 | `- **Host-owned (specialized — IS the app):** trance-shop **ticket-selling** · Tamlil **transcription**. **Generalizable → build/share even a` |
| 48 | `- **Still binding (these gates did NOT change — they bound *shape*, never *whether-to-build*):** **Gate-1 delete-test** (a real module's com` |
| 49 | `- **Capability altitude (R5 — thin core, importable growth):** disposition decides *whether a module exists*; R5 decides *how much of a matu` |
| 61 | `**Dispatch policy is MAIN-LOOP-ONLY and lives in the `platform-orchestrator` skill — invoke it before any `@platform-modules/*` build work.*` |
| 63 | `The assembly line — **shape only** (policy in the skill): **census ─▶ spec/gates ─▶ build ─▶ review (adversarial) ─▶ harness ─▶ ship**.` |
| 69 | `\| **`platform-extract-modules`** \| a capability is duplicated across ≥1 donor and you want it shared · asking "is X a module candidate?" ·` |
| 70 | `\| **`platform-make-modules`** \| building a **NET-NEW** module for a capability that exists in **zero** donors \| its **scan-gate** stops y` |
| 72 | `\| **`platform-make-template`** \| authoring a **NET-NEW template** — a multi-screen UI flow (screen-set) for a blueprint \| its **scan-gate` |
| 76 | `**Lifecycle map (two grains, one dispatcher):** **module grain** — **make-modules** (zero-donor, scan-gated) → routes to **extract** (donor ` |
| 80 | `- **Review criterion (§1):** a diff is judged against the module's **boundary spec** + the coding-standard **§4 seam checklist** + the R1–R3` |
| 104 | `- **Catalog discipline — explore once, query forever.** When you census/catalog something not catalogued before (a donor, a capability sweep` |

### `docs/plans/2026-06-14-helpdesk-module.md` (17 hits)

| Line | Offending substring |
|------|-------------------|
| 6 | `**Goal:** Ship `@platform-modules/helpdesk` — the cross-entity **case substrate**: polymorphic `support_messages` / `support_state_transitio` |
| 10 | `**Donors (census 2026-06-13):** zync (`tickets`+`ticket_messages`+`sla_policies`, single-entity, transitions in service layer), trance-shop ` |
| 17 | `2. **NO case-type registry / transition-engine** (Gate 2 over-engineering check — my earlier `registerCaseType(def)` sketch was **my** synth` |
| 18 | `3. **Transition-validation is a pure helper** — `isValidTransition(adjacency, from, to)` + optional `(ctx) => boolean` predicate guard. Zero` |
| 19 | `4. **Status enums are host config, not a module constant** (zync 5-state vs trance 5-state vs multideal per-entity — they **differ**). The m` |
| 20 | `5. **SLA: module supplies due-compute + breach-flag contract, host owns the scheduler.** `computeDue()` + a `breached` flag flip; breach det` |
| 27 | `- **Gate 1 (delete-test — FORWARD-looking, weaker than search, stated plainly):** deleting helpdesk does **not** simplify any existing app (` |
| 28 | `- **Gate 2 (adapter minimalism + over-engineering check):** the registry/engine is **dropped** (no donor built it). Ship polymorphic tables ` |
| 37 | `- **Threaded messages** — `support_messages (parentType, parentId, authorType: staff\|customer\|system, body, visibility?, createdAt)`. mult` |
| 39 | `- **Attachments** — `support_attachments (parentType, parentId, …)` (an R2/`uploads` object ref). zync + multideal have it; trance doesn't (` |
| 43 | `- **NOT in core (explicitly excluded — 1-donor product/domain):** KB/knowledge-base, AI-agent runner, escalation rule engine, decisions/reso` |
| 44 | `- **Returns — DISSOLVED (not a module, not a helpdesk mode):** domain parts don't converge (multideal liability/restocking agorot vs trance ` |
| 58 | `*(KB / AI-runner / escalation / negotiation / email-intake / returns = excluded or WATCH — not task-decomposed; built only on a 2nd clean do` |
| 88 | `- **Returns** → DISSOLVED (recipe + WATCH near `@platform-modules/billing`; spawns a case, sibling not child) · **dispute/offer-negotiation*` |
| 90 | `## Out of scope (census discipline)` |
| 91 | `- **Case-type registry / transition-engine** → over-engineering, dropped (no donor built it). **Per-entity status enums + values, category t` |
| 94 | `**Isolation floor in-plan** — the `(parentType, parentId)` polymorphic-key isolation is a required Task-2 hard floor with dedicated leak-reg` |

### `docs/plans/2026-06-14-jobs-module.md` (17 hits)

| Line | Offending substring |
|------|-------------------|
| 4 | `> **Source of truth:** `docs/specs/2026-06-12-jobs-cron-module-boundaries.md` — plan-grade (5-donor boundary map, decided, incl. the cron-di` |
| 10 | `**Donors:** multideal (mature donor — tx outbox + `HANDLER_BY_TYPE` + cron backstop + `JobRunnerDO`), zync (1 type-mux queue bus), ForumZone` |
| 17 | `- **Gate 1 (delete-test):** delete jobs → every app re-hand-rolls the per-message try/ack/retry wrapper, the `type`→handler `Map`, and the i` |
| 25 | `- `JobEnvelope<T> = { type: string; payload: T }`; shared `QueueMessage<T>` / `QueueBatch<T>` types (kills ForumZone's 6× local re-decl that` |
| 26 | `- `createJobRegistry()` → `{ register(type, schema, handle), dispatch(env, msg, opts?) }`. `register` stores `{ schema: StandardSchemaV1, ha` |
| 27 | `- **Ack/retry convention** (identical across zync/ForumZone/multideal): unknown type → warn + ack · `issues` from validate → ack-malformed ·` |
| 28 | `- `IdempotencyStore { seen(key): Promise<boolean>; mark(key, ttl?): Promise<void> }` — an **injected** strategy (the spec found 5 distinct d` |
| 29 | `- `strict` dispatch flag (multideal `outbox/types.ts:56`): missing-secret → throw (backstop path) vs log + ack (live path).` |
| 73 | `- [ ] `src/cf-queues.ts`: producer `enqueue(queue, body)` = `queue.send(body)` (**single-send default — no donor uses `sendBatch`**); option` |
| 79 | `- [ ] `src/db-poll.ts`: takes a `Querier<S>` from `@platform-modules/db`. `claim(db, { limit })` = `UPDATE jobs SET status='processing' WHER` |
| 84 | `### Task 5 — `outbox` (subpath, peer `@platform-modules/db`) — the mature multideal pattern` |
| 86 | `- [ ] `src/outbox.ts`: `insertOutboxRow(db, values)` called **inside the business DB tx** (atomicity with the side effect — multideal `queri` |
| 92 | `- [ ] `src/do-runner.ts`: a base `JobRunnerDO`-style class/mixin. `nudge()` → `ensureAlarm` (set `setAlarm(now)` **iff** none pending — idem` |
| 105 | `## Out of scope (census discipline — spec §Host / §Integration)` |
| 106 | `- **`util/cron` scheduler registry** (cron-string→handler fan-out) → folds into the **`@platform-modules/util`** build (zero-dep leaf), **no` |
| 109 | `- **`sendBatch`** — no donor uses it; single-send default.` |
| 113 | `Core is **real runtime yet zero heavy deps** (validator injected via `StandardSchemaV1`, bindings via subpaths, bundle-check proves it) — L1` |

### `docs/specs/2026-06-14-billing-module-boundaries.md` (17 hits)

| Line | Offending substring |
|------|-------------------|
| 3 | `> **Status:** boundary spec (census-grounded). Source for `docs/plans/2026-06-14-billing-module.md`.` |
| 4 | `> **Census (2026-06-14, this session):** multideal (Stripe), trance-shop-israel (Sumit), vibeflare (no PSP — internal credits, **not** a don` |
| 18 | `\| Seam element \| multideal (Stripe) \| trance (Sumit) \| Verdict \|` |
| 43 | `\| **Subscriptions / recurring** \| **FORWARD / WATCH** (1-donor, external engine) \| trance only; the recurring *engine* is outside the app` |
| 44 | `\| **Saved payment methods · disputes · vendor KYC/onboarding** \| **WATCH / host** (1-donor each) \| multideal-only `payment_methods`, disp` |
| 48 | `## Pattern A (refined by census) — invoice-on-charge is config **only when the PSP emits the doc**` |
| 50 | `The synthesis said "Sumit invoice-on-charge → billing config, not `@platform-modules/invoicing`." Census **confirms and refines**:` |
| 53 | `- **Stripe does NOT issue IL tax docs** — multideal calls a **separate pluggable** `getInvoiceProvider(env).issueTaxDoc()` after settle (`fi` |
| 55 | `**Rule:** the billing adapter carries an `emitsInvoiceOnCharge: boolean` capability. `true` (Sumit) → invoice is charge config. `false` (Str` |
| 85 | `//   EVERY variant carries `eventId` — the provider's own event id (Stripe `event.id` / Sumit's delivery id), extracted` |
| 153 | `//   STRIPE WEBHOOK RECOVERY (donor d9969623 + the one-ProviderEvent-per-webhook seam shape): bill the reversal off the` |
| 160 | `//   The donor only survives `charge.refunded` by LOOPING + re-asserting EVERY refund per event — which one ProviderEvent` |
| 263 | `Delete billing → each commerce app re-rolls: a provider adapter, idempotency-keyed charge, **webhook verify+dedup+dispatch**, refund-with-id` |
| 278 | `5. **Refund reversal is module-owned, and sync↔webhook CONVERGE on the provider-canonical refund id (symmetric with settlement; convergence ` |
| 283 | `**Conformance (money.md:83 + R4/§5.1) — carry the audit SCENARIOS, not the donor bytes.** Billing **rebuilds** the seam (it does not byte-po` |
| 285 | `## Out of scope (census discipline)` |
| 286 | `- **Order/purchase tables, status enums, fulfillment, split policy** → host. **Tax computation** → `tax`. **Ledger postings** → `ledger`. **` |

### `docs/specs/2026-06-14-db-module-boundaries.md` (17 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Layer:** L0 FOUNDATION (`@platform-modules/util · db` — `events` DISSOLVED 2026-06-14, census ×0). Core is **type-only** drizzle → zero ru` |
| 6 | `**Method:** Read real impl + call-sites across 4 census donors (multideal, zync, ForumZone, trance-shop) via read-only haiku scouts; every l` |
| 12 | `The donors do not converge on a fat DB layer to extract — they converge on a **handle-type union** (`Db \| DbTx`) every query helper accepts` |
| 17 | `- **ForumZone proves the footgun is real:** its DB is `drizzle(neon(url))` (`packages/db/src/tenant-resolver.ts:2`) — pure `neon-http`, driz` |
| 36 | `- **What disappears from N apps:** the lazy singleton client factory (every donor hand-rolls it — multideal memoized getter `client.ts:17-51` |
| 55 | `**Return the concrete driver type, not the agnostic vocabulary (amended 2026-06-16).** An earlier draft returned the agnostic `Database<S>`/` |
| 99 | `- `Querier<S>` reproduces the donors' union exactly — multideal `DrizzleDb \| PgTransaction`, zync `Db \| DbTx` — but as a **published, driv` |
| 117 | `## WATCH / out of scope (census discipline)` |
| 119 | `- **Tenant scoping → `@platform-modules/tenancy` (L1), not here.** ×2 donors scope (zync lint-enforced; ForumZone `ScopedDb` wrapper, `tenan` |
| 120 | `- **Raw `pg` manual `BEGIN/COMMIT`** (trance-shop `workers/ticketing/src/db.ts:581-628`) — a drizzle-bypassing legacy path. The platform pat` |
| 121 | `- **D1 → WATCH `@platform-modules/db-d1` (×1, separate package).** drizzle's `d1` driver is a different query-result paradigm (`drizzle-orm/` |
| 124 | `## Donor evidence (condensed)` |
| 126 | `- **multideal** — `apps/web/src/server/db/client.ts:17-51`: neon-serverless (`Pool`/WS), memoized lazy getter, **`DrizzleClient = DrizzleDb ` |
| 127 | `- **zync.is** — `packages/db/src/client.ts:1-14`: postgres-js over Hyperdrive (TCP), per-feature schema, **`Db \| DbTx`** union. The referen` |
| 128 | `- **ForumZone** — `packages/db/src/tenant-resolver.ts:2,34-58`: **neon-http**, `ScopedDb` tenant wrapper, schema **not** passed to `drizzle(` |
| 129 | `- **trance-shop** — `packages/core/src/db.ts`: neon-http via a lazy `Proxy`; `workers/ticketing/src/db.ts:581-628`: raw `pg` manual `BEGIN/C` |
| 131 | `**Driver census:** neon-http ×2 (ForumZone, trance-shop core) · neon-serverless ×1 (multideal) · postgres-js ×1 (zync) · raw pg ×1 (trance-s` |

### `docs/specs/2026-06-13-seo-module-boundaries.md` (16 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** Read real sitemap/robots/JSON-LD/hreflang/canonical/og-image impl across 4 census donors (trance-shop, ForumZone, multideal, Pre` |
| 7 | `**Amendment 2026-06-15 (pre-build census).** Re-read both donor JSON-LD serializers before dispatch. The hard-floor serializer is pinned to ` |
| 11 | `## Headline: `@platform-modules/seo` SURVIVES as a **thin scaffolding module** (like `@platform-modules/search`) — the algorithmic skeleton ` |
| 13 | `3 active donors (trance-shop, ForumZone, multideal) independently built the **same scaffolding**: typed JSON-LD serializer + sitemap XML bui` |
| 33 | `- **`@platform-modules/seo/jsonld`** — `serializeJsonLd(obj)` + generic `buildBreadcrumbList(items)` / `buildOrganization(input)` / `buildWe` |
| 34 | `- **`@platform-modules/seo/sitemap`** — `renderSitemapIndex(children)`, `renderUrlSet(urls)`, `buildUrlEntry(loc, {hrefLangs, lastmod})`. In` |
| 35 | `- **`@platform-modules/seo/gate`** — `isIndexable(tenant, node, thread?)` typed interface (ForumZone `indexable.ts:26-38` = cleanest ref) + ` |
| 36 | `- **`@platform-modules/seo/canonical`** — `getCanonicalOrigin(tenant)` (custom-domain-vs-subdomain, ForumZone ref) + `buildLocaleUrl(origin,` |
| 38 | `## 2/3 leaves — include (still ≥ census-equivalent, both real)` |
| 39 | `- **`@platform-modules/seo/hreflang`** — `buildHrefLangs(locales, current, urlFn)` + `LOCALE_BCP47` map. trance + multideal; ForumZone singl` |
| 40 | `- **`@platform-modules/seo/robots`** — `buildRobotsTxt({sitemapUrl, disallowPaths, allowAll})`. ForumZone + multideal dynamic; trance static` |
| 42 | `## WATCH — register nothing (1-donor)` |
| 43 | `- **og-image Satori pipeline** (ForumZone only — Satori→resvg-wasm→jsquash-webp, R2-cached, `og/[key].webp.ts`). Well-built but 1-donor (tra` |
| 44 | `- **IndexNow queue consumer** (ForumZone only — `queues/indexnow.ts`, `groupByHost`, CF-Queues retry). 1-donor → WATCH. (When extracted, it'` |
| 45 | `- **GEO meta tags** (multideal only — geoRegion/geoPosition/icbm, Israel-specific). Host-domain, not a module.` |
| 53 | ``@platform-modules/seo` row: **candidate (census ×4) → designed (thin scaffolding, 3 active donors).** Note: "thin skeleton (like search): l` |

### `docs/specs/2026-06-13-uploads-image-module-boundaries.md` (16 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** Read real upload/storage/R2 + image-processing impl across 6 donors (zync, ForumZone, multideal, trance-shop, vibeflare, Press.z` |
| 12 | `1. **`@platform-modules/uploads`:** R2 backend 6/6, image magic-byte validation 5/6, size-limit 5/6, quota-check 3/6 — the *validation* laye` |
| 13 | `2. **`@platform-modules/image`:** 3 donors, 3 engines (ForumZone jsquash WASM / multideal CF-Images-at-serve / trance Photon WASM) — **no sh` |
| 19 | `**`@platform-modules/uploads`:** delete it → the image magic-byte table (5/6 hand-roll it, **Press.zone has NONE = a real upload-security ho` |
| 27 | `- `uploads/presign-s3compat` — `aws4fetch` AwsClient `signQuery` browser-direct-PUT (zync/ForumZone). **`@aws-sdk/*` (Press.zone) is Node-on` |
| 29 | `The proxy-through-worker (multideal HMAC token) and direct-POST (trance) flows need **no module beyond the validation leaves** — they're jus` |
| 33 | ``apps/consumer`: (a) `detectMimeFromMagicBytes` accepts real JPEG/PNG/WebP/AVIF/GIF headers and **rejects a spoofed content-type whose bytes` |
| 39 | `- **`uploads/magic-bytes`** — `detectMimeFromMagicBytes(header): mime\|null` for JPEG/PNG/WebP/AVIF/GIF (5/6). **Security leaf:** use multid` |
| 40 | `- **`uploads/image-dimensions`** — multideal's pure header-only parser (PNG/WebP/JPEG, `imageDimensions.ts:60-201`). 1 clean impl (ForumZone` |
| 42 | `- **`uploads/quota`** — pure `checkStorageQuota(used, req, limit)` (3/6). **DB counter wiring = host** (tier tables differ: zync 4-tier, Pre` |
| 43 | `- **`uploads/presign-s3compat`** (adapter) — `presignR2Put(creds, key, contentType, expiresIn)` via aws4fetch (zync/ForumZone shape). Peer: ` |
| 47 | `Bucket name + key-prefix conventions, DB quota counters + tier tables, the upload-flow architecture choice (presign vs token-proxy vs direct` |
| 53 | `**A1 · A3 · A4 · A5 · A6 → HOST (the upload-finalize / adoption endpoint).** Bind-pending-upload-to-a-parent is **1-donor (multideal token-p` |
| 66 | `No shared engine. Magic-byte + dimension → `@platform-modules/uploads` leaves (above). Transcode/resize/encode = host (3-way engine split). ` |
| 71 | `- `@platform-modules/uploads` row: **candidate (census ×6) → designed (validation leaves + presign adapter).** Note: "Validation converges 5` |
| 72 | `- `@platform-modules/image` row: **candidate (census ×3) → DISSOLVED (not a module).** Note: "3 donors, 3 engines (jsquash/CF-Images/Photon)` |

### `docs/specs/2026-06-18-mod-cms-v0.0.2-gap.md` (16 hits)

| Line | Offending substring |
|------|-------------------|
| 7 | `> "admin dashboard — which modules and templates are missing? we probably need dashboard template, very universal to many projects → donor s` |
| 15 | `## Finding 2 — admin dashboard IS donor-proven + convergent (donor bank YES)` |
| 17 | `Source: `docs/catalog/2026-06-17-screen-flow-donor-census.md` §2.5 (admin) + §2.10 (moderation), SHA-pinned 2026-06-17.` |
| 21 | `\| Screen \| Best donor \| Maturity \|` |
| 23 | `\| shell / nav \| multideal (`apps/web/src/pages/admin/layout.astro` + `admin/index.astro`) \| H \|` |
| 24 | `\| metrics / overview \| trance-shop-israel (`[locale]/admin/index.astro`) \| H \|` |
| 25 | `\| data-table CRUD (list + detail/edit) \| multideal (`admin/deals/index.astro` + `[id].astro`) \| H \|` |
| 26 | `\| settings (largest sub-page set) \| trance-shop-israel (`admin/settings.astro`) \| H \|` |
| 27 | `\| users management \| trance-shop-israel `admin/users.astro` (+ multideal, FZ, zync) \| H \|` |
| 28 | `\| audit-log viewer \| trance-shop-israel + ForumZone `admin/audit.astro` \| M \|` |
| 29 | `\| analytics \| trance-shop-israel `admin/system.astro` + zync-admin \| M \|` |
| 31 | `Moderation (nested, also convergent, 2 donors): report-queue, content-moderation, mod-jobs, ban/mute (ForumZone tested API), community-mod d` |
| 33 | `**Best-donor hierarchy:** multideal = shell/nav + data-table CRUD pattern; trance-shop-israel = breadth (25+ admin pages) + settings + metri` |
| 48 | `\| `admin-dashboard` template \| host-owned screen-flow TEMPLATE (copied, never a package) via `/platform-make-template` \| not built; donor` |
| 59 | `4. **uploads-react** stays a SEPARATE gated track (needs `StorageAdapter` seam before extraction) — media library is post-MVP, not on the v0` |
| 60 | `5. **Donor sources (de-named, host-owned, public-language law):** multideal = shell/nav + data-table CRUD; trance-shop-israel = settings bre` |

### `docs/specs/2026-06-12-mail-family-module-boundaries.md` (14 hits)

| Line | Offending substring |
|------|-------------------|
| 14 | `- zync.is `packages/notifications/src/email/` → `sendEmail(opts, env)` (single send, locale-aware, resend adapter)` |
| 15 | `- ForumZone `packages/providers/src/email/` → `EmailProvider.send(msg)` + `makeEmailProvider()` adapter factory (sendgrid/resend/brevo), `Su` |
| 16 | `- Press.zone `emailService.ts`, achiron `functions/api/contact.ts`, AaAAA `server/adapters/mail/`, multideal `verify-email`` |
| 36 | `- **Maturity reference:** zync.is `packages/notifications` already runs email + telegram + webpush + ws-push under one `deliver()` seam with` |
| 44 | `- **webpush payload encryption is a security/data-loss floor — proven, not assumed.** The `notifications/webpush` adapter does real RFC 8291` |
| 52 | `- **Low frequency:** real campaign impls exist in only 2 projects — trance-shop (`api/admin/newsletter/[id].ts`, `subscriptions/email.ts`, `` |
| 56 | `Real usage (grepped): both trance-shop and ForumZone are **self-managed** — list in DB, loop, send each via raw `resend.emails.send()`. The ` |
| 65 | `1. **`self-managed`** (DEFAULT for this stack) — list in host DB (Drizzle), sends via the **`mail`** module, tracks opens (pixel) + clicks (` |
| 74 | `\| mail \| ForumZone, Press, fewtok, multideal, site-generator, trance-shop, zync (7) \| most common — but already its own `mail` module \|` |
| 75 | `\| webpush \| VirtuAc, multideal, trance-shop, zync (4) \| no \|` |
| 76 | `\| telegram \| Botmaster, Press, VirtuAc, multideal, trance-shop, zync (~6, some are the app's own bot) \| no \|` |
| 77 | `\| sms \| Press, multideal, trance-shop, zync (4) \| no \|` |
| 116 | `**Follow-up (flagged, needs review):** trance-shop + ForumZone send via raw resend with a **default-on tracking pixel** and self-rolled unsu` |
| 120 | `**One mechanism, pluggable backend — `makeCaptureAdapter({ store })`.** The in-memory test fake (option-1) and the persistent dev/preview ca` |

### `docs/plans/2026-06-14-tax-module.md` (13 hits)

| Line | Offending substring |
|------|-------------------|
| 6 | `**Goal:** Ship `@platform-modules/tax` — **`tax/rates-table`** (the 2-donor-designed self-compute VAT engine): `resolveVatRate(schedule, dat` |
| 10 | `**Donors:** zync (IL VAT engine — `vat_rates` 1976–2025 `NUMERIC(5,4)`, `getVatRate(country,date)` date-aware, `applyVat` **exclusive** add-` |
| 17 | `2. **Ship BOTH math directions** (spec §5 scope-caveat, do NOT overclaim a unified rounding fn): `applyVat(netAgorot, rate) → {vat, gross}` ` |
| 25 | `- **Gate 0/1:** zync + multideal independently built date-effective rate resolution → `tax/rates-table` **designed** (2 donors). Delete tax ` |
| 35 | `- `resolveVatRate(schedule, date) → rate` — the 2-donor convergence: last entry with `effectiveFrom ≤ date`. **Storage-agnostic** — the modu` |
| 36 | `- `applyVat(netAgorot, rate) → {vat, gross}` — **exclusive** (zync); `extractVat(grossAgorot, rate) → {net, vat}` — **inclusive** (multideal` |
| 37 | `- **Rate dataset** — seed the IL 1976–2025 historical set from zync (the more complete asset); EU per-country + reduced-category matrix = **` |
| 54 | `> **Build-kickoff flag (for task #8, not decided here):** build-urgency **inverts** donor-strength — the donor-proven `tax/rates-table` (IL)` |
| 63 | `- [ ] `src/rates-table/resolve.ts`: `resolveVatRate(schedule, date) → rate` — last entry with `effectiveFrom ≤ date`. **`date` is a host-res` |
| 68 | `- [ ] `src/rates-table/vat-math.ts`: `applyVat(netAgorot, rate) → {vat, gross}` (exclusive — VAT added to net, zync); `extractVat(grossAgoro` |
| 69 | `- [ ] **Tests:** `applyVat` exclusive matches zync's `ROUND(net*rate,2)` agorot for known cases; `extractVat` inclusive matches multideal's ` |
| 82 | `## Out of scope (census discipline)` |
| 90 | `**Financial-correctness floor in-plan** — date-effective rate resolution + exact integer-agorot rounding in **both** legally-distinct direct` |

### `docs/specs/2026-06-13-commerce-promotions-inventory-boundaries.md` (13 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** Read real coupon/discount + stock-reservation impl across the 2 commerce donors (multideal, trance-shop) via read-only **sonnet*` |
| 9 | `## `@platform-modules/promotions` → WATCH (effectively 1 real donor)` |
| 11 | `**Census ×2 is a mirage — it's 1 mature impl + 1 trivial inline.**` |
| 13 | `- **multideal:** mature layered engine — **pure** `validatePromo(code, ctx)` (`server/promo/validator.ts:15`, 11 rejection reasons) + **pure` |
| 14 | `- **trance-shop:** entire flow inlined in a **30-line API handler** (`pages/api/coupons/validate.ts:31-54`) — flat coupon (percentage/fixed)` |
| 16 | `**Delete test:** extracting multideal's pure fns just **moves the import path** — they're already locally modular in `server/promo/`; comple` |
| 18 | `**Verdict: WATCH** (same class as outbound-webhooks = 1-real-donor). Not DISSOLVED (the pure validator+resolver ARE a real, clean shape) — b` |
| 20 | `> Distinction from `@platform-modules/helpdesk` (which passed): helpdesk had 3-donor *shape*. Promotions has 1 mature + 1 trivial = effectiv` |
| 28 | `\| \| multideal \| trance-shop \|` |
| 36 | `**Shared only at the abstract `reserve/commit/release` + invariant `capacity-active≥qty` level** — that's *conceptual*, not *structural*. A ` |
| 38 | `**Delete test:** nothing shared exists to delete — both bespoke, well-integrated. **Verdict: WATCH.** The `reserve/commit/release` contract ` |
| 43 | `- `@platform-modules/promotions`: **candidate ×2 → WATCH.** Note: "1 mature donor (multideal pure `validatePromo`/`applyPromo` in `server/pr` |
| 44 | `- `@platform-modules/inventory`: **candidate ×2 → WATCH.** Note: "2 donors, structurally incompatible (multideal Postgres FOR-UPDATE+CAS, no` |

### `docs/specs/2026-06-13-community-cluster-boundaries.md` (13 hits)

| Line | Offending substring |
|------|-------------------|
| 4 | `**Status:** Decided (boundary mapping). **Cluster → WATCH (1 donor); carve `sanitize-html` security leaf candidate to `@platform-modules/uti` |
| 5 | `**Method:** Read real moderation/reputation/reactions/content-pipeline/DM impl across 2 donors (ForumZone, Press.zone) via read-only **sonne` |
| 9 | `## Headline: ALL 6 community sub-concerns are **ForumZone-only**. Census = 1 real donor → the whole cluster is WATCH. The agent's "promote a` |
| 11 | `Press.zone is a reference CMS-offload backend (Node/Express + Redis), architecturally a different tier: it has a **coin economy** (commerce,` |
| 13 | `\| Sub-concern \| ForumZone \| Press.zone \| Census \|` |
| 21 | `**No sub-concern recurs in both donors. 1 donor = WATCH, full stop.** Building the agent's proposed 3-module split (`@platform-modules/moder` |
| 23 | `> Why this differs from `@platform-modules/realtime` (also had a NONE donor): realtime had **2** independent full impls (zync + ForumZone) +` |
| 27 | `## The one exception — `sanitize-html` (security leaf, escapes the census on its own merit)` |
| 29 | `ForumZone `packages/shared/src/content/sanitize.ts` = strict-allowlist HTML sanitizer (strips scripts/event-handlers/protocol attacks, regex` |
| 31 | `**But — do NOT hard-commit on 1 mapped donor.** Flag as a **strong `@platform-modules/util/sanitize-html` candidate pending a quick census**` |
| 33 | `The `bbcode.ts`/`mentions.ts` pipeline around it = ForumZone-only → WATCH (future `@platform-modules/content-pipeline` on a 2nd consumer). T` |
| 38 | `- `@platform-modules/community`: **candidate ×2 → WATCH (1 real donor).** Note: "All 6 sub-concerns (moderation/reputation/reactions/polls/c` |
| 39 | `- `@platform-modules/util`: add **WATCH-leaning candidate `sanitize-html`** (XSS-safe allowlist, ForumZone `content/sanitize.ts`, zero-dep) ` |

### `docs/specs/2026-06-16-ui-product-brief.md` (13 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Grounded in:** `docs/catalog/2026-06-16-ui-donor-census.md` (the SHA-pinned UI census; all engine/token/taxonomy claims trace there). Memo` |
| 17 | `Generic AI agents write **UI slop**: inline styles, hardcoded hex, ad-hoc one-off components instead of the design system. The census proves` |
| 29 | `**The enforcement engine already exists — it's `slopgate` (`@alexcodeplace/slopgate`, shipped v1, already adopted in multideal + zync).** Bu` |
| 33 | `The census **closed** the engine question (the earlier "Park UI / Ark+Panda lead" hypothesis is dead — Ark/Panda appears in **zero** donors)` |
| 41 | `## 4. Who are the donors (census-grounded)` |
| 43 | `Seven, pinned in `docs/catalog/2026-06-16-ui-donor-census.md`. The four that matter for the engine: **multideal, trance-shop-israel, zync.is` |
| 51 | `The census taxonomy (generic primitives vs domain/sections/admin) *is* the boundary:` |
| 84 | `Until both clear: this brief is the plan; **do not** spec-to-build the full product, scaffold the shipping repo, or pick a repo/brand withou` |
| 86 | `**What the gate does NOT cover — the decoupled core (reconciles §9 ↔ §10).** §9's core — **token contract + enforcement triad + plain Radix ` |
| 89 | `- **Leg 2 — five `mod-ui` ast-grep rules:** `mod-ui-no-inline-style` (host `style=`; suppress-with-reason for legit dynamic positioning), `m` |
| 90 | `- **Leg 3 — `tokens.ts`:** generic semantic token unions (`TokenColor`/`TokenSpace`/…) with **no values** (values stay behind the `--token` ` |
| 92 | `- **False-positive measurement (the clean canary can't measure FP — so the pack was run across 568 real donor components):** design-independ` |
| 101 | `- **Enforcement engine = `slopgate` (adopt, don't build).** Leg 2 of the triad = a strict `mod-ui` **slopgate rule pack** the owner sets wit` |

### `docs/specs/2026-06-17-mod-www-foss-site-program-design.md` (13 hits)

| Line | Offending substring |
|------|-------------------|
| 14 | `3. **The instance — `mod-www`** (repo `github.com/alexcodeplace/mod-www`, lives `~/Projects/mod-www`): one *deployed* site = `content-site` ` |
| 15 | `4. **The proof — `create` v0.0.1** (the platform scaffolder): extracted *after* mod-www is hand-built and green; emits the `content-site` bl` |
| 19 | `**Public-language law (hard):** every word the site renders is **product language** — the modules are the product; the project's mission and` |
| 44 | `\| Comments \| ✅ **giscus** (GitHub Discussions) \| own Comments plugin (harvest reference CMS donor *logic*) \| Zero backend, GitHub identi` |
| 48 | `\| `create` scaffolder \| ⏳ extracted *after* mod-www is green \| full emitter / multi-surface-target / Distribution generation \| delivery-` |
| 58 | `- **(A) Platform scaffolder `create` (v0.0.1):** scaffolds the `content-site` **blueprint** (themeless, tier 1) into a *new* app. `create` e` |
| 128 | `These are **consumer skills** (for the adopter's agent building a site), distinct from the platform-dev skills (`platform-extract/make/embed` |
| 133 | `\| **`mod-design`** \| Keep it good *and* 100/100: token discipline (no arbitrary values, no `className`/inline-style escape), Radix a11y fl` |
| 138 | `**Harvest, then de-name:** the UI/UX rules already exist in `mod-ui-enforcement` + the UI brief + the donor census; `mod-design` lifts the *` |
| 167 | `7. **`create` v0.0.1** — extracted last (§2A).` |
| 183 | `- **Phase 1 — hand-build mod-www (the instance): ✅ DONE (2026-06-18).** Astro + Content Collections + 4 templates + dark instance theme + EN` |
| 184 | `- **Phase 2 — extract the blueprint + ship the 3 skills:** factor the generic *themeless* parts of mod-www into the `content-site` blueprint` |
| 185 | `- **Phase 3 — `create` v0.0.1:** extract the scaffolder; prove by the two §2A oracles — behavioral parity (regenerated site + a throwaway se` |

### `.claude/skills/platform-orchestrator/SKILL.md` (12 hits)

| Line | Offending substring |
|------|-------------------|
| 6 | `module census / spec / build / review / harness / ship work, before dispatching` |
| 23 | `\| **Census / donor-extraction** \| **cursor** (read-only over donor repos) \| Sweeps `~/Projects/{multideal,zync.is,ForumZone,Press.zone,tr` |
| 29 | `**Division:** cursor EXTRACTS and BUILDS · reviewer REVIEWS-IN-ITS-OWN-CONTEXT · **I OWN THREAD** (design · sequencing · integration). Keep ` |
| 31 | `> **Why cursor for census, not haiku `donor-scout`:** haiku extraction proved unreliable (wrong `file:line`, missed surface, bad smell-flags` |
| 36 | `- **cursor census / build → medium.**` |
| 69 | `- **L2:** `ledger` → `tax` (**by-need** — build-urgency inverts donor-strength) → … → `billing` (LAST; L2 pilot, Pattern B over tax+ledger).` |
| 70 | `- **L3 + WATCH** (`marketing`, `helpdesk`, `invoicing`, `affiliate`): wait for 2nd donor / real consumer.` |
| 81 | ``census ─▶ spec/gates ─▶ build ─▶ review (adversarial) ─▶ harness ─▶ ship`` |
| 85 | `- **`platform-extract-modules`** — donor-porting pipeline (candidate rubric, 3 axes, packaging, 10-step extraction, §9 boundary-mapping, ant` |
| 86 | `- **`platform-make-modules`** — net-new, scan-gated: census first → route to `platform-extract-modules` moment donor exists; only genuine ze` |
| 90 | `- **`platform-make-template`** — net-new screen-flow: scan-gate donor screens (`docs/catalog/2026-06-17-screen-flow-donor-census.md`) → harv` |
| 92 | `- **Build dispatch (delivery grain):** generic content template = often thin host glue → may build **IN-LOOP**; multi-screen harvest OR a di` |

### `docs/plans/2026-06-14-auth-module.md` (12 hits)

| Line | Offending substring |
|------|-------------------|
| 6 | `**Goal:** Ship `@platform-modules/auth` — a typed **identity + session seam** abstracting two genuinely-divergent engines, with the security` |
| 10 | `**Donors:** zync `packages/auth/` (jose engine — informs `engine-custom`), **multideal `server/auth/`** (the audited, solidest engine — raw ` |
| 21 | `2. **Signed-session token lands in `auth/engine-custom`, NOT `util/tokens`.** The util boundary spec deferred `signToken`/`verifySignedToken` |
| 42 | `- **Consumes (doesn't own):** `util/crypto`+`util/tokens`+`util/password` (engine-custom), `util/rate-limit` (login/OTP/refresh throttle — d` |
| 53 | `\| 3 \| Task 4 — `engine-custom`: session sign/verify (raw Web-Crypto HS256, multideal form, `sv` claim) \| `packages/auth/src/engine-custom` |
| 81 | `- [ ] `engine-custom/session.ts`: `signSession(claims, secret)` + `verifySession(token) → Principal \| null` — **raw Web-Crypto HMAC-SHA-256` |
| 86 | `- [ ] `engine-custom/refresh.ts`: atomic single-winner rotation `UPDATE … WHERE refreshTokenHash=old RETURNING` (race-safe — multideal `refr` |
| 88 | `- [ ] `engine-custom/index.ts`: `createCustomEngine(config) → AuthEngine` wiring sign-in/out/refresh/createUser over the above; hooks `util/` |
| 93 | `- [ ] `engine-better-auth.ts`: `createBetterAuthEngine(config) → AuthEngine` wrapping `betterAuth({ database: drizzleAdapter(pg), emailAndPa` |
| 111 | `- **`oauth`** (login client google/github) · **`oauth-provider`** (BE an OAuth2 authz server — PKCE/consent/scopes/redirect-validation, zync` |
| 114 | `## Out of scope (census discipline)` |
| 116 | `- **Legacy SHA-256 (`pbkdf2$…`) verify-in-place** → donor migration baggage; a new app has no legacy rows (by-need only).` |

### `docs/plans/2026-06-14-uploads-module.md` (12 hits)

| Line | Offending substring |
|------|-------------------|
| 6 | `**Goal:** Ship `@platform-modules/uploads` — **validation leaves + a thin presign/R2 adapter pair**, NOT a fat upload orchestration (the flo` |
| 10 | `2. **Authorization (Gate 4, `docs/standards/authz.md` A1–A6)** — a **distinct** vector from #1 (access-control, not content). Spec amendment` |
| 12 | `**Donors:** multideal (strict AVIF brand `r2.ts:50-117`, pure dimension parser `imageDimensions.ts:60-201`), zync/ForumZone (aws4fetch presi` |
| 37 | `- **`uploads/magic-bytes`** — `detectMimeFromMagicBytes(header) → mime\|null` for JPEG/PNG/WebP/AVIF/GIF. **Security leaf:** multideal's **s` |
| 38 | `- **`uploads/image-dimensions`** — multideal's pure header-only parser (PNG/WebP/JPEG). 1-clean-donor, flagged. No AVIF dim parse (none exis` |
| 42 | `- **`uploads/presign-s3compat`** — `presignR2Put(creds, key, contentType, expiresIn)` via **aws4fetch** (tiny peer). zync/ForumZone shape. *` |
| 65 | `- [ ] `src/magic-bytes.ts`: `detectMimeFromMagicBytes(header: Uint8Array) → mime\|null` for JPEG/PNG/WebP/AVIF/GIF. **Strict AVIF brand** (`` |
| 70 | `- [ ] `src/size-limit.ts`: `assertSizeLimit(bytes, limit)` throws over cap. `src/image-dimensions.ts`: multideal's pure PNG/WebP/JPEG header` |
| 88 | `- **`uploads/magic-bytes/audio`** (trance-only, 1-donor WATCH). **`@platform-modules/image/<engine>`** — only if 2 donors share an engine (c` |
| 90 | `## Out of scope (census discipline)` |
| 93 | `- **`@aws-sdk/*`** presign (Press.zone) → Node-only, out-of-house on Workers; aws4fetch is the Workers path.` |
| 96 | `**Content floor in-plan** — magic-bytes is a required task with spoofed-content-type + bare-ftyp-AVIF + SVG reject regression tests (the don` |

### `docs/specs/2026-06-13-auth-engine-security-audit.md` (12 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** read real code (zync `packages/auth/` jose engine; multideal `server/auth/` raw-WebCrypto engine + refresh rotation + password K` |
| 6 | `**Correction folded in:** multideal supports passwords (optional; OTP is default) — so the password-KDF axis DOES apply to multideal, not ju` |
| 15 | `\| core + `adapters/drizzle` + `plugins/jwt` (ForumZone real surface) \| 346 KB \| **97 KB** \|` |
| 19 | `**engine-custom for comparison:** multideal path = own code (~few KB) + **zero crypto deps** (raw Web Crypto). zync path = own code + `jose`` |
| 27 | `- **multideal `verifyAccessToken` (tokens.ts:87)** never trusts the JWT header's `alg` — it always recomputes HMAC-SHA-256 over the received` |
| 31 | `- **zync jose engine (jwt.ts):** `jwtVerify` with a symmetric Uint8Array key → jose permits only HMAC algs (RS-confusion blocked, `none` rej` |
| 39 | `**(b) The KDF family is still wrong — but it only matters once the pepper is also stolen (full host compromise).** `credentials.ts:37` — **P` |
| 42 | `- **IF you do (b): where to run it.** multideal runs on **Workers Free = ~10 ms CPU on the request worker.** It is NOT on the Standard Usage` |
| 44 | `- **Key the hashing DO `idFromName(userId)`** (or `idFromName(hash(normalizedEmail))` pre-auth) — *not* content-keyed like RenderDO. RenderD` |
| 51 | `**H1 (low) — explicit alg pinning.** zync `jwtVerify` should pass `algorithms: ['HS256']` (and issuer/audience) explicitly — defense in dept` |
| 55 | `**Unverified (1):** whether zync's request middleware actually calls `isTokenBlocklisted` on the hot path (blocklist exists in `sessions.ts`` |
| 72 | `3. A memory-hard KDF can't hash at strong params on the **Workers Free 10 ms worker** — it would need the **30 s-CPU Durable Object** multid` |

### `.claude/skills/platform-make-template/SKILL.md` (11 hits)

| Line | Offending substring |
|------|-------------------|
| 3 | `description: "Author a NET-NEW template — a multi-screen UI flow (screen-set) for a platform blueprint. ALWAYS starts with a scan-gate: cens` |
| 10 | `A **template** = a **multi-screen flow** (screen-set) assembled from the `@platform-modules/ui-*` kit + (for module-bound flows) one module'` |
| 16 | `Before designing or writing one screen, prove the flow's shape against donor screens. Reinventing a screen donors already converged on = the` |
| 19 | `2. **Census donor screens — check the catalogue FIRST, do not re-explore.** Read `docs/catalog/2026-06-17-screen-flow-donor-census.md` (the ` |
| 21 | `- **Donors converge on ONE reusable screen-shape →** harvest it (Step 4). The best-donor row in the census names the donor to lift from.` |
| 22 | `- **Donors only *look* alike (lookalike, not same shape) →** NOT a template yet. Record WATCH in the census; STOP.` |
| 23 | `- **Zero/one donor, no convergence →** a one-screen-shape invention is not a template (same bar as a one-consumer module). STOP unless forwa` |
| 49 | `## Step 4 — Author (harvest donor → de-name → host-owned scaffold)` |
| 51 | `- **Lift the convergent donor screen** named in the census; **de-name it** — strip every source-app reference, domain entity, and donor-spec` |
| 54 | `- **Public-language law (hard):** nothing the screen renders carries internal vocab (harvesting/donor/seam/layer codes) or source-app names.` |
| 63 | `A generic content template is often thin host glue → may build **in-loop**. A multi-screen harvest with real de-naming work → `cursor` in a ` |

### `docs/plans/2026-06-14-ledger-module.md` (11 hits)

| Line | Offending substring |
|------|-------------------|
| 10 | `**Donors:** multideal (`credit_ledger`+`wallet_balances` — the idempotent insert-first + multi-bucket FOR-UPDATE reference), Press.zone (`co` |
| 17 | `2. **Insert-ledger-FIRST ordering is MANDATORY** (spec §Statement-order, financial-correctness — *not* optional). `debit` = insert ledger ro` |
| 27 | `- **Gate 3 (consumer harness):** fixture **must exercise BOTH debit shapes + a host-supplied balance target** (not just the default table) —` |
| 40 | `- **Capability (opt-in subpath, own logic — Backlog):** `vesting` (pending/matured/withdrawable + maturation sweep, multideal), `lifetime` (` |
| 79 | `- **host-column target** (a `subscriptions.credit_balance`-style fixture, not the default table) debits correctly — the ForumZone fold-onto-` |
| 83 | `- [ ] `src/debit-with-read.ts`: `debitWithRead(tx: Transaction<S>, { target, reason }, fn)` — `SELECT … FOR UPDATE` the target row(s), pass ` |
| 95 | `- **`vesting`** — pending/matured/withdrawable buckets + maturation sweep (multideal CTE). **`lifetime`** — lifetime_earned/spent counters. ` |
| 97 | `## Out of scope (census discipline)` |
| 99 | `- **Redis/HTTP idempotency-replay cache** (Press.zone) → app concern, not the ledger.` |
| 100 | `- **Recording failed debits as `status='failed'` rows** (Press) → donor-specific, not core.` |
| 104 | `**Financial-correctness floor in-plan, not deferred** — insert-ledger-first ordering is a required constraint with a dedicated double-spend ` |

### `docs/plans/2026-06-17-record-store-module.md` (11 hits)

| Line | Offending substring |
|------|-------------------|
| 9 | `Bounded context (append/query a record log) · narrow stable interface (`append` + `list`) · owns its own data shape (`Stored<T>` envelope) ·` |
| 11 | `**Forward-need override (CLAUDE.md §3):** the 3× are *cousins not one contract* (§5 of the spec), so this is not a ×3 donor-converged build ` |
| 40 | `- **Core seam:** `RecordStore<T> = { append(record: T): Promise<Stored<T>>; list(filter?: ListFilter): Promise<Page<Stored<T>>> }`; `RecordS` |
| 43 | `- **Capability** (opt-in subpath, own logic): `RecordStoreAdmin` get/delete — **DEFERRED to the multideal embed** (no consumer in this build` |
| 62 | `- `src/types.ts` — `Stored<T>`, `ListFilter`, `Page<R>`, `RecordStore<T>`. Also DEFINE `RecordStoreAdmin<T>` (the planned get/delete extensi` |
| 69 | `- **FIRST, extract the derivation into ONE shared internal helper (advisor check 2 — DRY the correctness-critical path now that the 2nd cons` |
| 71 | `- `src/querier/index.ts` — `makeQuerierRecordStore<T,S>(db: Querier<S>, table, opts?)`: **compute `createdAtMs`/`createdAt`/the snapshot in ` |
| 75 | `- `src/d1/index.ts` — `makeD1RecordStore<T>(d1: D1Database, table, opts?)`: **derive `createdAtMs`/`createdAt`/the snapshot in JS via the SA` |
| 98 | `3. **`RecordStoreAdmin` get/delete:** deferred to the multideal embed (no consumer here) — YAGNI.` |
| 107 | `8. **JS-side time, never DB-default (check 1, HIGHEST — SQL propagation of Finding A):** querier + d1 compute `created_at_ms` in JS from the` |
| 108 | `9. **One shared `deriveStored` helper (check 2):** the `createdAtMs`/`createdAt`/snapshot derivation is extracted to an internal `src/derive` |

### `docs/specs/2026-06-13-compliance-module-boundaries.md` (11 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Method:** Read real GDPR-export / deletion / unsubscribe / consent impl across 3 donors (ForumZone, trance-shop, zync) via read-only **son` |
| 17 | `\| Capability \| Census \| Verdict \| Home \|` |
| 19 | `\| **List-Unsubscribe (RFC 8058) header + one-click endpoint + token verify** \| 3/3 (ForumZone RFC8058+HMAC cleanest; trance UUID no-RFC805` |
| 20 | `\| **Bounce/complaint suppression list** (check-before-send) \| 1/3 (ForumZone `emailSuppressions`) — but every ESP needs it \| reusable sea` |
| 21 | `\| **Async data-export job + poll + download-gate** \| 1 full (zync), 1 sync-thin (trance), 1 planned (ForumZone) \| generic async-job patte` |
| 22 | `\| **`exportTenantData` SQL fan-out** \| host-schema-aware (12 tables by name, zync) \| host-domain \| **HOST** — identical constraint to se` |
| 23 | `\| **Account deletion / anonymize** \| trance soft-anon, zync customer-anon (tx+audit); columns are host-schema \| host-domain + seam \| **H` |
| 24 | `\| **ToS / legal consent stamp** \| 1/3 (ForumZone `tosAcceptedAt`/`tosVersion` on account) \| auth-layer concern \| **`@platform-modules/au` |
| 38 | `- `@platform-modules/compliance` row: **candidate (census ×2-3) → DISSOLVED / FOLD (not a module).** Note: "Confirmed fold (row already hypo` |
| 39 | `- `@platform-modules/mail`: add capabilities — **`mail/list-unsubscribe`** (RFC 8058 `List-Unsubscribe` + `List-Unsubscribe-Post` header inj` |
| 41 | `- `@platform-modules/jobs`: note **export-with-download** as a WATCH consumer pattern (1 full donor; host supplies `collector` callback).` |

### `docs/specs/2026-06-16-delivery-stack.md` (11 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `> **Supersedes** `tmp/mining-docs/03-templates.md`, `04-blueprints.md`, `05-surface-targets.md` (an unverified ChatGPT draft, pre-reconcilia` |
| 50 | `**Authoring procedure (point, don't inline — this doc holds the vocabulary + gates; the skills hold the step-by-step):** a `template` is aut` |
| 66 | `- **`ui-primitive` (disposition RUN 2026-06-16 → the UMBRELLA killed; the flat family is the live form).** **Do not build `@platform-modules` |
| 68 | `- **Convergence > count.** Where donors converge they converge **on Radix**, not on a shared internal contract: zync `packages/ui` pulls the` |
| 71 | `- **UMBRELLA killed ≠ capability killed (do not re-kill it when re-reading this).** This kill is about a **single unified `ui-react` umbrell` |
| 76 | `**Promotion gate for any stage:** a stage moves `speculative → candidate → built` only when a **real consumer** (ideally non-donor) needs it` |
| 99 | `**Donor grounding — capability half DONE, screen half open.** The durable census (`docs/specs/2026-06-16-donor-capability-inventory.md`, SHA` |
| 109 | `- **Host-owned** = this app's entities, schema, routes, policy, copy, styling. The moment a blueprint tries to own these it becomes the **ge` |
| 129 | `\| **commerce** \| `presets.commerce` \| cart/checkout/coupon glue (trance donor `H`, ledger #7) \| **a blueprint, not a module** (ledger #7` |
| 170 | `- **Author only what is genuinely new.** The compose-distinct seams are the host-domain logic that neither constituent preset owns (for `mar` |
| 171 | `- **A trivially-needed, backward-compatible parameter on a reused seam is allowed** (e.g. generalize a notifications wiring's enabled-event ` |

### `docs/specs/mod-ui-enforcement/README.md` (11 hits)

| Line | Offending substring |
|------|-------------------|
| 34 | `**Convergence > count applies to the token contract too:** `tokens.ts` is the **generic semantic skeleton** (role names + scale steps), not ` |
| 40 | `1. **`mod-ui-no-inline-style`** — `style=` on a host (lowercase) JSX element. **Suppress-with-reason, not a built-in carve-out:** the rule f` |
| 43 | `4. **`mod-ui-no-token-cast`** — `as_expression` cast into a token union (`x as TokenColor`), forging past the typed prop. Matched by AST nod` |
| 46 | `- **Value-scoped to raw literals** (hex, `px/rem/em`, dynamic `${…}px`), **not** a blanket `-[…]`. A blanket rule scored an **~85% false-pos` |
| 50 | `Token unions (`TokenColor`, `TokenSpace`, `TokenRadius`, `TokenFontSize`, `TokenWeight`) + a reference `TokenStyleProps` shape with **no `st` |
| 52 | `## Measured against real donor code (not just the clean canary)` |
| 54 | ``fixtures/clean.tsx` proves the rules pass *correctly-written* code, but a hand-written clean fixture can't measure the false-positive rate ` |
| 56 | `\| Rule \| Class \| Donor hits \| Reading \|` |
| 61 | `\| `mod-ui-no-raw-interactive` \| **contract-coupled** \| 135 \| meaningless on a *non-adopting* donor (raw `<button>` is normal there); onl` |
| 62 | `\| `mod-ui-no-classname-on-primitive` \| **contract-coupled** \| 224 \| likewise — name-collisions on a non-adopting donor, a violation only` |
| 64 | `**The point:** *design-independent* rules (token-cast, arbitrary-value, inline-style) must hold ~0 FP on **any** good codebase, and now do. ` |

### `docs/plans/2026-06-14-seo-module.md` (10 hits)

| Line | Offending substring |
|------|-------------------|
| 6 | `**Goal:** Ship `@platform-modules/seo` — a **thin scaffolding module** of pure builders (JSON-LD serializer, sitemap XML, isIndexable gate, ` |
| 8 | `**Layer:** L2 DOMAIN PRIMITIVE (core = pure, zero-dep). **Hard floor — never cut: JSON-LD XSS escaping** (the serializer must neutralize the` |
| 10 | `**Donors:** trance-shop (escapes `<>&U+2028/2029`), ForumZone (escapes `</script`,`<!--`; cleanest `isIndexable` `indexable.ts:26-38`, `getC` |
| 18 | `3. **Security-union serializer** (like search's tsquery sanitizer): `serializeJsonLd` = `JSON.stringify(obj)` then escape **every** `<`→`<`,` |
| 36 | `- **`seo/gate`** — `isIndexable(tenant, node, thread?)` typed interface (ForumZone ref) + `robotsValue(indexable)`. Host extends inputs.` |
| 58 | `- [ ] `src/jsonld.ts`: `serializeJsonLd(obj)` = `JSON.stringify(obj)` then escape **every** `<`→`<`, `>`→`>`, `&`→`&`, `U+2028`→` `, `U+2029` |
| 59 | `- [ ] **Tests:** a payload with `</script>`, `</SCRIPT>` (case variant), `< /script`, `<!--`, `&`, U+2028, U+2029 → **all** neutralized (ass` |
| 73 | `## WATCH / out of scope (census discipline)` |
| 74 | `- **og-image Satori pipeline** (ForumZone-only, 1-donor) → `seo/og-image` on consumer #2 (would peer `@platform-modules/uploads`/image webp)` |
| 78 | `**Security floor in-plan** — `serializeJsonLd` is a required task escaping the full union (`<>&U+2028/2029` + `</script`/`<!--`), with a reg` |

### `docs/specs/2026-06-17-record-store-module-boundaries.md` (10 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**BLUF.** `record-store` is a host-pluggable, append-and-query **immutable record log**: `append(record)` + keyset-paginated `list()`, behin` |
| 11 | `- **Trigger = forward-need likelihood, not donor count.** A durable "append a structured record, list it back newest-first" store is broadly` |
| 12 | `- **In-repo evidence the shape recurs (3×) — but as cousins, not one contract:** `audit.listAudit` (keyset by `(createdAt,id)`), `jobs` outb` |
| 13 | `- **Build now, freeze later (both north-star rules, simultaneously):** stand the package up now on the mail consumer, but the contract ships` |
| 59 | `**Reader/mutation extension — `RecordStoreAdmin` is DEFERRED, not built in these waves (YAGNI).** The mail-capture admin surface (donor `ema` |
| 62 | `// PLANNED — built at consumer #1 (multideal admin), NOT in these waves:` |
| 78 | `- **Canonicalization:** inject a **deliberately non-canonical `now()`** (no-millis `…:00Z` and offset `…+02:00`); assert every backend retur` |
| 86 | `\| D1-native \| `makeD1RecordStore<T>(d1, table, opts?)` \| L1 \| raw CF D1 (`D1Database` type-only peer). Table `(seq INTEGER PRIMARY KEY A` |
| 125 | `- **Persistent dev/preview capture** (multideal's deployed worker) = the **same** `makeCaptureAdapter`, over a **D1** store the host builds ` |
| 146 | `Ship `0.x`. **Freeze `RecordStore<T>` to `1.0` only when a non-donor app** (not multideal, not another donor) adopts it and the `append`/`li` |

### `docs/specs/2026-06-18-ui-editor-primitive-boundaries.md` (10 hits)

| Line | Offending substring |
|------|-------------------|
| 4 | `**Status:** **BUILT** (2026-06-18, owner "build all waves" de-gate). Serialization resolved = **HTML string** (§3 recommended default — matc` |
| 6 | `**Source:** reference CMS gap §2A (the Gutenberg/rich-text editor — #1 reference CMS-parity gap). Census: `docs/catalog/2026-06-17-multideal` |
| 12 | `A headless-with-default-toolbar rich-text editor. Generic (`value/onChange/dir/aria-label` + swappable extensions). NOT `content/blocks` (KI` |
| 14 | `## 1. Contract (donor-proven signature)` |
| 19 | `dir?: 'ltr' \| 'rtl'                    // RTL-capable (donor is RTL-first)` |
| 26 | `Default extension set (donor-proven, ~25KB gz, no StarterKit): `Document, Paragraph, Text, History, Bold, Italic, Heading(H2), BulletList, L` |
| 30 | `- peerDeps (adopter-supplied): `react`, `react-dom`, `@tiptap/react` + the individual `@tiptap/extension-*` packages, `tiptap-text-direction` |
| 34 | `**RESOLVED 2026-06-18:** serialization = **HTML string** (the recommended default below). `content-react` (first consumer) binds `RichTextEd` |
| 36 | `The donor is **internally inconsistent**: Tiptap-**HTML** (`editor.getHTML()`) for deal content, markdown-**`<textarea>`** for KB articles. ` |
| 38 | `**Decision rule:** the FIRST real consuming screen picks serialization. **Recommended default = HTML string** — it matches `@platform-module` |

### `docs/plans/2026-06-14-realtime-server-module.md` (9 hits)

| Line | Offending substring |
|------|-------------------|
| 12 | `**Donors:** zync (`TenantRealtimeDO.ts` tags + `getWebSockets(userId)` scoped fan-out + `publish.ts` + `queues/realtime.ts` ack/retry), Foru` |
| 18 | `1. **Helper functions over `DurableObjectState`, NOT `abstract class BaseDurableRoom`** (design §2). The CF runtime *already* forces the hos` |
| 19 | `2. **Two distinct types, kept separate** (design §3): `RealtimeEvent` (producer→queue→DO transport; module owns `id`/`timestamp`/`scope`/`ta` |
| 30 | `- **Gate 3:** `apps/consumer` fake DO + a `cloudflare:workers` stub (ForumZone's 22-line DO stub): broadcast reaches both sockets; `targetTa` |
| 38 | `- `publishEvent(queue, event)` — stamp `id`+`timestamp`, fire-and-forget to a CF `Queue`, never mutates the caller's object (zync `publish.t` |
| 39 | `- `acceptHibernatable(ctx, ws, opts?)` — hibernatable accept; supports **both** `{tags}` (zync user-scoping) and `{attachment}` (ForumZone r` |
| 40 | `- `broadcastFrame(ctx, frame, opts?)` — `getWebSockets` → safe send (ignore closed). Bare loop = the 2-donor convergence; `targetTag` = zync` |
| 43 | `- `computeOffline(participantIds, online)` — presence helper, **1-donor (ForumZone)**, ~3 lines, mechanism-agnostic.` |
| 75 | `## Out of scope (census discipline)` |

### `docs/plans/2026-06-14-tenancy-module.md` (9 hits)

| Line | Offending substring |
|------|-------------------|
| 6 | `**Goal:** Ship `@platform-modules/tenancy` — a typed **seam** over genuinely-divergent multi-tenant impls: a **structural isolation boundary` |
| 10 | `**Donors:** zync.is (RBAC **triad** + lint-enforced shared-DB `tenant_id` — the superset, informs the defaults), ForumZone (`users.role` fla` |
| 26 | `- **Gate 1 (delete-test) — decisive on the seam:** delete tenancy → every multi-tenant app re-rolls tenant/membership tables, the capability` |
| 36 | `- `Tenant`, `Membership` (status `active\|frozen\|pending_approval` — zync superset), `TenantStatus`/`MembershipStatus`, `TenancyError` hier` |
| 89 | `- [ ] `src/rbac-triad.ts`: Drizzle `roles`/`permissions`/`role_permissions` schema (engine-owned, not core) + seeded system roles (`OWNER`/`` |
| 94 | `- [ ] `src/rbac-flat.ts`: `createFlatRbac(roleMap: Record<string, string[]>) → { resolveCapabilities }` — a static `role → capabilities` map` |
| 106 | `- **`isolation-connection`** (DEFERRED WATCH ×1) — per-tenant `connectionStr`/Hyperdrive routing (ForumZone `tenant-resolver.ts:34-58`). Add` |
| 110 | `## Out of scope (census discipline)` |
| 118 | `**Seam firm, shapes soft** — core is contract-only, every concrete RBAC/isolation shape is an adapter (matches the spec disposition, census ` |

### `.claude/skills/platform-make-modules/SKILL.md` (8 hits)

| Line | Offending substring |
|------|-------------------|
| 3 | `description: "Create a NET-NEW @platform-modules/* module from scratch — for a capability that does NOT already exist in any donor app. ALWA` |
| 10 | `Build module **from scratch** — only for capability that genuinely not exist anywhere in donor apps. Platform code *mostly ported* (that `/p` |
| 16 | `Before design or write one line, prove capability **not already implemented in any donor**. Reinventing what donor already battle-tested = m` |
| 19 | `2. **Census donors** — run read-only **`cursor`** census across donor repos (multideal, zync, fewtok, trance-shop, forumzone, press.zone, co` |
| 21 | `- **Found in ≥1 donor → STOP.** Not from-scratch job. Switch to **`/platform-extract-modules`** — port it; even one donor = starting impl, s` |
| 24 | `"Found it — routing to extract" outcome = gate **succeeding**, not failing.` |
| 30 | `- **Gate 0 (candidate rubric)** + **Gate 1 (delete-test keystone)** — `docs/plans/module-plan-template.md`. Copy template, fill gates honest` |
| 55 | `- **R2 / R3 (§3)** — even with no donor: no identity ceremony (R2 — factory that returns its input is a type), and memoize expensive natives` |

### `docs/plans/2026-06-14-billing-module.md` (8 hits)

| Line | Offending substring |
|------|-------------------|
| 4 | `> **Source of truth:** `docs/specs/2026-06-14-billing-module-boundaries.md` (census-grounded: thin money-seam over a Stripe-vs-Sumit adapter` |
| 10 | `**Donors (census 2026-06-14):** multideal/Stripe (`stripe-provider.ts:67-140` charge, `:458-468` refund, `webhook.ts:68/:77-88` verify+dedup` |
| 50 | `- **Backlog:** `billing/payplus`, `billing/paddle`, `billing/subscriptions` (recurring lifecycle, 1-donor external-engine).` |
| 75 | `- [ ] `src/index.ts`: `PaymentProvider` interface; `DedupStore` interface (`claim(eventId)→'won'\|'lost'` single-statement atomic, `markProc` |
| 81 | `- [ ] **Tests (faked Stripe SDK, no live keys):** charge maps req→PaymentIntent params with the idempotency key **(=chargeKey, asserted in t` |
| 96 | `- **`billing/subscriptions`** (1-donor, trance external-engine — recurring lifecycle, CIT/MIT token-on-file) · **`billing/payplus`** · **`bi` |
| 98 | `## Out of scope (census discipline)` |
| 102 | `**Gate-4 cross-check (2026-06-15) vs `docs/standards/money.md` M1–M8 — all six findings resolved in spec+plan before code:** (1/M5/M6) **web` |

### `docs/plans/2026-06-14-build-run-sheet.md` (8 hits)

| Line | Offending substring |
|------|-------------------|
| 23 | `\| 7 \| L2 \| `tax` \| ✅ \| by-need; Pattern C. shipped FF `31a2990` (7 commits). `tax/rates-table` = 2-donor self-compute VAT engine (axis=` |
| 24 | `\| 8 \| L2 \| `notifications` \| ✅ \| **security/data-loss floor** shipped FF `1542145` (9 commits + spec/plan amend `e09f38e`). Core = `not` |
| 25 | `\| 9 \| L2 \| `uploads` \| ✅ \| **dual hard-floor (content + authz)** shipped FF `5da6ef5` (6 commits) + Gate-4 spec/plan amend (`10db5d7`/`` |
| 26 | `\| 10 \| L2 \| `search` \| ✅ \| **dual security floor (injection + XSS) + federation seam** shipped FF `b1fb191` (7 commits, linear) + spec/` |
| 27 | `\| 11 \| L2 \| `seo` \| ✅ \| **XSS security floor + pure thin-scaffolding** shipped FF `075070c` (6 commits). NO provider axis; 6 zero-dep l` |
| 28 | `\| 12 \| L2 \| `ai` \| ✅ \| **no-cost census-discipline floor + thin provider-gateway** shipped FF `e163b6c` (7 commits, linear) + spec/plan` |
| 32 | `\| 16 \| L3 \| `helpdesk` \| ✅ \| **polymorphic-parent data-isolation floor + append-only audit trail** shipped FF `5a566e4` (8 commits). Th` |
| 37 | `- `ai-react` — gated on AI streaming (unbuilt). `invoicing`/`affiliate` — WATCH, 1-donor, no spec. `events`/`image`/`cache`/`audit` — DISSOL` |

### `docs/plans/2026-06-16-audit-module.md` (8 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**Module:** `@platform-modules/audit` · **Layer:** L2 · **Tier:** infra-leaf (domain primitive) · **Disposition:** EXTRACT (4 real donors: z` |
| 11 | `Bounded context (append-only actor/entity/action log) · narrow stable interface (`logAudit` + `listAudit`) · owns its own table (`audit_log`` |
| 15 | `- **Disappears from N apps:** the `audit_log` table + its 3 scaling indexes + the keyset-pagination `listAudit` query + the never-throw writ` |
| 31 | `1. **Never-throw (CONTRACT):** `logAudit` MUST NOT throw into the caller's business mutation. Audit failure is swallowed → `{ logged: false ` |
| 42 | `- `listAudit<S>(db: Querier<S>, filter?: ListAuditFilter): Promise<ListAuditResult>` — **keyset/cursor pagination** (zync `audit-list.ts:76`` |
| 43 | `- **Table `audit_log`** (4-donor consensus, open-string): `id` uuid pk · `actor_id` text **nullable** (null = system/AI) · `actor_type` text` |
| 44 | `- **Indexes (ship the GOOD ones — zync/ForumZone, NOT multideal's zero):** `(tenant_id, created_at DESC)` · `(tenant_id, entity_type, entity` |
| 45 | `- **Three axes:** Adapter = none. Capability = none built (diff/redact/retention/queue-sink all WATCH = 1-donor, register nothing — each is ` |

### `docs/plans/2026-06-14-search-module.md` (7 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `> **Amended 2026-06-15 (pre-build census):** `util/pagination` **dropped** (no leaf; cursor codec lives in `search`); provider contract gain` |
| 12 | `**Donors:** zync (14-entity federation, `buildTsquery` sanitize, push-down `{entityType,offset}` cursor honored **single-type only**, per-en` |
| 20 | `3. **FTS helpers split to `util`, NOT search** (build-order prerequisite): `util/fts/{sanitize-tsquery [security], safe-headline [XSS], rank` |
| 26 | `- **Gate 1 (keystone):** delete search → the federation loop (5/5 hand-roll it + reinvent the injection/XSS bugs), the safe-tsquery builder,` |
| 56 | `- [ ] In `@platform-modules/util` (its own worktree/plan — util backlog `:115`): add `util/fts/sanitize-tsquery` (the **security** sanitizer` |
| 75 | `## WATCH / out of scope (census discipline)` |
| 81 | `**No phantom adapter axis** — all donors Postgres, so the module is a seam + util leaves, not an engine (the spec's sharpest finding honored` |

### `docs/plans/2026-06-17-mod-cms-program-runsheet.md` (7 hits)

| Line | Offending substring |
|------|-------------------|
| 19 | `Public-language law: the preview is a maximally-public product — zero internal vocab (donor/seam/harvest/layer) or donor app names in anythi` |
| 64 | `4. **Plan + build #3**: content-react (harvest multideal; needs ui-primitives).` |
| 67 | `Dispatch policy: `platform-orchestrator` skill (census/build = cursor foreground via `~/.claude/skills/cursor-orchestrator/ca.sh`; per-diff ` |
| 79 | `\| `@platform-modules/ui-editor` (Tiptap primitive; `aria-label` REQUIRED a11y floor) \| `566531b` \| donor-proven, jsdom-testable w/o app c` |
| 87 | `\| `comments-react` \| **consumer-gated** \| a comments thread/mod-tools screen (blueprint or admin template) — donor FZ \|` |
| 88 | `\| `uploads-react` \| **HARD-BLOCKED on a seam** \| `StorageAdapter` seam in `uploads` first (R2-locked: everything past multipart POST is C` |
| 93 | `\| importables: `content/{revisions,menus,settings,fields,migrate,privacy}` · `util/{oembed,avatar}` \| **on-demand (R5)** \| a blueprint co` |

### `docs/plans/2026-06-18-mod-cms-v0.0.2-build-runsheet.md` (7 hits)

| Line | Offending substring |
|------|-------------------|
| 21 | `1. ★ **Census** (only if net-new + donor may exist): check `docs/catalog/index.md` freshness first; if stale/missing, dispatch **cursor cens` |
| 40 | `\| **0** \| specs + donor-screen census refresh \| — \| — \| — (judgment) \|` |
| 41 | `\| **1a** \| **theme-engine** on `ui-tokens` (contract + active-theme resolver + override layer) \| ui-tokens \| tools/ smoke + consumer \| ` |
| 42 | `\| **1b** \| ui-primitives **data/form set**: Input·Field·Select·Checkbox·Radio·Switch · Table·DataList·Pagination \| ui-primitives \| apps/` |
| 43 | `\| **1c** \| ui-primitives **chrome set**: DashboardShell · ErrorState · Calendar · ColorPicker · FontPicker · Toast · Badge · DropdownMenu ` |
| 64 | `- **templates**: host-owned screen specs (admin-dashboard first) — `/platform-make-template` scan-gate against `docs/catalog/2026-06-17-scre` |
| 66 | `**Census check first (Wave 0):** verify `docs/catalog/index.md` freshness for the screen-flow + UI donor census; lazy-refresh only stale don` |

### `docs/plans/module-plan-template.md` (7 hits)

| Line | Offending substring |
|------|-------------------|
| 10 | `Score against `platform-extract-modules` §1. Bounded context · narrow stable interface · owns its own data · low host coupling · external ca` |
| 12 | `**Forward-need override (CLAUDE.md §3 disposition):** the `3+ duplication` bar is a floor signal, not a hard gate — a *foundational* capabil` |
| 50 | `- A module is not "done" until its harness fixture catches broken exports/types/runtime-integration. This is the formalization of `platform-` |
| 57 | `- **Primary — the digested standards** (`docs/standards/money.md` · `docs/standards/authz.md`): the universal, provider-agnostic invariants ` |
| 58 | `- **Provenance — the raw audits** (consult to confirm a rule's origin or catch a *module-specific* finding the standards don't generalize): ` |
| 62 | `- A mapped finding **absent** from the spec = a spec gap → **kick back and amend the spec before porting** (the spec-first kickback, `CLAUDE` |
| 71 | `- **The three axes of variation** (canonical classification — both `platform-extract-modules` and `platform-make-modules` point here; classi` |

### `docs/specs/2026-06-18-mod-cms-v0.0.2-design.md` (7 hits)

| Line | Offending substring |
|------|-------------------|
| 9 | `**The shell is a PRIMITIVE, not host glue (corrected 2026-06-18).** A dashboard shell (sidebar + topbar + content slot) is **role-agnostic**` |
| 32 | `\| Menus / navigation builder \| no backing module; donor-convergent but YAGNI now \| later \|` |
| 33 | `\| Analytics / metrics dashboard \| needs a metrics source; donor shape is M-maturity \| later \|` |
| 45 | `- **`DashboardShell`** — layout primitive: `<Sidebar>` (nav slot, collapsible) + `<Topbar>` (title/actions slot) + main content slot. **Pure` |
| 79 | `- **Donor shape (de-named, public-language law):** multideal = shell/nav + data-table CRUD; trance-shop-israel = settings/metrics breadth (c` |
| 150 | `Everything the admin UI renders — labels, nav, help text, the login screen, docs — is maximally public: zero internal vocab (donor/seam/harv` |
| 165 | `- `DashboardShell` baked INTO the admin template (host-owned chrome) — REJECTED (the original spec's error). A shell that only the admin use` |

### `docs/standards/money.md` (7 hits)

| Line | Offending substring |
|------|-------------------|
| 3 | `> **Read before porting or writing any code that moves money** — a charge, refund, payout release, or payment-provider webhook handler. Appl` |
| 7 | `These invariants are **provider-agnostic** — true for Stripe, PayPlus, Sumit, Tranzila, any PSP. They are not one donor's shape; they are ho` |
| 26 | `Pair it with a **resolution short-circuit**: if a settled resolution already exists, the operation is a no-op (idempotent re-entry). Multide` |
| 34 | `If phase 2 fails, release the claim (`releaseRefundClaim` — revert the phase-1 state) and enqueue a retry. The retry handler is **itself** c` |
| 56 | `This is the subtle one — and the discriminator is the **failure point**, not whether the handler is idempotent overall. The multideal Opus g` |
| 67 | `Every minor-unit→display conversion uses the module's money formatter (`formatAgorot`/`formatILS` and friends), never an inline `(amountCent` |
| 83 | `An audit-hardened money export is not done until it carries the donor's executable security test (`secaudit-*` — multideal `tests/e2e/secaud` |

### `docs/specs/2026-06-17-comments-module-boundaries.md` (6 hits)

| Line | Offending substring |
|------|-------------------|
| 5 | `**BLUF.** `comments` is a generic, host-pluggable **threaded-comment store**: attach moderated, optionally-threaded comments to **any entity` |
| 12 | `- **Donor evidence (×1, generalize — do NOT port as-is):** ForumZone `posts` (self-ref `parentId`, depth-computed-on-read, N+1-avoided autho` |
| 13 | `- **Convergence>count — the moderation seam split (ledger #15):** comment *thread store/display* = ×1 (FZ). *Moderation/spam heuristics* = a` |
| 14 | `- **Build now, freeze later:** stand the package up now; ship `0.x` provisional; freeze (`1.0`) only when a **non-donor** app confirms the s` |
| 162 | `The ×2–3 moderation engine (multideal AI-rules+KB, FZ KB) sits on a **distinct composable seam**, never as optional methods on the core (an ` |
| 187 | `Ship `0.x`. Freeze `Comment*` contract to `1.0` only when a **non-donor** app (not multideal, not ForumZone) adopts it and the verb/type sha` |

### `docs/standards/authz.md` (6 hits)

| Line | Offending substring |
|------|-------------------|
| 3 | `> **Read before writing or porting any endpoint that reads or mutates a resource a caller might not own** — i.e. essentially every server ex` |
| 9 | `These invariants are universal authorization correctness — provider- and product-agnostic. They were paid for by the multideal converged aud` |
| 23 | `Resolve through the role-aware loader where one exists (multideal `requireCase` → `determineCaseRole` resolves customer / vendor-on-case / a` |
| 42 | `A "public" read enforces its visibility predicate in the query, not in handler branching that can be bypassed by a sibling code path. `findB` |
| 48 | `An audit-hardened authz export is not done until it carries the donor's `secaudit-*` authz test (multideal `tests/e2e/secaudit-attach-authz.` |
| 52 | `The 5-wave converged loop was internally consistent yet had a blind spot it kept missing; an independent fresh-eyes pass with a *different m` |

### `.claude/skills/platform-embed-module/SKILL.md` (5 hits)

| Line | Offending substring |
|------|-------------------|
| 17 | `Third verb in module lifecycle: **`platform-extract-modules`** (donor → module) · **`platform-make-modules`** (net-new module) · **embed** (` |
| 117 | `3. **Swap-survival parity** — assert module's output **equals** host's old hand-rolled output on host's real inputs (e.g. `serializeJsonLd(x` |
| 146 | `### host-constant-extraction-no-module-type \| fired:1 \| 2026-06-16` |
| 147 | `Wave spec added `import type { IanaTimezone }` + type annotation to host-side constant extraction (no module function called, no IANA picker` |
| 148 | `Prevent: if wave is pure host-side constant extraction (no new module function calls), spec must NOT add module type import. Plain `export c` |

### `docs/plans/2026-06-17-mod-www-phase-1-instance-handbuild.md` (5 hits)

| Line | Offending substring |
|------|-------------------|
| 7 | `**Goal:** Hand-build `mod-www` — the first `content-site` **instance** — as a real deployed FOSS-project site, proving the Phase-0 UI founda` |
| 628 | `- [ ] **Step 1: `src/data/site.ts`** — features list (for FeatureGrid), nav, social links. Public-language ONLY: NO "donor"/"seam"/"layer"/"` |
| 631 | `- [ ] **Step 4: Public-language grep gate** — `grep -riE 'donor\|harvest\|seam\|layer DAG\|multideal\|zync\|forumzone\|press\.zone\|trance-s` |
| 808 | `- [ ] **Step 6: Update platform docs** — in the monorepo: mark Phase 1 complete in this plan + the program design-doc §9 status; note the li` |
| 815 | `- **Public-language law (HARD):** nothing rendered/shipped carries internal vocab (donor/seam/layer/harvest) or source-app names — this is a` |

### `docs/specs/2026-06-17-mod-cms-program-design.md` (5 hits)

| Line | Offending substring |
|------|-------------------|
| 13 | `**This doc specs the PROGRAM decomposition + goes deep on sub-project #1 only.** The stack — net-new module + blueprint + two distributions ` |
| 50 | `**`content` is the ONLY net-new module this whole program builds.** Everything else composes shipped modules (`seo` metadata · `uploads` med` |
| 53 | `- **Make-with-harvest, NOT clean extract** (wasp-map §5A.1): build the corpus seam thin + net-new; harvest the *editor* (`RichTextEditor`/`P` |
| 139 | `Coupled installable reference-CMS parity: `mod-cms` + dynamic SSR public renderer (reads published entries from db at request, edge-cached p` |
| 173 | `- **Comments disposition (§5.3)** — standalone `@platform-modules/comments` vs mod-press-internal: open, decided at P4 with a census (commen` |

### `docs/specs/2026-06-18-content-react-boundaries.md` (5 hits)

| Line | Offending substring |
|------|-------------------|
| 39 | `useAutosave(save, value, opts?): { state: 'idle'\|'saving'\|'saved'\|'error' }   // donor pattern, endpoint→injected save` |
| 43 | `- Autosave state machine = donor-proven (`idle\|saving\|saved\|error`), endpoint→injected `save`.` |
| 44 | `- Slug field: donor has NO auto-slug-from-title → add it here as a generic util (`ui-util` candidate) IF the consumer wants it.` |
| 45 | `- SEO meta fields: donor has NONE → net-new when a blueprint needs them.` |
| 55 | `**Build scope NOW (real-regardless):** `ContentClient` interface + `useContentList`/`useContentEntry`/`useAutosave` (donor-proven state mach` |

### `.claude/agents/seam-reviewer.md` (4 hits)

| Line | Offending substring |
|------|-------------------|
| 4 | `Per-diff adversarial reviewer for @platform-modules/* ports. Dispatch after cursor builds a module (or a wave of tasks) to judge the diff IN` |
| 12 | `- The project `CLAUDE.md` (shared law: the §2 ladder, R1/R2/R3 porting hazards, the §4 seam checklist pointer, conventions, spec-first). You` |
| 21 | `4. **R1–R3 porting hazards** — R1 donor default baked at a seam; R2 identity factory returning its input; R3 expensive native (`new Intl.*`/` |
| 22 | `4b. **R4 preserve-hardened (§5.1)** — for a donor path the boundary spec marks **audit-hardened**, the body must be ported byte-faithfully (` |

### `docs/plans/2026-06-12-i18n-module-pilot.md` (4 hits)

| Line | Offending substring |
|------|-------------------|
| 756 | `## Wave 6 — R5 harvest extension (added 2026-06-15)` |
| 758 | `**Goal:** harvest the four under-harvested generic capabilities into importable subpaths (spec: `docs/specs/2026-06-12-i18n-module-pilot-des` |
| 764 | `### Task 7: i18n core harvest — nested keys + `/loader` `/pick` `/zod`` |
| 775 | `### Task 8: i18n-react harvest — namespaced memoized `useT`, `/store`, hydration parity, `DirectionProvider`` |

### `docs/plans/2026-06-14-db-module.md` (4 hits)

| Line | Offending substring |
|------|-------------------|
| 6 | `**Goal:** Ship `@platform-modules/db` — a **TYPE CONTRACT**, not a connection helper. Its entire value: make transaction-capability visible ` |
| 10 | `**Donors:** multideal (neon-serverless, the `Querier` union), zync (postgres-js), ForumZone (neon-http + the footgun, live), trance-shop (ne` |
| 95 | `## Out of scope (census discipline — spec §WATCH)` |
| 98 | `- **Raw `pg` `BEGIN/COMMIT`** (trance-shop ticketing) — donor anti-pattern, not ported.` |

### `docs/plans/2026-06-14-mail-module.md` (4 hits)

| Line | Offending substring |
|------|-------------------|
| 10 | `**Donors (7 projects send mail):** zync.is `notifications/src/email/ → sendEmail(opts, env)` (resend, locale-aware), ForumZone `providers/sr` |
| 29 | `- Types: `MailMessage { from; to; replyTo?; cc?; bcc?; subject; html?; text?; headers?; tags?; idempotencyKey? }`, `MailResult { id; provide` |
| 69 | `### Task 3 — `resend` adapter (subpath, peer `resend`) — priority 1 (most common donor)` |
| 97 | `## Out of scope (census discipline)` |

### `docs/plans/2026-06-14-notifications-module.md` (4 hits)

| Line | Offending substring |
|------|-------------------|
| 10 | `**Donors:** zync.is `packages/notifications` — already runs email + telegram + webpush + ws-push under one `deliver()` seam with channel ada` |
| 81 | `- [ ] `src/webpush.ts`: a `WebPushChannel` adapter — VAPID ES256 JWT via Web-Crypto, **real RFC 8291 `aes128gcm` payload encryption** (ECDH-` |
| 83 | `- [ ] **DONOR HAZARD — verify, do not copy blind:** zync `web-push/vapid.ts:123` calls `crypto.subtle.deriveBits({ name: 'ECDH', $public: cl` |
| 98 | `## Out of scope (census discipline)` |

### `docs/plans/2026-06-16-cache-module.md` (4 hits)

| Line | Offending substring |
|------|-------------------|
| 11 | `Bounded context (keyed value cache) · narrow stable interface (`get/set/del/getOrSet`) · owns its data (the keyspace) · low host coupling (w` |
| 15 | `- **What disappears in the apps:** the hand-rolled read-through (`read → miss → load → write`) all 4 donors duplicate inline, **and the sing` |
| 16 | `- **What cannot move in (stays host):** epoch invalidation (multideal `CacheEpochDO`, domain-coupled), scope/tag purge, DB-materialized aggr` |
| 77 | `- `src/redis.ts` — `createRedisBackend(client: Redis): CacheBackend`. `import type { Redis } from 'ioredis'` (optional peer). `get` null → u` |

### `.gitignore` (3 hits)

| Line | Offending substring |
|------|-------------------|
| 76 | `# Donor / extraction provenance — owner-PRIVATE, NEVER in github.` |
| 77 | `# All donor-app names + extraction-process records (census/bestDonor/harvest/` |
| 78 | `# verified_by/donor notes) live under .provenance/, gitignored. The tracked` |

### `AGENTS.md` (2 hits)

| Line | Offending substring |
|------|-------------------|
| 10 | `3. `docs/standards/coding-standard.md` — the §2 ladder, R1/R2/R3 porting hazards, the §4 seam checklist, §6 `-react` packaging.` |
| 16 | `**Audit-hardened donor code (coding-standard §5.1 / R4):** when the boundary spec marks a donor path **audit-hardened** (money · refund · we` |

### `.claude/skills/platform-make-distro/SKILL.md` (1 hits)

| Line | Offending substring |
|------|-------------------|
| 53 | `- **Public-language law (hard):** an installable product is maximally public — zero internal vocab (harvesting/donor/seam/layer) or source-a` |

---

## INCIDENTAL

One or two stray mentions in otherwise-clean files. Candidates for simple line-edits rather than file moves.

| File | Line | Offending substring |
|------|------|-------------------|
| `packages/tax/src/rates-table/vat-math.test.ts` | 5 | `/** zync `ROUND(net * rate, 2)` with rate as decimal fraction in agorot. */` |
| `packages/tax/src/rates-table/vat-math.test.ts` | 6 | `function zyncExclusiveVat(netAgorot: bigint, rateFraction: string): bigint {` |
| `packages/tax/src/rates-table/vat-math.test.ts` | 14 | `/** multideal `Math.round(gross * pct / (100 + pct))` in agorot. */` |
| `packages/tax/src/rates-table/vat-math.test.ts` | 15 | `function multidealInclusiveVat(grossAgorot: bigint, ratePercent: number): bigint {` |
| `packages/tax/src/rates-table/vat-math.test.ts` | 23 | `it('matches zync hand-computed agorot for known net amounts', () => {` |
| `packages/tax/src/rates-table/vat-math.test.ts` | 27 | `expect(vat).toBe(zyncExclusiveVat(net, '0.17'))` |
| `packages/tax/src/rates-table/vat-math.test.ts` | 55 | `it('matches multideal round(gross×pct/(100+pct)) for known gross amounts', () => {` |
| `packages/tax/src/rates-table/vat-math.test.ts` | 59 | `expect(vat).toBe(multidealInclusiveVat(gross, 17))` |
| `packages/tax/src/rates-table/vat-math.test.ts` | 82 | `const extracted = extractVat(applied.gross, rate)` |
| `packages/tax/src/rates-table/vat-math.test.ts` | 83 | `expect(extracted.net).toBe(net)` |
| `docs/plans/2026-06-14-marketing-module.md` | 10 | `**Donors (grep census across ~13 web projects):** trance-shop (`api/admin/newsletter/[id].ts`, `subscriptions/email.ts`,` |
| `docs/plans/2026-06-14-marketing-module.md` | 104 | `## Out of scope (census discipline)` |
| `docs/plans/2026-06-14-marketing-module.md` | 108 | `**Compliance floor in-plan** — double-opt-in (default-on IL/EU), suppression/consent-enforced `sendCampaign` (refuses su` |
| `docs/plans/2026-06-17-content-module.md` | 18 | `- **3+ duplication: NO** (×0–1 donors; multideal has page-builder primitives, not a corpus). → **Forward-need override (` |
| `docs/plans/2026-06-17-content-module.md` | 536 | `* Capability-based actor — NO role model baked in (R1: no donor defaults). The distribution's` |
| `docs/plans/2026-06-17-content-module.md` | 1375 | `- `content-react` author/reader components → **P2** (editor harvested from multideal; needs `mod-ui` + `-react` siblings` |
| `docs/plans/2026-06-17-mod-www-phase-3-create-scaffolder.md` | 3 | `> **STATUS: phase OUTLINE, not an executable plan.** The scaffolder is extracted *from* the green Phase-2 blueprint — it` |
| `docs/plans/2026-06-17-mod-www-phase-3-create-scaffolder.md` | 5 | `**Goal:** Extract a **minimal** scaffolder, `create` v0.0.1, that reads the in-monorepo `content-site` blueprint recipe ` |
| `docs/plans/2026-06-17-mod-www-phase-3-create-scaffolder.md` | 15 | `- [ ] **Phase 2 green** — `content-site` blueprint extracted, catalogued, composition-harness green. `create` has nothin` |
| `docs/plans/2026-06-18-mod-cms-v0.0.2-admin-dashboard.md` | 201 | `Export `EditorExtensionConfig` (type) and `defaultExtensions()` returning the donor-proven set (`Document, Paragraph, Te` |
| `docs/plans/2026-06-18-mod-cms-v0.0.2-admin-dashboard.md` | 674 | `- [ ] **Step 3: Implement the React screens** — `AdminApp` wraps `SessionProvider` (auth-react) with `makeAuthClient()`;` |
| `docs/plans/2026-06-18-mod-cms-v0.0.2-admin-dashboard.md` | 678 | `- [ ] **Step 5: Public-language audit** — grep the new admin files for internal vocab (`donor\|seam\|harvest\|layer\|mul` |
| `docs/specs/2026-06-16-ui-moat-spike-result.md` | 5 | `**Verdict:** **Mechanism works — slop matching authored rules is blocked at two independent layers (slopgate edit-time A` |
| `docs/specs/2026-06-16-ui-moat-spike-result.md` | 12 | `Throwaway dir `/tmp/ui-moat-spike` (deleted after). Used the **real `slopgate init` flow** (no schema guessing) against ` |
| `docs/specs/2026-06-16-ui-moat-spike-result.md` | 57 | `**False-positive measurement (folds in here — the spike's "zero false positives" verdict above was from a hand-written c` |
| `docs/specs/mod-ui-enforcement/tokens.ts` | 9 | `// recur across design systems, NOT one donor's bespoke palette. First-cut; the` |
| `docs/specs/mod-ui-enforcement/tokens.ts` | 10 | `// exact members are revisable until a non-donor consumer freezes the contract` |
| `docs/specs/mod-ui-enforcement/tokens.ts` | 11 | `// (R5 freeze-rule). Donor-specific roles (vendor-green, glass, countdown) stay` |
| `apps/consumer/src/blueprints/marketplace/wiring/split.ts` | 5 | `* community) owns. Per the extract skill (§2 axes), "marketplace splits = DOMAIN" — your product's` |
| `apps/consumer/src/blueprints/marketplace/wiring/split.ts` | 10 | `* TWO ALTITUDES of split (a real architectural nuance the donor billing code proves):` |
| `docs/plans/2026-06-17-mod-www-phase-0-ui-foundation.md` | 450 | `Expected: locate the `i18n` module object (L0, status `shipped`). Read its surrounding object to copy the exact field sh` |
| `docs/plans/2026-06-17-mod-www-phase-0-ui-foundation.md` | 461 | `- a `_note` (or the entry's census/note field): `"themeless token contract (typed unions lifted from mod-ui-enforcement/` |
| `docs/specs/2026-06-18-comments-moderation-boundaries.md` | 6 | `**Source:** comments spec §6 (NAMED, not built) `docs/specs/2026-06-17-comments-module-boundaries.md`; reference CMS gap` |
| `docs/specs/2026-06-18-comments-moderation-boundaries.md` | 24 | `Promise<{ status: Extract<CommentStatus, 'published' \| 'pending' \| 'spam'>; reason?: string }>` |
| `docs/triage/2026-06-16-multideal-test-rot-triage.md` | 344 | `**RESOLUTION (2026-06-17, commit `408a0cacb`):** harness fixed — `tests/setup.ts` `setBundles({he,en})` + `tests/helpers` |
| `docs/triage/2026-06-16-multideal-test-rot-triage.md` | 349 | `**NEW pre-existing failure (census-missed, 2026-06-17):** `tests/components/onboarding/BirthdayField.test.tsx` — renders` |
| `docs/viz/vendor/three.module.js` | 8077 | `// extract data from the cache hash` |
| `docs/viz/vendor/three.module.js` | 22022 | `// extract local rotation of light to derive width/height half vectors` |
| `docs/viz/viz/vendor/three.module.js` | 8077 | `// extract data from the cache hash` |
| `docs/viz/viz/vendor/three.module.js` | 22022 | `// extract local rotation of light to derive width/height half vectors` |
| `packages/realtime-react/src/index.tsx` | 140 | `/** Extract the online-id list from a presence frame. Default reads a string[] `online` field. */` |
| `packages/realtime-react/src/index.tsx` | 160 | `* Presence is a 1-donor (ForumZone) convention, so the frame `type` and the roster` |
| `packages/realtime/src/index.ts` | 31 | `* its own `type` union + fields. (ForumZone already versions its frames `v:1`; zync did not` |
| `packages/realtime/src/index.ts` | 32 | `* — versioning here adopts the more forward-compatible donor as the seam default.)` |
| `packages/tax/src/rates-table/dataset.test.ts` | 6 | `* Canonical IL VAT history (zync `IL_VAT_RATES` donor) as `[date, bp]`.` |
| `packages/tax/src/rates-table/dataset.test.ts` | 32 | `it('ships all 18 Israeli Tax Authority history rows, byte-faithful to donor', () => {` |
| `packages/tax/src/rates-table/vat-math.ts` | 26 | `/** Exclusive (zync): VAT added to net; `gross = net + vat`. */` |
| `packages/tax/src/rates-table/vat-math.ts` | 36 | `/** Inclusive (multideal): VAT extracted from gross; `net = gross − vat`. */` |
| `packages/tenancy/src/rbac-flat.ts` | 3 | `/** Census-sourced ForumZone roles (packages/shared/src/validators/admin.ts). */` |
| `packages/tenancy/src/rbac-flat.ts` | 14 | `/** Census-sourced capability map (ForumZone packages/auth/src/permissions.ts). */` |
| `packages/util/src/timezone.ts` | 7 | `* neutral listing fallback, never a policy choice (ported from zync, whose Israel default is` |
| `packages/util/src/timezone.ts` | 8 | `* stripped as donor host-policy).` |
| `apps/consumer/src/blueprints/marketplace/recipe.md` | 78 | `## The split lives at TWO altitudes (a real architectural nuance, grounded in donor code)` |
| `apps/consumer/tests/blueprint-marketplace.test.ts` | 112 | `//    split (the split is domain, extract-skill §2). Real provider idempotency is the host's job via` |
| `docs/plans/2026-06-14-auth-react-module.md` | 44 | `## Out of scope (§6 + census)` |
| `docs/plans/2026-06-14-notifications-react-module.md` | 45 | `## Out of scope (§6 + census)` |
| `docs/plans/2026-06-14-search-react-module.md` | 43 | `## Out of scope (§6 + census)` |
| `docs/plans/2026-06-14-uploads-react-module.md` | 43 | `## Out of scope (§6 + census)` |
| `docs/specs/2026-06-13-consumer-harness.md` | 13 | `It is the formalization of `platform-extract-modules` §6 step 7 ("verify on one pilot consumer") into a **standing testb` |
| `docs/specs/2026-06-18-content-visibility-access-axis.md` | 6 | `**Source of need:** reference CMS parity gap — `docs/specs/2026-06-17-mod-cms-feature-gap-analysis.md` §2A/§5. reference` |
| `docs/specs/2026-06-18-emdash-competitive-gap-analysis.md` | 4 | `**Date:** 2026-06-18 · **Source:** `github.com/emdash-cms/emdash` README + package.json (fetched, indexed). Feature surf` |
| `docs/specs/2026-06-18-mod-cms-onboarding-install-design.md` | 30 | `**Why (researched, all three providers):** Vercel / Cloudflare / Netlify Deploy buttons **clone the ENTIRE source repo**` |
| `docs/specs/2026-06-18-theme-engine.md` | 186 | `- **Census-checked before authoring (R5 harvest-don't-invent):** `docs/catalog/2026-06-16-ui-donor-census.md` — 6/6 dono` |
| `docs/specs/mod-ui-enforcement/rules/ast/mod-ui-no-arbitrary-value.yml` | 5 | `note: '{"severity":"high","category":"convention","resolution":"Use a token-backed utility (p-2, bg-accent) from the @th` |
| `docs/specs/mod-ui-enforcement/rules/ast/mod-ui-no-inline-style.yml` | 5 | `note: '{"severity":"high","category":"convention","resolution":"Style via token-driven utility classes (Tailwind @theme)` |
| `packages/ai/src/anthropic.ts` | 46 | `.filter((b): b is Extract<AIContentBlock, { type: 'text' }> => b.type === 'text')` |
| `packages/ai/src/google.ts` | 50 | `.filter((b): b is Extract<AIContentBlock, { type: 'text' }> => b.type === 'text')` |
| `packages/ai/src/redact.test.ts` | 30 | `// One pseudo-id per entity (donor design): email + phone both collapse to {user_a}.` |
| `packages/auth/src/engine-better-auth.test.ts` | 103 | `cookiePrefix: 'forumzone',` |
| `packages/auth/src/engine-better-auth.ts` | 85 | `* ForumZone-shaped better-auth adapter.` |
| `packages/auth/src/engine-custom/session.ts` | 2 | `* Raw Web-Crypto HS256 session tokens — multideal `tokens.ts:87` form.` |
| `packages/billing/src/sumit.ts` | 361 | `// best-effort doc-cancel per donor` |
| `packages/comments/src/cursor.ts` | 3 | `* Ported from @platform-modules/record-store/src/cursor.ts (spec §4 record-store lesson).` |
| `packages/comments/src/moderation.ts` | 24 | `type ModeratableStatus = Extract<CommentStatus, 'published' \| 'pending' \| 'spam'>` |
| `packages/comments/src/store.ts` | 393 | `// Helper: extract CommentAuthor from a row (used for authz checks)` |
| `packages/content/src/authz.ts` | 2 | `* Capability-based actor — NO role model baked in (R1: no donor defaults). The distribution's` |
| `packages/jobs/src/cf-queues.ts` | 9 | `/** ForumZone-style name → binding map for many named queues. */` |
| `packages/jobs/src/index.ts` | 3 | `/** Type-discriminated job envelope — every donor keys dispatch on `type`. */` |
| `packages/ledger/src/types.ts` | 24 | `/** Host-owned balance column folded onto an existing domain row (ForumZone-style). */` |
| `packages/mail/src/index.ts` | 1 | `/** Bounce / complaint / unsubscribe webhook payload shape (ForumZone donor). */` |
| `packages/realtime/src/server.ts` | 27 | `/** Hibernatable accept. Supports BOTH donor mechanisms — host picks, module forces neither:` |
| `packages/seo/src/gate.ts` | 1 | `/** Host-extensible tenant visibility inputs (ForumZone indexable.ts shape). */` |
| `packages/seo/src/jsonld.test.ts` | 14 | `it('neutralizes the security-union XSS payload (escape-all beats donor subsets)', () => {` |
| `packages/tax/src/rates-table/dataset.ts` | 4 | `* Israel VAT rate history — byte-faithful port of zync `IL_VAT_RATES` seed.` |
| `packages/tenancy/src/index.ts` | 66 | `export type ScopedTenantOmitKeys<T extends Table, C extends string> = Extract<` |
| `packages/tenancy/src/rbac-triad.test.ts` | 105 | `it('matches the zync census system role set (spec excludes ACCOUNTANT)', () => {` |
| `packages/tenancy/src/rbac-triad.ts` | 47 | `/** Census-sourced from zync.is packages/db/src/seed/permission-keys.ts (spec excludes ACCOUNTANT). */` |
| `packages/ui-editor/src/extensions.ts` | 18 | `/** Donor-proven default set (no StarterKit). */` |
| `packages/util/src/datetime.test.ts` | 27 | `it('matches the multideal / trance-shop donor seam (en-CA YYYY-MM-DD in Asia/Jerusalem)', () => {` |
| `packages/util/src/datetime.ts` | 32 | `* Uses the donor-proven, pinned `en-CA` locale with explicit numeric fields → ISO order,` |
| `packages/util/src/fts/README.md` | 17 | `The module never owns host tables, so the schema below is a **host-side migration recipe** (from the ForumZone donor's m` |
| `packages/util/src/fts/rank.ts` | 3 | `/** Choose Postgres rank function — zync uses `ts_rank_cd`, ForumZone uses `ts_rank`. */` |
| `packages/util/src/fts/safe-headline.ts` | 22 | `* Ported from ForumZone `buildSafeHeadlineHtml`.` |
| `packages/util/src/fts/sanitize-tsquery.ts` | 6 | `* Ported from zync `buildTsquery` — strips metachars, AND-joins prefix tokens.` |

---

## Git history leak

Git commit history (subjects, bodies, and file paths recorded in the object store) contains donor names. A sampling of affected commit subjects includes direct references to `multideal`, `zync`, `forumzone`, `trance-shop`, `fewtok`, `vibeflare`, and `press.zone`. This is **out of scope for the file-level cleanup** above and requires a **history rewrite** (e.g. `git filter-repo --message-callback` or BFG Repo-Cleaner) before the repository can be made public. The entire history must be scrubbed and all collaborators must re-clone.

> Confirmed: `git log --oneline --all | grep -iE "(multideal|zync|forumzone|trance|fewtok|vibeflare|press.zone|tamlil)"` will enumerate the affected commits. Do not run this as part of file cleanup — it is a separate pre-go-public gate.
