@ai-matrx/associations 0.14.82 → 0.14.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -3
- package/dist/{CommentThread-RI-iPDmV.d.cts → CommentThread-CFL2rITA.d.cts} +6 -1
- package/dist/{CommentThread-RI-iPDmV.d.ts → CommentThread-CFL2rITA.d.ts} +6 -1
- package/dist/{chunk-server-Y4DGNHLP.js → chunk-server-D6HFGF2J.js} +1004 -15
- package/dist/chunk-server-D6HFGF2J.js.map +1 -0
- package/dist/core/index.cjs +27 -14
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/index.cjs +1003 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +988 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +988 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/lazy/index.d.cts +1 -1
- package/dist/react/lazy/index.d.ts +1 -1
- package/dist/{results-Du0dzBb4.d.cts → results-BtyDwTD6.d.cts} +117 -16
- package/dist/{results-Du0dzBb4.d.ts → results-BtyDwTD6.d.ts} +117 -16
- package/package.json +4 -4
- package/dist/chunk-server-Y4DGNHLP.js.map +0 -1
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/ports.ts","../../src/core/defaultErrorSink.ts","../../src/core/guards.ts","../../src/core/rpcResult.ts","../../src/core/registry.ts","../../src/core/doors.ts","../../src/db/public.ts","../../src/core/associationsService.ts","../../src/core/categoriesService.ts","../../src/core/favoritesService.ts","../../src/core/candidates.ts","../../src/core/titles.ts","../../src/core/entityRows.ts","../../src/core/helpers.ts","../../src/core/commentsService.ts","../../src/core/store.ts","../../src/core/edgeClassifier.ts","../../src/core/categoryHierarchy.ts"],"sourcesContent":["// src/ports.ts — @ai-matrx/associations\n//\n// THE SEVEN PORTS (design Decision 2) — the exact seams measured in the\n// matrx-frontend census (2026-08-29), inverted into typed injection points —\n// plus the W6 `authorDisplay` seam (the comments canonical UI, ruling C4).\n// One provider config, declared here, bound once per host\n// (`AssociationsProvider` in /react; `createAssociationsStore(cfg)` in /core —\n// both arrive in later waves; the TYPES are the wave-1 contract).\n//\n// Required ports throw at construction when absent — never degraded. Optional\n// ports each have a DEFINED degradation (the table in\n// ASSOCIATIONS-PACKAGE-DESIGN.md Decision 2); \"the feature silently doesn't\n// work\" is never one of them.\n//\n// React appears as TYPE-ONLY imports (optional peer): this module is\n// import-inert and legal in any graph, server components included.\n\nimport type { ComponentType, ElementType, ReactNode } from \"react\";\n\nimport type { SupabaseLike } from \"@ai-matrx/data/db\";\nimport type { EntityTypeToken } from \"./entity-types.generated\";\n\n// ─── required ports (absence throws at construction) ────────────────────────\n\n/**\n * The data seam — a structural subset of `SupabaseClient<Database>`: any\n * client that can answer the demanded RPC families (README § The demanded\n * schema). The package IS data operations; there is no degraded mode without\n * one. `PromiseLike` because supabase-js returns a thenable builder, not a\n * `Promise`.\n *\n * 🚨 SINCE 0.14.0 THE PORT IS THE HOST'S SUPABASE CLIENT ITSELF (`@ai-matrx/data`'s structural\n * `SupabaseLike`: `schema(name).rpc(...)`). Every call goes through data's generated\n * function doors (`src/db/public.ts`); the four edge lists are read COMPLETE (paged by\n * the package — a host no longer pages them). Pass `supabase`, not an `{ rpc }` wrapper.\n *\n * 🚨 RPC AND NOTHING ELSE (DOORS-ONLY-4, 2026-09-21). This port used to carry\n * OPTIONAL `from`/`schema` table surfaces, used by exactly one service —\n * entity-row create/rename, which wrote the registered entity's backing table\n * directly. The doors-only ruling (`platform` and `iam` are not client-writable;\n * every write goes through a named SECURITY DEFINER door) made that path answer\n * `42501` on every closed table, so it now calls `entity_row_create` /\n * `entity_row_rename` like every other operation. With its one reader gone the\n * two optional members were a port nobody reads — removed rather than left as a\n * seam a future write could quietly reach for.\n */\nexport type AssociationsDataSource = SupabaseLike;\n\n/**\n * An `{ rpc }`-only client (a host bridge that forwards public-schema function calls, the shape\n * every host passed before 0.14.0). ACCEPTED AGAIN since 0.14.5: 0.14.0 refused it at\n * construction and every agent-catalog host with a bridge crashed (\"the REQUIRED dataSource port\n * is missing\"). The store adapts it — `schema(\"public\").rpc` is its `rpc` — so a caller cannot hit\n * that crash. Every function this package calls is a `public` one (`src/db/public.ts`); any other\n * schema, or a table read, is refused ALOUD by the adapter, never answered silently.\n */\nexport interface AssociationsRpcOnlyDataSource {\n rpc(fn: string, args?: Record<string, unknown>, opts?: { count?: \"exact\" | \"planned\" | \"estimated\" }): PromiseLike<any>;\n}\n\n/**\n * The one normalizer: a supabase-shaped client passes through untouched; an `{ rpc }`-only client\n * is wrapped so `schema(\"public\")` answers with its `rpc`. Anything else returns `null` (the store\n * throws its REQUIRED-port error).\n */\nexport function asAssociationsDataSource(source: unknown): AssociationsDataSource | null {\n const s = source as { schema?: unknown; rpc?: unknown } | null | undefined;\n if (!s || typeof s !== \"object\") return null;\n if (typeof s.schema === \"function\") return s as AssociationsDataSource;\n if (typeof s.rpc !== \"function\") return null;\n const rpcOnly = s as AssociationsRpcOnlyDataSource;\n const rpc = (fn: string, args?: Record<string, unknown>, opts?: { count?: \"exact\" | \"planned\" | \"estimated\" }) =>\n rpcOnly.rpc(fn, args, opts);\n return {\n schema(name: string) {\n if (name !== \"public\") {\n throw new Error(`@ai-matrx/associations: an { rpc }-only dataSource answers the public schema's functions only (asked for schema ${name}); pass the supabase-js client itself`);\n }\n return {\n rpc,\n from(table: string): never {\n throw new Error(`@ai-matrx/associations: an { rpc }-only dataSource answers functions only, never a table (asked for ${table}); pass the supabase-js client itself`);\n },\n };\n },\n };\n}\n\n/**\n * The identity seam — today a store-singleton read (`requireUserId`) plus the\n * org resolver `CategoryTagPicker` uses for created rows. `requireUserId`\n * failures stay LOUD (`Not authenticated`) — never silently anonymous.\n */\nexport interface AssociationsIdentity {\n requireUserId(): string;\n /** Org for created rows/edges (the CategoryTagPicker create path). */\n ensureOrgId?(): Promise<string>;\n /**\n * Whether the client's database session is attached right now. A 42501\n * \"permission denied for function\" from a demanded door means the request\n * went out anonymous (an ended or expired session) — UNLESS the session is\n * attached, when it is a real grant gap. Absent → treated as not attached.\n */\n sessionAttached?(): boolean;\n}\n\n/**\n * The scream seam. Every degraded path, every `demanded_schema_violation`,\n * every create-then-attach partial failure reports here regardless of\n * notifier availability.\n *\n * DEFAULT (0.6.0, C23): absent → `createDefaultErrorSink()` — a tagged\n * `console.error` per event that announces ONCE that no sink is bound and\n * names the remedy. A host with a diagnostics surface binds its own.\n */\nexport type ErrorSink = (event: {\n code: string;\n message: string;\n context?: object;\n}) => void;\n\n// ─── optional ports (each with a defined degradation) ───────────────────────\n\n/**\n * Per-token host overlay — the code-native values the DB registry cannot\n * carry (today: the 804-line ENTITY_OVERLAY literal in matrx-frontend's\n * entityRegistry). EVERY field optional; absence degrades per field:\n * convention columns, default icon, `${label}s`, no door, generic\n * titleColumn candidate read. A `reference_pickable` token with no title\n * column and no override is screamed to the errorSink, never shown broken.\n */\nexport interface EntityOverlayEntry {\n /** Icon component (host-supplied; packages never depend on an icon library). */\n Icon?: ElementType;\n /** Plural label; default `${label}s`. */\n labelPlural?: string;\n /** Owner column override; default the \"created_by\" convention. */\n ownerColumn?: string | null;\n /** Org column override; default the \"organization_id\" convention. */\n orgColumn?: string | null;\n /** Route for this token's rows; absent → no open door (label renders plain). */\n hrefFor?: (id: string) => string;\n /**\n * Candidate-list override for tokens whose backing table can't be read\n * client-side (e.g. `data_store` — rag.* is not PostgREST-exposed);\n * absent → the generic `reference_search_candidates` titleColumn read.\n */\n listCandidates?: (args: { search?: string; limit?: number }) => Promise<\n | { ok: true; data: { id: string; title: string }[] }\n | { ok: false; error: string }\n >;\n}\n\n/** The overlay registration map — bound per host, merged over the generated registry. */\nexport type EntityOverlayMap = Partial<\n Record<EntityTypeToken, EntityOverlayEntry>\n>;\n\n/**\n * The user-notification seam (today: `@/lib/toast` in 6 components).\n * Optional — /react warns once when absent. Every user-facing failure ALSO\n * routes to the errorSink + the component's inline error state, so the\n * create-then-associate loud-outcome law is satisfied structurally, not by\n * toast availability.\n */\nexport interface AssociationsNotifier {\n success(msg: string): void;\n error(\n msg: string,\n opts?: {\n description?: string;\n action?: { label: string; onClick(): void };\n },\n ): void;\n}\n\n/**\n * The window seam.\n *\n * DEFAULT (0.6.0, C23): absent → `DefaultWindowShell`, the package's OWN\n * window — draggable, resizable, maximizable, viewport-clamped, portalled,\n * non-modal, mobile bottom-card. Not a degradation; the shipped default.\n * A host binds this port only when its own window MANAGER (tray docking,\n * workspace persistence, cross-window z-order) must own the surface.\n */\nexport interface WindowShellPort {\n Window: ComponentType<{\n id: string;\n title: string;\n onClose(): void;\n children: ReactNode;\n }>;\n}\n\n/** Options for {@link CapturePort.requestUpload} (measured: uploadGuardOpeners). */\nexport interface CaptureUploadOpts {\n files: File[];\n /** Logical cloud-files folder new uploads land in (auto-created). */\n folderPath: string;\n /** Publish the uploads to the web (the only anonymous lane; access ladder T-13). */\n publishedToWeb?: boolean;\n /** The \"Shown to\" list filter stamped on uploads (`only_me` · `my_team` · `everyone` · `everyone_on_ai_matrx`). */\n shownTo?: CaptureShownTo;\n /** The retiring level word, derived from the two words above for hosts not yet on them. */\n visibility?: string; // T-13 transitional wire input\n}\n\n/** `platform.shown_to`: a list filter, never row security. */\nexport type CaptureShownTo = \"only_me\" | \"my_team\" | \"everyone\" | \"everyone_on_ai_matrx\";\n\n/** Honest outcome of a host upload — created-but-unlinked must be reportable. */\nexport interface CaptureUploadResult {\n cancelled?: boolean;\n uploaded: string[];\n aliased: { existingFileId: string }[];\n failed: { name: string; error: string }[];\n}\n\n/** Options for {@link CapturePort.openFilePicker} (measured: cloudFilesPickerOpeners). */\nexport interface CapturePickOpts {\n multi?: boolean;\n title?: string;\n description?: string;\n}\n\n/**\n * The capture-toolbar seam. PER-HANDLER optional: the toolbar renders only\n * the chips it can actually honor; a chip with no path behind it is never\n * rendered dead. NEVER dead buttons.\n *\n * THE UPLOAD DEFAULT (0.6.0, C23): a host does NOT have to build an upload\n * flow. Bind the one-file primitive `uploadFile` and the package ships the\n * WHOLE flow over it — the file input, whole-body drag-and-drop, sequential\n * uploads, the stall watchdog, per-file outcomes, and the loud\n * created-but-unattached report. `requestUpload` stays for a host that owns\n * a richer pipeline (duplicate-alias dialogs, progress UI); when both are\n * bound `requestUpload` wins.\n */\nexport interface CapturePort {\n /**\n * The MINIMAL upload primitive: persist ONE file, answer with its id (or\n * an honest error). Everything else — batching, drag-and-drop, progress\n * state, failure copy — is the package's job.\n */\n uploadFile?(\n file: File,\n opts: Omit<CaptureUploadOpts, \"files\">,\n ): Promise<{ ok: true; id: string } | { ok: false; error: string }>;\n /** The full host upload pipeline. Wins over `uploadFile` when bound. */\n requestUpload?(opts: CaptureUploadOpts): Promise<CaptureUploadResult>;\n /** Resolves with picked file ids, or null/empty on cancel. */\n openFilePicker?(opts: CapturePickOpts): Promise<string[] | null>;\n /** Creates a document in the authoritative organization of this container. */\n createDataTable?(opts: {\n name: string;\n organizationId: string;\n }): Promise<{ id: string } | null>;\n}\n\n/**\n * Props of the generic association picker face — ALSO the contract a\n * per-token override component must implement (today: the hardcoded\n * `token === \"file\"` → FilePickerWindow branch in AssociationPicker becomes a\n * `registerPickerOverride(\"file\", …)` host binding). Ported verbatim from the\n * measured component.\n */\nexport interface AssociationPickerProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n token: EntityTypeToken;\n /** Container display label, for the header (\"…to Titanium Marketing\"). */\n containerLabel?: string;\n /** Org stamped onto rows created by the \"+ New\" footer. */\n orgId?: string | null;\n /** Resource ids already attached to the container. */\n attachedIds: Set<string>;\n /** Attach a resource (returns ok/err so the row can surface failures). */\n onAttach: (\n resourceId: string,\n title: string,\n ) => Promise<{ ok: boolean; error?: string }>;\n /** Detach a resource. */\n onDetach: (resourceId: string) => Promise<{ ok: boolean; error?: string }>;\n /**\n * Filed-under mode: the primary is being FILED UNDER the picked items\n * (`primary → item`), so the header says \"File … under\" not \"Attach to\".\n */\n filing?: boolean;\n}\n\n/** Per-token picker override map — absent tokens use the generic picker sheet. */\nexport type PickerOverrideMap = Partial<\n Record<EntityTypeToken, ComponentType<AssociationPickerProps>>\n>;\n\n/**\n * Props the entity-doors port's `EntityRef` receives (the measured subset the\n * association faces pass today).\n */\nexport interface EntityRefProps {\n token: string;\n id: string;\n name?: string | null;\n showIcon?: boolean;\n openInNewTab?: boolean;\n alwaysShowActions?: boolean;\n className?: string;\n}\n\n/** Props the entity-doors port's `DoorControls` receives. */\nexport interface EntityDoorProps {\n token: string;\n id: string;\n name?: string | null;\n className?: string;\n}\n\n/** What the authorDisplay port receives — one comment's denormalized author. */\nexport interface AuthorDisplayInput {\n /** The auth user id (`created_by`), or null on an authorless legacy row. */\n userId: string | null;\n email: string | null;\n displayName: string | null;\n avatarUrl: string | null;\n}\n\n/**\n * The author-display seam (W6 comments UI). The package cannot resolve user\n * profiles itself — `cmt_list` denormalizes email/displayName/avatarUrl per\n * row, and a host with a richer profile store (presence, current names,\n * signed avatar URLs) overrides them here. Return `null` (or omit a field)\n * to keep the denormalized value.\n *\n * DEGRADATION (absent port): the RPC's denormalized fields render as-is;\n * a row with neither displayName nor email shows the package's\n * \"Unknown user\" label with the default initial avatar. Never blank, never\n * a crash.\n */\nexport type AuthorDisplayPort = (author: AuthorDisplayInput) => {\n displayName?: string | null;\n avatarUrl?: string | null;\n} | null;\n\n/**\n * The entity-doors seam (today: `EntityRef` / `EntityDoorControls` /\n * access-gate `UnresolvedEntityRef`). Absent → title text plus the overlay's\n * `hrefFor` link when present; unresolved rows render the package's plain\n * \"unavailable\" chip.\n */\nexport interface EntityDoorsPort {\n EntityRef?: ComponentType<EntityRefProps>;\n DoorControls?: ComponentType<EntityDoorProps>;\n UnresolvedRef?: ComponentType<{ token: string; id: string }>;\n}\n\n// ─── the one provider config ────────────────────────────────────────────────\n\n/**\n * Everything a host binds, once. `createAssociationsStore(cfg)` (/core)\n * throws when `dataSource` or `identity` is missing — those two ARE the\n * host's app identity and cannot be defaulted. Every other port ships a\n * working default (C23) or degrades per its own documented contract, never\n * silently.\n */\nexport interface AssociationsConfig {\n // required — TRUE app identity, the only two things a host must supply\n dataSource: AssociationsDataSource | AssociationsRpcOnlyDataSource;\n identity: AssociationsIdentity;\n // optional — each has a SHIPPED DEFAULT or a documented degradation\n errorSink?: ErrorSink;\n entityOverlay?: EntityOverlayMap;\n notifier?: AssociationsNotifier;\n windowShell?: WindowShellPort;\n capture?: CapturePort;\n pickerOverrides?: PickerOverrideMap;\n entityDoors?: EntityDoorsPort;\n authorDisplay?: AuthorDisplayPort;\n}\n","// core/defaultErrorSink.ts — @ai-matrx/associations/core\n//\n// THE shipped default for the `errorSink` port (0.6.0, C23: every port ships\n// a working default). Before 0.6.0 `errorSink` was REQUIRED and a host that\n// had not yet built a diagnostics pipeline could not construct the store at\n// all — the package refused to work rather than shipping the obvious sink.\n//\n// The default obeys the platform's nothing-fails-silently law: every event\n// reaches `console.error` under a tagged prefix, WITH a remedy line naming\n// what the host should bind and where to look. It also announces ITSELF once\n// — an app running on the default sink is told, so \"nobody saw the error\"\n// can never be explained by \"we didn't know there was no sink\".\n//\n// A host with a real diagnostics surface (matrx-frontend's Error Inspector)\n// binds `errorSink` and this default steps aside entirely.\n\nimport type { ErrorSink } from \"../ports\";\n\nconst REMEDY =\n \"Bind the `errorSink` port on createAssociationsStore({ errorSink }) to \" +\n \"route these into your diagnostics surface; until then they only reach \" +\n \"the console.\";\n\n/**\n * Build the default sink. `announce` is called once, on the first event, so\n * the absence of a bound sink is itself loud (never a silent substitution).\n */\nexport function createDefaultErrorSink(): ErrorSink {\n let announced = false;\n return (event) => {\n if (!announced) {\n announced = true;\n console.error(\n \"[associations] no errorSink port bound — using the package default. \" +\n REMEDY,\n );\n }\n console.error(\n `[associations] ${event.code}: ${event.message}`,\n event.context ?? {},\n );\n };\n}\n","// core/guards.ts — @ai-matrx/associations/core\n//\n// Pre-flight VALIDATION for the unified association edge — ported\n// behavior-verbatim from matrx-frontend\n// `features/scopes/service/associationGuards.ts` (associations extraction W2,\n// 2026-08-29). One seam inverted: the loud console.error scream becomes the\n// REQUIRED errorSink port, bound once via `createAssociationGuards(errorSink)`.\n//\n// Every write/read that goes through the services runs these guards BEFORE\n// the RPC fires, so the two classes of failure that keep biting surface as a\n// clean, described `invalid_argument` error at the callsite — never as an\n// opaque Postgres error chased through logs:\n//\n// 1. A non-UUID id — e.g. an agent passing a \"cute\" string literal instead\n// of a real row uuid (`22P02` at the DB; caught here with field + value).\n// 2. An unregistered type token — the `source_type`/`target_type` FK to\n// `platform.entity_types.token` is ENFORCED, so a guessed/phantom token\n// throws `23503` there; the generated `isEntityTypeToken` set rejects it\n// here with a clear message instead. This is also the WRITES-STRICT wall\n// of the token-skew policy (C18): a token the installed vocabulary lacks\n// fails here — upgrade the package, never widen to a raw string.\n//\n// LOUD by doctrine: a guard firing means a real code bug got this far, so it\n// reports to the errorSink (never silently swallowed) on its way to becoming\n// an `invalid_argument` result.\n\nimport { isUuidShape } from \"@ai-matrx/kit/uuid\";\n\nimport { isEntityTypeToken } from \"../entity-types.generated\";\nimport type { AssociationsRpcError } from \"../results\";\nimport type { ErrorSink } from \"../ports\";\n\n// The UUID predicates moved to `@ai-matrx/kit/uuid` on 2026-09-07 (duplication\n// census rows 6-8). The fleet had TWO predicates both called `isUuid` — this\n// LAX shape check, and a STRICT RFC-4122 one on six matrx-frontend API doors —\n// and the difference was invisible at the call site. They now live side by\n// side under names that say which is which (`isUuidShape` /\n// `isRfc4122Uuid`), in the package with no sibling dependencies that both an\n// association store and a Next.js route handler can reach. The guards below\n// want the LAX one: a v7 id, a nil UUID and a test fixture are all legitimate\n// association ids.\n\nfunction show(value: unknown): string {\n if (typeof value === \"string\") return JSON.stringify(value);\n if (value === null || value === undefined) return String(value);\n return JSON.stringify(value);\n}\n\n/**\n * Canonical replacements for legacy/phantom entity-type tokens (matrx-frontend\n * FOUND_DEFECTS D27). These aliases were never registered in\n * `platform.entity_types` — writes with them always FK-failed — but they\n * leaked into association callsites and persisted UI state.\n * `normalizeEntityToken` maps them to the registered canonical token so the\n * whole class of failure is structurally impossible, and it SCREAMS (to the\n * errorSink) when it fires, because an alias reaching this chokepoint means a\n * callsite is still emitting a dead token.\n *\n * Do NOT add entries casually: the fix for a new unregistered token is to\n * register it (or use the right one at the callsite), not to alias it here.\n */\nconst LEGACY_ENTITY_TOKEN_ALIASES: Record<string, string> = {\n cx_message: \"message\", // chat.message\n cx_conversation: \"conversation\", // chat.conversation\n user_file: \"file\", // files.files (mirrors war-room entityToSource)\n agent_app: \"app\", // app.definition\n // chat_block: a \"block\" is a slice of a chat message — the edge's id IS the\n // message id (metadata.block_index carries the slice), so it maps to message.\n chat_block: \"message\",\n};\n\n/** Return the first failing check, or null if all pass. Pure. */\nexport function firstError(\n ...checks: (AssociationsRpcError | null)[]\n): AssociationsRpcError | null {\n for (const c of checks) if (c) return c;\n return null;\n}\n\nexport interface AssociationGuards {\n /** A single id must be a real UUID. Kills the \"cute text id\" bug class. */\n checkUuid(field: string, value: unknown): AssociationsRpcError | null;\n /** Every id in an array must be a real UUID. */\n checkUuidArray(\n field: string,\n values: readonly unknown[],\n ): AssociationsRpcError | null;\n /** A type token must be registered in `platform.entity_types`. */\n checkToken(field: string, value: unknown): AssociationsRpcError | null;\n /**\n * Map a legacy/phantom token to its registered canonical token.\n * Pass-through for anything not in the alias table. Loud by doctrine — the\n * alias firing is a bug at the callsite, recovered here, never silent.\n */\n normalizeEntityToken(value: string): string;\n}\n\n/** Bind the guard set to the host's errorSink (the loud seam). */\nexport function createAssociationGuards(errorSink: ErrorSink): AssociationGuards {\n function invalid(\n field: string,\n value: unknown,\n reason: string,\n ): AssociationsRpcError {\n const message = `association ${field} ${reason} (got ${show(value)})`;\n errorSink({\n code: \"invalid_argument\",\n message: `[associations] invalid argument — ${message}`,\n context: { field },\n });\n return { code: \"invalid_argument\", message };\n }\n\n return {\n checkUuid(field, value) {\n return isUuidShape(value) ? null : invalid(field, value, \"must be a UUID\");\n },\n\n checkUuidArray(field, values) {\n for (let i = 0; i < values.length; i++) {\n if (!isUuidShape(values[i]))\n return invalid(`${field}[${i}]`, values[i], \"must be a UUID\");\n }\n return null;\n },\n\n checkToken(field, value) {\n if (typeof value !== \"string\" || value.length === 0)\n return invalid(field, value, \"must be a non-empty entity-type token\");\n if (!isEntityTypeToken(value))\n return invalid(\n field,\n value,\n \"is not a registered entity type (platform.entity_types) — \" +\n \"add it to the registry + upgrade @ai-matrx/associations, never guess a token\",\n );\n return null;\n },\n\n normalizeEntityToken(value) {\n const canonical = LEGACY_ENTITY_TOKEN_ALIASES[value];\n if (canonical) {\n errorSink({\n code: \"legacy_token_alias\",\n message:\n `[associations] phantom entity token ${JSON.stringify(value)} mapped to ` +\n `canonical ${JSON.stringify(canonical)} — fix the callsite to emit the ` +\n `canonical token (FOUND_DEFECTS D27)`,\n context: { value, canonical },\n });\n return canonical;\n }\n return value;\n },\n };\n}\n","// core/rpcResult.ts — @ai-matrx/associations/core\n//\n// The never-throw result funnel every service method in this package builds\n// through — ported behavior-verbatim from matrx-frontend\n// `features/scopes/service/rpcResult.ts` (associations extraction W2,\n// 2026-08-29), with the seams inverted:\n//\n// • console.warn / console.error → the REQUIRED errorSink port (the scream\n// seam). `createPgErrorMapper(errorSink)` binds the sink once; services\n// receive the bound mapper.\n// • `isTransportFailure` is the one body in `@ai-matrx/api/net` (its\n// NetError-class branches never fire here — /core makes no resilientFetch\n// calls — and every plain-object/TypeError/offline shape is identical).\n// • NEW (the demanded-schema scream, design Decision 4): a PostgREST\n// PGRST202 — \"could not find the function\" — on any demanded RPC maps to\n// the `demanded_schema_violation` code, names this package's contract in\n// its message, and ALWAYS reaches the errorSink. A consumer pointed at a\n// database without our schema gets one unambiguous scream, not a mystery\n// toast.\n//\n// 🚨 A POSTGREST ERROR IS NOT AN `Error`. supabase-js resolves a failed\n// request with a PLAIN OBJECT (`{ code, message, details, hint }`) parsed\n// straight from the response body — `PostgrestError` is only ever *thrown*\n// when `shouldThrowOnError` is set, which this package never sets. So an\n// `e instanceof Error ? e.message : <generic>` ternary discards the real\n// message on EVERY genuine database failure. Read the fields off the OBJECT,\n// and keep the Postgres/PostgREST code in `detail` so the next failure is\n// attributable instead of anonymous. (Incident: CRM record page 2026-08-14 —\n// a real `57014 statement timeout` reached the UI as \"Unexpected error\n// talking to Supabase\".)\n//\n// Sink policy (mirrors the original's console split):\n// • transport failures (browser offline/asleep/mid-handoff) report with\n// code \"transport_failure\" and `context.transient: true` — they carry no\n// database refusal an engineer can act on, and filing them as errors\n// buries real failures;\n// • THROWN application errors (identity port refusals, bugs) report with\n// their mapped code — the original console.error'ed these;\n// • plain PostgREST result errors do NOT reach the sink (the host's\n// dataSource layer is presumed to capture them with richer call-site\n// context, exactly as matrx-frontend's supabaseErrorCapture does — a\n// second sink event per request is a duplicate repair-queue row) —\n// EXCEPT PGRST202, which always screams.\n\nimport type {\n AssociationsRpcError,\n} from \"../results\";\nimport { isTransportFailure } from \"@ai-matrx/api/net\";\nimport type { ErrorSink } from \"../ports\";\n\nexport function err(\n code: AssociationsRpcError[\"code\"],\n message: string,\n detail?: unknown,\n hint?: string,\n): { ok: false; error: AssociationsRpcError } {\n const error: AssociationsRpcError = { code, message };\n if (detail !== undefined) error.detail = detail;\n if (hint !== undefined) error.hint = hint;\n return { ok: false, error };\n}\n\nexport function ok<T>(data: T): { ok: true; data: T } {\n return { ok: true, data };\n}\n\nfunction isPostgrestResultError(e: unknown): boolean {\n if (!e || typeof e !== \"object\") return false;\n const value = e as { code?: unknown; message?: unknown };\n return typeof value.code === \"string\" && typeof value.message === \"string\";\n}\n\n/**\n * Pull `code` / `message` / `hint` off whatever the dataSource handed us.\n *\n * Three shapes reach here and only the first is common:\n * 1. a PLAIN object from PostgREST — `{ code, message, details, hint }`\n * 2. a thrown `Error` (network stack, the identity port's refusal, a bug)\n * 3. something else entirely (a string, null) from a path we don't own\n */\nfunction readPgFields(e: unknown): {\n pgCode: string | null;\n pgMessage: string | null;\n pgHint: string | undefined;\n} {\n if (e && typeof e === \"object\") {\n const o = e as { code?: unknown; message?: unknown; hint?: unknown };\n return {\n pgCode: typeof o.code === \"string\" && o.code ? o.code : null,\n // `Error` instances land here too — `message` is an own/inherited\n // string property either way, so one read covers both shapes.\n pgMessage: typeof o.message === \"string\" && o.message ? o.message : null,\n pgHint: typeof o.hint === \"string\" && o.hint ? o.hint : undefined,\n };\n }\n return { pgCode: null, pgMessage: null, pgHint: undefined };\n}\n\nexport type PgErrorMapper = (e: unknown) => AssociationsRpcError;\nexport type PgErrorPairMapper = (\n e: unknown,\n) => [AssociationsRpcError[\"code\"], string, unknown, string | undefined];\n\nexport interface RpcResultHelpers {\n ok: typeof ok;\n err: typeof err;\n mapPgError: PgErrorMapper;\n mapPgErrorPair: PgErrorPairMapper;\n}\n\n/**\n * Bind the loud funnel to the host's errorSink. Every failure in this\n * package's services passes through the returned `mapPgError` exactly once.\n */\n/**\n * How every signed-out sentence starts (the host app's annotations speak the\n * same words), so a kept error string still says which remedy it needs.\n */\nexport const SIGNED_OUT_LEAD = \"You're signed out\";\nexport const SIGNED_OUT_MESSAGE = `${SIGNED_OUT_LEAD}. Sign in again — your text is kept here.`;\n\nexport function isSignedOutMessage(text: string | null | undefined): boolean {\n return typeof text === \"string\" && text.startsWith(SIGNED_OUT_LEAD);\n}\n\nexport function createRpcResultHelpers(\n errorSink: ErrorSink,\n sessionAttached?: () => boolean,\n): RpcResultHelpers {\n function mapPgError(e: unknown): AssociationsRpcError {\n const { pgCode, pgMessage, pgHint } = readPgFields(e);\n\n // THE DEMANDED-SCHEMA SCREAM (design Decision 4). Checked FIRST and\n // always sunk — a database that cannot answer a demanded function is not\n // this package's database, and nothing downstream may soften that.\n if (pgCode === \"PGRST202\") {\n const message =\n \"demanded schema violation: the database this client is pointed at \" +\n \"cannot answer a demanded @ai-matrx/associations RPC (PostgREST \" +\n \"PGRST202 — function not found). This package DEMANDS the platform \" +\n `schema (README § The demanded schema). ${pgMessage ?? \"\"}`.trim();\n errorSink({\n code: \"demanded_schema_violation\",\n message,\n context: { pgCode, detail: e },\n });\n const out: AssociationsRpcError = {\n code: \"demanded_schema_violation\",\n message,\n detail: e,\n };\n if (pgHint !== undefined) out.hint = pgHint;\n return out;\n }\n\n // Loud before lossy — but through the SINK, per the header's policy.\n if (isTransportFailure(e)) {\n errorSink({\n code: \"transport_failure\",\n message: \"network unreachable (browser offline?)\",\n context: { transient: true, detail: e },\n });\n } else if (!isPostgrestResultError(e)) {\n errorSink({\n code: \"internal\",\n message: pgMessage ?? \"Unexpected error talking to the data source\",\n context: { detail: e },\n });\n }\n\n if (pgCode === \"PGRST116\")\n return { code: \"not_found\", message: \"Not found\" };\n // The session's JWT is gone or expired — the user is signed out, not broken.\n if (pgCode === \"PGRST301\" || pgCode === \"PGRST303\" || pgCode === \"28000\")\n return { code: \"unauthorized\", message: SIGNED_OUT_MESSAGE };\n if (pgCode === \"42501\") {\n // An anonymous caller meets \"permission denied for function\" on every\n // demanded door (authenticated holds EXECUTE on them): a long-lived tab\n // whose session ended (measured on live 2026-10-17, cmt_list). With the\n // session attached it is a real grant gap and stays a permission verdict.\n const anonymous =\n /permission denied for function/i.test(pgMessage ?? \"\") &&\n !(sessionAttached?.() ?? false);\n if (anonymous) return { code: \"unauthorized\", message: SIGNED_OUT_MESSAGE };\n // Postgres 42501 (insufficient_privilege) — the server's own explicit\n // verdict, not a zero-row guess.\n return { code: \"forbidden_org\", message: \"Permission denied\" };\n }\n // Postgres killed the statement at the role's `statement_timeout`. The\n // database is up and the query is valid; it ran out of time. Say so,\n // because \"unexpected error\" sends the reader hunting for the wrong fault.\n if (pgCode === \"57014\") {\n const out: AssociationsRpcError = {\n code: \"internal\",\n message: \"The database took too long to respond\",\n detail: e,\n };\n if (pgHint !== undefined) out.hint = pgHint;\n return out;\n }\n\n const out: AssociationsRpcError = {\n // A real message from PostgREST beats our generic string every time;\n // the generic one is the LAST resort, not the default.\n message: pgMessage ?? \"Unexpected error talking to the data source\",\n code: \"internal\",\n detail: e,\n };\n if (pgHint !== undefined) out.hint = pgHint;\n return out;\n }\n\n function mapPgErrorPair(\n e: unknown,\n ): [AssociationsRpcError[\"code\"], string, unknown, string | undefined] {\n const mapped = mapPgError(e);\n return [mapped.code, mapped.message, mapped.detail, mapped.hint];\n }\n\n return { ok, err, mapPgError, mapPgErrorPair };\n}\n","// core/registry.ts — @ai-matrx/associations/core\n//\n// THE registry merge engine — the single resolver that turns an entity token\n// into everything a generic association surface needs to RENDER it and QUERY\n// for it. Ported behavior-verbatim from matrx-frontend\n// `features/scopes/registry/entityRegistry.ts` (associations extraction W2,\n// 2026-08-29), with the measured seams inverted:\n//\n// • the 804-line app ENTITY_OVERLAY literal (lucide icons, ~45 hrefFor\n// routes, `features/rag`/`features/hr` candidate loaders) → the OPTIONAL\n// `entityOverlay` port (`AssociationsConfig.entityOverlay` +\n// `registerEntityOverlay` on the store). The package ships NO overlay\n// entries — icons/routes/loaders are host-native values;\n// • the lucide DEFAULT_ICON → `Icon: null` (packages never depend on an\n// icon library, C19; /react supplies its inlined default in W4);\n// • console.error screams → the REQUIRED errorSink port.\n//\n// Two inputs, merged per token:\n// 1. The GENERATED registry `ENTITY_TYPE_METADATA` (mirrored 1:1 from\n// `platform.entity_types`) — the truth for `schema`/`table`/`label`/\n// `titleColumn`/`scopeable`/`category`/`contentRole`/`referencePickable`.\n// 2. The host overlay for the code-native values the DB cannot carry.\n//\n// OWNERSHIP + ORG ARE CONVENTIONS, NOT PER-TOKEN CONFIG. Verified live across\n// every cardable table after the 2026 schema reorg: each carries `created_by`\n// and `organization_id`. A token only overrides them when its table genuinely\n// diverges (`null` override = \"this table has no such column\").\n\nimport { isRecordStoreNounToken, recordStoreNoun } from \"../record-store-nouns\";\nimport {\n ENTITY_TYPE_METADATA,\n isEntityTypeToken,\n type EntityTypeMeta,\n type EntityTypeToken,\n} from \"../entity-types.generated\";\nimport type {\n EntityOverlayEntry,\n EntityOverlayMap,\n ErrorSink,\n} from \"../ports\";\n\n/** The universal ownership column post-2026-reorg. */\nexport const DEFAULT_OWNER_COLUMN = \"created_by\";\n/** The universal org-scoping column. */\nexport const DEFAULT_ORG_COLUMN = \"organization_id\";\n\n// ─── Content roles ──────────────────────────────────────────────────────────\n// The knowledge-model grouping axis. `platform.entity_types.content_role` is\n// the only per-entity authority; display metadata for the buckets (titles,\n// accents) is host/`react` chrome and deliberately NOT part of /core.\n\nexport type ContentRole =\n | \"utility\"\n | \"source\"\n | \"destination\"\n | \"hybrid\"\n | \"container\";\n\nconst CONTENT_ROLE_SET: ReadonlySet<string> = new Set([\n \"utility\",\n \"source\",\n \"destination\",\n \"hybrid\",\n \"container\",\n]);\n\n/** Runtime guard for the DB's free-text `content_role` column. */\nexport function isContentRole(value: string | null): value is ContentRole {\n return value !== null && CONTENT_ROLE_SET.has(value);\n}\n\n/**\n * Domain vocabularies that name a registered entity by a DIFFERENT string.\n * A `kind` column written by another system is not automatically a canonical\n * token — the Knowledge/ingest pipeline stamps `source_kind='cld_file'`, the\n * legacy name of the table now called `files.files`, which IS the registry's\n * `file`. One alias table, one place to add the next one. Only add an entry\n * VERIFIED to point at the same physical row.\n */\nconst TOKEN_ALIASES: Record<string, EntityTypeToken> = {\n cld_file: \"file\",\n};\n\n/**\n * Normalize a raw `kind`/`type` string onto its canonical entity token.\n * Returns the input unchanged when it is already canonical or unknown — the\n * caller's existing \"no registry entry → plain text\" path still applies.\n */\nexport function resolveEntityToken(raw: string): string {\n return TOKEN_ALIASES[raw] ?? raw;\n}\n\n/**\n * Fully-resolved entity descriptor — generated metadata + host overlay, with\n * safe fallbacks so an un-overlaid token still renders (derived plural, no\n * door, `Icon: null` → the consumer's default) even if it can't be queried\n * for candidates yet.\n */\nexport interface EntityInfo {\n token: EntityTypeToken;\n label: string;\n labelPlural: string;\n /** Postgres schema of the backing table (from the generated registry). */\n schema: string;\n /** Backing table name (from the generated registry). */\n table: string;\n /** Title column for the picker, or null when none is registered. */\n titleColumn: string | null;\n /** Ownership column to scope candidate reads to the current user. */\n ownerColumn: string;\n /** Org-scoping column. */\n orgColumn: string;\n /** Host-supplied icon component, or null (consumer renders its default). */\n Icon: EntityOverlayEntry[\"Icon\"] | null;\n hrefFor: ((id: string) => string) | null;\n scopeable: boolean;\n category: string | null;\n /** Knowledge-model grouping bucket (resource surfaces group by this). */\n contentRole: ContentRole;\n /** Candidate-source override (rag-backed tokens etc.); null = generic read. */\n listCandidates: EntityOverlayEntry[\"listCandidates\"] | null;\n /** True when a picker can list real candidates (title column OR override). */\n canListCandidates: boolean;\n}\n\n// Reverse index: \"schema.table\" → canonical token (first registered token wins\n// when several tokens share a physical table). Built once from the generated\n// metadata — immutable module constants, not mutable state.\nconst TABLE_TO_TOKEN: Record<string, EntityTypeToken> = (() => {\n const m: Record<string, EntityTypeToken> = {};\n for (const token of Object.keys(ENTITY_TYPE_METADATA) as EntityTypeToken[]) {\n const meta = ENTITY_TYPE_METADATA[token];\n const key = `${meta.schema}.${meta.table}`;\n if (!(key in m)) m[key] = token;\n }\n return m;\n})();\n\nconst UNIQUE_TABLE_NAME_TO_TOKEN: Record<string, EntityTypeToken | null> =\n (() => {\n const index: Record<string, EntityTypeToken | null> = {};\n for (const token of Object.keys(\n ENTITY_TYPE_METADATA,\n ) as EntityTypeToken[]) {\n const table = ENTITY_TYPE_METADATA[token].table;\n index[table] = table in index ? null : token;\n }\n return index;\n })();\n\nexport interface EntityRegistry {\n /** Merge more overlay entries in (host binding, W4 pickers, tests). */\n registerEntityOverlay(overlay: EntityOverlayMap): void;\n /** Resolve a KNOWN token to its full descriptor. */\n getEntityInfo(token: EntityTypeToken): EntityInfo;\n /** Safe variant for raw strings (e.g. an edge's `otherType`). */\n tryGetEntityInfo(token: string): EntityInfo | null;\n /** Resolve from a live `(schema, table)` pair, or null. */\n tryGetEntityInfoByTable(schema: string, table: string): EntityInfo | null;\n /** Resolve a raw table name only when it maps to exactly one entity. */\n tryGetEntityInfoByUniqueTableName(table: string): EntityInfo | null;\n /**\n * Tokens the DB classifies as knowledge resources via a valid\n * `content_role` AND that can list candidates. The default set for card\n * grids, resource sections, and attach pickers.\n */\n curatedTokens(): EntityTypeToken[];\n /**\n * Tokens offered as reference \"Allowed types\" — DB-driven via\n * `platform.entity_types.reference_pickable`. A pickable token with no\n * title column and no candidate override is a config defect: excluded and\n * screamed to the errorSink, never silently shown broken.\n */\n listableTokens(): EntityTypeToken[];\n}\n\n/** Build the merge engine over the host overlay (empty overlay is legal). */\nexport function createEntityRegistry(\n errorSink: ErrorSink,\n initialOverlay?: EntityOverlayMap,\n): EntityRegistry {\n // Instance state, never module state — dual-loaded graphs each construct\n // their own store, so there is nothing to split.\n const overlayByToken: Partial<Record<EntityTypeToken, EntityOverlayEntry>> = {\n ...(initialOverlay ?? {}),\n };\n\n // A host compiled against an older vocabulary can ask for a token the live\n // registry has since retired (2026-10-02: the custom-data cutover\n // deactivated `dataset` and `structured_list`; a module-scope\n // `getEntityInfo(\"structured_list\")` in the host then threw at import time\n // and every route of the app crashed). A retired token is a defect in the\n // HOST — it must be told, loudly, once per token — but it is never a reason\n // to take the whole product down. The stand-in names itself as retired.\n const retiredReported = new Set<string>();\n function retiredTokenMeta(token: string): EntityTypeMeta {\n if (!retiredReported.has(token)) {\n retiredReported.add(token);\n errorSink({\n code: \"retired_entity_token\",\n message:\n `[entityRegistry] \"${token}\" is not in the live entity vocabulary ` +\n `(retired or renamed in platform.entity_types). The host still ` +\n `references it; rename the reference to the live token, or drop it. ` +\n `Serving a stand-in so the page can render.`,\n context: { token },\n });\n }\n return {\n token: token as EntityTypeToken,\n schema: \"\",\n table: \"\",\n label: `${token} (retired)`,\n baseTier: 1,\n isComponent: false,\n isModule: false,\n isListed: false,\n scopeable: false,\n category: null,\n referencePickable: false,\n titleColumn: null,\n contentRole: null,\n referenceCategory: null,\n };\n }\n\n // The record store's kinds (Table, Pick list): live nouns with no entity-type row — named,\n // never screamed as retired, and never pointed at a table (see record-store-nouns.ts).\n function recordStoreMeta(token: string): EntityTypeMeta | null {\n const label = recordStoreNoun(token);\n if (label === null) return null;\n return {\n token: token as EntityTypeToken,\n schema: \"\",\n table: \"\",\n label,\n baseTier: 1,\n isComponent: false,\n isModule: false,\n isListed: false,\n scopeable: false,\n category: null,\n referencePickable: false,\n titleColumn: null,\n contentRole: null,\n referenceCategory: null,\n };\n }\n\n function getEntityInfo(token: EntityTypeToken): EntityInfo {\n const meta =\n ENTITY_TYPE_METADATA[token] ?? recordStoreMeta(token) ?? retiredTokenMeta(token);\n const overlay = overlayByToken[token];\n const labelPlural = overlay?.labelPlural ?? `${meta.label}s`;\n const titleColumn = meta.titleColumn;\n const contentRole = isContentRole(meta.contentRole)\n ? meta.contentRole\n : \"destination\";\n // NULL means \"not classified as a knowledge resource\" and is the normal\n // state for most entity types. Only a non-null, out-of-vocabulary value\n // is corrupt registry data and warrants a loud recovery.\n if (meta.contentRole !== null && !isContentRole(meta.contentRole)) {\n errorSink({\n code: \"invalid_content_role\",\n message:\n `[entityRegistry] \"${token}\" has invalid content_role ` +\n `\"${meta.contentRole}\" in platform.entity_types; using destination ` +\n `as a loud recovery.`,\n context: { token, contentRole: meta.contentRole },\n });\n }\n // `null` override means \"this table has no such column\"; `undefined`\n // (the common case) falls back to the convention.\n const ownerColumn =\n overlay?.ownerColumn === undefined\n ? DEFAULT_OWNER_COLUMN\n : (overlay.ownerColumn ?? \"\");\n const orgColumn =\n overlay?.orgColumn === undefined\n ? DEFAULT_ORG_COLUMN\n : (overlay.orgColumn ?? \"\");\n return {\n token,\n label: meta.label,\n labelPlural,\n schema: meta.schema,\n table: meta.table,\n titleColumn,\n ownerColumn,\n orgColumn,\n Icon: overlay?.Icon ?? null,\n hrefFor: overlay?.hrefFor ?? null,\n scopeable: meta.scopeable,\n category: meta.category,\n contentRole,\n listCandidates: overlay?.listCandidates ?? null,\n canListCandidates:\n titleColumn !== null || overlay?.listCandidates !== undefined,\n };\n }\n\n return {\n registerEntityOverlay(overlay) {\n for (const key of Object.keys(overlay) as EntityTypeToken[]) {\n const entry = overlay[key];\n if (!entry) continue;\n // Merge per token so a later registration adds fields (e.g. a\n // listCandidates loader) without erasing an earlier Icon/hrefFor.\n overlayByToken[key] = { ...overlayByToken[key], ...entry };\n }\n },\n\n getEntityInfo,\n\n tryGetEntityInfo(token) {\n const canonical = resolveEntityToken(token);\n if (isEntityTypeToken(canonical)) return getEntityInfo(canonical);\n return isRecordStoreNounToken(token)\n ? getEntityInfo(token as unknown as EntityTypeToken)\n : null;\n },\n\n tryGetEntityInfoByTable(schema, table) {\n const token = TABLE_TO_TOKEN[`${schema}.${table}`];\n return token ? getEntityInfo(token) : null;\n },\n\n tryGetEntityInfoByUniqueTableName(table) {\n const token = UNIQUE_TABLE_NAME_TO_TOKEN[table];\n return token ? getEntityInfo(token) : null;\n },\n\n curatedTokens() {\n return (Object.keys(ENTITY_TYPE_METADATA) as EntityTypeToken[]).filter(\n (t) => {\n const meta = ENTITY_TYPE_METADATA[t];\n const o = overlayByToken[t];\n return (\n isContentRole(meta.contentRole) &&\n (meta.titleColumn != null || o?.listCandidates !== undefined)\n );\n },\n );\n },\n\n listableTokens() {\n return (Object.keys(ENTITY_TYPE_METADATA) as EntityTypeToken[]).filter(\n (t) => {\n const meta = ENTITY_TYPE_METADATA[t];\n if (!meta.referencePickable) return false;\n const o = overlayByToken[t];\n const canList =\n meta.titleColumn != null || o?.listCandidates !== undefined;\n if (!canList) {\n errorSink({\n code: \"unlistable_pickable_token\",\n message:\n `[entityRegistry] \"${t}\" is reference_pickable in platform.entity_types ` +\n `but has NO title_column and no host candidate source — set its ` +\n `title_column in the registry or register a listCandidates override.`,\n context: { token: t },\n });\n }\n return canList;\n },\n );\n },\n };\n}\n","// core/doors.ts — every database call of this package goes through @ai-matrx/data's doors.\n//\n// The descriptors are generated into `src/db/public.ts` (`pnpm db:generate`, only the\n// functions this package calls). `rpcDoor` answers the `{ data, error }` pair the services\n// have always mapped (the database's own error, code kept), so every error path is\n// unchanged; a refusal before the wire (`DoorRefusedError`) throws into the service's\n// catch like any transport failure. `rpcDoorAll` is the complete read of an edge list:\n// every row, paged past the 1,000-row cap over position (nulls last), created_at, id —\n// the order the hosts' paged adapters used.\nimport { call, callAll, createDb, type Db, type FunctionDescriptor } from \"@ai-matrx/data/db\";\n\nimport type { AssociationsDataSource } from \"../ports\";\nimport type { PgError } from \"../results\";\n\nconst dbs = new WeakMap<object, Db>();\n\n/** The data connection over the host's client (one per client). */\nexport function dbOf(dataSource: AssociationsDataSource): Db {\n let db = dbs.get(dataSource);\n if (!db) {\n db = createDb({ client: dataSource });\n dbs.set(dataSource, db);\n }\n return db;\n}\n\n/**\n * `platform.assoc_add_many(p_edges jsonb) -> uuid[]` — THE BATCH DOOR (2026-10-09). One call = one\n * transaction: each element is applied exactly as `public.assoc_add` (the same argument names,\n * the same authorization, called as the caller) and the ids come back in input order; any\n * failure raises and NOTHING is applied. It lives in `platform` (nothing new goes in `public`),\n * so it is not in the generated `db/public.ts`. Born from a 140-card deck save that fired 140\n * concurrent single adds and lost 69 edges.\n */\nexport type AssocAddManyArgs = { p_edges: unknown[] };\nexport const assocAddMany = {\n schema: \"platform\",\n name: \"assoc_add_many\",\n roles: [\"authenticated\", \"service_role\"],\n registered: true,\n} as unknown as FunctionDescriptor<AssocAddManyArgs, string[]>;\n\ntype Pair<T> = { data: T | null; error: PgError | null };\n\n/**\n * The argument names are checked against the function; values stay as the services always\n * built them (an `undefined` optional is dropped on the wire, JSON values are `unknown`).\n */\ntype Args<F> = F extends FunctionDescriptor<infer A, any> ? { [K in keyof A]?: unknown } : never;\n\nfunction asPair<T>(e: unknown): Pair<T> {\n const err = e as { name?: string; cause?: PgError } | null;\n if (err?.name === \"DatabaseError\" && err.cause) return { data: null, error: err.cause };\n throw e;\n}\n\nexport async function rpcDoor<F extends FunctionDescriptor<any, any>>(\n dataSource: AssociationsDataSource,\n fn: F,\n args: Args<F>,\n): Promise<Pair<unknown>> {\n try {\n return { data: await call(dbOf(dataSource), fn, args as never), error: null };\n } catch (e) {\n return asPair(e);\n }\n}\n\nconst EDGE_ORDER = [{ column: \"position\", nullsFirst: false }, \"created_at\", \"id\"] as const;\n\nexport async function rpcDoorAll<F extends FunctionDescriptor<any, any>>(\n dataSource: AssociationsDataSource,\n fn: F,\n args: Args<F>,\n): Promise<Pair<unknown>> {\n try {\n return { data: await callAll(dbOf(dataSource), fn, args as never, { order: EDGE_ORDER }), error: null };\n } catch (e) {\n return asPair(e);\n }\n}\n","/**\n * GENERATED by `matrx-data generate` from the database description — never edit by hand.\n * schema: public · description eb4e70fa23e6\n * Regenerate: matrx-data generate (see @ai-matrx/data README).\n */\n/* eslint-disable */\nimport type { FunctionDescriptor } from \"@ai-matrx/data/db\";\n\ntype Json = string | number | boolean | null | { [key: string]: Json | undefined } | Json[];\n\nexport type AgentResourceAddArgs = { p_agent_id: string; p_source_type: string; p_source_id: string; p_label?: string; p_metadata?: Json };\nexport type AgentResourceAddResult = string;\nexport const agentResourceAdd = {\"schema\":\"public\",\"name\":\"agent_resource_add\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AgentResourceAddArgs, AgentResourceAddResult>;\n\nexport type AgentResourceRemoveArgs = { p_agent_id: string; p_source_type: string; p_source_id: string };\nexport type AgentResourceRemoveResult = undefined;\nexport const agentResourceRemove = {\"schema\":\"public\",\"name\":\"agent_resource_remove\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AgentResourceRemoveArgs, AgentResourceRemoveResult>;\n\nexport type AssocAddArgs = { p_source_type: string; p_source_id: string; p_target_type: string; p_target_id: string; p_org_id?: string; p_label?: string; p_metadata?: Json; p_role?: string; p_position?: number; p_payload_kind?: string; p_payload?: Json };\nexport type AssocAddResult = string;\nexport const assocAdd = {\"schema\":\"public\",\"name\":\"assoc_add\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocAddArgs, AssocAddResult>;\n\nexport type AssocForEntityArgs = { p_type: string; p_id: string };\nexport type AssocForEntityResult = { id: string | null; direction: string | null; other_type: string | null; other_id: string | null; role: string | null; label: string | null; position: number | null; metadata: Json | null; organization_id: string | null; created_at: string | null }[];\nexport const assocForEntity = {\"schema\":\"public\",\"name\":\"assoc_for_entity\",\"roles\":[\"anon\",\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocForEntityArgs, AssocForEntityResult>;\n\nexport type AssocForSourcesArgs = { p_source_type: string; p_source_ids: string[]; p_target_type?: string };\nexport type AssocForSourcesResult = { id: string | null; source_id: string | null; target_type: string | null; target_id: string | null; role: string | null; label: string | null; position: number | null; metadata: Json | null; organization_id: string | null; created_at: string | null }[];\nexport const assocForSources = {\"schema\":\"public\",\"name\":\"assoc_for_sources\",\"roles\":[\"anon\",\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocForSourcesArgs, AssocForSourcesResult>;\n\nexport type AssocForTargetsArgs = { p_target_type: string; p_target_ids: string[] };\nexport type AssocForTargetsResult = { id: string | null; target_id: string | null; source_type: string | null; source_id: string | null; role: string | null; label: string | null; position: number | null; metadata: Json | null; organization_id: string | null; created_at: string | null }[];\nexport const assocForTargets = {\"schema\":\"public\",\"name\":\"assoc_for_targets\",\"roles\":[\"anon\",\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocForTargetsArgs, AssocForTargetsResult>;\n\nexport type AssocMembersVisibleArgs = { p_target_type: string; p_target_ids: string[] };\nexport type AssocMembersVisibleResult = { id: string | null; target_id: string | null; source_type: string | null; source_id: string | null; role: string | null; label: string | null; position: number | null; metadata: Json | null; organization_id: string | null; created_at: string | null }[];\nexport const assocMembersVisible = {\"schema\":\"public\",\"name\":\"assoc_members_visible\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocMembersVisibleArgs, AssocMembersVisibleResult>;\n\nexport type AssocRemoveArgs = { p_source_type: string; p_source_id: string; p_target_type: string; p_target_id: string; p_role?: string };\nexport type AssocRemoveResult = undefined;\nexport const assocRemove = {\"schema\":\"public\",\"name\":\"assoc_remove\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocRemoveArgs, AssocRemoveResult>;\n\nexport type AssocRemoveForEntityArgs = { p_type: string; p_id: string };\nexport type AssocRemoveForEntityResult = undefined;\nexport const assocRemoveForEntity = {\"schema\":\"public\",\"name\":\"assoc_remove_for_entity\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocRemoveForEntityArgs, AssocRemoveForEntityResult>;\n\nexport type AssocSetTargetsArgs = { p_source_type: string; p_source_id: string; p_target_type: string; p_target_ids: string[]; p_org_id?: string; p_role?: string };\nexport type AssocSetTargetsResult = undefined;\nexport const assocSetTargets = {\"schema\":\"public\",\"name\":\"assoc_set_targets\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocSetTargetsArgs, AssocSetTargetsResult>;\n\nexport type CatCreateArgs = { p_dimension: string; p_name: string; p_org_id: string; p_parent_id?: string; p_color?: string; p_icon?: string; p_slug?: string };\nexport type CatCreateResult = string;\nexport const catCreate = {\"schema\":\"public\",\"name\":\"cat_create\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CatCreateArgs, CatCreateResult>;\n\nexport type CatDeleteArgs = { p_category_id: string };\nexport type CatDeleteResult = string;\nexport const catDelete = {\"schema\":\"public\",\"name\":\"cat_delete\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CatDeleteArgs, CatDeleteResult>;\n\nexport type CatListArgs = { p_dimension?: string };\nexport type CatListResult = { id: string | null; organization_id: string | null; dimension: string | null; name: string | null; slug: string | null; parent_id: string | null; is_system: boolean | null; color: string | null; icon: string | null; position: number | null; metadata: Json | null }[];\nexport const catList = {\"schema\":\"public\",\"name\":\"cat_list\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CatListArgs, CatListResult>;\n\nexport type CatReparentArgs = { p_category_id: string; p_parent_id?: string };\nexport type CatReparentResult = string;\nexport const catReparent = {\"schema\":\"public\",\"name\":\"cat_reparent\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CatReparentArgs, CatReparentResult>;\n\nexport type CatUpdateArgs = { p_category_id: string; p_name: string; p_slug?: string; p_color?: string; p_icon?: string; p_position?: number };\nexport type CatUpdateResult = string;\nexport const catUpdate = {\"schema\":\"public\",\"name\":\"cat_update\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CatUpdateArgs, CatUpdateResult>;\n\nexport type CmtAddArgs = { p_entity_type: string; p_entity_id: string; p_body: string; p_parent_id?: string; p_org_id?: string; p_anchor?: Json; p_suggested_text?: string; p_client_request_id?: string };\nexport type CmtAddResult = string;\nexport const cmtAdd = {\"schema\":\"public\",\"name\":\"cmt_add\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CmtAddArgs, CmtAddResult>;\n\nexport type CmtDeleteArgs = { p_id: string };\nexport type CmtDeleteResult = undefined;\nexport const cmtDelete = {\"schema\":\"public\",\"name\":\"cmt_delete\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CmtDeleteArgs, CmtDeleteResult>;\n\nexport type CmtEditArgs = { p_id: string; p_body: string; p_expected_version?: number };\nexport type CmtEditResult = number;\nexport const cmtEdit = {\"schema\":\"public\",\"name\":\"cmt_edit\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CmtEditArgs, CmtEditResult>;\n\nexport type CmtListArgs = { p_entity_type: string; p_entity_id: string };\nexport type CmtListResult = { id: string | null; organization_id: string | null; entity_type: string | null; entity_id: string | null; parent_id: string | null; body: string | null; created_at: string | null; updated_at: string | null; created_by: string | null; author_email: string | null; author_display_name: string | null; author_avatar_url: string | null; anchor: Json | null; resolved_at: string | null; resolved_by: string | null; suggested_text: string | null; version: number | null; client_request_id: string | null; edited_at: string | null; created_by_tier: string | null; author_agent_id: string | null; author_agent_name: string | null }[];\nexport const cmtList = {\"schema\":\"public\",\"name\":\"cmt_list\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CmtListArgs, CmtListResult>;\n\nexport type ConversationFileAddArgs = { p_conversation_id: string; p_file_id: string; p_label?: string; p_metadata?: Json; p_replace_metadata?: boolean };\nexport type ConversationFileAddResult = string;\nexport const conversationFileAdd = {\"schema\":\"public\",\"name\":\"conversation_file_add\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<ConversationFileAddArgs, ConversationFileAddResult>;\n\nexport type ConversationFileRemoveArgs = { p_conversation_id: string; p_file_id: string };\nexport type ConversationFileRemoveResult = undefined;\nexport const conversationFileRemove = {\"schema\":\"public\",\"name\":\"conversation_file_remove\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<ConversationFileRemoveArgs, ConversationFileRemoveResult>;\n\nexport type ConversationFilesArgs = { p_conversation_id: string };\nexport type ConversationFilesResult = { file_id: string | null; label: string | null; metadata: Json | null; created_at: string | null }[];\nexport const conversationFiles = {\"schema\":\"public\",\"name\":\"conversation_files\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<ConversationFilesArgs, ConversationFilesResult>;\n\nexport type EntityRowCreateArgs = { p_token: string; p_title: string; p_organization_id: string };\nexport type EntityRowCreateResult = Json;\nexport const entityRowCreate = {\"schema\":\"public\",\"name\":\"entity_row_create\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<EntityRowCreateArgs, EntityRowCreateResult>;\n\nexport type EntityRowRenameArgs = { p_token: string; p_id: string; p_title: string };\nexport type EntityRowRenameResult = Json;\nexport const entityRowRename = {\"schema\":\"public\",\"name\":\"entity_row_rename\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<EntityRowRenameArgs, EntityRowRenameResult>;\n\nexport type ReferenceSearchCandidatesArgs = { p_token: string; p_search?: string; p_limit?: number; p_ids?: string[]; p_order?: string; p_offset?: number; p_organization_id?: string; p_mine?: boolean; p_show_system_files?: boolean };\nexport type ReferenceSearchCandidatesResult = { id: string | null; title: string | null; updated_at: string | null }[];\nexport const referenceSearchCandidates = {\"schema\":\"public\",\"name\":\"reference_search_candidates\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<ReferenceSearchCandidatesArgs, ReferenceSearchCandidatesResult>;\n\nexport type UesGetBulkArgs = { p_entity_type: string; p_entity_ids: string[] };\nexport type UesGetBulkResult = { entity_id: string | null; is_favorite: boolean | null; is_pinned: boolean | null; is_hidden: boolean | null; last_viewed_at: string | null }[];\nexport const uesGetBulk = {\"schema\":\"public\",\"name\":\"ues_get_bulk\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<UesGetBulkArgs, UesGetBulkResult>;\n\nexport type UesListArgs = { p_kind?: string };\nexport type UesListResult = { entity_type: string | null; entity_id: string | null; is_favorite: boolean | null; is_pinned: boolean | null; is_hidden: boolean | null; last_viewed_at: string | null; updated_at: string | null }[];\nexport const uesList = {\"schema\":\"public\",\"name\":\"ues_list\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<UesListArgs, UesListResult>;\n\nexport type UesSetArgs = { p_entity_type: string; p_entity_id: string; p_is_favorite?: boolean; p_is_pinned?: boolean; p_is_hidden?: boolean };\nexport type UesSetResult = undefined;\nexport const uesSet = {\"schema\":\"public\",\"name\":\"ues_set\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<UesSetArgs, UesSetResult>;\n\nexport type UesTouchArgs = { p_entity_type: string; p_entity_id: string };\nexport type UesTouchResult = undefined;\nexport const uesTouch = {\"schema\":\"public\",\"name\":\"ues_touch\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<UesTouchArgs, UesTouchResult>;\n","// core/associationsService.ts — @ai-matrx/associations/core\n//\n// THE SOLE CHOKEPOINT for the unified association edge —\n// `platform.associations`. Ported behavior-verbatim from matrx-frontend\n// `features/scopes/service/associationsService.ts` (643 lines, associations\n// extraction W2, 2026-08-29); the seams inverted onto the W1 ports:\n//\n// • the browser supabase singleton → the REQUIRED `dataSource` port;\n// • `requireUserId` (a store-singleton read) → the REQUIRED `identity` port\n// (failures stay LOUD — the port throws, the funnel maps it, never\n// silently anonymous);\n// • console screams → the REQUIRED `errorSink` (via guards + rpcResult).\n//\n// This is the canonical attach/detach primitive: any entity to any other\n// entity. The client holds NO grant on `platform.associations`; every\n// read/write goes through the PUBLIC SECURITY-DEFINER RPCs (`assoc_*`, plus\n// the stricter `conversation_file_*` boundary for the access-conveying\n// file → conversation pair and the `agent_resource_*` pair for authorized\n// agent containment) — and every call goes through THIS module. Methods\n// always return an `AssociationsRpcResult` and NEVER throw.\n//\n// Direction is relative to the queried entity: an edge is \"outgoing\" when\n// the entity is the source and \"incoming\" when it is the target.\n// `assoc_for_entity` returns BOTH in one round-trip. Little→big direction is\n// registry-owned — `trg_associations_auto_orient` rejects reversed writes;\n// this package surfaces that error verbatim and never flips an edge.\n\nimport { registeredEdgeLabel } from \"../association-types.generated\";\nimport type {\n AssociationEdge,\n AssociationSourceEdge,\n AssociationTargetEdge,\n AssociationTargetType,\n} from \"../edges\";\nimport type { AssociationsRpcResult } from \"../results\";\nimport { firstError } from \"./guards\";\nimport type { CoreDeps } from \"./deps\";\nimport { assocAddMany, rpcDoor, rpcDoorAll } from \"./doors\";\nimport { agentResourceAdd, agentResourceRemove, assocAdd, assocForEntity, assocForSources, assocForTargets, assocMembersVisible, assocRemove, assocRemoveForEntity, assocSetTargets, conversationFileAdd, conversationFileRemove, conversationFiles } from \"../db/public\";\n\n// Shape of one `assoc_for_entity` row (snake_case, straight from PG).\ninterface AssocForEntityRow {\n id: string;\n direction: string;\n other_type: string;\n other_id: string;\n role: string | null;\n label: string | null;\n position: number | null;\n metadata: unknown;\n organization_id: string | null;\n created_at: string;\n}\n\ninterface ConversationFileRow {\n file_id: string;\n label: string | null;\n metadata: unknown;\n created_at: string;\n}\n\nexport interface ConversationFileLink {\n fileId: string;\n label: string | null;\n metadata: unknown;\n createdAt: string;\n}\n\nfunction toEdge(row: AssocForEntityRow): AssociationEdge {\n return {\n id: row.id,\n // PG only ever emits 'outgoing' | 'incoming'; widen-then-narrow for TS.\n direction: row.direction === \"incoming\" ? \"incoming\" : \"outgoing\",\n otherType: row.other_type,\n otherId: row.other_id,\n role: row.role ?? null,\n label: row.label ?? null,\n position: row.position ?? null,\n metadata: row.metadata ?? {},\n orgId: row.organization_id ?? null,\n createdAt: row.created_at,\n };\n}\n\n// Shape of one `assoc_for_targets` row (snake_case, straight from PG).\ninterface AssocForTargetsRow {\n id: string;\n target_id: string;\n source_type: string;\n source_id: string;\n role: string | null;\n label: string | null;\n position: number | null;\n metadata: unknown;\n organization_id: string | null;\n created_at: string;\n}\n\nfunction toTargetEdge(row: AssocForTargetsRow): AssociationTargetEdge {\n return {\n id: row.id,\n targetId: row.target_id,\n sourceType: row.source_type,\n sourceId: row.source_id,\n role: row.role ?? null,\n label: row.label ?? null,\n position: row.position ?? null,\n metadata: row.metadata ?? {},\n orgId: row.organization_id ?? null,\n createdAt: row.created_at,\n };\n}\n\n// Shape of one `assoc_for_sources` row (snake_case, straight from PG).\ninterface AssocForSourcesRow {\n id: string;\n source_id: string;\n target_type: string;\n target_id: string;\n role: string | null;\n label: string | null;\n position: number | null;\n metadata: unknown;\n organization_id: string | null;\n created_at: string;\n}\n\nfunction toSourceEdge(row: AssocForSourcesRow): AssociationSourceEdge {\n return {\n id: row.id,\n sourceId: row.source_id,\n targetType: row.target_type,\n targetId: row.target_id,\n role: row.role ?? null,\n label: row.label ?? null,\n position: row.position ?? null,\n metadata: row.metadata ?? {},\n orgId: row.organization_id ?? null,\n createdAt: row.created_at,\n };\n}\n\nexport interface AddAssociationArgs {\n sourceType: string;\n sourceId: string;\n targetType: AssociationTargetType;\n targetId: string;\n orgId?: string;\n label?: string;\n metadata?: unknown;\n /**\n * Exact file → conversation updates preserve existing metadata unless the\n * caller explicitly opts into replacement. Invalid for every other pair.\n */\n replaceMetadata?: boolean;\n role?: string;\n position?: number;\n /**\n * Typed edge payload (Edge Payload System). `payloadKind` must be a\n * registered `platform.edge_payload_kind`; the DB trigger validates\n * `payload` against its JSON Schema and hard-fails on any mismatch. Real\n * logic an edge carries goes HERE — `metadata` is for loose annotations.\n */\n payloadKind?: string;\n payload?: unknown;\n}\n\n/** Edges per `addMany` call — one transaction of ~12 ms/edge, far under the API's 8 s statement cap. */\nexport const ASSOC_ADD_MANY_CHUNK = 100;\n\nexport interface AssociationsServiceApi {\n listForEntity(\n rawType: string,\n id: string,\n ): Promise<AssociationsRpcResult<{ edges: AssociationEdge[] }>>;\n listConversationFiles(\n conversationId: string,\n ): Promise<AssociationsRpcResult<{ files: ConversationFileLink[] }>>;\n listForTargets(\n rawTargetType: string,\n targetIds: string[],\n ): Promise<AssociationsRpcResult<{ edges: AssociationTargetEdge[] }>>;\n listForTargetsVisible(\n rawTargetType: string,\n targetIds: string[],\n ): Promise<AssociationsRpcResult<{ edges: AssociationTargetEdge[] }>>;\n listForSources(\n rawSourceType: string,\n sourceIds: string[],\n rawTargetType?: string,\n ): Promise<AssociationsRpcResult<{ edges: AssociationSourceEdge[] }>>;\n add(args: AddAssociationArgs): Promise<AssociationsRpcResult<{ id: string }>>;\n /**\n * Attach MANY edges in ONE database transaction (`platform.assoc_add_many`): every edge is\n * applied exactly as {@link add} applies it, the ids come back in input order, and if ANY edge\n * is refused the whole call fails and NOTHING is applied. Keep a call under\n * {@link ASSOC_ADD_MANY_CHUNK} edges (the helpers' `linkEdges` chunks for you). The\n * file → conversation pair is not batchable (it has its own stricter door): use {@link add}.\n */\n addMany(\n args: AddAssociationArgs[],\n ): Promise<AssociationsRpcResult<{ ids: string[] }>>;\n remove(args: {\n sourceType: string;\n sourceId: string;\n targetType: string;\n targetId: string;\n role?: string;\n }): Promise<AssociationsRpcResult<null>>;\n setTargets(args: {\n sourceType: string;\n sourceId: string;\n targetType: AssociationTargetType;\n targetIds: string[];\n orgId?: string;\n role?: string;\n }): Promise<AssociationsRpcResult<null>>;\n addAgentResource(args: {\n agentId: string;\n sourceType: string;\n sourceId: string;\n label?: string;\n metadata?: unknown;\n }): Promise<AssociationsRpcResult<{ id: string }>>;\n removeAgentResource(args: {\n agentId: string;\n sourceType: string;\n sourceId: string;\n }): Promise<AssociationsRpcResult<null>>;\n removeForEntity(\n rawType: string,\n id: string,\n ): Promise<AssociationsRpcResult<null>>;\n}\n\nexport function createAssociationsService(deps: CoreDeps): AssociationsServiceApi {\n const { dataSource, identity, guards } = deps;\n const { ok, err, mapPgError, mapPgErrorPair } = deps.rpc;\n const { checkToken, checkUuid, checkUuidArray, normalizeEntityToken } = guards;\n\n return {\n /**\n * All edges where `${type}:${id}` is either source (\"outgoing\") or target\n * (\"incoming\"), org-filtered by RLS inside the RPC. One round-trip.\n */\n async listForEntity(rawType, id) {\n try {\n identity.requireUserId();\n // Legacy-alias recovery (loud) — see normalizeEntityToken / D27.\n const type = normalizeEntityToken(rawType);\n const bad = firstError(checkToken(\"type\", type), checkUuid(\"id\", id));\n if (bad) return { ok: false, error: bad };\n const { data, error } = await rpcDoorAll(dataSource, assocForEntity, {\n p_type: type,\n p_id: id,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as AssocForEntityRow[];\n return ok({ edges: rows.map(toEdge) });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Viewer-aware file attachments for a conversation. Unlike the generic\n * org-filtered association reader, this follows the conversation's\n * canonical viewer grant, so an explicitly shared cross-org conversation\n * has the same attachment inventory in every client.\n */\n async listConversationFiles(conversationId) {\n try {\n identity.requireUserId();\n const bad = checkUuid(\"conversationId\", conversationId);\n if (bad) return { ok: false, error: bad };\n const { data, error } = await rpcDoor(dataSource, conversationFiles, {\n p_conversation_id: conversationId,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as ConversationFileRow[];\n return ok({\n files: rows.map((row) => ({\n fileId: row.file_id,\n label: row.label ?? null,\n metadata: row.metadata ?? {},\n createdAt: row.created_at,\n })),\n });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Every edge whose target is one of `targetIds` (all the same\n * `targetType`), org-filtered by RLS inside the RPC. The batch\n * counterpart of `listForEntity` — each row carries `targetId` so\n * callers can group results back by container.\n */\n async listForTargets(rawTargetType, targetIds) {\n try {\n identity.requireUserId();\n const targetType = normalizeEntityToken(rawTargetType);\n const ids = Array.from(new Set(targetIds));\n if (ids.length === 0) return ok({ edges: [] });\n const bad = firstError(\n checkToken(\"targetType\", targetType),\n checkUuidArray(\"targetIds\", ids),\n );\n if (bad) return { ok: false, error: bad };\n const { data, error } = await rpcDoorAll(dataSource, assocForTargets, {\n p_target_type: targetType,\n p_target_ids: ids,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as AssocForTargetsRow[];\n return ok({ edges: rows.map(toTargetEdge) });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Like `listForTargets`, but VISIBILITY-AWARE: an edge is returned when\n * the caller EITHER shares org access to it OR can VIEW its target via\n * the canonical row-level authorization truth `iam.has_access(target,\n * 'viewer')` — honoring published-to-the-web rows, Anyone links, share grants,\n * container memberships, and reachability. A strict SUPERSET of\n * `listForTargets` access; a stranger with no grant on a private target\n * still gets nothing. Use for reading the members of a SHAREABLE\n * container; keep plain `listForTargets` for org-scoped tagging reads.\n */\n async listForTargetsVisible(rawTargetType, targetIds) {\n try {\n identity.requireUserId();\n const targetType = normalizeEntityToken(rawTargetType);\n const ids = Array.from(new Set(targetIds));\n if (ids.length === 0) return ok({ edges: [] });\n const bad = firstError(\n checkToken(\"targetType\", targetType),\n checkUuidArray(\"targetIds\", ids),\n );\n if (bad) return { ok: false, error: bad };\n const { data, error } = await rpcDoorAll(dataSource, assocMembersVisible, {\n p_target_type: targetType,\n p_target_ids: ids,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as AssocForTargetsRow[];\n return ok({ edges: rows.map(toTargetEdge) });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Every edge whose source is one of `sourceIds` (all the same\n * `sourceType`), org-filtered by RLS inside the RPC. Pass `targetType`\n * to push the target filter into the DB. Each row carries `sourceId` so\n * callers can group results back by source.\n */\n async listForSources(rawSourceType, sourceIds, rawTargetType) {\n try {\n identity.requireUserId();\n const sourceType = normalizeEntityToken(rawSourceType);\n const targetType =\n rawTargetType != null\n ? normalizeEntityToken(rawTargetType)\n : undefined;\n const ids = Array.from(new Set(sourceIds));\n if (ids.length === 0) return ok({ edges: [] });\n const bad = firstError(\n checkToken(\"sourceType\", sourceType),\n checkUuidArray(\"sourceIds\", ids),\n targetType ? checkToken(\"targetType\", targetType) : null,\n );\n if (bad) return { ok: false, error: bad };\n const { data, error } = await rpcDoorAll(dataSource, assocForSources, {\n p_source_type: sourceType,\n p_source_ids: ids,\n ...(targetType ? { p_target_type: targetType } : {}),\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as AssocForSourcesRow[];\n return ok({ edges: rows.map(toSourceEdge) });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Attach `source` → `target`. Idempotent (ON CONFLICT). When `orgId` is\n * omitted the RPC resolves org from the endpoints; pass `orgId` for\n * targets that don't carry one. Returns the association id.\n */\n async add(args) {\n try {\n identity.requireUserId();\n // Legacy-alias recovery (loud) — see normalizeEntityToken / D27.\n const sourceType = normalizeEntityToken(args.sourceType);\n const targetType = normalizeEntityToken(args.targetType);\n const bad = firstError(\n checkToken(\"sourceType\", sourceType),\n checkUuid(\"sourceId\", args.sourceId),\n checkToken(\"targetType\", targetType),\n checkUuid(\"targetId\", args.targetId),\n args.orgId != null ? checkUuid(\"orgId\", args.orgId) : null,\n );\n if (bad) return { ok: false, error: bad };\n // A file attachment conveys viewer access through the conversation.\n // Keep this service as the client chokepoint, but route this one\n // access-bearing pair through its stricter DB boundary.\n if (sourceType === \"file\" && targetType === \"conversation\") {\n if (\n args.role != null ||\n args.position != null ||\n args.payloadKind != null ||\n args.payload != null\n ) {\n return err(\n \"invalid_argument\",\n \"File conversation attachments support only the canonical role-less edge\",\n );\n }\n const { data, error } = await rpcDoor(\n dataSource, conversationFileAdd,\n {\n p_conversation_id: args.targetId,\n p_file_id: args.sourceId,\n p_label: args.label,\n p_metadata: args.metadata ?? {},\n p_replace_metadata: args.replaceMetadata ?? false,\n },\n );\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\n \"internal\",\n \"conversation_file_add returned no association id\",\n );\n }\n return ok({ id: data });\n }\n if (args.replaceMetadata != null) {\n return err(\n \"invalid_argument\",\n \"replaceMetadata is supported only for file conversation attachments\",\n );\n }\n // A pair the registry NAMES is written with that name — the DB\n // refuses any other label for it (enforce_known_association). A\n // display name only rides pairs registered without one.\n const { data, error } = await rpcDoor(dataSource, assocAdd, {\n p_source_type: sourceType,\n p_source_id: args.sourceId,\n p_target_type: targetType,\n p_target_id: args.targetId,\n p_org_id: args.orgId,\n p_label: registeredEdgeLabel(sourceType, targetType, args.label) ?? args.label,\n p_metadata: args.metadata ?? {},\n p_role: args.role,\n p_position: args.position,\n p_payload_kind: args.payloadKind,\n p_payload: args.payload ?? undefined,\n });\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\"internal\", \"assoc_add returned no association id\");\n }\n return ok({ id: data });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n async addMany(edges) {\n try {\n identity.requireUserId();\n if (edges.length === 0) return ok({ ids: [] });\n const wire: Record<string, unknown>[] = [];\n for (const args of edges) {\n const sourceType = normalizeEntityToken(args.sourceType);\n const targetType = normalizeEntityToken(args.targetType);\n const bad = firstError(\n checkToken(\"sourceType\", sourceType),\n checkUuid(\"sourceId\", args.sourceId),\n checkToken(\"targetType\", targetType),\n checkUuid(\"targetId\", args.targetId),\n args.orgId != null ? checkUuid(\"orgId\", args.orgId) : null,\n );\n if (bad) return { ok: false, error: bad };\n if (sourceType === \"file\" && targetType === \"conversation\") {\n return err(\n \"invalid_argument\",\n \"File conversation attachments have their own door: use add(), not addMany()\",\n );\n }\n if (args.replaceMetadata != null) {\n return err(\n \"invalid_argument\",\n \"replaceMetadata is supported only for file conversation attachments\",\n );\n }\n wire.push({\n p_source_type: sourceType,\n p_source_id: args.sourceId,\n p_target_type: targetType,\n p_target_id: args.targetId,\n p_org_id: args.orgId,\n p_label: registeredEdgeLabel(sourceType, targetType, args.label) ?? args.label,\n p_metadata: args.metadata ?? {},\n p_role: args.role,\n p_position: args.position,\n p_payload_kind: args.payloadKind,\n p_payload: args.payload ?? undefined,\n });\n }\n const { data, error } = await rpcDoor(dataSource, assocAddMany, { p_edges: wire });\n if (error) return err(...mapPgErrorPair(error));\n if (!Array.isArray(data) || data.length !== edges.length) {\n return err(\n \"internal\",\n `assoc_add_many returned ${Array.isArray(data) ? data.length : \"no\"} ids for ${edges.length} edges`,\n );\n }\n return ok({ ids: data as string[] });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Detach `source` → `target`. No-op if the edge doesn't exist. When\n * `role` is omitted only the role-less edge is removed (role IS NOT\n * DISTINCT FROM null); pass `role` to detach a specific typed edge.\n */\n async remove(args) {\n try {\n identity.requireUserId();\n const sourceType = normalizeEntityToken(args.sourceType);\n const targetType = normalizeEntityToken(args.targetType);\n const bad = firstError(\n checkToken(\"sourceType\", sourceType),\n checkUuid(\"sourceId\", args.sourceId),\n checkToken(\"targetType\", targetType),\n checkUuid(\"targetId\", args.targetId),\n );\n if (bad) return { ok: false, error: bad };\n if (sourceType === \"file\" && targetType === \"conversation\") {\n if (args.role != null) {\n return err(\n \"invalid_argument\",\n \"File conversation attachments support only the canonical role-less edge\",\n );\n }\n const { error } = await rpcDoor(dataSource, conversationFileRemove, {\n p_conversation_id: args.targetId,\n p_file_id: args.sourceId,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n }\n const { error } = await rpcDoor(dataSource, assocRemove, {\n p_source_type: sourceType,\n p_source_id: args.sourceId,\n p_target_type: targetType,\n p_target_id: args.targetId,\n p_role: args.role,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Make the source's edges of `targetType` exactly equal `targetIds`\n * (adds missing, removes extras) in one transaction.\n */\n async setTargets(args) {\n try {\n identity.requireUserId();\n const sourceType = normalizeEntityToken(args.sourceType);\n const targetType = normalizeEntityToken(args.targetType);\n const target = Array.from(new Set(args.targetIds));\n const bad = firstError(\n checkToken(\"sourceType\", sourceType),\n checkUuid(\"sourceId\", args.sourceId),\n checkToken(\"targetType\", targetType),\n checkUuidArray(\"targetIds\", target),\n args.orgId != null ? checkUuid(\"orgId\", args.orgId) : null,\n );\n if (bad) return { ok: false, error: bad };\n const { error } = await rpcDoor(dataSource, assocSetTargets, {\n p_source_type: sourceType,\n p_source_id: args.sourceId,\n p_target_type: targetType,\n p_target_ids: target,\n p_org_id: args.orgId,\n p_role: args.role,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Permanently attach a resource to an agent. The dedicated RPC enforces\n * the stronger authoring contract this containment edge requires: editor\n * access to both the agent and source resource. The stored edge is still\n * the canonical platform association (`role=agent_resource`).\n */\n async addAgentResource(args) {\n try {\n identity.requireUserId();\n const sourceType = normalizeEntityToken(args.sourceType);\n const bad = firstError(\n checkUuid(\"agentId\", args.agentId),\n checkToken(\"sourceType\", sourceType),\n checkUuid(\"sourceId\", args.sourceId),\n );\n if (bad) return { ok: false, error: bad };\n const { data, error } = await rpcDoor(dataSource, agentResourceAdd, {\n p_agent_id: args.agentId,\n p_source_type: sourceType,\n p_source_id: args.sourceId,\n p_label: args.label,\n p_metadata: args.metadata ?? {},\n });\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\"internal\", \"agent_resource_add returned no association id\");\n }\n return ok({ id: data });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /** Remove one permanent Agent Resource edge. */\n async removeAgentResource(args) {\n try {\n identity.requireUserId();\n const sourceType = normalizeEntityToken(args.sourceType);\n const bad = firstError(\n checkUuid(\"agentId\", args.agentId),\n checkToken(\"sourceType\", sourceType),\n checkUuid(\"sourceId\", args.sourceId),\n );\n if (bad) return { ok: false, error: bad };\n const { error } = await rpcDoor(dataSource, agentResourceRemove, {\n p_agent_id: args.agentId,\n p_source_type: sourceType,\n p_source_id: args.sourceId,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Remove every edge where `${type}:${id}` is the source OR the target,\n * org-filtered inside the RPC. The deletion counterpart of\n * `listForEntity` — call it when an entity is deleted so no edge is left\n * orphaned.\n */\n async removeForEntity(rawType, id) {\n try {\n identity.requireUserId();\n const type = normalizeEntityToken(rawType);\n const bad = firstError(checkToken(\"type\", type), checkUuid(\"id\", id));\n if (bad) return { ok: false, error: bad };\n const { error } = await rpcDoor(dataSource, assocRemoveForEntity, {\n p_type: type,\n p_id: id,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n };\n}\n","// core/categoriesService.ts — @ai-matrx/associations/core\n//\n// THE SOLE CHOKEPOINT for the canonical faceted taxonomy —\n// `platform.categories`. Ported behavior-verbatim from matrx-frontend\n// `features/scopes/service/categoriesService.ts` (associations extraction W2,\n// 2026-08-29); supabase singleton → `dataSource`, `requireUserId` →\n// `identity`, host `Database` RPC row type → the structural row shape below.\n//\n// One table, partitioned by `dimension` (the facet). The client has NO\n// direct grant on `platform.categories`; every read/write goes through the\n// PUBLIC SECURITY-DEFINER `cat_*` RPCs — and every call goes through THIS\n// module. Methods always return an `AssociationsRpcResult` and NEVER throw.\n//\n// ASSIGNMENT of a category to an entity is deliberately NOT here: it reuses\n// the association edge (`associationsService.add({ targetType: 'category',\n// … })`). A category is the noun this module owns; the attach is the verb\n// the associations service owns.\n\nimport type { CategoryDimension, PlatformCategory } from \"../edges\";\nimport type { AssociationsRpcResult } from \"../results\";\nimport type { CoreDeps } from \"./deps\";\nimport { rpcDoor } from \"./doors\";\nimport { catCreate, catDelete, catList, catReparent, catUpdate } from \"../db/public\";\n\n// One `cat_list` row (snake_case, straight from PG).\ninterface CatListRow {\n id: string;\n organization_id: string | null;\n dimension: string;\n name: string;\n slug: string | null;\n parent_id: string | null;\n is_system: boolean | null;\n color: string | null;\n icon: string | null;\n position: number | null;\n metadata: unknown;\n}\n\nfunction toCategory(row: CatListRow): PlatformCategory {\n return {\n id: row.id,\n orgId: row.organization_id ?? null,\n dimension: row.dimension,\n name: row.name,\n slug: row.slug ?? null,\n parentId: row.parent_id ?? null,\n isSystem: !!row.is_system,\n color: row.color ?? null,\n icon: row.icon ?? null,\n position: row.position ?? null,\n metadata:\n row.metadata &&\n typeof row.metadata === \"object\" &&\n !Array.isArray(row.metadata)\n ? (row.metadata as Record<string, unknown>)\n : null,\n };\n}\n\nexport interface CategoriesServiceApi {\n list(\n dimension?: CategoryDimension,\n ): Promise<AssociationsRpcResult<{ categories: PlatformCategory[] }>>;\n create(args: {\n dimension: CategoryDimension;\n name: string;\n orgId: string;\n parentId?: string | null;\n color?: string | null;\n icon?: string | null;\n slug?: string | null;\n }): Promise<AssociationsRpcResult<{ id: string }>>;\n update(args: {\n id: string;\n name: string;\n slug: string | null;\n color: string | null;\n icon: string | null;\n position: number | null;\n }): Promise<AssociationsRpcResult<{ id: string }>>;\n reparent(args: {\n id: string;\n parentId: string | null;\n }): Promise<AssociationsRpcResult<{ id: string }>>;\n delete(id: string): Promise<AssociationsRpcResult<{ id: string }>>;\n}\n\nexport function createCategoriesService(deps: CoreDeps): CategoriesServiceApi {\n const { dataSource, identity } = deps;\n const { ok, err, mapPgError, mapPgErrorPair } = deps.rpc;\n\n return {\n /**\n * Every category visible to the caller (system + their orgs),\n * org-filtered by `iam.has_org_access` inside the RPC. Pass `dimension`\n * to scope to one facet (the common case). Ordered by dimension, then\n * `position`, then name.\n */\n async list(dimension) {\n try {\n identity.requireUserId();\n const { data, error } = await rpcDoor(dataSource, catList, {\n p_dimension: dimension,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as CatListRow[];\n return ok({ categories: rows.map(toCategory) });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Create an org-owned category in `dimension`. `orgId` is REQUIRED and\n * the RPC rejects callers without access to it (`cat_create` raises\n * 42501). The created row is always `is_system = false`; seeding\n * system/global categories is a migration concern, never a client write.\n */\n async create(args) {\n try {\n identity.requireUserId();\n const { data, error } = await rpcDoor(dataSource, catCreate, {\n p_dimension: args.dimension,\n p_name: args.name,\n p_org_id: args.orgId,\n p_parent_id: args.parentId ?? undefined,\n p_color: args.color ?? undefined,\n p_icon: args.icon ?? undefined,\n p_slug: args.slug ?? undefined,\n });\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\"internal\", \"cat_create returned no category id\");\n }\n return ok({ id: data });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Replace the editable scalar fields of one category. The caller\n * supplies the complete desired state so nullable fields can be cleared\n * without a JSON patch or a second interpretation of `undefined`.\n */\n async update(args) {\n try {\n identity.requireUserId();\n const { data, error } = await rpcDoor(dataSource, catUpdate, {\n p_category_id: args.id,\n p_name: args.name,\n p_slug: args.slug ?? undefined,\n p_color: args.color ?? undefined,\n p_icon: args.icon ?? undefined,\n p_position: args.position ?? undefined,\n });\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\"internal\", \"cat_update returned no category id\");\n }\n return ok({ id: data });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /** Move a category to the root or directly beneath one root category. */\n async reparent(args) {\n try {\n identity.requireUserId();\n const { data, error } = await rpcDoor(dataSource, catReparent, {\n p_category_id: args.id,\n p_parent_id: args.parentId ?? undefined,\n });\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\"internal\", \"cat_reparent returned no category id\");\n }\n return ok({ id: data });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /** Soft-delete a leaf category. Parents with live children are rejected. */\n async delete(id) {\n try {\n identity.requireUserId();\n const { data, error } = await rpcDoor(dataSource, catDelete, {\n p_category_id: id,\n });\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\"internal\", \"cat_delete returned no category id\");\n }\n return ok({ id: data });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n };\n}\n","// core/favoritesService.ts — @ai-matrx/associations/core\n//\n// THE SOLE CHOKEPOINT for per-user entity state —\n// `platform.user_entity_state` (the caller's favorite / pinned / hidden\n// flags + recency on any entity). Ported behavior-verbatim from\n// matrx-frontend `features/scopes/service/favoritesService.ts` +\n// `favoritesCore.ts` (associations extraction W2, 2026-08-29). The two host\n// files existed only because the browser file was pinned to the supabase\n// singleton while server readers needed injection — the injectable\n// `favoritesCore` shape prefigured this package's `dataSource` port, so here\n// they collapse back into ONE implementation (recorded in the CHANGELOG).\n//\n// Every read/write goes through the four PUBLIC SECURITY-DEFINER RPCs\n// (`ues_set` / `ues_list` / `ues_get_bulk` / `ues_touch`) — through THIS\n// module only. Methods always return an `AssociationsRpcResult`, NEVER throw.\n//\n// Scope: unlike associations (org-gated), per-user state is gated on\n// `auth.uid()` INSIDE each RPC — the user's own flags on an entity, across\n// every org. `entity_type` is free text in the DB (the table tracks state\n// for non-graph things too, e.g. `\"nav\"` destinations), so callers pass a\n// canonical token where one exists, or another stable token.\n\nimport type { UserEntityState, UserStateKind } from \"../edges\";\nimport type { AssociationsRpcResult } from \"../results\";\nimport type { CoreDeps } from \"./deps\";\nimport { rpcDoor } from \"./doors\";\nimport { uesGetBulk, uesList, uesSet, uesTouch } from \"../db/public\";\n\n// Raw `ues_list` row (snake_case, straight from PG). Carries `entity_type`.\ninterface UesListRow {\n entity_type: string;\n entity_id: string;\n is_favorite: boolean;\n is_pinned: boolean;\n is_hidden: boolean;\n last_viewed_at: string | null;\n updated_at: string;\n}\n\n// Raw `ues_get_bulk` row — no `entity_type` (a query input the RPC doesn't echo).\ninterface UesBulkRow {\n entity_id: string;\n is_favorite: boolean;\n is_pinned: boolean;\n is_hidden: boolean;\n last_viewed_at: string | null;\n}\n\nfunction toState(row: UesListRow): UserEntityState {\n return {\n entityType: row.entity_type,\n entityId: row.entity_id,\n isFavorite: row.is_favorite,\n isPinned: row.is_pinned,\n isHidden: row.is_hidden,\n lastViewedAt: row.last_viewed_at ?? null,\n };\n}\n\nexport interface FavoritesServiceApi {\n setState(args: {\n entityType: string;\n entityId: string;\n isFavorite?: boolean;\n isPinned?: boolean;\n isHidden?: boolean;\n }): Promise<AssociationsRpcResult<null>>;\n setFavorite(\n entityType: string,\n entityId: string,\n isFavorite: boolean,\n ): Promise<AssociationsRpcResult<null>>;\n setPinned(\n entityType: string,\n entityId: string,\n isPinned: boolean,\n ): Promise<AssociationsRpcResult<null>>;\n setHidden(\n entityType: string,\n entityId: string,\n isHidden: boolean,\n ): Promise<AssociationsRpcResult<null>>;\n list(\n kind?: UserStateKind,\n ): Promise<AssociationsRpcResult<{ items: UserEntityState[] }>>;\n getBulk(\n entityType: string,\n entityIds: string[],\n ): Promise<AssociationsRpcResult<{ items: UserEntityState[] }>>;\n touch(\n entityType: string,\n entityId: string,\n ): Promise<AssociationsRpcResult<null>>;\n}\n\nexport function createFavoritesService(deps: CoreDeps): FavoritesServiceApi {\n const { dataSource, identity } = deps;\n const { ok, err, mapPgError, mapPgErrorPair } = deps.rpc;\n\n const api: FavoritesServiceApi = {\n /**\n * Upsert the caller's state row for one entity. An OMITTED flag is left\n * UNCHANGED (the RPC `coalesce`s null → existing), so you can flip just\n * `isFavorite` without clobbering `isPinned`/`isHidden`. Idempotent.\n */\n async setState(args) {\n try {\n identity.requireUserId();\n const { error } = await rpcDoor(dataSource, uesSet, {\n p_entity_type: args.entityType,\n p_entity_id: args.entityId,\n p_is_favorite: args.isFavorite,\n p_is_pinned: args.isPinned,\n p_is_hidden: args.isHidden,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /** Convenience: flip ONLY the favorite flag (leaves pinned/hidden intact). */\n async setFavorite(entityType, entityId, isFavorite) {\n return api.setState({ entityType, entityId, isFavorite });\n },\n\n /** Convenience: flip ONLY the pinned flag. */\n async setPinned(entityType, entityId, isPinned) {\n return api.setState({ entityType, entityId, isPinned });\n },\n\n /** Convenience: flip ONLY the hidden flag. */\n async setHidden(entityType, entityId, isHidden) {\n return api.setState({ entityType, entityId, isHidden });\n },\n\n /**\n * Every state row the caller owns, optionally filtered to a single\n * dimension (`\"favorite\"` | `\"pinned\"` | `\"hidden\"`). Pass nothing for all.\n */\n async list(kind) {\n try {\n identity.requireUserId();\n const { data, error } = await rpcDoor(dataSource, uesList, {\n p_kind: kind,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as UesListRow[];\n return ok({ items: rows.map(toState) });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Bulk-fetch the caller's flags for `entityIds` of one `entityType` —\n * the read a list view uses to paint its star column in one round-trip.\n * Only entities that HAVE a state row come back; absent ids mean \"no\n * state yet\".\n */\n async getBulk(entityType, entityIds) {\n try {\n identity.requireUserId();\n const ids = Array.from(new Set(entityIds));\n const { data, error } = await rpcDoor(dataSource, uesGetBulk, {\n p_entity_type: entityType,\n p_entity_ids: ids,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as UesBulkRow[];\n // `ues_get_bulk` doesn't echo entity_type (it's a query input) —\n // stamp it back so callers get the same shape as `list`.\n return ok({\n items: rows.map((r) => ({\n entityType,\n entityId: r.entity_id,\n isFavorite: r.is_favorite,\n isPinned: r.is_pinned,\n isHidden: r.is_hidden,\n lastViewedAt: r.last_viewed_at ?? null,\n })),\n });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /** Stamp `last_viewed_at = now()` (creates the row if absent). */\n async touch(entityType, entityId) {\n try {\n identity.requireUserId();\n const { error } = await rpcDoor(dataSource, uesTouch, {\n p_entity_type: entityType,\n p_entity_id: entityId,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n };\n\n return api;\n}\n","// core/candidates.ts — @ai-matrx/associations/core\n//\n// \"What can I attach?\" — the generic candidate reader behind every\n// association picker, plus the universal cross-token search. Ported\n// behavior-verbatim from matrx-frontend\n// `features/scopes/service/associationCandidates.ts` (associations extraction\n// W2, 2026-08-29); supabase singleton → `dataSource`, the app entityRegistry\n// → the /core registry merge engine, console screams → errorSink.\n//\n// Fully token-driven: NO per-entity code. Which candidates a reader sees, and any\n// entity-specific equality predicates come from `platform.entity_types` and\n// are enforced by `public.reference_search_candidates`. Tokens whose backing\n// table can't be read client-side list through the host overlay's\n// `listCandidates` override instead (the entity-overlay port).\n\nimport type { EntityTypeToken } from \"../entity-types.generated\";\nimport type { CoreDeps } from \"./deps\";\nimport { rpcDoor } from \"./doors\";\nimport { referenceSearchCandidates } from \"../db/public\";\n\nexport interface CandidateRecord {\n id: string;\n title: string;\n}\n\nexport interface ListCandidatesArgs {\n token: EntityTypeToken;\n /** Case-insensitive title filter. */\n search?: string;\n limit?: number;\n}\n\nexport type CandidatesResult =\n | { ok: true; data: CandidateRecord[] }\n | { ok: false; error: string };\n\nexport interface UniversalCandidate extends CandidateRecord {\n token: EntityTypeToken;\n}\n\nexport interface SearchAcrossTokensArgs {\n /** Tokens to search. Defaults to every curated token in the registry. */\n tokens?: EntityTypeToken[];\n search: string;\n /** Cap per token — a universal search shows a few of everything. */\n perTokenLimit?: number;\n /** Max in-flight token queries. */\n concurrency?: number;\n}\n\n/** One token whose candidate read failed during a cross-token search. */\nexport interface TokenSearchFailure {\n token: EntityTypeToken;\n error: string;\n}\n\n/**\n * A cross-token search's honest answer: what could be read, AND what could\n * not. An empty `results` with non-empty `failures` is \"we couldn't look\",\n * never \"there is nothing\".\n */\nexport interface SearchAcrossTokensResult {\n results: UniversalCandidate[];\n failures: TokenSearchFailure[];\n}\n\nexport interface ReferenceSearchCandidatesFn {\n (args: {\n p_token: string;\n p_search?: string;\n p_limit?: number;\n p_ids?: string[];\n }): Promise<\n | { data: Array<{ id: string; title: string | null }>; error: null }\n | { data: null; error: { message: string } }\n >;\n}\n\nexport interface CandidatesServiceApi {\n /**\n * The universal candidate reader RPC (`public.reference_search_candidates`)\n * — shared by candidate search here and title resolution in titles.ts.\n */\n callReferenceSearchCandidates: ReferenceSearchCandidatesFn;\n listAssociationCandidates(args: ListCandidatesArgs): Promise<CandidatesResult>;\n /**\n * ONE search over EVERY listable entity type — the \"attach anything from\n * anywhere\" primitive. Registry-driven client fan-out, capped and\n * concurrency-limited. One broken table never blanks the search: a failed\n * token is screamed (errorSink) AND reported in `failures` (registry\n * order), so a face can say what it could not search instead of showing\n * \"no results\".\n */\n searchCandidatesAcrossTokens(\n args: SearchAcrossTokensArgs,\n ): Promise<SearchAcrossTokensResult>;\n}\n\nexport function createCandidatesService(deps: CoreDeps): CandidatesServiceApi {\n const { dataSource, registry, errorSink } = deps;\n\n const callReferenceSearchCandidates: ReferenceSearchCandidatesFn = async (\n args,\n ) => {\n const { data, error } = await rpcDoor(\n dataSource, referenceSearchCandidates,\n args,\n );\n if (error) return { data: null, error };\n return {\n data: (Array.isArray(data) ? data : []) as Array<{\n id: string;\n title: string | null;\n }>,\n error: null,\n };\n };\n\n async function listAssociationCandidates(\n args: ListCandidatesArgs,\n ): Promise<CandidatesResult> {\n const { token, search, limit = 100 } = args;\n const info = registry.getEntityInfo(token);\n\n // Overlay-declared candidate-source override — for tokens whose backing\n // table can't be read client-side (e.g. data_store: rag isn't\n // PostgREST-exposed).\n if (info.listCandidates) {\n try {\n return await info.listCandidates({\n ...(search !== undefined ? { search } : {}),\n limit,\n });\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"Failed to load candidates\";\n errorSink({\n code: \"candidate_override_failed\",\n message: `[listAssociationCandidates] override failed for \"${token}\": ${msg}`,\n context: { token, detail: e },\n });\n return { ok: false, error: msg };\n }\n }\n\n if (!info.canListCandidates || !info.titleColumn) {\n const msg =\n `Entity \"${token}\" has no title column — set one in ` +\n `platform.entity_types (or register a listCandidates override) before listing candidates`;\n errorSink({\n code: \"unlistable_token\",\n message: `[listAssociationCandidates] ${msg}`,\n context: { token },\n });\n return { ok: false, error: msg };\n }\n const trimmedSearch = search?.trim() || undefined;\n const { data, error } = await callReferenceSearchCandidates({\n p_token: token,\n ...(trimmedSearch !== undefined ? { p_search: trimmedSearch } : {}),\n p_limit: limit,\n });\n if (error) {\n errorSink({\n code: \"candidate_rpc_failed\",\n message: `[listAssociationCandidates] candidate RPC failed for \"${token}\": ${error.message}`,\n context: { token, detail: error },\n });\n return { ok: false, error: error.message };\n }\n return {\n ok: true,\n data: data.map((row) => ({\n id: row.id,\n title: row.title?.trim() || \"Untitled\",\n })),\n };\n }\n\n async function searchCandidatesAcrossTokens(\n args: SearchAcrossTokensArgs,\n ): Promise<SearchAcrossTokensResult> {\n const { tokens, search, perTokenLimit = 5, concurrency = 6 } = args;\n // Universal attach/search is narrower than display: only tokens explicitly\n // registered as reference-pickable may generate candidate RPC traffic.\n const list = tokens ?? registry.listableTokens();\n if (list.length === 0) return { results: [], failures: [] };\n\n const out: UniversalCandidate[] = [];\n const failures: TokenSearchFailure[] = [];\n let cursor = 0;\n\n async function worker(): Promise<void> {\n while (cursor < list.length) {\n const token = list[cursor];\n cursor += 1;\n if (!token) continue;\n const res = await listAssociationCandidates({\n token,\n search,\n limit: perTokenLimit,\n });\n if (res.ok) {\n for (const c of res.data) out.push({ ...c, token });\n } else {\n // Screamed inside listAssociationCandidates; recorded here so the\n // caller can tell \"nothing matched\" from \"couldn't look\".\n failures.push({ token, error: res.error });\n }\n }\n }\n\n await Promise.all(\n Array.from({ length: Math.min(concurrency, list.length) }, worker),\n );\n\n // Stable order: registry (role-grouped) token order, then title.\n const tokenOrder = new Map(list.map((t, i) => [t, i]));\n out.sort((a, b) => {\n const ta = tokenOrder.get(a.token) ?? 0;\n const tb = tokenOrder.get(b.token) ?? 0;\n if (ta !== tb) return ta - tb;\n return a.title.localeCompare(b.title);\n });\n failures.sort(\n (a, b) => (tokenOrder.get(a.token) ?? 0) - (tokenOrder.get(b.token) ?? 0),\n );\n return { results: out, failures };\n }\n\n return {\n callReferenceSearchCandidates,\n listAssociationCandidates,\n searchCandidatesAcrossTokens,\n };\n}\n","// core/titles.ts — @ai-matrx/associations/core\n//\n// Batched entity-title resolution — the \"UUIDs never render\" primitive.\n// Ported behavior-verbatim from matrx-frontend\n// `features/scopes/service/entityTitles.ts` (associations extraction W2,\n// 2026-08-29). One structural inversion: the MODULE-level session Map (banned\n// by the packaging standard — dual-loaded graphs silently split module\n// state) becomes STORE-INSTANCE state — the cache lives on the titles\n// service the store constructs once, so there is nothing to split and no\n// globalThis slot is needed.\n//\n// Association edges SHOULD carry a `label` stamped at attach time; this\n// service covers the rest (legacy unlabeled edges, rows renamed since\n// attach). Given a token + ids, it resolves titles through the\n// registry-driven candidate RPC and memoizes per store lifetime. Tokens\n// without a title column (or unregistered tokens) resolve to nothing —\n// callers fall back to `Untitled <label>` via `fallback`.\n\nimport { humanizeIdentifier } from \"@ai-matrx/kit/text-case\";\nimport type { CoreDeps } from \"./deps\";\nimport type { CandidatesServiceApi } from \"./candidates\";\n\nconst CHUNK = 200;\n\nexport function entityTitleCacheKey(token: string, id: string): string {\n return `${token}:${id}`;\n}\n\nexport interface TitlesServiceApi {\n /** Read the cache synchronously (for render paths after a fetch settled). */\n get(token: string, id: string): string | null;\n /**\n * Push a known-fresh title into the cache (after a rename or a create), so\n * surfaces that resolve through this service never show a stale name.\n */\n prime(token: string, id: string, title: string): void;\n /** Display fallback when no label and no fetched title exist. */\n fallback(token: string): string;\n /**\n * Resolve titles for `ids` of one token. Returns ONLY the resolved entries\n * (cache + fresh reads); missing rows (deleted, no access) stay absent.\n */\n fetch(token: string, ids: string[]): Promise<Map<string, string>>;\n}\n\nexport function createTitlesService(\n deps: CoreDeps,\n candidates: CandidatesServiceApi,\n): TitlesServiceApi {\n const { registry, errorSink } = deps;\n\n /** `${token}:${id}` → resolved title. Store-lifetime; titles change rarely. */\n const titleCache = new Map<string, string>();\n\n return {\n get(token, id) {\n return titleCache.get(entityTitleCacheKey(token, id)) ?? null;\n },\n\n prime(token, id, title) {\n const trimmed = title.trim();\n if (trimmed) titleCache.set(entityTitleCacheKey(token, id), trimmed);\n },\n\n fallback(token) {\n const info = registry.tryGetEntityInfo(token);\n // Never the raw token (\"Untitled html_page\"): the ONE humanizer names it.\n return `Untitled ${info?.label ?? humanizeIdentifier(token)}`;\n },\n\n async fetch(token, ids) {\n const out = new Map<string, string>();\n if (ids.length === 0) return out;\n\n const info = registry.tryGetEntityInfo(token);\n const missing: string[] = [];\n for (const id of ids) {\n const cached = titleCache.get(entityTitleCacheKey(token, id));\n if (cached !== undefined) out.set(id, cached);\n else missing.push(id);\n }\n if (missing.length === 0 || !info?.titleColumn) return out;\n\n for (let index = 0; index < missing.length; index += CHUNK) {\n const chunk = missing.slice(index, index + CHUNK);\n const { data, error } = await candidates.callReferenceSearchCandidates({\n p_token: token,\n p_ids: chunk,\n p_limit: chunk.length,\n });\n if (error) {\n errorSink({\n code: \"title_rpc_failed\",\n message: `[fetchEntityTitles] candidate RPC failed for \"${token}\": ${error.message}`,\n context: {\n token,\n chunkStart: index,\n chunkSize: chunk.length,\n detail: error,\n },\n });\n continue;\n }\n for (const row of data) {\n const title = row.title?.trim();\n if (!title) continue;\n titleCache.set(entityTitleCacheKey(token, row.id), title);\n out.set(row.id, title);\n }\n }\n return out;\n },\n };\n}\n","// core/entityRows.ts — @ai-matrx/associations/core\n//\n// THE GENERIC \"CREATE A NEW ONE\" GOES THROUGH THE GENERIC DOOR.\n//\n// 🚨 WHAT THIS CLOSES (DOORS-ONLY-4, 2026-09-21). Until this version both functions\n// below wrote the registered entity's backing table DIRECTLY:\n//\n// dataSource.schema(info.schema).from(info.table)\n// .insert({ [titleColumn]: title, created_by, organization_id })\n//\n// That is the ONE generic write path on the platform — one call site (the reference\n// picker's \"create a new one\") generic over all 650 registry tokens. The doors-only\n// ruling (`platform` and `iam` are not client-writable schemas; every write goes\n// through a named SECURITY DEFINER door) therefore broke it SILENTLY, one table at a\n// time, for forty-four already-closed tables before anybody looked. The failure\n// surfaces as a `42501` inside a picker toast, which no release notices.\n//\n// So the write is now `public.entity_row_create` / `public.entity_row_rename`: one\n// registry-driven door that resolves schema, table and title column from\n// `platform.entity_types` — the same registry `entity-types.generated.ts` is emitted\n// from — decides on the one ladder, and stamps `created_by` from `auth.uid()`. It is\n// the same fix for every token, present and future, instead of a door per table.\n//\n// AND IT REFUSES BY NAME two things the direct path merely FAILED at:\n// • a token whose `audit_class` is `machinery` — access machinery owns the inputs\n// the access resolver consumes, and a generic \"make me a row\" affordance must\n// never reach it;\n// • a token whose table has no `organization_id` column. `iam.organizations` is\n// exactly that, and the picker had been sending it one and getting\n// `42703 column does not exist` for as long as it has passed an org — a dead path\n// that read as a working feature. Creating an organization is `public.org_create`.\n//\n// TWO THINGS THE DOOR CANNOT DO, AND NEITHER IS SWALLOWED:\n// • `extraColumns` — the door writes exactly the name, the owner and the\n// organization. A caller that hands over extra columns gets a loud `{ok:false}`\n// naming them and naming the remedy (its feature's own create service), never a\n// row quietly missing the NOT NULL column it was meant to carry.\n// • a create with no organization — the door requires one. That is refused here,\n// before the round trip, with the same sentence a human can act on.\n//\n// On success both functions prime the shared title cache so every title-resolving\n// surface sees the new name, exactly as before.\n\nimport type { EntityTypeToken } from \"../entity-types.generated\";\nimport type { CoreDeps } from \"./deps\";\nimport type { TitlesServiceApi } from \"./titles\";\nimport { rpcDoor } from \"./doors\";\nimport { entityRowCreate, entityRowRename } from \"../db/public\";\n\nexport type EntityRowResult =\n | { ok: true; data: { id: string; title: string } }\n | { ok: false; error: string };\n\nexport interface CreateEntityRowArgs {\n /** The new row's human name — written to the registry `titleColumn`. */\n title: string;\n /**\n * The organization the new row belongs to. REQUIRED by\n * `public.entity_row_create`: every creatable token's table carries\n * `organization_id`, and the door refuses a row with nobody owning it.\n */\n orgId?: string | null;\n /**\n * 🚨 NO LONGER WRITABLE THROUGH THIS SERVICE (DOORS-ONLY-4). The door writes the\n * name, the owner and the organization and nothing else, so a non-empty value here\n * is REFUSED with the columns named rather than dropped on the floor. A token whose\n * table needs more than a name is created by its own feature's create service; this\n * generic path then only renames it.\n */\n extraColumns?: Record<string, unknown>;\n}\n\nexport interface EntityRowsServiceApi {\n createEntityRow(\n token: EntityTypeToken,\n args: CreateEntityRowArgs,\n ): Promise<EntityRowResult>;\n renameEntityRow(\n token: EntityTypeToken,\n id: string,\n title: string,\n ): Promise<{ ok: true } | { ok: false; error: string }>;\n}\n\nexport function createEntityRowsService(\n deps: CoreDeps,\n titles: TitlesServiceApi,\n): EntityRowsServiceApi {\n const { dataSource, registry, errorSink } = deps;\n\n /**\n * The registry still decides whether a token is nameable AT ALL, before the round\n * trip — a token with no `title_column` cannot be created from a name, and saying so\n * here costs nothing and reads better than the door's own refusal.\n */\n function requireTitleColumn(\n token: EntityTypeToken,\n op: string,\n ): { ok: true } | { ok: false; error: string } {\n const info = registry.getEntityInfo(token);\n if (!info.titleColumn) {\n const error =\n `Entity \"${token}\" has no title_column in platform.entity_types — ` +\n `add one in the registry before ${op}`;\n errorSink({\n code: \"missing_title_column\",\n message: `[entityRows] ${error}`,\n context: { token },\n });\n return { ok: false, error };\n }\n return { ok: true };\n }\n\n return {\n /**\n * Create one row of `token`'s backing table named `title`, through\n * `public.entity_row_create`. The door stamps `created_by` from `auth.uid()`,\n * checks the caller can act in the organization, and refuses machinery tokens and\n * tables with no organization by name. Returns the new row's id + title. The\n * caller wires associations afterwards — this layer never writes edges.\n */\n async createEntityRow(token, args) {\n const gate = requireTitleColumn(token, \"creating rows\");\n if (!gate.ok) return gate;\n const title = args.title.trim();\n if (!title) return { ok: false, error: \"Name is required\" };\n\n // NOTHING FAILS SILENTLY. The door has no arm for these, so they are refused\n // with their own names in the sentence rather than dropped.\n const extras = Object.keys(args.extraColumns ?? {});\n if (extras.length > 0) {\n const error =\n `A new ${registry.getEntityInfo(token).label} cannot be created ` +\n `here with ${extras.join(\", \")}: the shared create door writes the name, ` +\n `the owner and the organization and nothing else. Create it with this ` +\n `feature's own create service, then attach it.`;\n errorSink({\n code: \"entity_row_extra_columns_unsupported\",\n message: `[createEntityRow] extraColumns are not writable through entity_row_create for \"${token}\": ${extras.join(\", \")}`,\n context: { token, extras },\n });\n return { ok: false, error };\n }\n if (!args.orgId) {\n const error =\n `Name the organization this ${registry.getEntityInfo(token).label} belongs to.`;\n errorSink({\n code: \"entity_row_missing_organization\",\n message: `[createEntityRow] no organization supplied for \"${token}\"; entity_row_create requires one`,\n context: { token },\n });\n return { ok: false, error };\n }\n\n try {\n const { data, error } = await rpcDoor(dataSource, entityRowCreate, {\n p_token: token,\n p_title: title,\n p_organization_id: args.orgId,\n });\n if (error) {\n errorSink({\n code: \"entity_row_insert_failed\",\n message: `[createEntityRow] entity_row_create failed for \"${token}\": ${error.message}`,\n context: { token, detail: error },\n });\n return { ok: false, error: error.message };\n }\n const row = data as { id?: unknown; title?: unknown } | null;\n if (!row || typeof row.id !== \"string\" || !row.id) {\n const msg = \"The create door returned no record.\";\n errorSink({\n code: \"entity_row_insert_failed\",\n message: `[createEntityRow] entity_row_create returned no id for \"${token}\"`,\n context: { token, detail: data },\n });\n return { ok: false, error: msg };\n }\n const id = row.id;\n const named = typeof row.title === \"string\" && row.title ? row.title : title;\n titles.prime(token, id, named);\n return { ok: true, data: { id, title: named } };\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"Failed to create\";\n errorSink({\n code: \"entity_row_insert_failed\",\n message: `[createEntityRow] exception for \"${token}\": ${msg}`,\n context: { token, detail: e },\n });\n return { ok: false, error: msg };\n }\n },\n\n /**\n * Rename one row of `token`'s table through `public.entity_row_rename`. The door\n * decides on the one ladder — the row's author, `editor` on the row, or a platform\n * admin — and answers \"there is no such thing here\" rather than telling a caller\n * that somebody else's row exists.\n */\n async renameEntityRow(token, id, title) {\n const gate = requireTitleColumn(token, \"renaming rows\");\n if (!gate.ok) return gate;\n const trimmed = title.trim();\n if (!trimmed) return { ok: false, error: \"Name is required\" };\n\n try {\n const { error } = await rpcDoor(dataSource, entityRowRename, {\n p_token: token,\n p_id: id,\n p_title: trimmed,\n });\n if (error) {\n errorSink({\n code: \"entity_row_update_failed\",\n message: `[renameEntityRow] entity_row_rename failed for \"${token}\": ${error.message}`,\n context: { token, id, detail: error },\n });\n return { ok: false, error: error.message };\n }\n titles.prime(token, id, trimmed);\n return { ok: true };\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"Failed to rename\";\n errorSink({\n code: \"entity_row_update_failed\",\n message: `[renameEntityRow] exception for \"${token}\": ${msg}`,\n context: { token, id, detail: e },\n });\n return { ok: false, error: msg };\n }\n },\n };\n}\n","// core/helpers.ts — @ai-matrx/associations/core\n//\n// TYPED convenience wrappers over the canonical associations service for the\n// common COMPOSITE shapes — \"attach one thing to many\", \"attach many things\n// to one\", \"create N edges in one call\", \"replace a whole set\". Ported\n// behavior-verbatim from matrx-frontend\n// `features/scopes/service/associationHelpers.ts` (associations extraction\n// W2, 2026-08-29). They add NO new DB access: every wrapper composes the\n// same `assoc_*` primitives, so the single-chokepoint + runtime-guard\n// guarantees still hold.\n//\n// Why wrappers (not more RPCs): per-entity / per-shape SQL functions are an\n// N-explosion and each copy reintroduces bugs. Composition belongs in typed\n// helpers; the DB layer stays generic and dumb.\n//\n// Type safety: a `source` is any registered entity (`EntityTypeToken`); a\n// `target` is one of the deliberate container types\n// (`AssociationTargetType`). Bad tokens / non-UUID ids are caught by the\n// base service's guards and surface as `invalid_argument` before any RPC.\n\nimport type { AssociationTargetType } from \"../edges\";\nimport type { EntityTypeToken } from \"../entity-types.generated\";\nimport {\n isAssociationsRpcErr,\n type AssociationsRpcError,\n type AssociationsRpcResult,\n} from \"../results\";\nimport { err, ok } from \"./rpcResult\";\nimport { ASSOC_ADD_MANY_CHUNK, type AssociationsServiceApi } from \"./associationsService\";\n\n/** A typed reference to a single row — `{ type, id }`. */\nexport interface EntityRef {\n type: EntityTypeToken;\n id: string;\n}\n\n/** A container reference — the deliberate set an edge may point at. */\nexport interface ContainerRef {\n type: AssociationTargetType;\n id: string;\n}\n\n/** Per-edge attributes shared by the link helpers. */\nexport interface EdgeAttrs {\n orgId?: string;\n label?: string;\n metadata?: unknown;\n role?: string;\n position?: number;\n}\n\n/** One fully-specified edge for {@link AssociationHelpersApi.linkEdges}. */\nexport interface EdgeSpec extends EdgeAttrs {\n source: EntityRef;\n target: ContainerRef;\n}\n\n/** Combine many per-edge errors into one loud, described result error. */\nfunction combine(\n failures: AssociationsRpcError[],\n total: number,\n): AssociationsRpcError {\n const first = failures[0] ?? {\n code: \"internal\" as const,\n message: \"unknown failure\",\n };\n return {\n code: failures.every((f) => f.code === first.code) ? first.code : \"internal\",\n message: `${failures.length}/${total} association edge(s) failed: ${first.message}`,\n detail: failures,\n };\n}\n\nfunction errArgs(\n e: AssociationsRpcError,\n): [AssociationsRpcError[\"code\"], string, unknown] {\n return [e.code, e.message, e.detail];\n}\n\nexport interface AssociationHelpersApi {\n /**\n * Add an arbitrary batch of edges in one call (idempotent per edge).\n * Written through the batch door (`platform.assoc_add_many`) in sequential chunks of\n * {@link ASSOC_ADD_MANY_CHUNK}; each chunk is ONE transaction (all or nothing). The result\n * is `ok` with the ids in input order only when ALL succeed, otherwise `err` whose\n * `detail` lists a failure for every edge that was not written (chunks that DID succeed\n * remain applied — re-running is safe via ON CONFLICT).\n */\n linkEdges(edges: EdgeSpec[]): Promise<AssociationsRpcResult<{ ids: string[] }>>;\n /** Attach ONE source to MANY containers in a single shot. */\n linkOneToMany(args: {\n source: EntityRef;\n targets: ContainerRef[];\n attrs?: EdgeAttrs;\n }): Promise<AssociationsRpcResult<{ ids: string[] }>>;\n /** Attach MANY sources to ONE container in a single shot. */\n linkManyToOne(args: {\n sources: EntityRef[];\n target: ContainerRef;\n attrs?: EdgeAttrs;\n }): Promise<AssociationsRpcResult<{ ids: string[] }>>;\n /**\n * REPLACE the full set of a source's edges of one container type (adds\n * missing, removes extras) in one DB transaction — the set-semantics\n * one-shot. Thin, named pass-through to `assoc_set_targets`.\n */\n replaceTargets(args: {\n source: EntityRef;\n targetType: AssociationTargetType;\n targetIds: string[];\n orgId?: string;\n role?: string;\n }): Promise<AssociationsRpcResult<null>>;\n /**\n * Wire edges onto a JUST-CREATED entity. The caller inserts its own row\n * (entity tables are feature-owned), then passes the new id here to attach\n * it to any number of containers (orphan-on-partial-fail is harmless and\n * re-runnable). `created` is the new entity; it becomes the edges' SOURCE.\n */\n linkCreated(args: {\n created: EntityRef;\n targets: ContainerRef[];\n attrs?: EdgeAttrs;\n }): Promise<AssociationsRpcResult<{ ids: string[] }>>;\n /** Remove an arbitrary batch of edges (best-effort; no-op per missing edge). */\n unlinkEdges(\n edges: { source: EntityRef; target: ContainerRef; role?: string }[],\n ): Promise<AssociationsRpcResult<null>>;\n}\n\nexport function createAssociationHelpers(\n service: AssociationsServiceApi,\n): AssociationHelpersApi {\n async function linkEdges(\n edges: EdgeSpec[],\n ): Promise<AssociationsRpcResult<{ ids: string[] }>> {\n if (edges.length === 0) return ok({ ids: [] });\n const toArgs = (e: EdgeSpec) => ({\n sourceType: e.source.type,\n sourceId: e.source.id,\n targetType: e.target.type,\n targetId: e.target.id,\n ...(e.orgId !== undefined ? { orgId: e.orgId } : {}),\n ...(e.label !== undefined ? { label: e.label } : {}),\n ...(e.metadata !== undefined ? { metadata: e.metadata } : {}),\n ...(e.role !== undefined ? { role: e.role } : {}),\n ...(e.position !== undefined ? { position: e.position } : {}),\n });\n // The file -> conversation pair has its own stricter door and is not batchable; every\n // other edge goes through the batch door in chunks — ONE transaction per chunk, chunks\n // one after another (never an unbounded fan-out of single adds: 140 concurrent\n // assoc_add calls lost 69 edges on 2026-09-26).\n const ids: (string | undefined)[] = new Array(edges.length).fill(undefined);\n const failures: AssociationsRpcError[] = [];\n const batchable: number[] = [];\n for (let i = 0; i < edges.length; i++) {\n const e = edges[i]!;\n if (e.source.type === \"file\" && e.target.type === \"conversation\") {\n const r = await service.add(toArgs(e));\n if (isAssociationsRpcErr(r)) failures.push(r.error);\n else ids[i] = r.data.id;\n } else batchable.push(i);\n }\n for (let at = 0; at < batchable.length; at += ASSOC_ADD_MANY_CHUNK) {\n const slice = batchable.slice(at, at + ASSOC_ADD_MANY_CHUNK);\n const r = await service.addMany(slice.map((i) => toArgs(edges[i]!)));\n if (isAssociationsRpcErr(r)) {\n // The chunk is atomic: none of its edges were written. Every one of them failed.\n for (let k = 0; k < slice.length; k++) failures.push(r.error);\n } else slice.forEach((edgeIndex, k) => (ids[edgeIndex] = r.data.ids[k]));\n }\n if (failures.length > 0)\n return err(...errArgs(combine(failures, edges.length)));\n return ok({ ids: ids as string[] });\n }\n\n return {\n linkEdges,\n\n async linkOneToMany({ source, targets, attrs }) {\n return linkEdges(targets.map((target) => ({ source, target, ...attrs })));\n },\n\n async linkManyToOne({ sources, target, attrs }) {\n return linkEdges(sources.map((source) => ({ source, target, ...attrs })));\n },\n\n async replaceTargets(args) {\n return service.setTargets({\n sourceType: args.source.type,\n sourceId: args.source.id,\n targetType: args.targetType,\n targetIds: args.targetIds,\n ...(args.orgId !== undefined ? { orgId: args.orgId } : {}),\n ...(args.role !== undefined ? { role: args.role } : {}),\n });\n },\n\n async linkCreated(args) {\n return linkEdges(\n args.targets.map((target) => ({\n source: args.created,\n target,\n ...args.attrs,\n })),\n );\n },\n\n async unlinkEdges(edges) {\n if (edges.length === 0) return ok(null);\n const results = await Promise.all(\n edges.map((e) =>\n service.remove({\n sourceType: e.source.type,\n sourceId: e.source.id,\n targetType: e.target.type,\n targetId: e.target.id,\n ...(e.role !== undefined ? { role: e.role } : {}),\n }),\n ),\n );\n const failures: AssociationsRpcError[] = [];\n for (const r of results) if (isAssociationsRpcErr(r)) failures.push(r.error);\n if (failures.length > 0)\n return err(...errArgs(combine(failures, edges.length)));\n return ok(null);\n },\n };\n}\n","// core/commentsService.ts — @ai-matrx/associations/core\n//\n// THE SOLE CHOKEPOINT for the unified comment table — `platform.comments`\n// (W6, ruling C4: the comments canonical UI is built IN this package).\n// Behavior ported verbatim from matrx-frontend\n// `features/comments/service/commentsService.ts` (2026-08-29); the supabase\n// singleton / `requireUserId` / rpcResult seams inverted onto the package's\n// dataSource / identity / rpc deps, and the package's guard wall added in\n// front of every call (token writes-strict per C18, uuid wall).\n//\n// The client holds NO grant on `platform.comments`; every read/write goes\n// through the four PUBLIC SECURITY-DEFINER RPCs (`cmt_list` / `cmt_add` /\n// `cmt_edit` / `cmt_delete`) — part of the demanded schema (probed by\n// the demanded RPC contract), called only from THIS module. Methods always\n// return an `AssociationsRpcResult`, NEVER throw.\n//\n// Access lives in the RPCs, not here: `cmt_list` org-filters inside;\n// `cmt_add` resolves the org from THE COMMENTED RECORD ITSELF, for every\n// registered entity type (`orgId` overrides and must AGREE with the record, or\n// the RPC raises 22023); where neither the call nor the record names an\n// organization it raises 23502 rather than filing the comment in the author's\n// own workspace (DEFAULT-ORG-3, 2026-09-22);\n// `cmt_edit` is author-only; `cmt_delete` is author-or-org-member with\n// soft-delete. This package makes zero access decisions (link ≠ grant).\n\nimport type { CommentAnchor, PlatformComment } from \"../comments\";\nimport type { AssociationsRpcResult } from \"../results\";\nimport { firstError } from \"./guards\";\nimport type { CoreDeps } from \"./deps\";\nimport { rpcDoor } from \"./doors\";\nimport { cmtAdd, cmtDelete, cmtEdit, cmtList } from \"../db/public\";\n\n// Shape of one `cmt_list` row (snake_case, straight from PG).\ninterface CmtListRow {\n id: string;\n organization_id: string | null;\n entity_type: string;\n entity_id: string;\n parent_id: string | null;\n body: string;\n created_at: string;\n updated_at: string;\n created_by: string | null;\n author_email: string | null;\n author_display_name: string | null;\n author_avatar_url: string | null;\n anchor?: CommentAnchor | null;\n author_agent_id?: string | null;\n author_agent_name?: string | null;\n}\n\nfunction toComment(row: CmtListRow): PlatformComment {\n return {\n id: row.id,\n orgId: row.organization_id ?? null,\n entityType: row.entity_type,\n entityId: row.entity_id,\n parentId: row.parent_id ?? null,\n body: row.body,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n createdBy: row.created_by ?? null,\n author: {\n email: row.author_email ?? null,\n displayName: row.author_display_name ?? null,\n avatarUrl: row.author_avatar_url ?? null,\n },\n authorAgent: row.author_agent_id\n ? { id: row.author_agent_id, name: row.author_agent_name ?? null }\n : null,\n anchor: row.anchor && typeof row.anchor === \"object\" ? row.anchor : null,\n };\n}\n\nexport interface AddCommentArgs {\n /** Registered entity-type token the comment hangs on (writes-strict, C18). */\n entityType: string;\n entityId: string;\n body: string;\n /** Reply target — an existing comment's id. Top-level when omitted. */\n parentId?: string | null;\n /** Org override; the RPC resolves task-org/personal-org when omitted. */\n orgId?: string | null;\n /** Where on the record the comment points (a `part_anchor`, a `text_anchor`); whole record when omitted. */\n anchor?: CommentAnchor | null;\n}\n\nexport interface CommentsServiceApi {\n listForEntity(\n entityType: string,\n entityId: string,\n ): Promise<AssociationsRpcResult<{ comments: PlatformComment[] }>>;\n add(args: AddCommentArgs): Promise<AssociationsRpcResult<{ id: string }>>;\n edit(id: string, body: string): Promise<AssociationsRpcResult<null>>;\n remove(id: string): Promise<AssociationsRpcResult<null>>;\n}\n\nexport function createCommentsService(deps: CoreDeps): CommentsServiceApi {\n const { dataSource, identity, guards } = deps;\n const { ok, err, mapPgError, mapPgErrorPair } = deps.rpc;\n\n return {\n /**\n * All comments on `${entityType}:${entityId}`, org-filtered by RLS\n * inside the RPC, ordered oldest→newest. Build the thread from each\n * row's `parentId` (top-level comments have `parentId === null`).\n */\n async listForEntity(entityType, entityId) {\n try {\n identity.requireUserId();\n const token = guards.normalizeEntityToken(entityType);\n const invalid = firstError(\n guards.checkToken(\"entityType\", token),\n guards.checkUuid(\"entityId\", entityId),\n );\n if (invalid) return { ok: false, error: invalid };\n const { data, error } = await rpcDoor(dataSource, cmtList, {\n p_entity_type: token,\n p_entity_id: entityId,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as CmtListRow[];\n return ok({ comments: rows.map(toComment) });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Post `body` on `${entityType}:${entityId}`; pass `parentId` to reply.\n * Returns the new comment id.\n */\n async add(args) {\n try {\n identity.requireUserId();\n const token = guards.normalizeEntityToken(args.entityType);\n const invalid = firstError(\n guards.checkToken(\"entityType\", token),\n guards.checkUuid(\"entityId\", args.entityId),\n args.parentId != null\n ? guards.checkUuid(\"parentId\", args.parentId)\n : null,\n );\n if (invalid) return { ok: false, error: invalid };\n if (!args.body || args.body.trim().length === 0) {\n return err(\"invalid_argument\", \"comment body must be non-empty\");\n }\n const { data, error } = await rpcDoor(dataSource, cmtAdd, {\n p_entity_type: token,\n p_entity_id: args.entityId,\n p_body: args.body,\n p_parent_id: args.parentId ?? undefined,\n p_org_id: args.orgId ?? undefined,\n ...(args.anchor ? { p_anchor: args.anchor } : {}),\n });\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\"internal\", \"cmt_add returned no comment id\");\n }\n return ok({ id: data });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /** Replace a comment's body. Author-only; the RPC rejects everyone else. */\n async edit(id, body) {\n try {\n identity.requireUserId();\n const invalid = guards.checkUuid(\"commentId\", id);\n if (invalid) return { ok: false, error: invalid };\n if (!body || body.trim().length === 0) {\n return err(\"invalid_argument\", \"comment body must be non-empty\");\n }\n const { error } = await rpcDoor(dataSource, cmtEdit, {\n p_id: id,\n p_body: body,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /** Soft-delete a comment. Author or org member; enforced server-side. */\n async remove(id) {\n try {\n identity.requireUserId();\n const invalid = guards.checkUuid(\"commentId\", id);\n if (invalid) return { ok: false, error: invalid };\n const { error } = await rpcDoor(dataSource, cmtDelete, { p_id: id });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n };\n}\n","// core/store.ts — @ai-matrx/associations/core\n//\n// THE package-owned, store-agnostic cache (design Decision 3) — the one\n// runtime object a host constructs (`createAssociationsStore(cfg)`),\n// replacing matrx-frontend's ~530 lines of Redux fragments\n// (`scopesTree.associationsByKey` + `categoriesByDimension` + the\n// association/category thunks + selectors) with a subscribable store the\n// /react hooks (W3) ride via `useSyncExternalStore`. Behavior ported\n// verbatim from `features/scopes/redux/thunks/{associations,categories}.ts`\n// + the matching `scopesSlice` reducers + selectors (2026-08-29):\n//\n// • lazy `load` with per-key IN-FLIGHT DEDUP (the thunks' Map) and\n// `status === \"ready\"` short-circuit unless `force`;\n// • pending keeps previous edges AND the visible error (consumers use\n// status to disable/spin the same retry control);\n// • add/remove reload BOTH endpoints on success (a write touches TWO\n// endpoints — the source and the target each see the edge);\n// • setTargets reloads the SOURCE only (the only endpoint with a\n// deterministic post-state);\n// • createCategory does the optimistic ECHO-INSERT then force-reloads to\n// pick up server-derived fields authoritatively;\n// • `getEdges`/`getCategories` return a STABLE idle default (never a fresh\n// object per read — the useSyncExternalStore contract).\n//\n// THE NEVER-TOUCHES-CONTEXT INVARIANT, now structural: the thunks' law\n// \"NEVER dispatch appContextSlice actions\" (a durable association is NOT the\n// user's active working context) is carried over as architecture — this\n// package has no import path to any host store, and a write notifies ONLY\n// the association subscribers of the endpoints it touched (proven by test).\n//\n// Invalidation is owned here (subscribe/notify + `invalidate`). It does NOT\n// depend on `@ai-matrx/kit` — but the shape is deliberately bridgeable: a\n// host binding may register `store.invalidate` under kit `/invalidation`\n// names so ubiquitous modules can invalidate association caches with zero\n// import edge into this package's chunk.\n//\n// NO module-level mutable state anywhere in /core: every cache lives on the\n// store instance the host constructs, so the dual-bundle split-registry\n// failure the packaging standard's globalThis-slot rule exists for cannot\n// occur (there is no module state to split).\n\nimport type {\n AssociationsEntry,\n AssociationTargetType,\n CategoriesEntry,\n CategoryDimension,\n PlatformCategory,\n} from \"../edges\";\nimport type { CommentAnchor, CommentsEntry } from \"../comments\";\nimport { isAssociationsRpcErr } from \"../results\";\nimport type {\n AssociationsConfig,\n AssociationsDataSource,\n ErrorSink,\n} from \"../ports\";\nimport { asAssociationsDataSource } from \"../ports\";\nimport { createDefaultErrorSink } from \"./defaultErrorSink\";\nimport type { CoreDeps } from \"./deps\";\nimport { createAssociationGuards } from \"./guards\";\nimport { createRpcResultHelpers } from \"./rpcResult\";\nimport { createEntityRegistry, type EntityRegistry } from \"./registry\";\nimport {\n createAssociationsService,\n type AssociationsServiceApi,\n} from \"./associationsService\";\nimport {\n createCategoriesService,\n type CategoriesServiceApi,\n} from \"./categoriesService\";\nimport {\n createFavoritesService,\n type FavoritesServiceApi,\n} from \"./favoritesService\";\nimport { createCandidatesService, type CandidatesServiceApi } from \"./candidates\";\nimport { createTitlesService, type TitlesServiceApi } from \"./titles\";\nimport {\n createEntityRowsService,\n type EntityRowsServiceApi,\n} from \"./entityRows\";\nimport {\n createAssociationHelpers,\n type AssociationHelpersApi,\n} from \"./helpers\";\nimport {\n createCommentsService,\n type CommentsServiceApi,\n} from \"./commentsService\";\n\n/** Cache key for one association endpoint. */\nexport function associationsKey(type: string, id: string): string {\n return `${type}:${id}`;\n}\n\nexport interface AssociationWriteResult {\n ok: boolean;\n /** Set on a successful single-edge `add`. */\n id?: string;\n error?: string;\n}\n\nexport interface CategoryMutationResult {\n ok: boolean;\n /** Set on a successful mutation. */\n id?: string;\n error?: string;\n}\n\nconst IDLE_ASSOCIATIONS: AssociationsEntry = Object.freeze({\n status: \"idle\",\n edges: Object.freeze([]) as unknown as AssociationsEntry[\"edges\"],\n fetchedAt: null,\n error: null,\n});\n\nconst IDLE_CATEGORIES: CategoriesEntry = Object.freeze({\n status: \"idle\",\n categories: Object.freeze([]) as unknown as CategoriesEntry[\"categories\"],\n fetchedAt: null,\n error: null,\n});\n\nconst IDLE_COMMENTS: CommentsEntry = Object.freeze({\n status: \"idle\",\n comments: Object.freeze([]) as unknown as CommentsEntry[\"comments\"],\n fetchedAt: null,\n error: null,\n});\n\nexport interface CommentMutationResult {\n ok: boolean;\n /** Set on a successful `addComment`. */\n id?: string;\n error?: string;\n}\n\nexport interface AssociationsStore {\n // ── the cache (association endpoints) ────────────────────────────────\n /** Stable, sync read of one endpoint's entry (idle default when uncached). */\n getEdges(type: string, id: string): AssociationsEntry;\n /**\n * Lazy load of every edge touching `${type}:${id}` (both directions).\n * Deduped per key; `status === \"ready\"` short-circuits unless `force`.\n */\n load(type: string, id: string, opts?: { force?: boolean }): Promise<void>;\n /** External-store contract: notified whenever the key's entry changes. */\n subscribe(key: string, cb: () => void): () => void;\n /** Attach source → target; on success reloads BOTH endpoints. */\n add(args: {\n sourceType: string;\n sourceId: string;\n targetType: AssociationTargetType;\n targetId: string;\n orgId?: string;\n label?: string;\n role?: string;\n metadata?: unknown;\n replaceMetadata?: boolean;\n }): Promise<AssociationWriteResult>;\n /** Detach source → target; on success reloads BOTH endpoints. */\n remove(args: {\n sourceType: string;\n sourceId: string;\n targetType: string;\n targetId: string;\n role?: string;\n }): Promise<AssociationWriteResult>;\n /** Replace the source's `targetType` edge set; reloads the SOURCE. */\n setTargets(args: {\n sourceType: string;\n sourceId: string;\n targetType: AssociationTargetType;\n targetIds: string[];\n orgId?: string;\n role?: string;\n }): Promise<AssociationWriteResult>;\n /** Reset one endpoint to idle and notify its subscribers. */\n invalidate(type: string, id: string): void;\n /** Reset every association endpoint, category facet, and comment thread. */\n invalidateAll(): void;\n\n // ── the cache (category facets) ──────────────────────────────────────\n getCategories(dimension: CategoryDimension): CategoriesEntry;\n loadCategories(\n dimension: CategoryDimension,\n opts?: { force?: boolean },\n ): Promise<void>;\n subscribeCategories(dimension: CategoryDimension, cb: () => void): () => void;\n /** Create + echo-insert + authoritative force reload. Returns the new id. */\n createCategory(args: {\n dimension: CategoryDimension;\n name: string;\n orgId: string;\n parentId?: string | null;\n color?: string | null;\n icon?: string | null;\n slug?: string | null;\n }): Promise<CategoryMutationResult>;\n updateCategory(args: {\n dimension: CategoryDimension;\n id: string;\n name: string;\n slug: string | null;\n color: string | null;\n icon: string | null;\n position: number | null;\n }): Promise<CategoryMutationResult>;\n reparentCategory(args: {\n dimension: CategoryDimension;\n id: string;\n parentId: string | null;\n }): Promise<CategoryMutationResult>;\n deleteCategory(args: {\n dimension: CategoryDimension;\n id: string;\n }): Promise<CategoryMutationResult>;\n\n // ── the cache (comment threads, W6) ──────────────────────────────────\n /** Stable, sync read of one entity's comment thread (idle when uncached). */\n getComments(type: string, id: string): CommentsEntry;\n /**\n * Lazy load of every comment on `${type}:${id}` (oldest→newest; thread by\n * `parentId`). Deduped per key; `status === \"ready\"` short-circuits unless\n * `force`.\n */\n loadComments(\n type: string,\n id: string,\n opts?: { force?: boolean },\n ): Promise<void>;\n /** External-store contract for one entity's comment thread. */\n subscribeComments(key: string, cb: () => void): () => void;\n /** Post a comment (or a reply); on success force-reloads the thread. */\n addComment(args: {\n entityType: string;\n entityId: string;\n body: string;\n parentId?: string | null;\n orgId?: string | null;\n anchor?: CommentAnchor | null;\n }): Promise<CommentMutationResult>;\n /** Edit a comment body (author-only in the RPC); reloads the thread. */\n editComment(args: {\n entityType: string;\n entityId: string;\n id: string;\n body: string;\n }): Promise<CommentMutationResult>;\n /** Soft-delete a comment (author/org member in the RPC); reloads the thread. */\n deleteComment(args: {\n entityType: string;\n entityId: string;\n id: string;\n }): Promise<CommentMutationResult>;\n /** Reset one entity's comment thread to idle and notify its subscribers. */\n invalidateComments(type: string, id: string): void;\n\n // ── the seams under the cache ────────────────────────────────────────\n /** Batched title resolution + the session cache + prime. */\n titles: TitlesServiceApi;\n /** Per-user favorite/pinned/hidden state (`ues_*`). */\n favorites: FavoritesServiceApi;\n /** Candidate reads for the pickers. */\n candidates: CandidatesServiceApi;\n /** Generic registry-convention row create/rename. */\n entityRows: EntityRowsServiceApi;\n /** Composite link helpers over the chokepoint. */\n helpers: AssociationHelpersApi;\n /** The registry merge engine (generated metadata + host overlay). */\n registry: EntityRegistry;\n /**\n * The raw chokepoint services — every RPC family, results-enveloped.\n * `associations` writes here do NOT touch the cache; use the store-level\n * `add`/`remove`/`setTargets` when a cached surface must stay fresh.\n */\n services: {\n associations: AssociationsServiceApi;\n categories: CategoriesServiceApi;\n comments: CommentsServiceApi;\n };\n /** Merge more host overlay entries in (icons/routes/candidate loaders). */\n registerEntityOverlay: EntityRegistry[\"registerEntityOverlay\"];\n /**\n * The bound scream seam (W3, additive): /react surfaces route their loud\n * recoveries here (the originals' console.error sites) without a second\n * sink binding. Same function the host passed at construction.\n */\n errorSink: ErrorSink;\n /**\n * The bound data seam (0.6.0, additive): the provider's demanded-schema\n * boot probe reads it so hosts stop re-exporting their dataSource just to\n * run a check the package owns.\n */\n dataSource: AssociationsDataSource;\n /**\n * The bound identity port (W3, additive): /react hooks that FILTER by the\n * current user (candidate owner scoping) read it leniently; write paths\n * keep going through the services, where `requireUserId` failures stay\n * loud. Same object the host passed at construction.\n */\n identity: AssociationsConfig[\"identity\"];\n}\n\n/**\n * Build the one store a host binds. The REQUIRED ports (dataSource /\n * identity — true app identity, C23) throw at construction when absent.\n * Every other port has a SHIPPED DEFAULT (errorSink since 0.6.0) or a\n * documented degradation; nothing is ever silently missing.\n */\nexport function createAssociationsStore(\n config: AssociationsConfig,\n): AssociationsStore {\n // An { rpc }-only client is adapted (0.14.5), so the bridges every host passed before 0.14.0\n // keep working; only a missing client, or one with neither schema() nor rpc(), throws.\n const dataSource = asAssociationsDataSource(config?.dataSource);\n if (!config || !dataSource) {\n throw new Error(\n \"@ai-matrx/associations: the REQUIRED dataSource port is missing \" +\n \"(pass the supabase-js client itself, or an { rpc } client for the \" +\n \"public schema's functions). The package IS data operations; there \" +\n \"is no degraded mode without one.\",\n );\n }\n if (typeof config.identity?.requireUserId !== \"function\") {\n throw new Error(\n \"@ai-matrx/associations: the REQUIRED identity port is missing \" +\n \"(need requireUserId(): string that THROWS when unauthenticated). \" +\n \"Identity never comes from a store import.\",\n );\n }\n // `errorSink` stopped being required in 0.6.0 (C23): the package ships the\n // obvious sink instead of refusing to construct. The default is LOUD about\n // being the default — see createDefaultErrorSink.\n const errorSink: ErrorSink =\n typeof config.errorSink === \"function\"\n ? config.errorSink\n : createDefaultErrorSink();\n const registry = createEntityRegistry(errorSink, config.entityOverlay);\n const deps: CoreDeps = {\n dataSource,\n identity: config.identity,\n errorSink,\n guards: createAssociationGuards(errorSink),\n rpc: createRpcResultHelpers(\n errorSink,\n config.identity.sessionAttached\n ? () => config.identity.sessionAttached!()\n : undefined,\n ),\n registry,\n };\n\n const associations = createAssociationsService(deps);\n const categories = createCategoriesService(deps);\n const favorites = createFavoritesService(deps);\n const candidates = createCandidatesService(deps);\n const titles = createTitlesService(deps, candidates);\n const entityRows = createEntityRowsService(deps, titles);\n const helpers = createAssociationHelpers(associations);\n const comments = createCommentsService(deps);\n\n // ── instance state (never module state) ────────────────────────────────\n const assocByKey = new Map<string, AssociationsEntry>();\n const assocSubs = new Map<string, Set<() => void>>();\n const assocInFlight = new Map<string, Promise<void>>();\n const catByDim = new Map<string, CategoriesEntry>();\n const catSubs = new Map<string, Set<() => void>>();\n const catInFlight = new Map<string, Promise<void>>();\n const cmtByKey = new Map<string, CommentsEntry>();\n const cmtSubs = new Map<string, Set<() => void>>();\n const cmtInFlight = new Map<string, Promise<void>>();\n\n function notifyAssoc(key: string): void {\n const subs = assocSubs.get(key);\n if (subs) for (const cb of [...subs]) cb();\n }\n function notifyCat(dimension: string): void {\n const subs = catSubs.get(dimension);\n if (subs) for (const cb of [...subs]) cb();\n }\n function setAssoc(key: string, entry: AssociationsEntry): void {\n assocByKey.set(key, entry);\n notifyAssoc(key);\n }\n function setCat(dimension: string, entry: CategoriesEntry): void {\n catByDim.set(dimension, entry);\n notifyCat(dimension);\n }\n function notifyCmt(key: string): void {\n const subs = cmtSubs.get(key);\n if (subs) for (const cb of [...subs]) cb();\n }\n function setCmt(key: string, entry: CommentsEntry): void {\n cmtByKey.set(key, entry);\n notifyCmt(key);\n }\n\n // ── association cache ops (verbatim thunk/reducer behavior) ────────────\n async function load(\n type: string,\n id: string,\n opts: { force?: boolean } = {},\n ): Promise<void> {\n const force = opts.force ?? false;\n if (!type || !id) return;\n const key = associationsKey(type, id);\n const entry = assocByKey.get(key);\n\n if (!force && entry?.status === \"ready\") return;\n const pending = assocInFlight.get(key);\n if (!force && entry?.status === \"loading\" && pending) return pending;\n\n const prev = assocByKey.get(key);\n setAssoc(key, {\n status: \"loading\",\n edges: prev?.edges ?? [],\n fetchedAt: prev?.fetchedAt ?? null,\n // Retain the visible failure while a retry is pending — consumers use\n // status to disable/spin the same retry control.\n error: prev?.error ?? null,\n });\n\n const promise = (async () => {\n try {\n const res = await associations.listForEntity(type, id);\n if (isAssociationsRpcErr(res)) {\n const before = assocByKey.get(key);\n setAssoc(key, {\n status: \"error\",\n edges: before?.edges ?? [],\n fetchedAt: before?.fetchedAt ?? null,\n error: res.error.message,\n });\n } else {\n setAssoc(key, {\n status: \"ready\",\n edges: res.data.edges,\n fetchedAt: Date.now(),\n error: null,\n });\n }\n } finally {\n assocInFlight.delete(key);\n }\n })();\n\n assocInFlight.set(key, promise);\n return promise;\n }\n\n /** Reload both endpoints of an edge so each side's cache is fresh. */\n async function reloadBoth(\n sourceType: string,\n sourceId: string,\n targetType: string,\n targetId: string,\n ): Promise<void> {\n await Promise.all([\n load(sourceType, sourceId, { force: true }),\n load(targetType, targetId, { force: true }),\n ]);\n }\n\n // ── category cache ops (verbatim thunk/reducer behavior) ───────────────\n async function loadCategories(\n dimension: CategoryDimension,\n opts: { force?: boolean } = {},\n ): Promise<void> {\n const force = opts.force ?? false;\n if (!dimension) return;\n const entry = catByDim.get(dimension);\n\n if (!force && entry?.status === \"ready\") return;\n const pending = catInFlight.get(dimension);\n if (!force && entry?.status === \"loading\" && pending) return pending;\n\n const prev = catByDim.get(dimension);\n setCat(dimension, {\n status: \"loading\",\n categories: prev?.categories ?? [],\n fetchedAt: prev?.fetchedAt ?? null,\n error: null,\n });\n\n const promise = (async () => {\n try {\n const res = await categories.list(dimension);\n if (isAssociationsRpcErr(res)) {\n const before = catByDim.get(dimension);\n setCat(dimension, {\n status: \"error\",\n categories: before?.categories ?? [],\n fetchedAt: before?.fetchedAt ?? null,\n error: res.error.message,\n });\n } else {\n setCat(dimension, {\n status: \"ready\",\n categories: res.data.categories,\n fetchedAt: Date.now(),\n error: null,\n });\n }\n } finally {\n catInFlight.delete(dimension);\n }\n })();\n\n catInFlight.set(dimension, promise);\n return promise;\n }\n\n // ── comment-thread cache ops (W6; same lifecycle as associations) ──────\n async function loadComments(\n type: string,\n id: string,\n opts: { force?: boolean } = {},\n ): Promise<void> {\n const force = opts.force ?? false;\n if (!type || !id) return;\n const key = associationsKey(type, id);\n const entry = cmtByKey.get(key);\n\n if (!force && entry?.status === \"ready\") return;\n const pending = cmtInFlight.get(key);\n if (!force && entry?.status === \"loading\" && pending) return pending;\n\n const prev = cmtByKey.get(key);\n setCmt(key, {\n status: \"loading\",\n comments: prev?.comments ?? [],\n fetchedAt: prev?.fetchedAt ?? null,\n // Retain the visible failure while a retry is pending (same contract\n // as the association cache).\n error: prev?.error ?? null,\n });\n\n const promise = (async () => {\n try {\n const res = await comments.listForEntity(type, id);\n if (isAssociationsRpcErr(res)) {\n const before = cmtByKey.get(key);\n setCmt(key, {\n status: \"error\",\n comments: before?.comments ?? [],\n fetchedAt: before?.fetchedAt ?? null,\n error: res.error.message,\n });\n } else {\n setCmt(key, {\n status: \"ready\",\n comments: res.data.comments,\n fetchedAt: Date.now(),\n error: null,\n });\n }\n } finally {\n cmtInFlight.delete(key);\n }\n })();\n\n cmtInFlight.set(key, promise);\n return promise;\n }\n\n return {\n // ── associations ─────────────────────────────────────────────────────\n getEdges(type, id) {\n if (!type || !id) return IDLE_ASSOCIATIONS;\n return assocByKey.get(associationsKey(type, id)) ?? IDLE_ASSOCIATIONS;\n },\n\n load,\n\n subscribe(key, cb) {\n let subs = assocSubs.get(key);\n if (!subs) {\n subs = new Set();\n assocSubs.set(key, subs);\n }\n subs.add(cb);\n return () => {\n subs.delete(cb);\n if (subs.size === 0) assocSubs.delete(key);\n };\n },\n\n async add(args) {\n const res = await associations.add(args);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await reloadBoth(\n args.sourceType,\n args.sourceId,\n args.targetType,\n args.targetId,\n );\n return { ok: true, id: res.data.id };\n },\n\n async remove(args) {\n const res = await associations.remove(args);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await reloadBoth(\n args.sourceType,\n args.sourceId,\n args.targetType,\n args.targetId,\n );\n return { ok: true };\n },\n\n /**\n * Reloads the SOURCE endpoint only — the one endpoint with a\n * deterministic post-state; each affected target reload would need the\n * full before/after diff, so callers displaying a specific target\n * refresh it via `load(..., { force: true })`.\n */\n async setTargets(args) {\n const res = await associations.setTargets(args);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await load(args.sourceType, args.sourceId, { force: true });\n return { ok: true };\n },\n\n invalidate(type, id) {\n const key = associationsKey(type, id);\n if (assocByKey.delete(key)) notifyAssoc(key);\n },\n\n invalidateAll() {\n const assocKeys = [...assocByKey.keys()];\n assocByKey.clear();\n for (const key of assocKeys) notifyAssoc(key);\n const dims = [...catByDim.keys()];\n catByDim.clear();\n for (const dim of dims) notifyCat(dim);\n const cmtKeys = [...cmtByKey.keys()];\n cmtByKey.clear();\n for (const key of cmtKeys) notifyCmt(key);\n },\n\n // ── categories ───────────────────────────────────────────────────────\n getCategories(dimension) {\n if (!dimension) return IDLE_CATEGORIES;\n return catByDim.get(dimension) ?? IDLE_CATEGORIES;\n },\n\n loadCategories,\n\n subscribeCategories(dimension, cb) {\n let subs = catSubs.get(dimension);\n if (!subs) {\n subs = new Set();\n catSubs.set(dimension, subs);\n }\n subs.add(cb);\n return () => {\n subs.delete(cb);\n if (subs.size === 0) catSubs.delete(dimension);\n };\n },\n\n async createCategory(args) {\n const res = await categories.create(args);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n // Optimistic echo so the new id shows immediately, then force-reload\n // to pick up server-derived fields (slug, position) authoritatively.\n const optimistic: PlatformCategory = {\n id: res.data.id,\n orgId: args.orgId,\n dimension: args.dimension,\n name: args.name,\n slug: args.slug ?? null,\n parentId: args.parentId ?? null,\n isSystem: false,\n color: args.color ?? null,\n icon: args.icon ?? null,\n metadata: null,\n position: null,\n };\n const prev = catByDim.get(args.dimension);\n const existing = prev?.categories ?? [];\n if (!existing.some((c) => c.id === optimistic.id)) {\n setCat(args.dimension, {\n status: \"ready\",\n categories: [...existing, optimistic],\n fetchedAt: prev?.fetchedAt ?? Date.now(),\n error: null,\n });\n }\n await loadCategories(args.dimension, { force: true });\n return { ok: true, id: res.data.id };\n },\n\n async updateCategory(args) {\n const res = await categories.update(args);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await loadCategories(args.dimension, { force: true });\n return { ok: true, id: res.data.id };\n },\n\n async reparentCategory(args) {\n const res = await categories.reparent(args);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await loadCategories(args.dimension, { force: true });\n return { ok: true, id: res.data.id };\n },\n\n async deleteCategory(args) {\n const res = await categories.delete(args.id);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await loadCategories(args.dimension, { force: true });\n return { ok: true, id: res.data.id };\n },\n\n // ── comments (W6) ────────────────────────────────────────────────────\n getComments(type, id) {\n if (!type || !id) return IDLE_COMMENTS;\n return cmtByKey.get(associationsKey(type, id)) ?? IDLE_COMMENTS;\n },\n\n loadComments,\n\n subscribeComments(key, cb) {\n let subs = cmtSubs.get(key);\n if (!subs) {\n subs = new Set();\n cmtSubs.set(key, subs);\n }\n subs.add(cb);\n return () => {\n subs.delete(cb);\n if (subs.size === 0) cmtSubs.delete(key);\n };\n },\n\n async addComment(args) {\n const res = await comments.add(args);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await loadComments(args.entityType, args.entityId, { force: true });\n return { ok: true, id: res.data.id };\n },\n\n async editComment(args) {\n const res = await comments.edit(args.id, args.body);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await loadComments(args.entityType, args.entityId, { force: true });\n return { ok: true, id: args.id };\n },\n\n async deleteComment(args) {\n const res = await comments.remove(args.id);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await loadComments(args.entityType, args.entityId, { force: true });\n return { ok: true, id: args.id };\n },\n\n invalidateComments(type, id) {\n const key = associationsKey(type, id);\n if (cmtByKey.delete(key)) notifyCmt(key);\n },\n\n // ── seams ────────────────────────────────────────────────────────────\n titles,\n favorites,\n candidates,\n entityRows,\n helpers,\n registry,\n services: { associations, categories, comments },\n registerEntityOverlay: registry.registerEntityOverlay,\n errorSink,\n dataSource,\n identity: config.identity,\n };\n}\n","// core/edgeClassifier.ts — @ai-matrx/associations/core\n//\n// THE canonical classifier for `platform.associations` edges: is an edge\n// CONTENT (\"this container holds that resource\") or STRUCTURE (membership,\n// context tagging, org attachment)? Ported behavior-verbatim from\n// matrx-frontend `features/scopes/service/associationEdges.ts` (associations\n// extraction W2, 2026-08-29); the host `Json` type becomes `unknown` (the\n// packaging standard's JSON-boundary rule).\n//\n// Every surface that lists \"what's attached to X\" must use this ONE\n// predicate. The old pattern — each consumer keeping its own whitelist of\n// allowed source tokens — silently dropped every newly registered entity\n// type. An EXCLUSION list inverts that: any registered token is content\n// unless it is structural, so a new token participates everywhere with zero\n// code changes.\n//\n// Structural edges are:\n// • container-membership edges (`thread → war_room`, marked\n// `metadata.membership: true`) — the thread is IN the room, not held BY it;\n// • scope / scope_type edges — context tagging, owned by the scopes system;\n// • organization edges — org attachment, owned by iam/memberships;\n// • container tokens themselves (`thread`, `war_room`) appearing as a\n// source — a container is never another container's content.\n\n/** Source tokens that are structure, never container content. */\nexport const NON_CONTENT_SOURCE_TYPES: ReadonlySet<string> = new Set([\n \"thread\",\n \"war_room\",\n \"scope\",\n \"scope_type\",\n \"organization\",\n]);\n\n/** True when edge metadata marks a container-membership edge. */\nexport function isMembershipMetadata(metadata: unknown): boolean {\n return (\n typeof metadata === \"object\" &&\n metadata !== null &&\n !Array.isArray(metadata) &&\n (metadata as Record<string, unknown>).membership === true\n );\n}\n\n/**\n * True when an edge into a container represents CONTENT the container holds.\n * `sourceType` is the edge's raw `source_type` token; `metadata` the edge's\n * jsonb (pass it when available so membership edges are excluded even if a\n * structural token is ever missed).\n */\nexport function isContentSourceEdge(\n sourceType: string,\n metadata?: unknown,\n): boolean {\n if (NON_CONTENT_SOURCE_TYPES.has(sourceType)) return false;\n if (isMembershipMetadata(metadata)) return false;\n return true;\n}\n","// core/categoryHierarchy.ts — @ai-matrx/associations/core\n//\n// The canonical two-level display order for one category facet — ported\n// VERBATIM from matrx-frontend `features/scopes/utils/categoryHierarchy.ts`\n// (W4 completion, 2026-08-29). Pure data → data, React-free, so it lives in\n// /core beside the category service; the `CategorySelect` /\n// `CategoryTagPicker` faces are its measured consumers.\n\nimport type { PlatformCategory } from \"../edges\";\n\nexport interface CategoryHierarchyItem {\n category: PlatformCategory;\n depth: 0 | 1;\n parent: PlatformCategory | null;\n displayName: string;\n}\n\nexport interface CategoryHierarchy {\n items: CategoryHierarchyItem[];\n roots: PlatformCategory[];\n hasHierarchy: boolean;\n}\n\n/**\n * Turns the RPC's ordered flat rows into the canonical two-level display order.\n * Flat facets retain their exact input order. Invalid/orphaned rows remain\n * visible at the root; the database guard prevents new ones from being made.\n */\nexport function buildCategoryHierarchy(\n categories: PlatformCategory[],\n): CategoryHierarchy {\n const byId = new Map(categories.map((category) => [category.id, category]));\n const hasHierarchy = categories.some(\n (category) => category.parentId !== null && byId.has(category.parentId),\n );\n\n if (!hasHierarchy) {\n return {\n items: categories.map((category) => ({\n category,\n depth: 0,\n parent: null,\n displayName: category.name,\n })),\n roots: categories.filter((category) => category.parentId === null),\n hasHierarchy: false,\n };\n }\n\n const roots = categories.filter(\n (category) => category.parentId === null || !byId.has(category.parentId),\n );\n const childrenByParent = new Map<string, PlatformCategory[]>();\n for (const category of categories) {\n if (!category.parentId || !byId.has(category.parentId)) continue;\n const children = childrenByParent.get(category.parentId) ?? [];\n children.push(category);\n childrenByParent.set(category.parentId, children);\n }\n\n const items: CategoryHierarchyItem[] = [];\n const seen = new Set<string>();\n for (const root of roots) {\n items.push({\n category: root,\n depth: 0,\n parent: null,\n displayName: root.name,\n });\n seen.add(root.id);\n\n for (const child of childrenByParent.get(root.id) ?? []) {\n items.push({\n category: child,\n depth: 1,\n parent: root,\n displayName: `${root.name} / ${child.name}`,\n });\n seen.add(child.id);\n }\n }\n\n // Loud database guards make this fallback unreachable for valid data, but a\n // picker must never hide an identity merely because older data is malformed.\n for (const category of categories) {\n if (seen.has(category.id)) continue;\n items.push({\n category,\n depth: 0,\n parent: null,\n displayName: category.name,\n });\n }\n\n return {\n items,\n roots: categories.filter((category) => category.parentId === null),\n hasHierarchy: true,\n };\n}\n"],"mappings":"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","names":["out","err","ok","err","data","error","ok","err","ok","err","ok","err"]}
|
|
1
|
+
{"version":3,"sources":["../../src/ports.ts","../../src/core/defaultErrorSink.ts","../../src/core/guards.ts","../../src/core/rpcResult.ts","../../src/core/registry.ts","../../src/core/doors.ts","../../src/db/public.ts","../../src/core/associationsService.ts","../../src/core/categoriesService.ts","../../src/core/favoritesService.ts","../../src/core/candidates.ts","../../src/core/titles.ts","../../src/core/entityRows.ts","../../src/core/helpers.ts","../../src/core/commentsService.ts","../../src/core/store.ts","../../src/core/edgeClassifier.ts","../../src/core/categoryHierarchy.ts"],"sourcesContent":["// src/ports.ts — @ai-matrx/associations\n//\n// THE SEVEN PORTS (design Decision 2) — the exact seams measured in the\n// matrx-frontend census (2026-08-29), inverted into typed injection points —\n// plus the W6 `authorDisplay` seam (the comments canonical UI, ruling C4).\n// One provider config, declared here, bound once per host\n// (`AssociationsProvider` in /react; `createAssociationsStore(cfg)` in /core —\n// both arrive in later waves; the TYPES are the wave-1 contract).\n//\n// Required ports throw at construction when absent — never degraded. Optional\n// ports each have a DEFINED degradation (the table in\n// ASSOCIATIONS-PACKAGE-DESIGN.md Decision 2); \"the feature silently doesn't\n// work\" is never one of them.\n//\n// React appears as TYPE-ONLY imports (optional peer): this module is\n// import-inert and legal in any graph, server components included.\n\nimport type { ComponentType, ElementType, ReactNode } from \"react\";\n\nimport type { SupabaseLike } from \"@ai-matrx/data/db\";\nimport type { EntityTypeToken } from \"./entity-types.generated\";\n\n// ─── required ports (absence throws at construction) ────────────────────────\n\n/**\n * The data seam — a structural subset of `SupabaseClient<Database>`: any\n * client that can answer the demanded RPC families (README § The demanded\n * schema). The package IS data operations; there is no degraded mode without\n * one. `PromiseLike` because supabase-js returns a thenable builder, not a\n * `Promise`.\n *\n * 🚨 SINCE 0.14.0 THE PORT IS THE HOST'S SUPABASE CLIENT ITSELF (`@ai-matrx/data`'s structural\n * `SupabaseLike`: `schema(name).rpc(...)`). Every call goes through data's generated\n * function doors (`src/db/public.ts`); the four edge lists are read COMPLETE (paged by\n * the package — a host no longer pages them). Pass `supabase`, not an `{ rpc }` wrapper.\n *\n * 🚨 RPC AND NOTHING ELSE (DOORS-ONLY-4, 2026-09-21). This port used to carry\n * OPTIONAL `from`/`schema` table surfaces, used by exactly one service —\n * entity-row create/rename, which wrote the registered entity's backing table\n * directly. The doors-only ruling (`platform` and `iam` are not client-writable;\n * every write goes through a named SECURITY DEFINER door) made that path answer\n * `42501` on every closed table, so it now calls `entity_row_create` /\n * `entity_row_rename` like every other operation. With its one reader gone the\n * two optional members were a port nobody reads — removed rather than left as a\n * seam a future write could quietly reach for.\n */\nexport type AssociationsDataSource = SupabaseLike;\n\n/**\n * An `{ rpc }`-only client (a host bridge that forwards public-schema function calls, the shape\n * every host passed before 0.14.0). ACCEPTED AGAIN since 0.14.5: 0.14.0 refused it at\n * construction and every agent-catalog host with a bridge crashed (\"the REQUIRED dataSource port\n * is missing\"). The store adapts it — `schema(\"public\").rpc` is its `rpc` — so a caller cannot hit\n * that crash. Every function this package calls is a `public` one (`src/db/public.ts`); any other\n * schema, or a table read, is refused ALOUD by the adapter, never answered silently.\n */\nexport interface AssociationsRpcOnlyDataSource {\n rpc(fn: string, args?: Record<string, unknown>, opts?: { count?: \"exact\" | \"planned\" | \"estimated\" }): PromiseLike<any>;\n}\n\n/**\n * The one normalizer: a supabase-shaped client passes through untouched; an `{ rpc }`-only client\n * is wrapped so `schema(\"public\")` answers with its `rpc`. Anything else returns `null` (the store\n * throws its REQUIRED-port error).\n */\nexport function asAssociationsDataSource(source: unknown): AssociationsDataSource | null {\n const s = source as { schema?: unknown; rpc?: unknown } | null | undefined;\n if (!s || typeof s !== \"object\") return null;\n if (typeof s.schema === \"function\") return s as AssociationsDataSource;\n if (typeof s.rpc !== \"function\") return null;\n const rpcOnly = s as AssociationsRpcOnlyDataSource;\n const rpc = (fn: string, args?: Record<string, unknown>, opts?: { count?: \"exact\" | \"planned\" | \"estimated\" }) =>\n rpcOnly.rpc(fn, args, opts);\n return {\n schema(name: string) {\n if (name !== \"public\") {\n throw new Error(`@ai-matrx/associations: an { rpc }-only dataSource answers the public schema's functions only (asked for schema ${name}); pass the supabase-js client itself`);\n }\n return {\n rpc,\n from(table: string): never {\n throw new Error(`@ai-matrx/associations: an { rpc }-only dataSource answers functions only, never a table (asked for ${table}); pass the supabase-js client itself`);\n },\n };\n },\n };\n}\n\n/**\n * The identity seam — today a store-singleton read (`requireUserId`) plus the\n * org resolver `CategoryTagPicker` uses for created rows. `requireUserId`\n * failures stay LOUD (`Not authenticated`) — never silently anonymous.\n */\nexport interface AssociationsIdentity {\n requireUserId(): string;\n /** Org for created rows/edges (the CategoryTagPicker create path). */\n ensureOrgId?(): Promise<string>;\n /**\n * Whether the client's database session is attached right now. A 42501\n * \"permission denied for function\" from a demanded door means the request\n * went out anonymous (an ended or expired session) — UNLESS the session is\n * attached, when it is a real grant gap. Absent → treated as not attached.\n */\n sessionAttached?(): boolean;\n}\n\n/**\n * The scream seam. Every degraded path, every `demanded_schema_violation`,\n * every create-then-attach partial failure reports here regardless of\n * notifier availability.\n *\n * DEFAULT (0.6.0, C23): absent → `createDefaultErrorSink()` — a tagged\n * `console.error` per event that announces ONCE that no sink is bound and\n * names the remedy. A host with a diagnostics surface binds its own.\n */\nexport type ErrorSink = (event: {\n code: string;\n message: string;\n context?: object;\n}) => void;\n\n// ─── optional ports (each with a defined degradation) ───────────────────────\n\n/**\n * Per-token host overlay — the code-native values the DB registry cannot\n * carry (today: the 804-line ENTITY_OVERLAY literal in matrx-frontend's\n * entityRegistry). EVERY field optional; absence degrades per field:\n * convention columns, default icon, `${label}s`, no door, generic\n * titleColumn candidate read. A `reference_pickable` token with no title\n * column and no override is screamed to the errorSink, never shown broken.\n */\nexport interface EntityOverlayEntry {\n /** Icon component (host-supplied; packages never depend on an icon library). */\n Icon?: ElementType;\n /** Plural label; default `${label}s`. */\n labelPlural?: string;\n /** Owner column override; default the \"created_by\" convention. */\n ownerColumn?: string | null;\n /** Org column override; default the \"organization_id\" convention. */\n orgColumn?: string | null;\n /** Route for this token's rows; absent → no open door (label renders plain). */\n hrefFor?: (id: string) => string;\n /**\n * Candidate-list override for tokens whose backing table can't be read\n * client-side (e.g. `data_store` — rag.* is not PostgREST-exposed);\n * absent → the generic `reference_search_candidates` titleColumn read.\n */\n listCandidates?: (args: { search?: string; limit?: number }) => Promise<\n | { ok: true; data: { id: string; title: string }[] }\n | { ok: false; error: string }\n >;\n}\n\n/** The overlay registration map — bound per host, merged over the generated registry. */\nexport type EntityOverlayMap = Partial<\n Record<EntityTypeToken, EntityOverlayEntry>\n>;\n\n/**\n * The user-notification seam (today: `@/lib/toast` in 6 components).\n * Optional — /react warns once when absent. Every user-facing failure ALSO\n * routes to the errorSink + the component's inline error state, so the\n * create-then-associate loud-outcome law is satisfied structurally, not by\n * toast availability.\n */\nexport interface AssociationsNotifier {\n success(msg: string): void;\n error(\n msg: string,\n opts?: {\n description?: string;\n action?: { label: string; onClick(): void };\n },\n ): void;\n}\n\n/**\n * The window seam.\n *\n * DEFAULT (0.6.0, C23): absent → `DefaultWindowShell`, the package's OWN\n * window — draggable, resizable, maximizable, viewport-clamped, portalled,\n * non-modal, mobile bottom-card. Not a degradation; the shipped default.\n * A host binds this port only when its own window MANAGER (tray docking,\n * workspace persistence, cross-window z-order) must own the surface.\n */\nexport interface WindowShellPort {\n Window: ComponentType<{\n id: string;\n title: string;\n onClose(): void;\n children: ReactNode;\n }>;\n}\n\n/** Options for {@link CapturePort.requestUpload} (measured: uploadGuardOpeners). */\nexport interface CaptureUploadOpts {\n files: File[];\n /** Logical cloud-files folder new uploads land in (auto-created). */\n folderPath: string;\n /** Publish the uploads to the web (the only anonymous lane; access ladder T-13). */\n publishedToWeb?: boolean;\n /** The \"Shown to\" list filter stamped on uploads (`only_me` · `my_team` · `everyone` · `everyone_on_ai_matrx`). */\n shownTo?: CaptureShownTo;\n /** The retiring level word, derived from the two words above for hosts not yet on them. */\n visibility?: string; // T-13 transitional wire input\n}\n\n/** `platform.shown_to`: a list filter, never row security. */\nexport type CaptureShownTo = \"only_me\" | \"my_team\" | \"everyone\" | \"everyone_on_ai_matrx\";\n\n/** Honest outcome of a host upload — created-but-unlinked must be reportable. */\nexport interface CaptureUploadResult {\n cancelled?: boolean;\n uploaded: string[];\n aliased: { existingFileId: string }[];\n failed: { name: string; error: string }[];\n}\n\n/** Options for {@link CapturePort.openFilePicker} (measured: cloudFilesPickerOpeners). */\nexport interface CapturePickOpts {\n multi?: boolean;\n title?: string;\n description?: string;\n}\n\n/**\n * The capture-toolbar seam. PER-HANDLER optional: the toolbar renders only\n * the chips it can actually honor; a chip with no path behind it is never\n * rendered dead. NEVER dead buttons.\n *\n * THE UPLOAD DEFAULT (0.6.0, C23): a host does NOT have to build an upload\n * flow. Bind the one-file primitive `uploadFile` and the package ships the\n * WHOLE flow over it — the file input, whole-body drag-and-drop, sequential\n * uploads, the stall watchdog, per-file outcomes, and the loud\n * created-but-unattached report. `requestUpload` stays for a host that owns\n * a richer pipeline (duplicate-alias dialogs, progress UI); when both are\n * bound `requestUpload` wins.\n */\nexport interface CapturePort {\n /**\n * The MINIMAL upload primitive: persist ONE file, answer with its id (or\n * an honest error). Everything else — batching, drag-and-drop, progress\n * state, failure copy — is the package's job.\n */\n uploadFile?(\n file: File,\n opts: Omit<CaptureUploadOpts, \"files\">,\n ): Promise<{ ok: true; id: string } | { ok: false; error: string }>;\n /** The full host upload pipeline. Wins over `uploadFile` when bound. */\n requestUpload?(opts: CaptureUploadOpts): Promise<CaptureUploadResult>;\n /** Resolves with picked file ids, or null/empty on cancel. */\n openFilePicker?(opts: CapturePickOpts): Promise<string[] | null>;\n /** Creates a document in the authoritative organization of this container. */\n createDataTable?(opts: {\n name: string;\n organizationId: string;\n }): Promise<{ id: string } | null>;\n}\n\n/**\n * Props of the generic association picker face — ALSO the contract a\n * per-token override component must implement (today: the hardcoded\n * `token === \"file\"` → FilePickerWindow branch in AssociationPicker becomes a\n * `registerPickerOverride(\"file\", …)` host binding). Ported verbatim from the\n * measured component.\n */\nexport interface AssociationPickerProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n token: EntityTypeToken;\n /** Container display label, for the header (\"…to Titanium Marketing\"). */\n containerLabel?: string;\n /** Org stamped onto rows created by the \"+ New\" footer. */\n orgId?: string | null;\n /** Resource ids already attached to the container. */\n attachedIds: Set<string>;\n /** Attach a resource (returns ok/err so the row can surface failures). */\n onAttach: (\n resourceId: string,\n title: string,\n ) => Promise<{ ok: boolean; error?: string }>;\n /** Detach a resource. */\n onDetach: (resourceId: string) => Promise<{ ok: boolean; error?: string }>;\n /**\n * Filed-under mode: the primary is being FILED UNDER the picked items\n * (`primary → item`), so the header says \"File … under\" not \"Attach to\".\n */\n filing?: boolean;\n}\n\n/** Per-token picker override map — absent tokens use the generic picker sheet. */\nexport type PickerOverrideMap = Partial<\n Record<EntityTypeToken, ComponentType<AssociationPickerProps>>\n>;\n\n/**\n * Props the entity-doors port's `EntityRef` receives (the measured subset the\n * association faces pass today).\n */\nexport interface EntityRefProps {\n token: string;\n id: string;\n name?: string | null;\n showIcon?: boolean;\n openInNewTab?: boolean;\n alwaysShowActions?: boolean;\n className?: string;\n}\n\n/** Props the entity-doors port's `DoorControls` receives. */\nexport interface EntityDoorProps {\n token: string;\n id: string;\n name?: string | null;\n className?: string;\n}\n\n/** What the authorDisplay port receives — one comment's denormalized author. */\nexport interface AuthorDisplayInput {\n /** The auth user id (`created_by`), or null on an authorless legacy row. */\n userId: string | null;\n email: string | null;\n displayName: string | null;\n avatarUrl: string | null;\n}\n\n/**\n * The author-display seam (W6 comments UI). The package cannot resolve user\n * profiles itself — `cmt_list` denormalizes email/displayName/avatarUrl per\n * row, and a host with a richer profile store (presence, current names,\n * signed avatar URLs) overrides them here. Return `null` (or omit a field)\n * to keep the denormalized value.\n *\n * DEGRADATION (absent port): the RPC's denormalized fields render as-is;\n * a row with neither displayName nor email shows the package's\n * \"Unknown user\" label with the default initial avatar. Never blank, never\n * a crash.\n */\nexport type AuthorDisplayPort = (author: AuthorDisplayInput) => {\n displayName?: string | null;\n avatarUrl?: string | null;\n} | null;\n\n/**\n * The entity-doors seam (today: `EntityRef` / `EntityDoorControls` /\n * access-gate `UnresolvedEntityRef`). Absent → title text plus the overlay's\n * `hrefFor` link when present; unresolved rows render the package's plain\n * \"unavailable\" chip.\n */\nexport interface EntityDoorsPort {\n EntityRef?: ComponentType<EntityRefProps>;\n DoorControls?: ComponentType<EntityDoorProps>;\n UnresolvedRef?: ComponentType<{ token: string; id: string }>;\n}\n\n// ─── the one provider config ────────────────────────────────────────────────\n\n/**\n * Everything a host binds, once. `createAssociationsStore(cfg)` (/core)\n * throws when `dataSource` or `identity` is missing — those two ARE the\n * host's app identity and cannot be defaulted. Every other port ships a\n * working default (C23) or degrades per its own documented contract, never\n * silently.\n */\nexport interface AssociationsConfig {\n // required — TRUE app identity, the only two things a host must supply\n dataSource: AssociationsDataSource | AssociationsRpcOnlyDataSource;\n identity: AssociationsIdentity;\n // optional — each has a SHIPPED DEFAULT or a documented degradation\n errorSink?: ErrorSink;\n entityOverlay?: EntityOverlayMap;\n notifier?: AssociationsNotifier;\n windowShell?: WindowShellPort;\n capture?: CapturePort;\n pickerOverrides?: PickerOverrideMap;\n entityDoors?: EntityDoorsPort;\n authorDisplay?: AuthorDisplayPort;\n}\n","// core/defaultErrorSink.ts — @ai-matrx/associations/core\n//\n// THE shipped default for the `errorSink` port (0.6.0, C23: every port ships\n// a working default). Before 0.6.0 `errorSink` was REQUIRED and a host that\n// had not yet built a diagnostics pipeline could not construct the store at\n// all — the package refused to work rather than shipping the obvious sink.\n//\n// The default obeys the platform's nothing-fails-silently law: every event\n// reaches `console.error` under a tagged prefix, WITH a remedy line naming\n// what the host should bind and where to look. It also announces ITSELF once\n// — an app running on the default sink is told, so \"nobody saw the error\"\n// can never be explained by \"we didn't know there was no sink\".\n//\n// A host with a real diagnostics surface (matrx-frontend's Error Inspector)\n// binds `errorSink` and this default steps aside entirely.\n\nimport type { ErrorSink } from \"../ports\";\n\nconst REMEDY =\n \"Bind the `errorSink` port on createAssociationsStore({ errorSink }) to \" +\n \"route these into your diagnostics surface; until then they only reach \" +\n \"the console.\";\n\n/**\n * Build the default sink. `announce` is called once, on the first event, so\n * the absence of a bound sink is itself loud (never a silent substitution).\n */\nexport function createDefaultErrorSink(): ErrorSink {\n let announced = false;\n return (event) => {\n if (!announced) {\n announced = true;\n console.error(\n \"[associations] no errorSink port bound — using the package default. \" +\n REMEDY,\n );\n }\n console.error(\n `[associations] ${event.code}: ${event.message}`,\n event.context ?? {},\n );\n };\n}\n","// core/guards.ts — @ai-matrx/associations/core\n//\n// Pre-flight VALIDATION for the unified association edge — ported\n// behavior-verbatim from matrx-frontend\n// `features/scopes/service/associationGuards.ts` (associations extraction W2,\n// 2026-08-29). One seam inverted: the loud console.error scream becomes the\n// REQUIRED errorSink port, bound once via `createAssociationGuards(errorSink)`.\n//\n// Every write/read that goes through the services runs these guards BEFORE\n// the RPC fires, so the two classes of failure that keep biting surface as a\n// clean, described `invalid_argument` error at the callsite — never as an\n// opaque Postgres error chased through logs:\n//\n// 1. A non-UUID id — e.g. an agent passing a \"cute\" string literal instead\n// of a real row uuid (`22P02` at the DB; caught here with field + value).\n// 2. An unregistered type token — the `source_type`/`target_type` FK to\n// `platform.entity_types.token` is ENFORCED, so a guessed/phantom token\n// throws `23503` there; the generated `isEntityTypeToken` set rejects it\n// here with a clear message instead. This is also the WRITES-STRICT wall\n// of the token-skew policy (C18): a token the installed vocabulary lacks\n// fails here — upgrade the package, never widen to a raw string.\n//\n// LOUD by doctrine: a guard firing means a real code bug got this far, so it\n// reports to the errorSink (never silently swallowed) on its way to becoming\n// an `invalid_argument` result.\n\nimport { isUuidShape } from \"@ai-matrx/kit/uuid\";\n\nimport { isEntityTypeToken } from \"../entity-types.generated\";\nimport type { AssociationsRpcError } from \"../results\";\nimport type { ErrorSink } from \"../ports\";\n\n// The UUID predicates moved to `@ai-matrx/kit/uuid` on 2026-09-07 (duplication\n// census rows 6-8). The fleet had TWO predicates both called `isUuid` — this\n// LAX shape check, and a STRICT RFC-4122 one on six matrx-frontend API doors —\n// and the difference was invisible at the call site. They now live side by\n// side under names that say which is which (`isUuidShape` /\n// `isRfc4122Uuid`), in the package with no sibling dependencies that both an\n// association store and a Next.js route handler can reach. The guards below\n// want the LAX one: a v7 id, a nil UUID and a test fixture are all legitimate\n// association ids.\n\nfunction show(value: unknown): string {\n if (typeof value === \"string\") return JSON.stringify(value);\n if (value === null || value === undefined) return String(value);\n return JSON.stringify(value);\n}\n\n/**\n * Canonical replacements for legacy/phantom entity-type tokens (matrx-frontend\n * FOUND_DEFECTS D27). These aliases were never registered in\n * `platform.entity_types` — writes with them always FK-failed — but they\n * leaked into association callsites and persisted UI state.\n * `normalizeEntityToken` maps them to the registered canonical token so the\n * whole class of failure is structurally impossible, and it SCREAMS (to the\n * errorSink) when it fires, because an alias reaching this chokepoint means a\n * callsite is still emitting a dead token.\n *\n * Do NOT add entries casually: the fix for a new unregistered token is to\n * register it (or use the right one at the callsite), not to alias it here.\n */\nconst LEGACY_ENTITY_TOKEN_ALIASES: Record<string, string> = {\n cx_message: \"message\", // chat.message\n cx_conversation: \"conversation\", // chat.conversation\n user_file: \"file\", // files.files (mirrors war-room entityToSource)\n agent_app: \"app\", // app.definition\n // chat_block: a \"block\" is a slice of a chat message — the edge's id IS the\n // message id (metadata.block_index carries the slice), so it maps to message.\n chat_block: \"message\",\n};\n\n/** Return the first failing check, or null if all pass. Pure. */\nexport function firstError(\n ...checks: (AssociationsRpcError | null)[]\n): AssociationsRpcError | null {\n for (const c of checks) if (c) return c;\n return null;\n}\n\nexport interface AssociationGuards {\n /** A single id must be a real UUID. Kills the \"cute text id\" bug class. */\n checkUuid(field: string, value: unknown): AssociationsRpcError | null;\n /** Every id in an array must be a real UUID. */\n checkUuidArray(\n field: string,\n values: readonly unknown[],\n ): AssociationsRpcError | null;\n /** A type token must be registered in `platform.entity_types`. */\n checkToken(field: string, value: unknown): AssociationsRpcError | null;\n /**\n * Map a legacy/phantom token to its registered canonical token.\n * Pass-through for anything not in the alias table. Loud by doctrine — the\n * alias firing is a bug at the callsite, recovered here, never silent.\n */\n normalizeEntityToken(value: string): string;\n}\n\n/** Bind the guard set to the host's errorSink (the loud seam). */\nexport function createAssociationGuards(errorSink: ErrorSink): AssociationGuards {\n function invalid(\n field: string,\n value: unknown,\n reason: string,\n ): AssociationsRpcError {\n const message = `association ${field} ${reason} (got ${show(value)})`;\n errorSink({\n code: \"invalid_argument\",\n message: `[associations] invalid argument — ${message}`,\n context: { field },\n });\n return { code: \"invalid_argument\", message };\n }\n\n return {\n checkUuid(field, value) {\n return isUuidShape(value) ? null : invalid(field, value, \"must be a UUID\");\n },\n\n checkUuidArray(field, values) {\n for (let i = 0; i < values.length; i++) {\n if (!isUuidShape(values[i]))\n return invalid(`${field}[${i}]`, values[i], \"must be a UUID\");\n }\n return null;\n },\n\n checkToken(field, value) {\n if (typeof value !== \"string\" || value.length === 0)\n return invalid(field, value, \"must be a non-empty entity-type token\");\n if (!isEntityTypeToken(value))\n return invalid(\n field,\n value,\n \"is not a registered entity type (platform.entity_types) — \" +\n \"add it to the registry + upgrade @ai-matrx/associations, never guess a token\",\n );\n return null;\n },\n\n normalizeEntityToken(value) {\n const canonical = LEGACY_ENTITY_TOKEN_ALIASES[value];\n if (canonical) {\n errorSink({\n code: \"legacy_token_alias\",\n message:\n `[associations] phantom entity token ${JSON.stringify(value)} mapped to ` +\n `canonical ${JSON.stringify(canonical)} — fix the callsite to emit the ` +\n `canonical token (FOUND_DEFECTS D27)`,\n context: { value, canonical },\n });\n return canonical;\n }\n return value;\n },\n };\n}\n","// core/rpcResult.ts — @ai-matrx/associations/core\n//\n// The never-throw result funnel every service method in this package builds\n// through — ported behavior-verbatim from matrx-frontend\n// `features/scopes/service/rpcResult.ts` (associations extraction W2,\n// 2026-08-29), with the seams inverted:\n//\n// • console.warn / console.error → the REQUIRED errorSink port (the scream\n// seam). `createPgErrorMapper(errorSink)` binds the sink once; services\n// receive the bound mapper.\n// • `isTransportFailure` is the one body in `@ai-matrx/api/net` (its\n// NetError-class branches never fire here — /core makes no resilientFetch\n// calls — and every plain-object/TypeError/offline shape is identical).\n// • NEW (the demanded-schema scream, design Decision 4): a PostgREST\n// PGRST202 — \"could not find the function\" — on any demanded RPC maps to\n// the `demanded_schema_violation` code, names this package's contract in\n// its message, and ALWAYS reaches the errorSink. A consumer pointed at a\n// database without our schema gets one unambiguous scream, not a mystery\n// toast.\n//\n// 🚨 A POSTGREST ERROR IS NOT AN `Error`. supabase-js resolves a failed\n// request with a PLAIN OBJECT (`{ code, message, details, hint }`) parsed\n// straight from the response body — `PostgrestError` is only ever *thrown*\n// when `shouldThrowOnError` is set, which this package never sets. So an\n// `e instanceof Error ? e.message : <generic>` ternary discards the real\n// message on EVERY genuine database failure. Read the fields off the OBJECT,\n// and keep the Postgres/PostgREST code in `detail` so the next failure is\n// attributable instead of anonymous. (Incident: CRM record page 2026-08-14 —\n// a real `57014 statement timeout` reached the UI as \"Unexpected error\n// talking to Supabase\".)\n//\n// Sink policy (mirrors the original's console split):\n// • transport failures (browser offline/asleep/mid-handoff) report with\n// code \"transport_failure\" and `context.transient: true` — they carry no\n// database refusal an engineer can act on, and filing them as errors\n// buries real failures;\n// • THROWN application errors (identity port refusals, bugs) report with\n// their mapped code — the original console.error'ed these;\n// • plain PostgREST result errors do NOT reach the sink (the host's\n// dataSource layer is presumed to capture them with richer call-site\n// context, exactly as matrx-frontend's supabaseErrorCapture does — a\n// second sink event per request is a duplicate repair-queue row) —\n// EXCEPT PGRST202, which always screams.\n\nimport type {\n AssociationsRpcError,\n} from \"../results\";\nimport { isTransportFailure } from \"@ai-matrx/api/net\";\nimport type { ErrorSink } from \"../ports\";\n\nexport function err(\n code: AssociationsRpcError[\"code\"],\n message: string,\n detail?: unknown,\n hint?: string,\n): { ok: false; error: AssociationsRpcError } {\n const error: AssociationsRpcError = { code, message };\n if (detail !== undefined) error.detail = detail;\n if (hint !== undefined) error.hint = hint;\n return { ok: false, error };\n}\n\nexport function ok<T>(data: T): { ok: true; data: T } {\n return { ok: true, data };\n}\n\nfunction isPostgrestResultError(e: unknown): boolean {\n if (!e || typeof e !== \"object\") return false;\n const value = e as { code?: unknown; message?: unknown };\n return typeof value.code === \"string\" && typeof value.message === \"string\";\n}\n\n/**\n * Pull `code` / `message` / `hint` off whatever the dataSource handed us.\n *\n * Three shapes reach here and only the first is common:\n * 1. a PLAIN object from PostgREST — `{ code, message, details, hint }`\n * 2. a thrown `Error` (network stack, the identity port's refusal, a bug)\n * 3. something else entirely (a string, null) from a path we don't own\n */\nfunction readPgFields(e: unknown): {\n pgCode: string | null;\n pgMessage: string | null;\n pgHint: string | undefined;\n} {\n if (e && typeof e === \"object\") {\n const o = e as { code?: unknown; message?: unknown; hint?: unknown };\n return {\n pgCode: typeof o.code === \"string\" && o.code ? o.code : null,\n // `Error` instances land here too — `message` is an own/inherited\n // string property either way, so one read covers both shapes.\n pgMessage: typeof o.message === \"string\" && o.message ? o.message : null,\n pgHint: typeof o.hint === \"string\" && o.hint ? o.hint : undefined,\n };\n }\n return { pgCode: null, pgMessage: null, pgHint: undefined };\n}\n\nexport type PgErrorMapper = (e: unknown) => AssociationsRpcError;\nexport type PgErrorPairMapper = (\n e: unknown,\n) => [AssociationsRpcError[\"code\"], string, unknown, string | undefined];\n\nexport interface RpcResultHelpers {\n ok: typeof ok;\n err: typeof err;\n mapPgError: PgErrorMapper;\n mapPgErrorPair: PgErrorPairMapper;\n}\n\n/**\n * Bind the loud funnel to the host's errorSink. Every failure in this\n * package's services passes through the returned `mapPgError` exactly once.\n */\n/**\n * How every signed-out sentence starts (the host app's annotations speak the\n * same words), so a kept error string still says which remedy it needs.\n */\nexport const SIGNED_OUT_LEAD = \"You're signed out\";\nexport const SIGNED_OUT_MESSAGE = `${SIGNED_OUT_LEAD}. Sign in again — your text is kept here.`;\n\nexport function isSignedOutMessage(text: string | null | undefined): boolean {\n return typeof text === \"string\" && text.startsWith(SIGNED_OUT_LEAD);\n}\n\nexport function createRpcResultHelpers(\n errorSink: ErrorSink,\n sessionAttached?: () => boolean,\n): RpcResultHelpers {\n function mapPgError(e: unknown): AssociationsRpcError {\n const { pgCode, pgMessage, pgHint } = readPgFields(e);\n\n // THE DEMANDED-SCHEMA SCREAM (design Decision 4). Checked FIRST and\n // always sunk — a database that cannot answer a demanded function is not\n // this package's database, and nothing downstream may soften that.\n if (pgCode === \"PGRST202\") {\n const message =\n \"demanded schema violation: the database this client is pointed at \" +\n \"cannot answer a demanded @ai-matrx/associations RPC (PostgREST \" +\n \"PGRST202 — function not found). This package DEMANDS the platform \" +\n `schema (README § The demanded schema). ${pgMessage ?? \"\"}`.trim();\n errorSink({\n code: \"demanded_schema_violation\",\n message,\n context: { pgCode, detail: e },\n });\n const out: AssociationsRpcError = {\n code: \"demanded_schema_violation\",\n message,\n detail: e,\n };\n if (pgHint !== undefined) out.hint = pgHint;\n return out;\n }\n\n // Loud before lossy — but through the SINK, per the header's policy.\n if (isTransportFailure(e)) {\n errorSink({\n code: \"transport_failure\",\n message: \"network unreachable (browser offline?)\",\n context: { transient: true, detail: e },\n });\n } else if (!isPostgrestResultError(e)) {\n errorSink({\n code: \"internal\",\n message: pgMessage ?? \"Unexpected error talking to the data source\",\n context: { detail: e },\n });\n }\n\n if (pgCode === \"PGRST116\")\n return { code: \"not_found\", message: \"Not found\" };\n // The session's JWT is gone or expired — the user is signed out, not broken.\n if (pgCode === \"PGRST301\" || pgCode === \"PGRST303\" || pgCode === \"28000\")\n return { code: \"unauthorized\", message: SIGNED_OUT_MESSAGE };\n if (pgCode === \"42501\") {\n // An anonymous caller meets \"permission denied for function\" on every\n // demanded door (authenticated holds EXECUTE on them): a long-lived tab\n // whose session ended (measured on live 2026-10-17, cmt_list). With the\n // session attached it is a real grant gap and stays a permission verdict.\n const anonymous =\n /permission denied for function/i.test(pgMessage ?? \"\") &&\n !(sessionAttached?.() ?? false);\n if (anonymous) return { code: \"unauthorized\", message: SIGNED_OUT_MESSAGE };\n // Postgres 42501 (insufficient_privilege) — the server's own explicit\n // verdict, not a zero-row guess.\n return { code: \"forbidden_org\", message: \"Permission denied\" };\n }\n // Postgres killed the statement at the role's `statement_timeout`. The\n // database is up and the query is valid; it ran out of time. Say so,\n // because \"unexpected error\" sends the reader hunting for the wrong fault.\n if (pgCode === \"57014\") {\n const out: AssociationsRpcError = {\n code: \"internal\",\n message: \"The database took too long to respond\",\n detail: e,\n };\n if (pgHint !== undefined) out.hint = pgHint;\n return out;\n }\n\n const out: AssociationsRpcError = {\n // A real message from PostgREST beats our generic string every time;\n // the generic one is the LAST resort, not the default.\n message: pgMessage ?? \"Unexpected error talking to the data source\",\n code: \"internal\",\n detail: e,\n };\n if (pgHint !== undefined) out.hint = pgHint;\n return out;\n }\n\n function mapPgErrorPair(\n e: unknown,\n ): [AssociationsRpcError[\"code\"], string, unknown, string | undefined] {\n const mapped = mapPgError(e);\n return [mapped.code, mapped.message, mapped.detail, mapped.hint];\n }\n\n return { ok, err, mapPgError, mapPgErrorPair };\n}\n","// core/registry.ts — @ai-matrx/associations/core\n//\n// THE registry merge engine — the single resolver that turns an entity token\n// into everything a generic association surface needs to RENDER it and QUERY\n// for it. Ported behavior-verbatim from matrx-frontend\n// `features/scopes/registry/entityRegistry.ts` (associations extraction W2,\n// 2026-08-29), with the measured seams inverted:\n//\n// • the 804-line app ENTITY_OVERLAY literal (lucide icons, ~45 hrefFor\n// routes, `features/rag`/`features/hr` candidate loaders) → the OPTIONAL\n// `entityOverlay` port (`AssociationsConfig.entityOverlay` +\n// `registerEntityOverlay` on the store). The package ships NO overlay\n// entries — icons/routes/loaders are host-native values;\n// • the lucide DEFAULT_ICON → `Icon: null` (packages never depend on an\n// icon library, C19; /react supplies its inlined default in W4);\n// • console.error screams → the REQUIRED errorSink port.\n//\n// Two inputs, merged per token:\n// 1. The GENERATED registry `ENTITY_TYPE_METADATA` (mirrored 1:1 from\n// `platform.entity_types`) — the truth for `schema`/`table`/`label`/\n// `titleColumn`/`scopeable`/`category`/`contentRole`/`referencePickable`.\n// 2. The host overlay for the code-native values the DB cannot carry.\n//\n// OWNERSHIP + ORG ARE CONVENTIONS, NOT PER-TOKEN CONFIG. Verified live across\n// every cardable table after the 2026 schema reorg: each carries `created_by`\n// and `organization_id`. A token only overrides them when its table genuinely\n// diverges (`null` override = \"this table has no such column\").\n\nimport { isRecordStoreNounToken, recordStoreNoun } from \"../record-store-nouns\";\nimport {\n ENTITY_TYPE_METADATA,\n isEntityTypeToken,\n type EntityTypeMeta,\n type EntityTypeToken,\n} from \"../entity-types.generated\";\nimport type {\n EntityOverlayEntry,\n EntityOverlayMap,\n ErrorSink,\n} from \"../ports\";\n\n/** The universal ownership column post-2026-reorg. */\nexport const DEFAULT_OWNER_COLUMN = \"created_by\";\n/** The universal org-scoping column. */\nexport const DEFAULT_ORG_COLUMN = \"organization_id\";\n\n// ─── Content roles ──────────────────────────────────────────────────────────\n// The knowledge-model grouping axis. `platform.entity_types.content_role` is\n// the only per-entity authority; display metadata for the buckets (titles,\n// accents) is host/`react` chrome and deliberately NOT part of /core.\n\nexport type ContentRole =\n | \"utility\"\n | \"source\"\n | \"destination\"\n | \"hybrid\"\n | \"container\";\n\nconst CONTENT_ROLE_SET: ReadonlySet<string> = new Set([\n \"utility\",\n \"source\",\n \"destination\",\n \"hybrid\",\n \"container\",\n]);\n\n/** Runtime guard for the DB's free-text `content_role` column. */\nexport function isContentRole(value: string | null): value is ContentRole {\n return value !== null && CONTENT_ROLE_SET.has(value);\n}\n\n/**\n * Domain vocabularies that name a registered entity by a DIFFERENT string.\n * A `kind` column written by another system is not automatically a canonical\n * token — the Knowledge/ingest pipeline stamps `source_kind='cld_file'`, the\n * legacy name of the table now called `files.files`, which IS the registry's\n * `file`. One alias table, one place to add the next one. Only add an entry\n * VERIFIED to point at the same physical row.\n */\nconst TOKEN_ALIASES: Record<string, EntityTypeToken> = {\n cld_file: \"file\",\n};\n\n/**\n * Normalize a raw `kind`/`type` string onto its canonical entity token.\n * Returns the input unchanged when it is already canonical or unknown — the\n * caller's existing \"no registry entry → plain text\" path still applies.\n */\nexport function resolveEntityToken(raw: string): string {\n return TOKEN_ALIASES[raw] ?? raw;\n}\n\n/**\n * Fully-resolved entity descriptor — generated metadata + host overlay, with\n * safe fallbacks so an un-overlaid token still renders (derived plural, no\n * door, `Icon: null` → the consumer's default) even if it can't be queried\n * for candidates yet.\n */\nexport interface EntityInfo {\n token: EntityTypeToken;\n label: string;\n labelPlural: string;\n /** Postgres schema of the backing table (from the generated registry). */\n schema: string;\n /** Backing table name (from the generated registry). */\n table: string;\n /** Title column for the picker, or null when none is registered. */\n titleColumn: string | null;\n /** Ownership column to scope candidate reads to the current user. */\n ownerColumn: string;\n /** Org-scoping column. */\n orgColumn: string;\n /** Host-supplied icon component, or null (consumer renders its default). */\n Icon: EntityOverlayEntry[\"Icon\"] | null;\n hrefFor: ((id: string) => string) | null;\n scopeable: boolean;\n category: string | null;\n /** Knowledge-model grouping bucket (resource surfaces group by this). */\n contentRole: ContentRole;\n /** Candidate-source override (rag-backed tokens etc.); null = generic read. */\n listCandidates: EntityOverlayEntry[\"listCandidates\"] | null;\n /** True when a picker can list real candidates (title column OR override). */\n canListCandidates: boolean;\n}\n\n// Reverse index: \"schema.table\" → canonical token (first registered token wins\n// when several tokens share a physical table). Built once from the generated\n// metadata — immutable module constants, not mutable state.\nconst TABLE_TO_TOKEN: Record<string, EntityTypeToken> = (() => {\n const m: Record<string, EntityTypeToken> = {};\n for (const token of Object.keys(ENTITY_TYPE_METADATA) as EntityTypeToken[]) {\n const meta = ENTITY_TYPE_METADATA[token];\n const key = `${meta.schema}.${meta.table}`;\n if (!(key in m)) m[key] = token;\n }\n return m;\n})();\n\nconst UNIQUE_TABLE_NAME_TO_TOKEN: Record<string, EntityTypeToken | null> =\n (() => {\n const index: Record<string, EntityTypeToken | null> = {};\n for (const token of Object.keys(\n ENTITY_TYPE_METADATA,\n ) as EntityTypeToken[]) {\n const table = ENTITY_TYPE_METADATA[token].table;\n index[table] = table in index ? null : token;\n }\n return index;\n })();\n\nexport interface EntityRegistry {\n /** Merge more overlay entries in (host binding, W4 pickers, tests). */\n registerEntityOverlay(overlay: EntityOverlayMap): void;\n /** Resolve a KNOWN token to its full descriptor. */\n getEntityInfo(token: EntityTypeToken): EntityInfo;\n /** Safe variant for raw strings (e.g. an edge's `otherType`). */\n tryGetEntityInfo(token: string): EntityInfo | null;\n /** Resolve from a live `(schema, table)` pair, or null. */\n tryGetEntityInfoByTable(schema: string, table: string): EntityInfo | null;\n /** Resolve a raw table name only when it maps to exactly one entity. */\n tryGetEntityInfoByUniqueTableName(table: string): EntityInfo | null;\n /**\n * Tokens the DB classifies as knowledge resources via a valid\n * `content_role` AND that can list candidates. The default set for card\n * grids, resource sections, and attach pickers.\n */\n curatedTokens(): EntityTypeToken[];\n /**\n * Tokens offered as reference \"Allowed types\" — DB-driven via\n * `platform.entity_types.reference_pickable`. A pickable token with no\n * title column and no candidate override is a config defect: excluded and\n * screamed to the errorSink, never silently shown broken.\n */\n listableTokens(): EntityTypeToken[];\n}\n\n/** Build the merge engine over the host overlay (empty overlay is legal). */\nexport function createEntityRegistry(\n errorSink: ErrorSink,\n initialOverlay?: EntityOverlayMap,\n): EntityRegistry {\n // Instance state, never module state — dual-loaded graphs each construct\n // their own store, so there is nothing to split.\n const overlayByToken: Partial<Record<EntityTypeToken, EntityOverlayEntry>> = {\n ...(initialOverlay ?? {}),\n };\n\n // A host compiled against an older vocabulary can ask for a token the live\n // registry has since retired (2026-10-02: the custom-data cutover\n // deactivated `dataset` and `structured_list`; a module-scope\n // `getEntityInfo(\"structured_list\")` in the host then threw at import time\n // and every route of the app crashed). A retired token is a defect in the\n // HOST — it must be told, loudly, once per token — but it is never a reason\n // to take the whole product down. The stand-in names itself as retired.\n const retiredReported = new Set<string>();\n function retiredTokenMeta(token: string): EntityTypeMeta {\n if (!retiredReported.has(token)) {\n retiredReported.add(token);\n errorSink({\n code: \"retired_entity_token\",\n message:\n `[entityRegistry] \"${token}\" is not in the live entity vocabulary ` +\n `(retired or renamed in platform.entity_types). The host still ` +\n `references it; rename the reference to the live token, or drop it. ` +\n `Serving a stand-in so the page can render.`,\n context: { token },\n });\n }\n return {\n token: token as EntityTypeToken,\n schema: \"\",\n table: \"\",\n label: `${token} (retired)`,\n baseTier: 1,\n isComponent: false,\n isModule: false,\n isListed: false,\n scopeable: false,\n category: null,\n referencePickable: false,\n titleColumn: null,\n contentRole: null,\n referenceCategory: null,\n };\n }\n\n // The record store's kinds (Table, Pick list): live nouns with no entity-type row — named,\n // never screamed as retired, and never pointed at a table (see record-store-nouns.ts).\n function recordStoreMeta(token: string): EntityTypeMeta | null {\n const label = recordStoreNoun(token);\n if (label === null) return null;\n return {\n token: token as EntityTypeToken,\n schema: \"\",\n table: \"\",\n label,\n baseTier: 1,\n isComponent: false,\n isModule: false,\n isListed: false,\n scopeable: false,\n category: null,\n referencePickable: false,\n titleColumn: null,\n contentRole: null,\n referenceCategory: null,\n };\n }\n\n function getEntityInfo(token: EntityTypeToken): EntityInfo {\n const meta =\n ENTITY_TYPE_METADATA[token] ?? recordStoreMeta(token) ?? retiredTokenMeta(token);\n const overlay = overlayByToken[token];\n const labelPlural = overlay?.labelPlural ?? `${meta.label}s`;\n const titleColumn = meta.titleColumn;\n const contentRole = isContentRole(meta.contentRole)\n ? meta.contentRole\n : \"destination\";\n // NULL means \"not classified as a knowledge resource\" and is the normal\n // state for most entity types. Only a non-null, out-of-vocabulary value\n // is corrupt registry data and warrants a loud recovery.\n if (meta.contentRole !== null && !isContentRole(meta.contentRole)) {\n errorSink({\n code: \"invalid_content_role\",\n message:\n `[entityRegistry] \"${token}\" has invalid content_role ` +\n `\"${meta.contentRole}\" in platform.entity_types; using destination ` +\n `as a loud recovery.`,\n context: { token, contentRole: meta.contentRole },\n });\n }\n // `null` override means \"this table has no such column\"; `undefined`\n // (the common case) falls back to the convention.\n const ownerColumn =\n overlay?.ownerColumn === undefined\n ? DEFAULT_OWNER_COLUMN\n : (overlay.ownerColumn ?? \"\");\n const orgColumn =\n overlay?.orgColumn === undefined\n ? DEFAULT_ORG_COLUMN\n : (overlay.orgColumn ?? \"\");\n return {\n token,\n label: meta.label,\n labelPlural,\n schema: meta.schema,\n table: meta.table,\n titleColumn,\n ownerColumn,\n orgColumn,\n Icon: overlay?.Icon ?? null,\n hrefFor: overlay?.hrefFor ?? null,\n scopeable: meta.scopeable,\n category: meta.category,\n contentRole,\n listCandidates: overlay?.listCandidates ?? null,\n canListCandidates:\n titleColumn !== null || overlay?.listCandidates !== undefined,\n };\n }\n\n return {\n registerEntityOverlay(overlay) {\n for (const key of Object.keys(overlay) as EntityTypeToken[]) {\n const entry = overlay[key];\n if (!entry) continue;\n // Merge per token so a later registration adds fields (e.g. a\n // listCandidates loader) without erasing an earlier Icon/hrefFor.\n overlayByToken[key] = { ...overlayByToken[key], ...entry };\n }\n },\n\n getEntityInfo,\n\n tryGetEntityInfo(token) {\n const canonical = resolveEntityToken(token);\n if (isEntityTypeToken(canonical)) return getEntityInfo(canonical);\n return isRecordStoreNounToken(token)\n ? getEntityInfo(token as unknown as EntityTypeToken)\n : null;\n },\n\n tryGetEntityInfoByTable(schema, table) {\n const token = TABLE_TO_TOKEN[`${schema}.${table}`];\n return token ? getEntityInfo(token) : null;\n },\n\n tryGetEntityInfoByUniqueTableName(table) {\n const token = UNIQUE_TABLE_NAME_TO_TOKEN[table];\n return token ? getEntityInfo(token) : null;\n },\n\n curatedTokens() {\n return (Object.keys(ENTITY_TYPE_METADATA) as EntityTypeToken[]).filter(\n (t) => {\n const meta = ENTITY_TYPE_METADATA[t];\n const o = overlayByToken[t];\n return (\n isContentRole(meta.contentRole) &&\n (meta.titleColumn != null || o?.listCandidates !== undefined)\n );\n },\n );\n },\n\n listableTokens() {\n return (Object.keys(ENTITY_TYPE_METADATA) as EntityTypeToken[]).filter(\n (t) => {\n const meta = ENTITY_TYPE_METADATA[t];\n if (!meta.referencePickable) return false;\n const o = overlayByToken[t];\n const canList =\n meta.titleColumn != null || o?.listCandidates !== undefined;\n if (!canList) {\n errorSink({\n code: \"unlistable_pickable_token\",\n message:\n `[entityRegistry] \"${t}\" is reference_pickable in platform.entity_types ` +\n `but has NO title_column and no host candidate source — set its ` +\n `title_column in the registry or register a listCandidates override.`,\n context: { token: t },\n });\n }\n return canList;\n },\n );\n },\n };\n}\n","// core/doors.ts — every database call of this package goes through @ai-matrx/data's doors.\n//\n// The descriptors are generated into `src/db/public.ts` (`pnpm db:generate`, only the\n// functions this package calls). `rpcDoor` answers the `{ data, error }` pair the services\n// have always mapped (the database's own error, code kept), so every error path is\n// unchanged; a refusal before the wire (`DoorRefusedError`) throws into the service's\n// catch like any transport failure. `rpcDoorAll` is the complete read of an edge list:\n// every row, paged past the 1,000-row cap over position (nulls last), created_at, id —\n// the order the hosts' paged adapters used.\nimport { call, callAll, createDb, type Db, type FunctionDescriptor } from \"@ai-matrx/data/db\";\n\nimport type { AssociationsDataSource } from \"../ports\";\nimport type { PgError } from \"../results\";\n\nconst dbs = new WeakMap<object, Db>();\n\n/** The data connection over the host's client (one per client). */\nexport function dbOf(dataSource: AssociationsDataSource): Db {\n let db = dbs.get(dataSource);\n if (!db) {\n db = createDb({ client: dataSource });\n dbs.set(dataSource, db);\n }\n return db;\n}\n\n/**\n * `platform.assoc_add_many(p_edges jsonb) -> uuid[]` — THE BATCH DOOR (2026-10-09). One call = one\n * transaction: each element is applied exactly as `public.assoc_add` (the same argument names,\n * the same authorization, called as the caller) and the ids come back in input order; any\n * failure raises and NOTHING is applied. It lives in `platform` (nothing new goes in `public`),\n * so it is not in the generated `db/public.ts`. Born from a 140-card deck save that fired 140\n * concurrent single adds and lost 69 edges.\n */\nexport type AssocAddManyArgs = { p_edges: unknown[] };\nexport const assocAddMany = {\n schema: \"platform\",\n name: \"assoc_add_many\",\n roles: [\"authenticated\", \"service_role\"],\n registered: true,\n} as unknown as FunctionDescriptor<AssocAddManyArgs, string[]>;\n\ntype Pair<T> = { data: T | null; error: PgError | null };\n\n/**\n * The argument names are checked against the function; values stay as the services always\n * built them (an `undefined` optional is dropped on the wire, JSON values are `unknown`).\n */\ntype Args<F> = F extends FunctionDescriptor<infer A, any> ? { [K in keyof A]?: unknown } : never;\n\nfunction asPair<T>(e: unknown): Pair<T> {\n const err = e as { name?: string; cause?: PgError } | null;\n if (err?.name === \"DatabaseError\" && err.cause) return { data: null, error: err.cause };\n throw e;\n}\n\nexport async function rpcDoor<F extends FunctionDescriptor<any, any>>(\n dataSource: AssociationsDataSource,\n fn: F,\n args: Args<F>,\n): Promise<Pair<unknown>> {\n try {\n return { data: await call(dbOf(dataSource), fn, args as never), error: null };\n } catch (e) {\n return asPair(e);\n }\n}\n\nconst EDGE_ORDER = [{ column: \"position\", nullsFirst: false }, \"created_at\", \"id\"] as const;\n\nexport async function rpcDoorAll<F extends FunctionDescriptor<any, any>>(\n dataSource: AssociationsDataSource,\n fn: F,\n args: Args<F>,\n): Promise<Pair<unknown>> {\n try {\n return { data: await callAll(dbOf(dataSource), fn, args as never, { order: EDGE_ORDER }), error: null };\n } catch (e) {\n return asPair(e);\n }\n}\n","/**\n * GENERATED by `matrx-data generate` from the database description — never edit by hand.\n * schema: public · description eb4e70fa23e6\n * Regenerate: matrx-data generate (see @ai-matrx/data README).\n */\n/* eslint-disable */\nimport type { FunctionDescriptor } from \"@ai-matrx/data/db\";\n\ntype Json = string | number | boolean | null | { [key: string]: Json | undefined } | Json[];\n\nexport type AgentResourceAddArgs = { p_agent_id: string; p_source_type: string; p_source_id: string; p_label?: string; p_metadata?: Json };\nexport type AgentResourceAddResult = string;\nexport const agentResourceAdd = {\"schema\":\"public\",\"name\":\"agent_resource_add\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AgentResourceAddArgs, AgentResourceAddResult>;\n\nexport type AgentResourceRemoveArgs = { p_agent_id: string; p_source_type: string; p_source_id: string };\nexport type AgentResourceRemoveResult = undefined;\nexport const agentResourceRemove = {\"schema\":\"public\",\"name\":\"agent_resource_remove\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AgentResourceRemoveArgs, AgentResourceRemoveResult>;\n\nexport type AssocAddArgs = { p_source_type: string; p_source_id: string; p_target_type: string; p_target_id: string; p_org_id?: string; p_label?: string; p_metadata?: Json; p_role?: string; p_position?: number; p_payload_kind?: string; p_payload?: Json };\nexport type AssocAddResult = string;\nexport const assocAdd = {\"schema\":\"public\",\"name\":\"assoc_add\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocAddArgs, AssocAddResult>;\n\nexport type AssocForEntityArgs = { p_type: string; p_id: string };\nexport type AssocForEntityResult = { id: string | null; direction: string | null; other_type: string | null; other_id: string | null; role: string | null; label: string | null; position: number | null; metadata: Json | null; organization_id: string | null; created_at: string | null }[];\nexport const assocForEntity = {\"schema\":\"public\",\"name\":\"assoc_for_entity\",\"roles\":[\"anon\",\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocForEntityArgs, AssocForEntityResult>;\n\nexport type AssocForSourcesArgs = { p_source_type: string; p_source_ids: string[]; p_target_type?: string };\nexport type AssocForSourcesResult = { id: string | null; source_id: string | null; target_type: string | null; target_id: string | null; role: string | null; label: string | null; position: number | null; metadata: Json | null; organization_id: string | null; created_at: string | null }[];\nexport const assocForSources = {\"schema\":\"public\",\"name\":\"assoc_for_sources\",\"roles\":[\"anon\",\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocForSourcesArgs, AssocForSourcesResult>;\n\nexport type AssocForTargetsArgs = { p_target_type: string; p_target_ids: string[] };\nexport type AssocForTargetsResult = { id: string | null; target_id: string | null; source_type: string | null; source_id: string | null; role: string | null; label: string | null; position: number | null; metadata: Json | null; organization_id: string | null; created_at: string | null }[];\nexport const assocForTargets = {\"schema\":\"public\",\"name\":\"assoc_for_targets\",\"roles\":[\"anon\",\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocForTargetsArgs, AssocForTargetsResult>;\n\nexport type AssocMembersVisibleArgs = { p_target_type: string; p_target_ids: string[] };\nexport type AssocMembersVisibleResult = { id: string | null; target_id: string | null; source_type: string | null; source_id: string | null; role: string | null; label: string | null; position: number | null; metadata: Json | null; organization_id: string | null; created_at: string | null }[];\nexport const assocMembersVisible = {\"schema\":\"public\",\"name\":\"assoc_members_visible\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocMembersVisibleArgs, AssocMembersVisibleResult>;\n\nexport type AssocRemoveArgs = { p_source_type: string; p_source_id: string; p_target_type: string; p_target_id: string; p_role?: string };\nexport type AssocRemoveResult = undefined;\nexport const assocRemove = {\"schema\":\"public\",\"name\":\"assoc_remove\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocRemoveArgs, AssocRemoveResult>;\n\nexport type AssocRemoveForEntityArgs = { p_type: string; p_id: string };\nexport type AssocRemoveForEntityResult = undefined;\nexport const assocRemoveForEntity = {\"schema\":\"public\",\"name\":\"assoc_remove_for_entity\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocRemoveForEntityArgs, AssocRemoveForEntityResult>;\n\nexport type AssocSetTargetsArgs = { p_source_type: string; p_source_id: string; p_target_type: string; p_target_ids: string[]; p_org_id?: string; p_role?: string };\nexport type AssocSetTargetsResult = undefined;\nexport const assocSetTargets = {\"schema\":\"public\",\"name\":\"assoc_set_targets\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<AssocSetTargetsArgs, AssocSetTargetsResult>;\n\nexport type CatCreateArgs = { p_dimension: string; p_name: string; p_org_id: string; p_parent_id?: string; p_color?: string; p_icon?: string; p_slug?: string };\nexport type CatCreateResult = string;\nexport const catCreate = {\"schema\":\"public\",\"name\":\"cat_create\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CatCreateArgs, CatCreateResult>;\n\nexport type CatDeleteArgs = { p_category_id: string };\nexport type CatDeleteResult = string;\nexport const catDelete = {\"schema\":\"public\",\"name\":\"cat_delete\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CatDeleteArgs, CatDeleteResult>;\n\nexport type CatListArgs = { p_dimension?: string };\nexport type CatListResult = { id: string | null; organization_id: string | null; dimension: string | null; name: string | null; slug: string | null; parent_id: string | null; is_system: boolean | null; color: string | null; icon: string | null; position: number | null; metadata: Json | null }[];\nexport const catList = {\"schema\":\"public\",\"name\":\"cat_list\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CatListArgs, CatListResult>;\n\nexport type CatReparentArgs = { p_category_id: string; p_parent_id?: string };\nexport type CatReparentResult = string;\nexport const catReparent = {\"schema\":\"public\",\"name\":\"cat_reparent\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CatReparentArgs, CatReparentResult>;\n\nexport type CatUpdateArgs = { p_category_id: string; p_name: string; p_slug?: string; p_color?: string; p_icon?: string; p_position?: number };\nexport type CatUpdateResult = string;\nexport const catUpdate = {\"schema\":\"public\",\"name\":\"cat_update\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CatUpdateArgs, CatUpdateResult>;\n\nexport type CmtAddArgs = { p_entity_type: string; p_entity_id: string; p_body: string; p_parent_id?: string; p_org_id?: string; p_anchor?: Json; p_suggested_text?: string; p_client_request_id?: string };\nexport type CmtAddResult = string;\nexport const cmtAdd = {\"schema\":\"public\",\"name\":\"cmt_add\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CmtAddArgs, CmtAddResult>;\n\nexport type CmtDeleteArgs = { p_id: string };\nexport type CmtDeleteResult = undefined;\nexport const cmtDelete = {\"schema\":\"public\",\"name\":\"cmt_delete\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CmtDeleteArgs, CmtDeleteResult>;\n\nexport type CmtEditArgs = { p_id: string; p_body: string; p_expected_version?: number };\nexport type CmtEditResult = number;\nexport const cmtEdit = {\"schema\":\"public\",\"name\":\"cmt_edit\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CmtEditArgs, CmtEditResult>;\n\nexport type CmtListArgs = { p_entity_type: string; p_entity_id: string };\nexport type CmtListResult = { id: string | null; organization_id: string | null; entity_type: string | null; entity_id: string | null; parent_id: string | null; body: string | null; created_at: string | null; updated_at: string | null; created_by: string | null; author_email: string | null; author_display_name: string | null; author_avatar_url: string | null; anchor: Json | null; resolved_at: string | null; resolved_by: string | null; suggested_text: string | null; version: number | null; client_request_id: string | null; edited_at: string | null; created_by_tier: string | null; author_agent_id: string | null; author_agent_name: string | null }[];\nexport const cmtList = {\"schema\":\"public\",\"name\":\"cmt_list\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<CmtListArgs, CmtListResult>;\n\nexport type ConversationFileAddArgs = { p_conversation_id: string; p_file_id: string; p_label?: string; p_metadata?: Json; p_replace_metadata?: boolean };\nexport type ConversationFileAddResult = string;\nexport const conversationFileAdd = {\"schema\":\"public\",\"name\":\"conversation_file_add\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<ConversationFileAddArgs, ConversationFileAddResult>;\n\nexport type ConversationFileRemoveArgs = { p_conversation_id: string; p_file_id: string };\nexport type ConversationFileRemoveResult = undefined;\nexport const conversationFileRemove = {\"schema\":\"public\",\"name\":\"conversation_file_remove\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<ConversationFileRemoveArgs, ConversationFileRemoveResult>;\n\nexport type ConversationFilesArgs = { p_conversation_id: string };\nexport type ConversationFilesResult = { file_id: string | null; label: string | null; metadata: Json | null; created_at: string | null }[];\nexport const conversationFiles = {\"schema\":\"public\",\"name\":\"conversation_files\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<ConversationFilesArgs, ConversationFilesResult>;\n\nexport type EntityRowCreateArgs = { p_token: string; p_title: string; p_organization_id: string };\nexport type EntityRowCreateResult = Json;\nexport const entityRowCreate = {\"schema\":\"public\",\"name\":\"entity_row_create\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<EntityRowCreateArgs, EntityRowCreateResult>;\n\nexport type EntityRowRenameArgs = { p_token: string; p_id: string; p_title: string };\nexport type EntityRowRenameResult = Json;\nexport const entityRowRename = {\"schema\":\"public\",\"name\":\"entity_row_rename\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<EntityRowRenameArgs, EntityRowRenameResult>;\n\nexport type ReferenceSearchCandidatesArgs = { p_token: string; p_search?: string; p_limit?: number; p_ids?: string[]; p_order?: string; p_offset?: number; p_organization_id?: string; p_mine?: boolean; p_show_system_files?: boolean };\nexport type ReferenceSearchCandidatesResult = { id: string | null; title: string | null; updated_at: string | null }[];\nexport const referenceSearchCandidates = {\"schema\":\"public\",\"name\":\"reference_search_candidates\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<ReferenceSearchCandidatesArgs, ReferenceSearchCandidatesResult>;\n\nexport type UesGetBulkArgs = { p_entity_type: string; p_entity_ids: string[] };\nexport type UesGetBulkResult = { entity_id: string | null; is_favorite: boolean | null; is_pinned: boolean | null; is_hidden: boolean | null; last_viewed_at: string | null }[];\nexport const uesGetBulk = {\"schema\":\"public\",\"name\":\"ues_get_bulk\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<UesGetBulkArgs, UesGetBulkResult>;\n\nexport type UesListArgs = { p_kind?: string };\nexport type UesListResult = { entity_type: string | null; entity_id: string | null; is_favorite: boolean | null; is_pinned: boolean | null; is_hidden: boolean | null; last_viewed_at: string | null; updated_at: string | null }[];\nexport const uesList = {\"schema\":\"public\",\"name\":\"ues_list\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<UesListArgs, UesListResult>;\n\nexport type UesSetArgs = { p_entity_type: string; p_entity_id: string; p_is_favorite?: boolean; p_is_pinned?: boolean; p_is_hidden?: boolean };\nexport type UesSetResult = undefined;\nexport const uesSet = {\"schema\":\"public\",\"name\":\"ues_set\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<UesSetArgs, UesSetResult>;\n\nexport type UesTouchArgs = { p_entity_type: string; p_entity_id: string };\nexport type UesTouchResult = undefined;\nexport const uesTouch = {\"schema\":\"public\",\"name\":\"ues_touch\",\"roles\":[\"authenticated\",\"service_role\"],\"registered\":true} as unknown as FunctionDescriptor<UesTouchArgs, UesTouchResult>;\n","// core/associationsService.ts — @ai-matrx/associations/core\n//\n// THE SOLE CHOKEPOINT for the unified association edge —\n// `platform.associations`. Ported behavior-verbatim from matrx-frontend\n// `features/scopes/service/associationsService.ts` (643 lines, associations\n// extraction W2, 2026-08-29); the seams inverted onto the W1 ports:\n//\n// • the browser supabase singleton → the REQUIRED `dataSource` port;\n// • `requireUserId` (a store-singleton read) → the REQUIRED `identity` port\n// (failures stay LOUD — the port throws, the funnel maps it, never\n// silently anonymous);\n// • console screams → the REQUIRED `errorSink` (via guards + rpcResult).\n//\n// This is the canonical attach/detach primitive: any entity to any other\n// entity. The client holds NO grant on `platform.associations`; every\n// read/write goes through the PUBLIC SECURITY-DEFINER RPCs (`assoc_*`, plus\n// the stricter `conversation_file_*` boundary for the access-conveying\n// file → conversation pair and the `agent_resource_*` pair for authorized\n// agent containment) — and every call goes through THIS module. Methods\n// always return an `AssociationsRpcResult` and NEVER throw.\n//\n// Direction is relative to the queried entity: an edge is \"outgoing\" when\n// the entity is the source and \"incoming\" when it is the target.\n// `assoc_for_entity` returns BOTH in one round-trip. Little→big direction is\n// registry-owned — `trg_associations_auto_orient` rejects reversed writes;\n// this package surfaces that error verbatim and never flips an edge.\n\nimport { registeredEdgeLabel } from \"../association-types.generated\";\nimport type {\n AssociationEdge,\n AssociationSourceEdge,\n AssociationTargetEdge,\n AssociationTargetType,\n} from \"../edges\";\nimport type { AssociationsRpcResult } from \"../results\";\nimport { firstError } from \"./guards\";\nimport type { CoreDeps } from \"./deps\";\nimport { assocAddMany, rpcDoor, rpcDoorAll } from \"./doors\";\nimport { agentResourceAdd, agentResourceRemove, assocAdd, assocForEntity, assocForSources, assocForTargets, assocMembersVisible, assocRemove, assocRemoveForEntity, assocSetTargets, conversationFileAdd, conversationFileRemove, conversationFiles } from \"../db/public\";\n\n// Shape of one `assoc_for_entity` row (snake_case, straight from PG).\ninterface AssocForEntityRow {\n id: string;\n direction: string;\n other_type: string;\n other_id: string;\n role: string | null;\n label: string | null;\n position: number | null;\n metadata: unknown;\n organization_id: string | null;\n created_at: string;\n}\n\ninterface ConversationFileRow {\n file_id: string;\n label: string | null;\n metadata: unknown;\n created_at: string;\n}\n\nexport interface ConversationFileLink {\n fileId: string;\n label: string | null;\n metadata: unknown;\n createdAt: string;\n}\n\nfunction toEdge(row: AssocForEntityRow): AssociationEdge {\n return {\n id: row.id,\n // PG only ever emits 'outgoing' | 'incoming'; widen-then-narrow for TS.\n direction: row.direction === \"incoming\" ? \"incoming\" : \"outgoing\",\n otherType: row.other_type,\n otherId: row.other_id,\n role: row.role ?? null,\n label: row.label ?? null,\n position: row.position ?? null,\n metadata: row.metadata ?? {},\n orgId: row.organization_id ?? null,\n createdAt: row.created_at,\n };\n}\n\n// Shape of one `assoc_for_targets` row (snake_case, straight from PG).\ninterface AssocForTargetsRow {\n id: string;\n target_id: string;\n source_type: string;\n source_id: string;\n role: string | null;\n label: string | null;\n position: number | null;\n metadata: unknown;\n organization_id: string | null;\n created_at: string;\n}\n\nfunction toTargetEdge(row: AssocForTargetsRow): AssociationTargetEdge {\n return {\n id: row.id,\n targetId: row.target_id,\n sourceType: row.source_type,\n sourceId: row.source_id,\n role: row.role ?? null,\n label: row.label ?? null,\n position: row.position ?? null,\n metadata: row.metadata ?? {},\n orgId: row.organization_id ?? null,\n createdAt: row.created_at,\n };\n}\n\n// Shape of one `assoc_for_sources` row (snake_case, straight from PG).\ninterface AssocForSourcesRow {\n id: string;\n source_id: string;\n target_type: string;\n target_id: string;\n role: string | null;\n label: string | null;\n position: number | null;\n metadata: unknown;\n organization_id: string | null;\n created_at: string;\n}\n\nfunction toSourceEdge(row: AssocForSourcesRow): AssociationSourceEdge {\n return {\n id: row.id,\n sourceId: row.source_id,\n targetType: row.target_type,\n targetId: row.target_id,\n role: row.role ?? null,\n label: row.label ?? null,\n position: row.position ?? null,\n metadata: row.metadata ?? {},\n orgId: row.organization_id ?? null,\n createdAt: row.created_at,\n };\n}\n\nexport interface AddAssociationArgs {\n sourceType: string;\n sourceId: string;\n targetType: AssociationTargetType;\n targetId: string;\n orgId?: string;\n label?: string;\n metadata?: unknown;\n /**\n * Exact file → conversation updates preserve existing metadata unless the\n * caller explicitly opts into replacement. Invalid for every other pair.\n */\n replaceMetadata?: boolean;\n role?: string;\n position?: number;\n /**\n * Typed edge payload (Edge Payload System). `payloadKind` must be a\n * registered `platform.edge_payload_kind`; the DB trigger validates\n * `payload` against its JSON Schema and hard-fails on any mismatch. Real\n * logic an edge carries goes HERE — `metadata` is for loose annotations.\n */\n payloadKind?: string;\n payload?: unknown;\n}\n\n/** Edges per `addMany` call — one transaction of ~12 ms/edge, far under the API's 8 s statement cap. */\nexport const ASSOC_ADD_MANY_CHUNK = 100;\n\nexport interface AssociationsServiceApi {\n listForEntity(\n rawType: string,\n id: string,\n ): Promise<AssociationsRpcResult<{ edges: AssociationEdge[] }>>;\n listConversationFiles(\n conversationId: string,\n ): Promise<AssociationsRpcResult<{ files: ConversationFileLink[] }>>;\n listForTargets(\n rawTargetType: string,\n targetIds: string[],\n ): Promise<AssociationsRpcResult<{ edges: AssociationTargetEdge[] }>>;\n listForTargetsVisible(\n rawTargetType: string,\n targetIds: string[],\n ): Promise<AssociationsRpcResult<{ edges: AssociationTargetEdge[] }>>;\n listForSources(\n rawSourceType: string,\n sourceIds: string[],\n rawTargetType?: string,\n ): Promise<AssociationsRpcResult<{ edges: AssociationSourceEdge[] }>>;\n add(args: AddAssociationArgs): Promise<AssociationsRpcResult<{ id: string }>>;\n /**\n * Attach MANY edges in ONE database transaction (`platform.assoc_add_many`): every edge is\n * applied exactly as {@link add} applies it, the ids come back in input order, and if ANY edge\n * is refused the whole call fails and NOTHING is applied. Keep a call under\n * {@link ASSOC_ADD_MANY_CHUNK} edges (the helpers' `linkEdges` chunks for you). The\n * file → conversation pair is not batchable (it has its own stricter door): use {@link add}.\n */\n addMany(\n args: AddAssociationArgs[],\n ): Promise<AssociationsRpcResult<{ ids: string[] }>>;\n remove(args: {\n sourceType: string;\n sourceId: string;\n targetType: string;\n targetId: string;\n role?: string;\n }): Promise<AssociationsRpcResult<null>>;\n setTargets(args: {\n sourceType: string;\n sourceId: string;\n targetType: AssociationTargetType;\n targetIds: string[];\n orgId?: string;\n role?: string;\n }): Promise<AssociationsRpcResult<null>>;\n addAgentResource(args: {\n agentId: string;\n sourceType: string;\n sourceId: string;\n label?: string;\n metadata?: unknown;\n }): Promise<AssociationsRpcResult<{ id: string }>>;\n removeAgentResource(args: {\n agentId: string;\n sourceType: string;\n sourceId: string;\n }): Promise<AssociationsRpcResult<null>>;\n removeForEntity(\n rawType: string,\n id: string,\n ): Promise<AssociationsRpcResult<null>>;\n}\n\nexport function createAssociationsService(deps: CoreDeps): AssociationsServiceApi {\n const { dataSource, identity, guards } = deps;\n const { ok, err, mapPgError, mapPgErrorPair } = deps.rpc;\n const { checkToken, checkUuid, checkUuidArray, normalizeEntityToken } = guards;\n\n return {\n /**\n * All edges where `${type}:${id}` is either source (\"outgoing\") or target\n * (\"incoming\"), org-filtered by RLS inside the RPC. One round-trip.\n */\n async listForEntity(rawType, id) {\n try {\n identity.requireUserId();\n // Legacy-alias recovery (loud) — see normalizeEntityToken / D27.\n const type = normalizeEntityToken(rawType);\n const bad = firstError(checkToken(\"type\", type), checkUuid(\"id\", id));\n if (bad) return { ok: false, error: bad };\n const { data, error } = await rpcDoorAll(dataSource, assocForEntity, {\n p_type: type,\n p_id: id,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as AssocForEntityRow[];\n return ok({ edges: rows.map(toEdge) });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Viewer-aware file attachments for a conversation. Unlike the generic\n * org-filtered association reader, this follows the conversation's\n * canonical viewer grant, so an explicitly shared cross-org conversation\n * has the same attachment inventory in every client.\n */\n async listConversationFiles(conversationId) {\n try {\n identity.requireUserId();\n const bad = checkUuid(\"conversationId\", conversationId);\n if (bad) return { ok: false, error: bad };\n const { data, error } = await rpcDoor(dataSource, conversationFiles, {\n p_conversation_id: conversationId,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as ConversationFileRow[];\n return ok({\n files: rows.map((row) => ({\n fileId: row.file_id,\n label: row.label ?? null,\n metadata: row.metadata ?? {},\n createdAt: row.created_at,\n })),\n });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Every edge whose target is one of `targetIds` (all the same\n * `targetType`), org-filtered by RLS inside the RPC. The batch\n * counterpart of `listForEntity` — each row carries `targetId` so\n * callers can group results back by container.\n */\n async listForTargets(rawTargetType, targetIds) {\n try {\n identity.requireUserId();\n const targetType = normalizeEntityToken(rawTargetType);\n const ids = Array.from(new Set(targetIds));\n if (ids.length === 0) return ok({ edges: [] });\n const bad = firstError(\n checkToken(\"targetType\", targetType),\n checkUuidArray(\"targetIds\", ids),\n );\n if (bad) return { ok: false, error: bad };\n const { data, error } = await rpcDoorAll(dataSource, assocForTargets, {\n p_target_type: targetType,\n p_target_ids: ids,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as AssocForTargetsRow[];\n return ok({ edges: rows.map(toTargetEdge) });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Like `listForTargets`, but VISIBILITY-AWARE: an edge is returned when\n * the caller EITHER shares org access to it OR can VIEW its target via\n * the canonical row-level authorization truth `iam.has_access(target,\n * 'viewer')` — honoring published-to-the-web rows, Anyone links, share grants,\n * container memberships, and reachability. A strict SUPERSET of\n * `listForTargets` access; a stranger with no grant on a private target\n * still gets nothing. Use for reading the members of a SHAREABLE\n * container; keep plain `listForTargets` for org-scoped tagging reads.\n */\n async listForTargetsVisible(rawTargetType, targetIds) {\n try {\n identity.requireUserId();\n const targetType = normalizeEntityToken(rawTargetType);\n const ids = Array.from(new Set(targetIds));\n if (ids.length === 0) return ok({ edges: [] });\n const bad = firstError(\n checkToken(\"targetType\", targetType),\n checkUuidArray(\"targetIds\", ids),\n );\n if (bad) return { ok: false, error: bad };\n const { data, error } = await rpcDoorAll(dataSource, assocMembersVisible, {\n p_target_type: targetType,\n p_target_ids: ids,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as AssocForTargetsRow[];\n return ok({ edges: rows.map(toTargetEdge) });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Every edge whose source is one of `sourceIds` (all the same\n * `sourceType`), org-filtered by RLS inside the RPC. Pass `targetType`\n * to push the target filter into the DB. Each row carries `sourceId` so\n * callers can group results back by source.\n */\n async listForSources(rawSourceType, sourceIds, rawTargetType) {\n try {\n identity.requireUserId();\n const sourceType = normalizeEntityToken(rawSourceType);\n const targetType =\n rawTargetType != null\n ? normalizeEntityToken(rawTargetType)\n : undefined;\n const ids = Array.from(new Set(sourceIds));\n if (ids.length === 0) return ok({ edges: [] });\n const bad = firstError(\n checkToken(\"sourceType\", sourceType),\n checkUuidArray(\"sourceIds\", ids),\n targetType ? checkToken(\"targetType\", targetType) : null,\n );\n if (bad) return { ok: false, error: bad };\n const { data, error } = await rpcDoorAll(dataSource, assocForSources, {\n p_source_type: sourceType,\n p_source_ids: ids,\n ...(targetType ? { p_target_type: targetType } : {}),\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as AssocForSourcesRow[];\n return ok({ edges: rows.map(toSourceEdge) });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Attach `source` → `target`. Idempotent (ON CONFLICT). When `orgId` is\n * omitted the RPC resolves org from the endpoints; pass `orgId` for\n * targets that don't carry one. Returns the association id.\n */\n async add(args) {\n try {\n identity.requireUserId();\n // Legacy-alias recovery (loud) — see normalizeEntityToken / D27.\n const sourceType = normalizeEntityToken(args.sourceType);\n const targetType = normalizeEntityToken(args.targetType);\n const bad = firstError(\n checkToken(\"sourceType\", sourceType),\n checkUuid(\"sourceId\", args.sourceId),\n checkToken(\"targetType\", targetType),\n checkUuid(\"targetId\", args.targetId),\n args.orgId != null ? checkUuid(\"orgId\", args.orgId) : null,\n );\n if (bad) return { ok: false, error: bad };\n // A file attachment conveys viewer access through the conversation.\n // Keep this service as the client chokepoint, but route this one\n // access-bearing pair through its stricter DB boundary.\n if (sourceType === \"file\" && targetType === \"conversation\") {\n if (\n args.role != null ||\n args.position != null ||\n args.payloadKind != null ||\n args.payload != null\n ) {\n return err(\n \"invalid_argument\",\n \"File conversation attachments support only the canonical role-less edge\",\n );\n }\n const { data, error } = await rpcDoor(\n dataSource, conversationFileAdd,\n {\n p_conversation_id: args.targetId,\n p_file_id: args.sourceId,\n p_label: args.label,\n p_metadata: args.metadata ?? {},\n p_replace_metadata: args.replaceMetadata ?? false,\n },\n );\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\n \"internal\",\n \"conversation_file_add returned no association id\",\n );\n }\n return ok({ id: data });\n }\n if (args.replaceMetadata != null) {\n return err(\n \"invalid_argument\",\n \"replaceMetadata is supported only for file conversation attachments\",\n );\n }\n // A pair the registry NAMES is written with that name — the DB\n // refuses any other label for it (enforce_known_association). A\n // display name only rides pairs registered without one.\n const { data, error } = await rpcDoor(dataSource, assocAdd, {\n p_source_type: sourceType,\n p_source_id: args.sourceId,\n p_target_type: targetType,\n p_target_id: args.targetId,\n p_org_id: args.orgId,\n p_label: registeredEdgeLabel(sourceType, targetType, args.label) ?? args.label,\n p_metadata: args.metadata ?? {},\n p_role: args.role,\n p_position: args.position,\n p_payload_kind: args.payloadKind,\n p_payload: args.payload ?? undefined,\n });\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\"internal\", \"assoc_add returned no association id\");\n }\n return ok({ id: data });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n async addMany(edges) {\n try {\n identity.requireUserId();\n if (edges.length === 0) return ok({ ids: [] });\n const wire: Record<string, unknown>[] = [];\n for (const args of edges) {\n const sourceType = normalizeEntityToken(args.sourceType);\n const targetType = normalizeEntityToken(args.targetType);\n const bad = firstError(\n checkToken(\"sourceType\", sourceType),\n checkUuid(\"sourceId\", args.sourceId),\n checkToken(\"targetType\", targetType),\n checkUuid(\"targetId\", args.targetId),\n args.orgId != null ? checkUuid(\"orgId\", args.orgId) : null,\n );\n if (bad) return { ok: false, error: bad };\n if (sourceType === \"file\" && targetType === \"conversation\") {\n return err(\n \"invalid_argument\",\n \"File conversation attachments have their own door: use add(), not addMany()\",\n );\n }\n if (args.replaceMetadata != null) {\n return err(\n \"invalid_argument\",\n \"replaceMetadata is supported only for file conversation attachments\",\n );\n }\n wire.push({\n p_source_type: sourceType,\n p_source_id: args.sourceId,\n p_target_type: targetType,\n p_target_id: args.targetId,\n p_org_id: args.orgId,\n p_label: registeredEdgeLabel(sourceType, targetType, args.label) ?? args.label,\n p_metadata: args.metadata ?? {},\n p_role: args.role,\n p_position: args.position,\n p_payload_kind: args.payloadKind,\n p_payload: args.payload ?? undefined,\n });\n }\n const { data, error } = await rpcDoor(dataSource, assocAddMany, { p_edges: wire });\n if (error) return err(...mapPgErrorPair(error));\n if (!Array.isArray(data) || data.length !== edges.length) {\n return err(\n \"internal\",\n `assoc_add_many returned ${Array.isArray(data) ? data.length : \"no\"} ids for ${edges.length} edges`,\n );\n }\n return ok({ ids: data as string[] });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Detach `source` → `target`. No-op if the edge doesn't exist. When\n * `role` is omitted only the role-less edge is removed (role IS NOT\n * DISTINCT FROM null); pass `role` to detach a specific typed edge.\n */\n async remove(args) {\n try {\n identity.requireUserId();\n const sourceType = normalizeEntityToken(args.sourceType);\n const targetType = normalizeEntityToken(args.targetType);\n const bad = firstError(\n checkToken(\"sourceType\", sourceType),\n checkUuid(\"sourceId\", args.sourceId),\n checkToken(\"targetType\", targetType),\n checkUuid(\"targetId\", args.targetId),\n );\n if (bad) return { ok: false, error: bad };\n if (sourceType === \"file\" && targetType === \"conversation\") {\n if (args.role != null) {\n return err(\n \"invalid_argument\",\n \"File conversation attachments support only the canonical role-less edge\",\n );\n }\n const { error } = await rpcDoor(dataSource, conversationFileRemove, {\n p_conversation_id: args.targetId,\n p_file_id: args.sourceId,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n }\n const { error } = await rpcDoor(dataSource, assocRemove, {\n p_source_type: sourceType,\n p_source_id: args.sourceId,\n p_target_type: targetType,\n p_target_id: args.targetId,\n p_role: args.role,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Make the source's edges of `targetType` exactly equal `targetIds`\n * (adds missing, removes extras) in one transaction.\n */\n async setTargets(args) {\n try {\n identity.requireUserId();\n const sourceType = normalizeEntityToken(args.sourceType);\n const targetType = normalizeEntityToken(args.targetType);\n const target = Array.from(new Set(args.targetIds));\n const bad = firstError(\n checkToken(\"sourceType\", sourceType),\n checkUuid(\"sourceId\", args.sourceId),\n checkToken(\"targetType\", targetType),\n checkUuidArray(\"targetIds\", target),\n args.orgId != null ? checkUuid(\"orgId\", args.orgId) : null,\n );\n if (bad) return { ok: false, error: bad };\n const { error } = await rpcDoor(dataSource, assocSetTargets, {\n p_source_type: sourceType,\n p_source_id: args.sourceId,\n p_target_type: targetType,\n p_target_ids: target,\n p_org_id: args.orgId,\n p_role: args.role,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Permanently attach a resource to an agent. The dedicated RPC enforces\n * the stronger authoring contract this containment edge requires: editor\n * access to both the agent and source resource. The stored edge is still\n * the canonical platform association (`role=agent_resource`).\n */\n async addAgentResource(args) {\n try {\n identity.requireUserId();\n const sourceType = normalizeEntityToken(args.sourceType);\n const bad = firstError(\n checkUuid(\"agentId\", args.agentId),\n checkToken(\"sourceType\", sourceType),\n checkUuid(\"sourceId\", args.sourceId),\n );\n if (bad) return { ok: false, error: bad };\n const { data, error } = await rpcDoor(dataSource, agentResourceAdd, {\n p_agent_id: args.agentId,\n p_source_type: sourceType,\n p_source_id: args.sourceId,\n p_label: args.label,\n p_metadata: args.metadata ?? {},\n });\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\"internal\", \"agent_resource_add returned no association id\");\n }\n return ok({ id: data });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /** Remove one permanent Agent Resource edge. */\n async removeAgentResource(args) {\n try {\n identity.requireUserId();\n const sourceType = normalizeEntityToken(args.sourceType);\n const bad = firstError(\n checkUuid(\"agentId\", args.agentId),\n checkToken(\"sourceType\", sourceType),\n checkUuid(\"sourceId\", args.sourceId),\n );\n if (bad) return { ok: false, error: bad };\n const { error } = await rpcDoor(dataSource, agentResourceRemove, {\n p_agent_id: args.agentId,\n p_source_type: sourceType,\n p_source_id: args.sourceId,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Remove every edge where `${type}:${id}` is the source OR the target,\n * org-filtered inside the RPC. The deletion counterpart of\n * `listForEntity` — call it when an entity is deleted so no edge is left\n * orphaned.\n */\n async removeForEntity(rawType, id) {\n try {\n identity.requireUserId();\n const type = normalizeEntityToken(rawType);\n const bad = firstError(checkToken(\"type\", type), checkUuid(\"id\", id));\n if (bad) return { ok: false, error: bad };\n const { error } = await rpcDoor(dataSource, assocRemoveForEntity, {\n p_type: type,\n p_id: id,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n };\n}\n","// core/categoriesService.ts — @ai-matrx/associations/core\n//\n// THE SOLE CHOKEPOINT for the canonical faceted taxonomy —\n// `platform.categories`. Ported behavior-verbatim from matrx-frontend\n// `features/scopes/service/categoriesService.ts` (associations extraction W2,\n// 2026-08-29); supabase singleton → `dataSource`, `requireUserId` →\n// `identity`, host `Database` RPC row type → the structural row shape below.\n//\n// One table, partitioned by `dimension` (the facet). The client has NO\n// direct grant on `platform.categories`; every read/write goes through the\n// PUBLIC SECURITY-DEFINER `cat_*` RPCs — and every call goes through THIS\n// module. Methods always return an `AssociationsRpcResult` and NEVER throw.\n//\n// ASSIGNMENT of a category to an entity is deliberately NOT here: it reuses\n// the association edge (`associationsService.add({ targetType: 'category',\n// … })`). A category is the noun this module owns; the attach is the verb\n// the associations service owns.\n\nimport type { CategoryDimension, PlatformCategory } from \"../edges\";\nimport type { AssociationsRpcResult } from \"../results\";\nimport type { CoreDeps } from \"./deps\";\nimport { rpcDoor } from \"./doors\";\nimport { catCreate, catDelete, catList, catReparent, catUpdate } from \"../db/public\";\n\n// One `cat_list` row (snake_case, straight from PG).\ninterface CatListRow {\n id: string;\n organization_id: string | null;\n dimension: string;\n name: string;\n slug: string | null;\n parent_id: string | null;\n is_system: boolean | null;\n color: string | null;\n icon: string | null;\n position: number | null;\n metadata: unknown;\n}\n\nfunction toCategory(row: CatListRow): PlatformCategory {\n return {\n id: row.id,\n orgId: row.organization_id ?? null,\n dimension: row.dimension,\n name: row.name,\n slug: row.slug ?? null,\n parentId: row.parent_id ?? null,\n isSystem: !!row.is_system,\n color: row.color ?? null,\n icon: row.icon ?? null,\n position: row.position ?? null,\n metadata:\n row.metadata &&\n typeof row.metadata === \"object\" &&\n !Array.isArray(row.metadata)\n ? (row.metadata as Record<string, unknown>)\n : null,\n };\n}\n\nexport interface CategoriesServiceApi {\n list(\n dimension?: CategoryDimension,\n ): Promise<AssociationsRpcResult<{ categories: PlatformCategory[] }>>;\n create(args: {\n dimension: CategoryDimension;\n name: string;\n orgId: string;\n parentId?: string | null;\n color?: string | null;\n icon?: string | null;\n slug?: string | null;\n }): Promise<AssociationsRpcResult<{ id: string }>>;\n update(args: {\n id: string;\n name: string;\n slug: string | null;\n color: string | null;\n icon: string | null;\n position: number | null;\n }): Promise<AssociationsRpcResult<{ id: string }>>;\n reparent(args: {\n id: string;\n parentId: string | null;\n }): Promise<AssociationsRpcResult<{ id: string }>>;\n delete(id: string): Promise<AssociationsRpcResult<{ id: string }>>;\n}\n\nexport function createCategoriesService(deps: CoreDeps): CategoriesServiceApi {\n const { dataSource, identity } = deps;\n const { ok, err, mapPgError, mapPgErrorPair } = deps.rpc;\n\n return {\n /**\n * Every category visible to the caller (system + their orgs),\n * org-filtered by `iam.has_org_access` inside the RPC. Pass `dimension`\n * to scope to one facet (the common case). Ordered by dimension, then\n * `position`, then name.\n */\n async list(dimension) {\n try {\n identity.requireUserId();\n const { data, error } = await rpcDoor(dataSource, catList, {\n p_dimension: dimension,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as CatListRow[];\n return ok({ categories: rows.map(toCategory) });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Create an org-owned category in `dimension`. `orgId` is REQUIRED and\n * the RPC rejects callers without access to it (`cat_create` raises\n * 42501). The created row is always `is_system = false`; seeding\n * system/global categories is a migration concern, never a client write.\n */\n async create(args) {\n try {\n identity.requireUserId();\n const { data, error } = await rpcDoor(dataSource, catCreate, {\n p_dimension: args.dimension,\n p_name: args.name,\n p_org_id: args.orgId,\n p_parent_id: args.parentId ?? undefined,\n p_color: args.color ?? undefined,\n p_icon: args.icon ?? undefined,\n p_slug: args.slug ?? undefined,\n });\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\"internal\", \"cat_create returned no category id\");\n }\n return ok({ id: data });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Replace the editable scalar fields of one category. The caller\n * supplies the complete desired state so nullable fields can be cleared\n * without a JSON patch or a second interpretation of `undefined`.\n */\n async update(args) {\n try {\n identity.requireUserId();\n const { data, error } = await rpcDoor(dataSource, catUpdate, {\n p_category_id: args.id,\n p_name: args.name,\n p_slug: args.slug ?? undefined,\n p_color: args.color ?? undefined,\n p_icon: args.icon ?? undefined,\n p_position: args.position ?? undefined,\n });\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\"internal\", \"cat_update returned no category id\");\n }\n return ok({ id: data });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /** Move a category to the root or directly beneath one root category. */\n async reparent(args) {\n try {\n identity.requireUserId();\n const { data, error } = await rpcDoor(dataSource, catReparent, {\n p_category_id: args.id,\n p_parent_id: args.parentId ?? undefined,\n });\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\"internal\", \"cat_reparent returned no category id\");\n }\n return ok({ id: data });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /** Soft-delete a leaf category. Parents with live children are rejected. */\n async delete(id) {\n try {\n identity.requireUserId();\n const { data, error } = await rpcDoor(dataSource, catDelete, {\n p_category_id: id,\n });\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\"internal\", \"cat_delete returned no category id\");\n }\n return ok({ id: data });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n };\n}\n","// core/favoritesService.ts — @ai-matrx/associations/core\n//\n// THE SOLE CHOKEPOINT for per-user entity state —\n// `platform.user_entity_state` (the caller's favorite / pinned / hidden\n// flags + recency on any entity). Ported behavior-verbatim from\n// matrx-frontend `features/scopes/service/favoritesService.ts` +\n// `favoritesCore.ts` (associations extraction W2, 2026-08-29). The two host\n// files existed only because the browser file was pinned to the supabase\n// singleton while server readers needed injection — the injectable\n// `favoritesCore` shape prefigured this package's `dataSource` port, so here\n// they collapse back into ONE implementation (recorded in the CHANGELOG).\n//\n// Every read/write goes through the four PUBLIC SECURITY-DEFINER RPCs\n// (`ues_set` / `ues_list` / `ues_get_bulk` / `ues_touch`) — through THIS\n// module only. Methods always return an `AssociationsRpcResult`, NEVER throw.\n//\n// Scope: unlike associations (org-gated), per-user state is gated on\n// `auth.uid()` INSIDE each RPC — the user's own flags on an entity, across\n// every org. `entity_type` is free text in the DB (the table tracks state\n// for non-graph things too, e.g. `\"nav\"` destinations), so callers pass a\n// canonical token where one exists, or another stable token.\n\nimport type { UserEntityState, UserStateKind } from \"../edges\";\nimport type { AssociationsRpcResult } from \"../results\";\nimport type { CoreDeps } from \"./deps\";\nimport { rpcDoor } from \"./doors\";\nimport { uesGetBulk, uesList, uesSet, uesTouch } from \"../db/public\";\n\n// Raw `ues_list` row (snake_case, straight from PG). Carries `entity_type`.\ninterface UesListRow {\n entity_type: string;\n entity_id: string;\n is_favorite: boolean;\n is_pinned: boolean;\n is_hidden: boolean;\n last_viewed_at: string | null;\n updated_at: string;\n}\n\n// Raw `ues_get_bulk` row — no `entity_type` (a query input the RPC doesn't echo).\ninterface UesBulkRow {\n entity_id: string;\n is_favorite: boolean;\n is_pinned: boolean;\n is_hidden: boolean;\n last_viewed_at: string | null;\n}\n\nfunction toState(row: UesListRow): UserEntityState {\n return {\n entityType: row.entity_type,\n entityId: row.entity_id,\n isFavorite: row.is_favorite,\n isPinned: row.is_pinned,\n isHidden: row.is_hidden,\n lastViewedAt: row.last_viewed_at ?? null,\n };\n}\n\nexport interface FavoritesServiceApi {\n setState(args: {\n entityType: string;\n entityId: string;\n isFavorite?: boolean;\n isPinned?: boolean;\n isHidden?: boolean;\n }): Promise<AssociationsRpcResult<null>>;\n setFavorite(\n entityType: string,\n entityId: string,\n isFavorite: boolean,\n ): Promise<AssociationsRpcResult<null>>;\n setPinned(\n entityType: string,\n entityId: string,\n isPinned: boolean,\n ): Promise<AssociationsRpcResult<null>>;\n setHidden(\n entityType: string,\n entityId: string,\n isHidden: boolean,\n ): Promise<AssociationsRpcResult<null>>;\n list(\n kind?: UserStateKind,\n ): Promise<AssociationsRpcResult<{ items: UserEntityState[] }>>;\n getBulk(\n entityType: string,\n entityIds: string[],\n ): Promise<AssociationsRpcResult<{ items: UserEntityState[] }>>;\n touch(\n entityType: string,\n entityId: string,\n ): Promise<AssociationsRpcResult<null>>;\n}\n\nexport function createFavoritesService(deps: CoreDeps): FavoritesServiceApi {\n const { dataSource, identity } = deps;\n const { ok, err, mapPgError, mapPgErrorPair } = deps.rpc;\n\n const api: FavoritesServiceApi = {\n /**\n * Upsert the caller's state row for one entity. An OMITTED flag is left\n * UNCHANGED (the RPC `coalesce`s null → existing), so you can flip just\n * `isFavorite` without clobbering `isPinned`/`isHidden`. Idempotent.\n */\n async setState(args) {\n try {\n identity.requireUserId();\n const { error } = await rpcDoor(dataSource, uesSet, {\n p_entity_type: args.entityType,\n p_entity_id: args.entityId,\n p_is_favorite: args.isFavorite,\n p_is_pinned: args.isPinned,\n p_is_hidden: args.isHidden,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /** Convenience: flip ONLY the favorite flag (leaves pinned/hidden intact). */\n async setFavorite(entityType, entityId, isFavorite) {\n return api.setState({ entityType, entityId, isFavorite });\n },\n\n /** Convenience: flip ONLY the pinned flag. */\n async setPinned(entityType, entityId, isPinned) {\n return api.setState({ entityType, entityId, isPinned });\n },\n\n /** Convenience: flip ONLY the hidden flag. */\n async setHidden(entityType, entityId, isHidden) {\n return api.setState({ entityType, entityId, isHidden });\n },\n\n /**\n * Every state row the caller owns, optionally filtered to a single\n * dimension (`\"favorite\"` | `\"pinned\"` | `\"hidden\"`). Pass nothing for all.\n */\n async list(kind) {\n try {\n identity.requireUserId();\n const { data, error } = await rpcDoor(dataSource, uesList, {\n p_kind: kind,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as UesListRow[];\n return ok({ items: rows.map(toState) });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Bulk-fetch the caller's flags for `entityIds` of one `entityType` —\n * the read a list view uses to paint its star column in one round-trip.\n * Only entities that HAVE a state row come back; absent ids mean \"no\n * state yet\".\n */\n async getBulk(entityType, entityIds) {\n try {\n identity.requireUserId();\n const ids = Array.from(new Set(entityIds));\n const { data, error } = await rpcDoor(dataSource, uesGetBulk, {\n p_entity_type: entityType,\n p_entity_ids: ids,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as UesBulkRow[];\n // `ues_get_bulk` doesn't echo entity_type (it's a query input) —\n // stamp it back so callers get the same shape as `list`.\n return ok({\n items: rows.map((r) => ({\n entityType,\n entityId: r.entity_id,\n isFavorite: r.is_favorite,\n isPinned: r.is_pinned,\n isHidden: r.is_hidden,\n lastViewedAt: r.last_viewed_at ?? null,\n })),\n });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /** Stamp `last_viewed_at = now()` (creates the row if absent). */\n async touch(entityType, entityId) {\n try {\n identity.requireUserId();\n const { error } = await rpcDoor(dataSource, uesTouch, {\n p_entity_type: entityType,\n p_entity_id: entityId,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n };\n\n return api;\n}\n","// core/candidates.ts — @ai-matrx/associations/core\n//\n// \"What can I attach?\" — the generic candidate reader behind every\n// association picker, plus the universal cross-token search. Ported\n// behavior-verbatim from matrx-frontend\n// `features/scopes/service/associationCandidates.ts` (associations extraction\n// W2, 2026-08-29); supabase singleton → `dataSource`, the app entityRegistry\n// → the /core registry merge engine, console screams → errorSink.\n//\n// Fully token-driven: NO per-entity code. Which candidates a reader sees, and any\n// entity-specific equality predicates come from `platform.entity_types` and\n// are enforced by `public.reference_search_candidates`. Tokens whose backing\n// table can't be read client-side list through the host overlay's\n// `listCandidates` override instead (the entity-overlay port).\n\nimport type { EntityTypeToken } from \"../entity-types.generated\";\nimport type { CoreDeps } from \"./deps\";\nimport { rpcDoor } from \"./doors\";\nimport { referenceSearchCandidates } from \"../db/public\";\n\nexport interface CandidateRecord {\n id: string;\n title: string;\n}\n\nexport interface ListCandidatesArgs {\n token: EntityTypeToken;\n /** Case-insensitive title filter. */\n search?: string;\n limit?: number;\n}\n\nexport type CandidatesResult =\n | { ok: true; data: CandidateRecord[] }\n | { ok: false; error: string };\n\nexport interface UniversalCandidate extends CandidateRecord {\n token: EntityTypeToken;\n}\n\nexport interface SearchAcrossTokensArgs {\n /** Tokens to search. Defaults to every curated token in the registry. */\n tokens?: EntityTypeToken[];\n search: string;\n /** Cap per token — a universal search shows a few of everything. */\n perTokenLimit?: number;\n /** Max in-flight token queries. */\n concurrency?: number;\n}\n\n/** One token whose candidate read failed during a cross-token search. */\nexport interface TokenSearchFailure {\n token: EntityTypeToken;\n error: string;\n}\n\n/**\n * A cross-token search's honest answer: what could be read, AND what could\n * not. An empty `results` with non-empty `failures` is \"we couldn't look\",\n * never \"there is nothing\".\n */\nexport interface SearchAcrossTokensResult {\n results: UniversalCandidate[];\n failures: TokenSearchFailure[];\n}\n\nexport interface ReferenceSearchCandidatesFn {\n (args: {\n p_token: string;\n p_search?: string;\n p_limit?: number;\n p_ids?: string[];\n }): Promise<\n | { data: Array<{ id: string; title: string | null }>; error: null }\n | { data: null; error: { message: string } }\n >;\n}\n\nexport interface CandidatesServiceApi {\n /**\n * The universal candidate reader RPC (`public.reference_search_candidates`)\n * — shared by candidate search here and title resolution in titles.ts.\n */\n callReferenceSearchCandidates: ReferenceSearchCandidatesFn;\n listAssociationCandidates(args: ListCandidatesArgs): Promise<CandidatesResult>;\n /**\n * ONE search over EVERY listable entity type — the \"attach anything from\n * anywhere\" primitive. Registry-driven client fan-out, capped and\n * concurrency-limited. One broken table never blanks the search: a failed\n * token is screamed (errorSink) AND reported in `failures` (registry\n * order), so a face can say what it could not search instead of showing\n * \"no results\".\n */\n searchCandidatesAcrossTokens(\n args: SearchAcrossTokensArgs,\n ): Promise<SearchAcrossTokensResult>;\n}\n\nexport function createCandidatesService(deps: CoreDeps): CandidatesServiceApi {\n const { dataSource, registry, errorSink } = deps;\n\n const callReferenceSearchCandidates: ReferenceSearchCandidatesFn = async (\n args,\n ) => {\n const { data, error } = await rpcDoor(\n dataSource, referenceSearchCandidates,\n args,\n );\n if (error) return { data: null, error };\n return {\n data: (Array.isArray(data) ? data : []) as Array<{\n id: string;\n title: string | null;\n }>,\n error: null,\n };\n };\n\n async function listAssociationCandidates(\n args: ListCandidatesArgs,\n ): Promise<CandidatesResult> {\n const { token, search, limit = 100 } = args;\n const info = registry.getEntityInfo(token);\n\n // Overlay-declared candidate-source override — for tokens whose backing\n // table can't be read client-side (e.g. data_store: rag isn't\n // PostgREST-exposed).\n if (info.listCandidates) {\n try {\n return await info.listCandidates({\n ...(search !== undefined ? { search } : {}),\n limit,\n });\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"Failed to load candidates\";\n errorSink({\n code: \"candidate_override_failed\",\n message: `[listAssociationCandidates] override failed for \"${token}\": ${msg}`,\n context: { token, detail: e },\n });\n return { ok: false, error: msg };\n }\n }\n\n if (!info.canListCandidates || !info.titleColumn) {\n const msg =\n `Entity \"${token}\" has no title column — set one in ` +\n `platform.entity_types (or register a listCandidates override) before listing candidates`;\n errorSink({\n code: \"unlistable_token\",\n message: `[listAssociationCandidates] ${msg}`,\n context: { token },\n });\n return { ok: false, error: msg };\n }\n const trimmedSearch = search?.trim() || undefined;\n const { data, error } = await callReferenceSearchCandidates({\n p_token: token,\n ...(trimmedSearch !== undefined ? { p_search: trimmedSearch } : {}),\n p_limit: limit,\n });\n if (error) {\n errorSink({\n code: \"candidate_rpc_failed\",\n message: `[listAssociationCandidates] candidate RPC failed for \"${token}\": ${error.message}`,\n context: { token, detail: error },\n });\n return { ok: false, error: error.message };\n }\n return {\n ok: true,\n data: data.map((row) => ({\n id: row.id,\n title: row.title?.trim() || \"Untitled\",\n })),\n };\n }\n\n async function searchCandidatesAcrossTokens(\n args: SearchAcrossTokensArgs,\n ): Promise<SearchAcrossTokensResult> {\n const { tokens, search, perTokenLimit = 5, concurrency = 6 } = args;\n // Universal attach/search is narrower than display: only tokens explicitly\n // registered as reference-pickable may generate candidate RPC traffic.\n const list = tokens ?? registry.listableTokens();\n if (list.length === 0) return { results: [], failures: [] };\n\n const out: UniversalCandidate[] = [];\n const failures: TokenSearchFailure[] = [];\n let cursor = 0;\n\n async function worker(): Promise<void> {\n while (cursor < list.length) {\n const token = list[cursor];\n cursor += 1;\n if (!token) continue;\n const res = await listAssociationCandidates({\n token,\n search,\n limit: perTokenLimit,\n });\n if (res.ok) {\n for (const c of res.data) out.push({ ...c, token });\n } else {\n // Screamed inside listAssociationCandidates; recorded here so the\n // caller can tell \"nothing matched\" from \"couldn't look\".\n failures.push({ token, error: res.error });\n }\n }\n }\n\n await Promise.all(\n Array.from({ length: Math.min(concurrency, list.length) }, worker),\n );\n\n // Stable order: registry (role-grouped) token order, then title.\n const tokenOrder = new Map(list.map((t, i) => [t, i]));\n out.sort((a, b) => {\n const ta = tokenOrder.get(a.token) ?? 0;\n const tb = tokenOrder.get(b.token) ?? 0;\n if (ta !== tb) return ta - tb;\n return a.title.localeCompare(b.title);\n });\n failures.sort(\n (a, b) => (tokenOrder.get(a.token) ?? 0) - (tokenOrder.get(b.token) ?? 0),\n );\n return { results: out, failures };\n }\n\n return {\n callReferenceSearchCandidates,\n listAssociationCandidates,\n searchCandidatesAcrossTokens,\n };\n}\n","// core/titles.ts — @ai-matrx/associations/core\n//\n// Batched entity-title resolution — the \"UUIDs never render\" primitive.\n// Ported behavior-verbatim from matrx-frontend\n// `features/scopes/service/entityTitles.ts` (associations extraction W2,\n// 2026-08-29). One structural inversion: the MODULE-level session Map (banned\n// by the packaging standard — dual-loaded graphs silently split module\n// state) becomes STORE-INSTANCE state — the cache lives on the titles\n// service the store constructs once, so there is nothing to split and no\n// globalThis slot is needed.\n//\n// Association edges SHOULD carry a `label` stamped at attach time; this\n// service covers the rest (legacy unlabeled edges, rows renamed since\n// attach). Given a token + ids, it resolves titles through the\n// registry-driven candidate RPC and memoizes per store lifetime. Tokens\n// without a title column (or unregistered tokens) resolve to nothing —\n// callers fall back to `Untitled <label>` via `fallback`.\n\nimport { humanizeIdentifier } from \"@ai-matrx/kit/text-case\";\nimport type { CoreDeps } from \"./deps\";\nimport type { CandidatesServiceApi } from \"./candidates\";\n\nconst CHUNK = 200;\n\nexport function entityTitleCacheKey(token: string, id: string): string {\n return `${token}:${id}`;\n}\n\nexport interface TitlesServiceApi {\n /** Read the cache synchronously (for render paths after a fetch settled). */\n get(token: string, id: string): string | null;\n /**\n * Push a known-fresh title into the cache (after a rename or a create), so\n * surfaces that resolve through this service never show a stale name.\n */\n prime(token: string, id: string, title: string): void;\n /** Display fallback when no label and no fetched title exist. */\n fallback(token: string): string;\n /**\n * Resolve titles for `ids` of one token. Returns ONLY the resolved entries\n * (cache + fresh reads); missing rows (deleted, no access) stay absent.\n */\n fetch(token: string, ids: string[]): Promise<Map<string, string>>;\n}\n\nexport function createTitlesService(\n deps: CoreDeps,\n candidates: CandidatesServiceApi,\n): TitlesServiceApi {\n const { registry, errorSink } = deps;\n\n /** `${token}:${id}` → resolved title. Store-lifetime; titles change rarely. */\n const titleCache = new Map<string, string>();\n\n return {\n get(token, id) {\n return titleCache.get(entityTitleCacheKey(token, id)) ?? null;\n },\n\n prime(token, id, title) {\n const trimmed = title.trim();\n if (trimmed) titleCache.set(entityTitleCacheKey(token, id), trimmed);\n },\n\n fallback(token) {\n const info = registry.tryGetEntityInfo(token);\n // Never the raw token (\"Untitled html_page\"): the ONE humanizer names it.\n return `Untitled ${info?.label ?? humanizeIdentifier(token)}`;\n },\n\n async fetch(token, ids) {\n const out = new Map<string, string>();\n if (ids.length === 0) return out;\n\n const info = registry.tryGetEntityInfo(token);\n const missing: string[] = [];\n for (const id of ids) {\n const cached = titleCache.get(entityTitleCacheKey(token, id));\n if (cached !== undefined) out.set(id, cached);\n else missing.push(id);\n }\n if (missing.length === 0 || !info?.titleColumn) return out;\n\n for (let index = 0; index < missing.length; index += CHUNK) {\n const chunk = missing.slice(index, index + CHUNK);\n const { data, error } = await candidates.callReferenceSearchCandidates({\n p_token: token,\n p_ids: chunk,\n p_limit: chunk.length,\n });\n if (error) {\n errorSink({\n code: \"title_rpc_failed\",\n message: `[fetchEntityTitles] candidate RPC failed for \"${token}\": ${error.message}`,\n context: {\n token,\n chunkStart: index,\n chunkSize: chunk.length,\n detail: error,\n },\n });\n continue;\n }\n for (const row of data) {\n const title = row.title?.trim();\n if (!title) continue;\n titleCache.set(entityTitleCacheKey(token, row.id), title);\n out.set(row.id, title);\n }\n }\n return out;\n },\n };\n}\n","// core/entityRows.ts — @ai-matrx/associations/core\n//\n// THE GENERIC \"CREATE A NEW ONE\" GOES THROUGH THE GENERIC DOOR.\n//\n// 🚨 WHAT THIS CLOSES (DOORS-ONLY-4, 2026-09-21). Until this version both functions\n// below wrote the registered entity's backing table DIRECTLY:\n//\n// dataSource.schema(info.schema).from(info.table)\n// .insert({ [titleColumn]: title, created_by, organization_id })\n//\n// That is the ONE generic write path on the platform — one call site (the reference\n// picker's \"create a new one\") generic over all 650 registry tokens. The doors-only\n// ruling (`platform` and `iam` are not client-writable schemas; every write goes\n// through a named SECURITY DEFINER door) therefore broke it SILENTLY, one table at a\n// time, for forty-four already-closed tables before anybody looked. The failure\n// surfaces as a `42501` inside a picker toast, which no release notices.\n//\n// So the write is now `public.entity_row_create` / `public.entity_row_rename`: one\n// registry-driven door that resolves schema, table and title column from\n// `platform.entity_types` — the same registry `entity-types.generated.ts` is emitted\n// from — decides on the one ladder, and stamps `created_by` from `auth.uid()`. It is\n// the same fix for every token, present and future, instead of a door per table.\n//\n// AND IT REFUSES BY NAME two things the direct path merely FAILED at:\n// • a token whose `audit_class` is `machinery` — access machinery owns the inputs\n// the access resolver consumes, and a generic \"make me a row\" affordance must\n// never reach it;\n// • a token whose table has no `organization_id` column. `iam.organizations` is\n// exactly that, and the picker had been sending it one and getting\n// `42703 column does not exist` for as long as it has passed an org — a dead path\n// that read as a working feature. Creating an organization is `public.org_create`.\n//\n// TWO THINGS THE DOOR CANNOT DO, AND NEITHER IS SWALLOWED:\n// • `extraColumns` — the door writes exactly the name, the owner and the\n// organization. A caller that hands over extra columns gets a loud `{ok:false}`\n// naming them and naming the remedy (its feature's own create service), never a\n// row quietly missing the NOT NULL column it was meant to carry.\n// • a create with no organization — the door requires one. That is refused here,\n// before the round trip, with the same sentence a human can act on.\n//\n// On success both functions prime the shared title cache so every title-resolving\n// surface sees the new name, exactly as before.\n\nimport type { EntityTypeToken } from \"../entity-types.generated\";\nimport type { CoreDeps } from \"./deps\";\nimport type { TitlesServiceApi } from \"./titles\";\nimport { rpcDoor } from \"./doors\";\nimport { entityRowCreate, entityRowRename } from \"../db/public\";\n\nexport type EntityRowResult =\n | { ok: true; data: { id: string; title: string } }\n | { ok: false; error: string };\n\nexport interface CreateEntityRowArgs {\n /** The new row's human name — written to the registry `titleColumn`. */\n title: string;\n /**\n * The organization the new row belongs to. REQUIRED by\n * `public.entity_row_create`: every creatable token's table carries\n * `organization_id`, and the door refuses a row with nobody owning it.\n */\n orgId?: string | null;\n /**\n * 🚨 NO LONGER WRITABLE THROUGH THIS SERVICE (DOORS-ONLY-4). The door writes the\n * name, the owner and the organization and nothing else, so a non-empty value here\n * is REFUSED with the columns named rather than dropped on the floor. A token whose\n * table needs more than a name is created by its own feature's create service; this\n * generic path then only renames it.\n */\n extraColumns?: Record<string, unknown>;\n}\n\nexport interface EntityRowsServiceApi {\n createEntityRow(\n token: EntityTypeToken,\n args: CreateEntityRowArgs,\n ): Promise<EntityRowResult>;\n renameEntityRow(\n token: EntityTypeToken,\n id: string,\n title: string,\n ): Promise<{ ok: true } | { ok: false; error: string }>;\n}\n\nexport function createEntityRowsService(\n deps: CoreDeps,\n titles: TitlesServiceApi,\n): EntityRowsServiceApi {\n const { dataSource, registry, errorSink } = deps;\n\n /**\n * The registry still decides whether a token is nameable AT ALL, before the round\n * trip — a token with no `title_column` cannot be created from a name, and saying so\n * here costs nothing and reads better than the door's own refusal.\n */\n function requireTitleColumn(\n token: EntityTypeToken,\n op: string,\n ): { ok: true } | { ok: false; error: string } {\n const info = registry.getEntityInfo(token);\n if (!info.titleColumn) {\n const error =\n `Entity \"${token}\" has no title_column in platform.entity_types — ` +\n `add one in the registry before ${op}`;\n errorSink({\n code: \"missing_title_column\",\n message: `[entityRows] ${error}`,\n context: { token },\n });\n return { ok: false, error };\n }\n return { ok: true };\n }\n\n return {\n /**\n * Create one row of `token`'s backing table named `title`, through\n * `public.entity_row_create`. The door stamps `created_by` from `auth.uid()`,\n * checks the caller can act in the organization, and refuses machinery tokens and\n * tables with no organization by name. Returns the new row's id + title. The\n * caller wires associations afterwards — this layer never writes edges.\n */\n async createEntityRow(token, args) {\n const gate = requireTitleColumn(token, \"creating rows\");\n if (!gate.ok) return gate;\n const title = args.title.trim();\n if (!title) return { ok: false, error: \"Name is required\" };\n\n // NOTHING FAILS SILENTLY. The door has no arm for these, so they are refused\n // with their own names in the sentence rather than dropped.\n const extras = Object.keys(args.extraColumns ?? {});\n if (extras.length > 0) {\n const error =\n `A new ${registry.getEntityInfo(token).label} cannot be created ` +\n `here with ${extras.join(\", \")}: the shared create door writes the name, ` +\n `the owner and the organization and nothing else. Create it with this ` +\n `feature's own create service, then attach it.`;\n errorSink({\n code: \"entity_row_extra_columns_unsupported\",\n message: `[createEntityRow] extraColumns are not writable through entity_row_create for \"${token}\": ${extras.join(\", \")}`,\n context: { token, extras },\n });\n return { ok: false, error };\n }\n if (!args.orgId) {\n const error =\n `Name the organization this ${registry.getEntityInfo(token).label} belongs to.`;\n errorSink({\n code: \"entity_row_missing_organization\",\n message: `[createEntityRow] no organization supplied for \"${token}\"; entity_row_create requires one`,\n context: { token },\n });\n return { ok: false, error };\n }\n\n try {\n const { data, error } = await rpcDoor(dataSource, entityRowCreate, {\n p_token: token,\n p_title: title,\n p_organization_id: args.orgId,\n });\n if (error) {\n errorSink({\n code: \"entity_row_insert_failed\",\n message: `[createEntityRow] entity_row_create failed for \"${token}\": ${error.message}`,\n context: { token, detail: error },\n });\n return { ok: false, error: error.message };\n }\n const row = data as { id?: unknown; title?: unknown } | null;\n if (!row || typeof row.id !== \"string\" || !row.id) {\n const msg = \"The create door returned no record.\";\n errorSink({\n code: \"entity_row_insert_failed\",\n message: `[createEntityRow] entity_row_create returned no id for \"${token}\"`,\n context: { token, detail: data },\n });\n return { ok: false, error: msg };\n }\n const id = row.id;\n const named = typeof row.title === \"string\" && row.title ? row.title : title;\n titles.prime(token, id, named);\n return { ok: true, data: { id, title: named } };\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"Failed to create\";\n errorSink({\n code: \"entity_row_insert_failed\",\n message: `[createEntityRow] exception for \"${token}\": ${msg}`,\n context: { token, detail: e },\n });\n return { ok: false, error: msg };\n }\n },\n\n /**\n * Rename one row of `token`'s table through `public.entity_row_rename`. The door\n * decides on the one ladder — the row's author, `editor` on the row, or a platform\n * admin — and answers \"there is no such thing here\" rather than telling a caller\n * that somebody else's row exists.\n */\n async renameEntityRow(token, id, title) {\n const gate = requireTitleColumn(token, \"renaming rows\");\n if (!gate.ok) return gate;\n const trimmed = title.trim();\n if (!trimmed) return { ok: false, error: \"Name is required\" };\n\n try {\n const { error } = await rpcDoor(dataSource, entityRowRename, {\n p_token: token,\n p_id: id,\n p_title: trimmed,\n });\n if (error) {\n errorSink({\n code: \"entity_row_update_failed\",\n message: `[renameEntityRow] entity_row_rename failed for \"${token}\": ${error.message}`,\n context: { token, id, detail: error },\n });\n return { ok: false, error: error.message };\n }\n titles.prime(token, id, trimmed);\n return { ok: true };\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"Failed to rename\";\n errorSink({\n code: \"entity_row_update_failed\",\n message: `[renameEntityRow] exception for \"${token}\": ${msg}`,\n context: { token, id, detail: e },\n });\n return { ok: false, error: msg };\n }\n },\n };\n}\n","// core/helpers.ts — @ai-matrx/associations/core\n//\n// TYPED convenience wrappers over the canonical associations service for the\n// common COMPOSITE shapes — \"attach one thing to many\", \"attach many things\n// to one\", \"create N edges in one call\", \"replace a whole set\". Ported\n// behavior-verbatim from matrx-frontend\n// `features/scopes/service/associationHelpers.ts` (associations extraction\n// W2, 2026-08-29). They add NO new DB access: every wrapper composes the\n// same `assoc_*` primitives, so the single-chokepoint + runtime-guard\n// guarantees still hold.\n//\n// Why wrappers (not more RPCs): per-entity / per-shape SQL functions are an\n// N-explosion and each copy reintroduces bugs. Composition belongs in typed\n// helpers; the DB layer stays generic and dumb.\n//\n// Type safety: a `source` is any registered entity (`EntityTypeToken`); a\n// `target` is one of the deliberate container types\n// (`AssociationTargetType`). Bad tokens / non-UUID ids are caught by the\n// base service's guards and surface as `invalid_argument` before any RPC.\n\nimport type { AssociationTargetType } from \"../edges\";\nimport type { EntityTypeToken } from \"../entity-types.generated\";\nimport {\n isAssociationsRpcErr,\n type AssociationsRpcError,\n type AssociationsRpcResult,\n} from \"../results\";\nimport { err, ok } from \"./rpcResult\";\nimport { ASSOC_ADD_MANY_CHUNK, type AssociationsServiceApi } from \"./associationsService\";\n\n/** A typed reference to a single row — `{ type, id }`. */\nexport interface EntityRef {\n type: EntityTypeToken;\n id: string;\n}\n\n/** A container reference — the deliberate set an edge may point at. */\nexport interface ContainerRef {\n type: AssociationTargetType;\n id: string;\n}\n\n/** Per-edge attributes shared by the link helpers. */\nexport interface EdgeAttrs {\n orgId?: string;\n label?: string;\n metadata?: unknown;\n role?: string;\n position?: number;\n}\n\n/** One fully-specified edge for {@link AssociationHelpersApi.linkEdges}. */\nexport interface EdgeSpec extends EdgeAttrs {\n source: EntityRef;\n target: ContainerRef;\n}\n\n/** Combine many per-edge errors into one loud, described result error. */\nfunction combine(\n failures: AssociationsRpcError[],\n total: number,\n): AssociationsRpcError {\n const first = failures[0] ?? {\n code: \"internal\" as const,\n message: \"unknown failure\",\n };\n return {\n code: failures.every((f) => f.code === first.code) ? first.code : \"internal\",\n message: `${failures.length}/${total} association edge(s) failed: ${first.message}`,\n detail: failures,\n };\n}\n\nfunction errArgs(\n e: AssociationsRpcError,\n): [AssociationsRpcError[\"code\"], string, unknown] {\n return [e.code, e.message, e.detail];\n}\n\nexport interface AssociationHelpersApi {\n /**\n * Add an arbitrary batch of edges in one call (idempotent per edge).\n * Written through the batch door (`platform.assoc_add_many`) in sequential chunks of\n * {@link ASSOC_ADD_MANY_CHUNK}; each chunk is ONE transaction (all or nothing). The result\n * is `ok` with the ids in input order only when ALL succeed, otherwise `err` whose\n * `detail` lists a failure for every edge that was not written (chunks that DID succeed\n * remain applied — re-running is safe via ON CONFLICT).\n */\n linkEdges(edges: EdgeSpec[]): Promise<AssociationsRpcResult<{ ids: string[] }>>;\n /** Attach ONE source to MANY containers in a single shot. */\n linkOneToMany(args: {\n source: EntityRef;\n targets: ContainerRef[];\n attrs?: EdgeAttrs;\n }): Promise<AssociationsRpcResult<{ ids: string[] }>>;\n /** Attach MANY sources to ONE container in a single shot. */\n linkManyToOne(args: {\n sources: EntityRef[];\n target: ContainerRef;\n attrs?: EdgeAttrs;\n }): Promise<AssociationsRpcResult<{ ids: string[] }>>;\n /**\n * REPLACE the full set of a source's edges of one container type (adds\n * missing, removes extras) in one DB transaction — the set-semantics\n * one-shot. Thin, named pass-through to `assoc_set_targets`.\n */\n replaceTargets(args: {\n source: EntityRef;\n targetType: AssociationTargetType;\n targetIds: string[];\n orgId?: string;\n role?: string;\n }): Promise<AssociationsRpcResult<null>>;\n /**\n * Wire edges onto a JUST-CREATED entity. The caller inserts its own row\n * (entity tables are feature-owned), then passes the new id here to attach\n * it to any number of containers (orphan-on-partial-fail is harmless and\n * re-runnable). `created` is the new entity; it becomes the edges' SOURCE.\n */\n linkCreated(args: {\n created: EntityRef;\n targets: ContainerRef[];\n attrs?: EdgeAttrs;\n }): Promise<AssociationsRpcResult<{ ids: string[] }>>;\n /** Remove an arbitrary batch of edges (best-effort; no-op per missing edge). */\n unlinkEdges(\n edges: { source: EntityRef; target: ContainerRef; role?: string }[],\n ): Promise<AssociationsRpcResult<null>>;\n}\n\nexport function createAssociationHelpers(\n service: AssociationsServiceApi,\n): AssociationHelpersApi {\n async function linkEdges(\n edges: EdgeSpec[],\n ): Promise<AssociationsRpcResult<{ ids: string[] }>> {\n if (edges.length === 0) return ok({ ids: [] });\n const toArgs = (e: EdgeSpec) => ({\n sourceType: e.source.type,\n sourceId: e.source.id,\n targetType: e.target.type,\n targetId: e.target.id,\n ...(e.orgId !== undefined ? { orgId: e.orgId } : {}),\n ...(e.label !== undefined ? { label: e.label } : {}),\n ...(e.metadata !== undefined ? { metadata: e.metadata } : {}),\n ...(e.role !== undefined ? { role: e.role } : {}),\n ...(e.position !== undefined ? { position: e.position } : {}),\n });\n // The file -> conversation pair has its own stricter door and is not batchable; every\n // other edge goes through the batch door in chunks — ONE transaction per chunk, chunks\n // one after another (never an unbounded fan-out of single adds: 140 concurrent\n // assoc_add calls lost 69 edges on 2026-09-26).\n const ids: (string | undefined)[] = new Array(edges.length).fill(undefined);\n const failures: AssociationsRpcError[] = [];\n const batchable: number[] = [];\n for (let i = 0; i < edges.length; i++) {\n const e = edges[i]!;\n if (e.source.type === \"file\" && e.target.type === \"conversation\") {\n const r = await service.add(toArgs(e));\n if (isAssociationsRpcErr(r)) failures.push(r.error);\n else ids[i] = r.data.id;\n } else batchable.push(i);\n }\n for (let at = 0; at < batchable.length; at += ASSOC_ADD_MANY_CHUNK) {\n const slice = batchable.slice(at, at + ASSOC_ADD_MANY_CHUNK);\n const r = await service.addMany(slice.map((i) => toArgs(edges[i]!)));\n if (isAssociationsRpcErr(r)) {\n // The chunk is atomic: none of its edges were written. Every one of them failed.\n for (let k = 0; k < slice.length; k++) failures.push(r.error);\n } else slice.forEach((edgeIndex, k) => (ids[edgeIndex] = r.data.ids[k]));\n }\n if (failures.length > 0)\n return err(...errArgs(combine(failures, edges.length)));\n return ok({ ids: ids as string[] });\n }\n\n return {\n linkEdges,\n\n async linkOneToMany({ source, targets, attrs }) {\n return linkEdges(targets.map((target) => ({ source, target, ...attrs })));\n },\n\n async linkManyToOne({ sources, target, attrs }) {\n return linkEdges(sources.map((source) => ({ source, target, ...attrs })));\n },\n\n async replaceTargets(args) {\n return service.setTargets({\n sourceType: args.source.type,\n sourceId: args.source.id,\n targetType: args.targetType,\n targetIds: args.targetIds,\n ...(args.orgId !== undefined ? { orgId: args.orgId } : {}),\n ...(args.role !== undefined ? { role: args.role } : {}),\n });\n },\n\n async linkCreated(args) {\n return linkEdges(\n args.targets.map((target) => ({\n source: args.created,\n target,\n ...args.attrs,\n })),\n );\n },\n\n async unlinkEdges(edges) {\n if (edges.length === 0) return ok(null);\n const results = await Promise.all(\n edges.map((e) =>\n service.remove({\n sourceType: e.source.type,\n sourceId: e.source.id,\n targetType: e.target.type,\n targetId: e.target.id,\n ...(e.role !== undefined ? { role: e.role } : {}),\n }),\n ),\n );\n const failures: AssociationsRpcError[] = [];\n for (const r of results) if (isAssociationsRpcErr(r)) failures.push(r.error);\n if (failures.length > 0)\n return err(...errArgs(combine(failures, edges.length)));\n return ok(null);\n },\n };\n}\n","// core/commentsService.ts — @ai-matrx/associations/core\n//\n// THE SOLE CHOKEPOINT for the unified comment table — `platform.comments`\n// (W6, ruling C4: the comments canonical UI is built IN this package).\n// Behavior ported verbatim from matrx-frontend\n// `features/comments/service/commentsService.ts` (2026-08-29); the supabase\n// singleton / `requireUserId` / rpcResult seams inverted onto the package's\n// dataSource / identity / rpc deps, and the package's guard wall added in\n// front of every call (token writes-strict per C18, uuid wall).\n//\n// The client holds NO grant on `platform.comments`; every read/write goes\n// through the four PUBLIC SECURITY-DEFINER RPCs (`cmt_list` / `cmt_add` /\n// `cmt_edit` / `cmt_delete`) — part of the demanded schema (probed by\n// the demanded RPC contract), called only from THIS module. Methods always\n// return an `AssociationsRpcResult`, NEVER throw.\n//\n// Access lives in the RPCs, not here: `cmt_list` org-filters inside;\n// `cmt_add` resolves the org from THE COMMENTED RECORD ITSELF, for every\n// registered entity type (`orgId` overrides and must AGREE with the record, or\n// the RPC raises 22023); where neither the call nor the record names an\n// organization it raises 23502 rather than filing the comment in the author's\n// own workspace (DEFAULT-ORG-3, 2026-09-22);\n// `cmt_edit` is author-only; `cmt_delete` is author-or-org-member with\n// soft-delete. This package makes zero access decisions (link ≠ grant).\n\nimport type { CommentAnchor, PlatformComment } from \"../comments\";\nimport type { AssociationsRpcResult } from \"../results\";\nimport { firstError } from \"./guards\";\nimport type { CoreDeps } from \"./deps\";\nimport { rpcDoor } from \"./doors\";\nimport { cmtAdd, cmtDelete, cmtEdit, cmtList } from \"../db/public\";\n\n// Shape of one `cmt_list` row (snake_case, straight from PG).\ninterface CmtListRow {\n id: string;\n organization_id: string | null;\n entity_type: string;\n entity_id: string;\n parent_id: string | null;\n body: string;\n created_at: string;\n updated_at: string;\n created_by: string | null;\n author_email: string | null;\n author_display_name: string | null;\n author_avatar_url: string | null;\n anchor?: CommentAnchor | null;\n author_agent_id?: string | null;\n author_agent_name?: string | null;\n created_by_tier?: string | null;\n}\n\nfunction toComment(row: CmtListRow): PlatformComment {\n return {\n id: row.id,\n orgId: row.organization_id ?? null,\n entityType: row.entity_type,\n entityId: row.entity_id,\n parentId: row.parent_id ?? null,\n body: row.body,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n createdBy: row.created_by ?? null,\n author: {\n email: row.author_email ?? null,\n displayName: row.author_display_name ?? null,\n avatarUrl: row.author_avatar_url ?? null,\n },\n authorAgent: row.author_agent_id\n ? { id: row.author_agent_id, name: row.author_agent_name ?? null }\n : null,\n ...(row.created_by_tier === \"system\" && !row.author_agent_id ? { authorSystem: true } : {}),\n anchor: row.anchor && typeof row.anchor === \"object\" ? row.anchor : null,\n };\n}\n\nexport interface AddCommentArgs {\n /** Registered entity-type token the comment hangs on (writes-strict, C18). */\n entityType: string;\n entityId: string;\n body: string;\n /** Reply target — an existing comment's id. Top-level when omitted. */\n parentId?: string | null;\n /** Org override; the RPC resolves task-org/personal-org when omitted. */\n orgId?: string | null;\n /** Where on the record the comment points (a `part_anchor`, a `text_anchor`); whole record when omitted. */\n anchor?: CommentAnchor | null;\n}\n\nexport interface CommentsServiceApi {\n listForEntity(\n entityType: string,\n entityId: string,\n ): Promise<AssociationsRpcResult<{ comments: PlatformComment[] }>>;\n add(args: AddCommentArgs): Promise<AssociationsRpcResult<{ id: string }>>;\n edit(id: string, body: string): Promise<AssociationsRpcResult<null>>;\n remove(id: string): Promise<AssociationsRpcResult<null>>;\n}\n\nexport function createCommentsService(deps: CoreDeps): CommentsServiceApi {\n const { dataSource, identity, guards } = deps;\n const { ok, err, mapPgError, mapPgErrorPair } = deps.rpc;\n\n return {\n /**\n * All comments on `${entityType}:${entityId}`, org-filtered by RLS\n * inside the RPC, ordered oldest→newest. Build the thread from each\n * row's `parentId` (top-level comments have `parentId === null`).\n */\n async listForEntity(entityType, entityId) {\n try {\n identity.requireUserId();\n const token = guards.normalizeEntityToken(entityType);\n const invalid = firstError(\n guards.checkToken(\"entityType\", token),\n guards.checkUuid(\"entityId\", entityId),\n );\n if (invalid) return { ok: false, error: invalid };\n const { data, error } = await rpcDoor(dataSource, cmtList, {\n p_entity_type: token,\n p_entity_id: entityId,\n });\n if (error) return err(...mapPgErrorPair(error));\n const rows = (Array.isArray(data) ? data : []) as CmtListRow[];\n return ok({ comments: rows.map(toComment) });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /**\n * Post `body` on `${entityType}:${entityId}`; pass `parentId` to reply.\n * Returns the new comment id.\n */\n async add(args) {\n try {\n identity.requireUserId();\n const token = guards.normalizeEntityToken(args.entityType);\n const invalid = firstError(\n guards.checkToken(\"entityType\", token),\n guards.checkUuid(\"entityId\", args.entityId),\n args.parentId != null\n ? guards.checkUuid(\"parentId\", args.parentId)\n : null,\n );\n if (invalid) return { ok: false, error: invalid };\n if (!args.body || args.body.trim().length === 0) {\n return err(\"invalid_argument\", \"comment body must be non-empty\");\n }\n const { data, error } = await rpcDoor(dataSource, cmtAdd, {\n p_entity_type: token,\n p_entity_id: args.entityId,\n p_body: args.body,\n p_parent_id: args.parentId ?? undefined,\n p_org_id: args.orgId ?? undefined,\n ...(args.anchor ? { p_anchor: args.anchor } : {}),\n });\n if (error) return err(...mapPgErrorPair(error));\n if (!data || typeof data !== \"string\") {\n return err(\"internal\", \"cmt_add returned no comment id\");\n }\n return ok({ id: data });\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /** Replace a comment's body. Author-only; the RPC rejects everyone else. */\n async edit(id, body) {\n try {\n identity.requireUserId();\n const invalid = guards.checkUuid(\"commentId\", id);\n if (invalid) return { ok: false, error: invalid };\n if (!body || body.trim().length === 0) {\n return err(\"invalid_argument\", \"comment body must be non-empty\");\n }\n const { error } = await rpcDoor(dataSource, cmtEdit, {\n p_id: id,\n p_body: body,\n });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n\n /** Soft-delete a comment. Author or org member; enforced server-side. */\n async remove(id) {\n try {\n identity.requireUserId();\n const invalid = guards.checkUuid(\"commentId\", id);\n if (invalid) return { ok: false, error: invalid };\n const { error } = await rpcDoor(dataSource, cmtDelete, { p_id: id });\n if (error) return err(...mapPgErrorPair(error));\n return ok(null);\n } catch (e) {\n return { ok: false, error: mapPgError(e) };\n }\n },\n };\n}\n","// core/store.ts — @ai-matrx/associations/core\n//\n// THE package-owned, store-agnostic cache (design Decision 3) — the one\n// runtime object a host constructs (`createAssociationsStore(cfg)`),\n// replacing matrx-frontend's ~530 lines of Redux fragments\n// (`scopesTree.associationsByKey` + `categoriesByDimension` + the\n// association/category thunks + selectors) with a subscribable store the\n// /react hooks (W3) ride via `useSyncExternalStore`. Behavior ported\n// verbatim from `features/scopes/redux/thunks/{associations,categories}.ts`\n// + the matching `scopesSlice` reducers + selectors (2026-08-29):\n//\n// • lazy `load` with per-key IN-FLIGHT DEDUP (the thunks' Map) and\n// `status === \"ready\"` short-circuit unless `force`;\n// • pending keeps previous edges AND the visible error (consumers use\n// status to disable/spin the same retry control);\n// • add/remove reload BOTH endpoints on success (a write touches TWO\n// endpoints — the source and the target each see the edge);\n// • setTargets reloads the SOURCE only (the only endpoint with a\n// deterministic post-state);\n// • createCategory does the optimistic ECHO-INSERT then force-reloads to\n// pick up server-derived fields authoritatively;\n// • `getEdges`/`getCategories` return a STABLE idle default (never a fresh\n// object per read — the useSyncExternalStore contract).\n//\n// THE NEVER-TOUCHES-CONTEXT INVARIANT, now structural: the thunks' law\n// \"NEVER dispatch appContextSlice actions\" (a durable association is NOT the\n// user's active working context) is carried over as architecture — this\n// package has no import path to any host store, and a write notifies ONLY\n// the association subscribers of the endpoints it touched (proven by test).\n//\n// Invalidation is owned here (subscribe/notify + `invalidate`). It does NOT\n// depend on `@ai-matrx/kit` — but the shape is deliberately bridgeable: a\n// host binding may register `store.invalidate` under kit `/invalidation`\n// names so ubiquitous modules can invalidate association caches with zero\n// import edge into this package's chunk.\n//\n// NO module-level mutable state anywhere in /core: every cache lives on the\n// store instance the host constructs, so the dual-bundle split-registry\n// failure the packaging standard's globalThis-slot rule exists for cannot\n// occur (there is no module state to split).\n\nimport type {\n AssociationsEntry,\n AssociationTargetType,\n CategoriesEntry,\n CategoryDimension,\n PlatformCategory,\n} from \"../edges\";\nimport type { CommentAnchor, CommentsEntry } from \"../comments\";\nimport { isAssociationsRpcErr } from \"../results\";\nimport type {\n AssociationsConfig,\n AssociationsDataSource,\n ErrorSink,\n} from \"../ports\";\nimport { asAssociationsDataSource } from \"../ports\";\nimport { createDefaultErrorSink } from \"./defaultErrorSink\";\nimport type { CoreDeps } from \"./deps\";\nimport { createAssociationGuards } from \"./guards\";\nimport { createRpcResultHelpers } from \"./rpcResult\";\nimport { createEntityRegistry, type EntityRegistry } from \"./registry\";\nimport {\n createAssociationsService,\n type AssociationsServiceApi,\n} from \"./associationsService\";\nimport {\n createCategoriesService,\n type CategoriesServiceApi,\n} from \"./categoriesService\";\nimport {\n createFavoritesService,\n type FavoritesServiceApi,\n} from \"./favoritesService\";\nimport { createCandidatesService, type CandidatesServiceApi } from \"./candidates\";\nimport { createTitlesService, type TitlesServiceApi } from \"./titles\";\nimport {\n createEntityRowsService,\n type EntityRowsServiceApi,\n} from \"./entityRows\";\nimport {\n createAssociationHelpers,\n type AssociationHelpersApi,\n} from \"./helpers\";\nimport {\n createCommentsService,\n type CommentsServiceApi,\n} from \"./commentsService\";\n\n/** Cache key for one association endpoint. */\nexport function associationsKey(type: string, id: string): string {\n return `${type}:${id}`;\n}\n\nexport interface AssociationWriteResult {\n ok: boolean;\n /** Set on a successful single-edge `add`. */\n id?: string;\n error?: string;\n}\n\nexport interface CategoryMutationResult {\n ok: boolean;\n /** Set on a successful mutation. */\n id?: string;\n error?: string;\n}\n\nconst IDLE_ASSOCIATIONS: AssociationsEntry = Object.freeze({\n status: \"idle\",\n edges: Object.freeze([]) as unknown as AssociationsEntry[\"edges\"],\n fetchedAt: null,\n error: null,\n});\n\nconst IDLE_CATEGORIES: CategoriesEntry = Object.freeze({\n status: \"idle\",\n categories: Object.freeze([]) as unknown as CategoriesEntry[\"categories\"],\n fetchedAt: null,\n error: null,\n});\n\nconst IDLE_COMMENTS: CommentsEntry = Object.freeze({\n status: \"idle\",\n comments: Object.freeze([]) as unknown as CommentsEntry[\"comments\"],\n fetchedAt: null,\n error: null,\n});\n\nexport interface CommentMutationResult {\n ok: boolean;\n /** Set on a successful `addComment`. */\n id?: string;\n error?: string;\n}\n\nexport interface AssociationsStore {\n // ── the cache (association endpoints) ────────────────────────────────\n /** Stable, sync read of one endpoint's entry (idle default when uncached). */\n getEdges(type: string, id: string): AssociationsEntry;\n /**\n * Lazy load of every edge touching `${type}:${id}` (both directions).\n * Deduped per key; `status === \"ready\"` short-circuits unless `force`.\n */\n load(type: string, id: string, opts?: { force?: boolean }): Promise<void>;\n /** External-store contract: notified whenever the key's entry changes. */\n subscribe(key: string, cb: () => void): () => void;\n /** Attach source → target; on success reloads BOTH endpoints. */\n add(args: {\n sourceType: string;\n sourceId: string;\n targetType: AssociationTargetType;\n targetId: string;\n orgId?: string;\n label?: string;\n role?: string;\n metadata?: unknown;\n replaceMetadata?: boolean;\n }): Promise<AssociationWriteResult>;\n /** Detach source → target; on success reloads BOTH endpoints. */\n remove(args: {\n sourceType: string;\n sourceId: string;\n targetType: string;\n targetId: string;\n role?: string;\n }): Promise<AssociationWriteResult>;\n /** Replace the source's `targetType` edge set; reloads the SOURCE. */\n setTargets(args: {\n sourceType: string;\n sourceId: string;\n targetType: AssociationTargetType;\n targetIds: string[];\n orgId?: string;\n role?: string;\n }): Promise<AssociationWriteResult>;\n /** Reset one endpoint to idle and notify its subscribers. */\n invalidate(type: string, id: string): void;\n /** Reset every association endpoint, category facet, and comment thread. */\n invalidateAll(): void;\n\n // ── the cache (category facets) ──────────────────────────────────────\n getCategories(dimension: CategoryDimension): CategoriesEntry;\n loadCategories(\n dimension: CategoryDimension,\n opts?: { force?: boolean },\n ): Promise<void>;\n subscribeCategories(dimension: CategoryDimension, cb: () => void): () => void;\n /** Create + echo-insert + authoritative force reload. Returns the new id. */\n createCategory(args: {\n dimension: CategoryDimension;\n name: string;\n orgId: string;\n parentId?: string | null;\n color?: string | null;\n icon?: string | null;\n slug?: string | null;\n }): Promise<CategoryMutationResult>;\n updateCategory(args: {\n dimension: CategoryDimension;\n id: string;\n name: string;\n slug: string | null;\n color: string | null;\n icon: string | null;\n position: number | null;\n }): Promise<CategoryMutationResult>;\n reparentCategory(args: {\n dimension: CategoryDimension;\n id: string;\n parentId: string | null;\n }): Promise<CategoryMutationResult>;\n deleteCategory(args: {\n dimension: CategoryDimension;\n id: string;\n }): Promise<CategoryMutationResult>;\n\n // ── the cache (comment threads, W6) ──────────────────────────────────\n /** Stable, sync read of one entity's comment thread (idle when uncached). */\n getComments(type: string, id: string): CommentsEntry;\n /**\n * Lazy load of every comment on `${type}:${id}` (oldest→newest; thread by\n * `parentId`). Deduped per key; `status === \"ready\"` short-circuits unless\n * `force`.\n */\n loadComments(\n type: string,\n id: string,\n opts?: { force?: boolean },\n ): Promise<void>;\n /** External-store contract for one entity's comment thread. */\n subscribeComments(key: string, cb: () => void): () => void;\n /** Post a comment (or a reply); on success force-reloads the thread. */\n addComment(args: {\n entityType: string;\n entityId: string;\n body: string;\n parentId?: string | null;\n orgId?: string | null;\n anchor?: CommentAnchor | null;\n }): Promise<CommentMutationResult>;\n /** Edit a comment body (author-only in the RPC); reloads the thread. */\n editComment(args: {\n entityType: string;\n entityId: string;\n id: string;\n body: string;\n }): Promise<CommentMutationResult>;\n /** Soft-delete a comment (author/org member in the RPC); reloads the thread. */\n deleteComment(args: {\n entityType: string;\n entityId: string;\n id: string;\n }): Promise<CommentMutationResult>;\n /** Reset one entity's comment thread to idle and notify its subscribers. */\n invalidateComments(type: string, id: string): void;\n\n // ── the seams under the cache ────────────────────────────────────────\n /** Batched title resolution + the session cache + prime. */\n titles: TitlesServiceApi;\n /** Per-user favorite/pinned/hidden state (`ues_*`). */\n favorites: FavoritesServiceApi;\n /** Candidate reads for the pickers. */\n candidates: CandidatesServiceApi;\n /** Generic registry-convention row create/rename. */\n entityRows: EntityRowsServiceApi;\n /** Composite link helpers over the chokepoint. */\n helpers: AssociationHelpersApi;\n /** The registry merge engine (generated metadata + host overlay). */\n registry: EntityRegistry;\n /**\n * The raw chokepoint services — every RPC family, results-enveloped.\n * `associations` writes here do NOT touch the cache; use the store-level\n * `add`/`remove`/`setTargets` when a cached surface must stay fresh.\n */\n services: {\n associations: AssociationsServiceApi;\n categories: CategoriesServiceApi;\n comments: CommentsServiceApi;\n };\n /** Merge more host overlay entries in (icons/routes/candidate loaders). */\n registerEntityOverlay: EntityRegistry[\"registerEntityOverlay\"];\n /**\n * The bound scream seam (W3, additive): /react surfaces route their loud\n * recoveries here (the originals' console.error sites) without a second\n * sink binding. Same function the host passed at construction.\n */\n errorSink: ErrorSink;\n /**\n * The bound data seam (0.6.0, additive): the provider's demanded-schema\n * boot probe reads it so hosts stop re-exporting their dataSource just to\n * run a check the package owns.\n */\n dataSource: AssociationsDataSource;\n /**\n * The bound identity port (W3, additive): /react hooks that FILTER by the\n * current user (candidate owner scoping) read it leniently; write paths\n * keep going through the services, where `requireUserId` failures stay\n * loud. Same object the host passed at construction.\n */\n identity: AssociationsConfig[\"identity\"];\n}\n\n/**\n * Build the one store a host binds. The REQUIRED ports (dataSource /\n * identity — true app identity, C23) throw at construction when absent.\n * Every other port has a SHIPPED DEFAULT (errorSink since 0.6.0) or a\n * documented degradation; nothing is ever silently missing.\n */\nexport function createAssociationsStore(\n config: AssociationsConfig,\n): AssociationsStore {\n // An { rpc }-only client is adapted (0.14.5), so the bridges every host passed before 0.14.0\n // keep working; only a missing client, or one with neither schema() nor rpc(), throws.\n const dataSource = asAssociationsDataSource(config?.dataSource);\n if (!config || !dataSource) {\n throw new Error(\n \"@ai-matrx/associations: the REQUIRED dataSource port is missing \" +\n \"(pass the supabase-js client itself, or an { rpc } client for the \" +\n \"public schema's functions). The package IS data operations; there \" +\n \"is no degraded mode without one.\",\n );\n }\n if (typeof config.identity?.requireUserId !== \"function\") {\n throw new Error(\n \"@ai-matrx/associations: the REQUIRED identity port is missing \" +\n \"(need requireUserId(): string that THROWS when unauthenticated). \" +\n \"Identity never comes from a store import.\",\n );\n }\n // `errorSink` stopped being required in 0.6.0 (C23): the package ships the\n // obvious sink instead of refusing to construct. The default is LOUD about\n // being the default — see createDefaultErrorSink.\n const errorSink: ErrorSink =\n typeof config.errorSink === \"function\"\n ? config.errorSink\n : createDefaultErrorSink();\n const registry = createEntityRegistry(errorSink, config.entityOverlay);\n const deps: CoreDeps = {\n dataSource,\n identity: config.identity,\n errorSink,\n guards: createAssociationGuards(errorSink),\n rpc: createRpcResultHelpers(\n errorSink,\n config.identity.sessionAttached\n ? () => config.identity.sessionAttached!()\n : undefined,\n ),\n registry,\n };\n\n const associations = createAssociationsService(deps);\n const categories = createCategoriesService(deps);\n const favorites = createFavoritesService(deps);\n const candidates = createCandidatesService(deps);\n const titles = createTitlesService(deps, candidates);\n const entityRows = createEntityRowsService(deps, titles);\n const helpers = createAssociationHelpers(associations);\n const comments = createCommentsService(deps);\n\n // ── instance state (never module state) ────────────────────────────────\n const assocByKey = new Map<string, AssociationsEntry>();\n const assocSubs = new Map<string, Set<() => void>>();\n const assocInFlight = new Map<string, Promise<void>>();\n const catByDim = new Map<string, CategoriesEntry>();\n const catSubs = new Map<string, Set<() => void>>();\n const catInFlight = new Map<string, Promise<void>>();\n const cmtByKey = new Map<string, CommentsEntry>();\n const cmtSubs = new Map<string, Set<() => void>>();\n const cmtInFlight = new Map<string, Promise<void>>();\n\n function notifyAssoc(key: string): void {\n const subs = assocSubs.get(key);\n if (subs) for (const cb of [...subs]) cb();\n }\n function notifyCat(dimension: string): void {\n const subs = catSubs.get(dimension);\n if (subs) for (const cb of [...subs]) cb();\n }\n function setAssoc(key: string, entry: AssociationsEntry): void {\n assocByKey.set(key, entry);\n notifyAssoc(key);\n }\n function setCat(dimension: string, entry: CategoriesEntry): void {\n catByDim.set(dimension, entry);\n notifyCat(dimension);\n }\n function notifyCmt(key: string): void {\n const subs = cmtSubs.get(key);\n if (subs) for (const cb of [...subs]) cb();\n }\n function setCmt(key: string, entry: CommentsEntry): void {\n cmtByKey.set(key, entry);\n notifyCmt(key);\n }\n\n // ── association cache ops (verbatim thunk/reducer behavior) ────────────\n async function load(\n type: string,\n id: string,\n opts: { force?: boolean } = {},\n ): Promise<void> {\n const force = opts.force ?? false;\n if (!type || !id) return;\n const key = associationsKey(type, id);\n const entry = assocByKey.get(key);\n\n if (!force && entry?.status === \"ready\") return;\n const pending = assocInFlight.get(key);\n if (!force && entry?.status === \"loading\" && pending) return pending;\n\n const prev = assocByKey.get(key);\n setAssoc(key, {\n status: \"loading\",\n edges: prev?.edges ?? [],\n fetchedAt: prev?.fetchedAt ?? null,\n // Retain the visible failure while a retry is pending — consumers use\n // status to disable/spin the same retry control.\n error: prev?.error ?? null,\n });\n\n const promise = (async () => {\n try {\n const res = await associations.listForEntity(type, id);\n if (isAssociationsRpcErr(res)) {\n const before = assocByKey.get(key);\n setAssoc(key, {\n status: \"error\",\n edges: before?.edges ?? [],\n fetchedAt: before?.fetchedAt ?? null,\n error: res.error.message,\n });\n } else {\n setAssoc(key, {\n status: \"ready\",\n edges: res.data.edges,\n fetchedAt: Date.now(),\n error: null,\n });\n }\n } finally {\n assocInFlight.delete(key);\n }\n })();\n\n assocInFlight.set(key, promise);\n return promise;\n }\n\n /** Reload both endpoints of an edge so each side's cache is fresh. */\n async function reloadBoth(\n sourceType: string,\n sourceId: string,\n targetType: string,\n targetId: string,\n ): Promise<void> {\n await Promise.all([\n load(sourceType, sourceId, { force: true }),\n load(targetType, targetId, { force: true }),\n ]);\n }\n\n // ── category cache ops (verbatim thunk/reducer behavior) ───────────────\n async function loadCategories(\n dimension: CategoryDimension,\n opts: { force?: boolean } = {},\n ): Promise<void> {\n const force = opts.force ?? false;\n if (!dimension) return;\n const entry = catByDim.get(dimension);\n\n if (!force && entry?.status === \"ready\") return;\n const pending = catInFlight.get(dimension);\n if (!force && entry?.status === \"loading\" && pending) return pending;\n\n const prev = catByDim.get(dimension);\n setCat(dimension, {\n status: \"loading\",\n categories: prev?.categories ?? [],\n fetchedAt: prev?.fetchedAt ?? null,\n error: null,\n });\n\n const promise = (async () => {\n try {\n const res = await categories.list(dimension);\n if (isAssociationsRpcErr(res)) {\n const before = catByDim.get(dimension);\n setCat(dimension, {\n status: \"error\",\n categories: before?.categories ?? [],\n fetchedAt: before?.fetchedAt ?? null,\n error: res.error.message,\n });\n } else {\n setCat(dimension, {\n status: \"ready\",\n categories: res.data.categories,\n fetchedAt: Date.now(),\n error: null,\n });\n }\n } finally {\n catInFlight.delete(dimension);\n }\n })();\n\n catInFlight.set(dimension, promise);\n return promise;\n }\n\n // ── comment-thread cache ops (W6; same lifecycle as associations) ──────\n async function loadComments(\n type: string,\n id: string,\n opts: { force?: boolean } = {},\n ): Promise<void> {\n const force = opts.force ?? false;\n if (!type || !id) return;\n const key = associationsKey(type, id);\n const entry = cmtByKey.get(key);\n\n if (!force && entry?.status === \"ready\") return;\n const pending = cmtInFlight.get(key);\n if (!force && entry?.status === \"loading\" && pending) return pending;\n\n const prev = cmtByKey.get(key);\n setCmt(key, {\n status: \"loading\",\n comments: prev?.comments ?? [],\n fetchedAt: prev?.fetchedAt ?? null,\n // Retain the visible failure while a retry is pending (same contract\n // as the association cache).\n error: prev?.error ?? null,\n });\n\n const promise = (async () => {\n try {\n const res = await comments.listForEntity(type, id);\n if (isAssociationsRpcErr(res)) {\n const before = cmtByKey.get(key);\n setCmt(key, {\n status: \"error\",\n comments: before?.comments ?? [],\n fetchedAt: before?.fetchedAt ?? null,\n error: res.error.message,\n });\n } else {\n setCmt(key, {\n status: \"ready\",\n comments: res.data.comments,\n fetchedAt: Date.now(),\n error: null,\n });\n }\n } finally {\n cmtInFlight.delete(key);\n }\n })();\n\n cmtInFlight.set(key, promise);\n return promise;\n }\n\n return {\n // ── associations ─────────────────────────────────────────────────────\n getEdges(type, id) {\n if (!type || !id) return IDLE_ASSOCIATIONS;\n return assocByKey.get(associationsKey(type, id)) ?? IDLE_ASSOCIATIONS;\n },\n\n load,\n\n subscribe(key, cb) {\n let subs = assocSubs.get(key);\n if (!subs) {\n subs = new Set();\n assocSubs.set(key, subs);\n }\n subs.add(cb);\n return () => {\n subs.delete(cb);\n if (subs.size === 0) assocSubs.delete(key);\n };\n },\n\n async add(args) {\n const res = await associations.add(args);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await reloadBoth(\n args.sourceType,\n args.sourceId,\n args.targetType,\n args.targetId,\n );\n return { ok: true, id: res.data.id };\n },\n\n async remove(args) {\n const res = await associations.remove(args);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await reloadBoth(\n args.sourceType,\n args.sourceId,\n args.targetType,\n args.targetId,\n );\n return { ok: true };\n },\n\n /**\n * Reloads the SOURCE endpoint only — the one endpoint with a\n * deterministic post-state; each affected target reload would need the\n * full before/after diff, so callers displaying a specific target\n * refresh it via `load(..., { force: true })`.\n */\n async setTargets(args) {\n const res = await associations.setTargets(args);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await load(args.sourceType, args.sourceId, { force: true });\n return { ok: true };\n },\n\n invalidate(type, id) {\n const key = associationsKey(type, id);\n if (assocByKey.delete(key)) notifyAssoc(key);\n },\n\n invalidateAll() {\n const assocKeys = [...assocByKey.keys()];\n assocByKey.clear();\n for (const key of assocKeys) notifyAssoc(key);\n const dims = [...catByDim.keys()];\n catByDim.clear();\n for (const dim of dims) notifyCat(dim);\n const cmtKeys = [...cmtByKey.keys()];\n cmtByKey.clear();\n for (const key of cmtKeys) notifyCmt(key);\n },\n\n // ── categories ───────────────────────────────────────────────────────\n getCategories(dimension) {\n if (!dimension) return IDLE_CATEGORIES;\n return catByDim.get(dimension) ?? IDLE_CATEGORIES;\n },\n\n loadCategories,\n\n subscribeCategories(dimension, cb) {\n let subs = catSubs.get(dimension);\n if (!subs) {\n subs = new Set();\n catSubs.set(dimension, subs);\n }\n subs.add(cb);\n return () => {\n subs.delete(cb);\n if (subs.size === 0) catSubs.delete(dimension);\n };\n },\n\n async createCategory(args) {\n const res = await categories.create(args);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n // Optimistic echo so the new id shows immediately, then force-reload\n // to pick up server-derived fields (slug, position) authoritatively.\n const optimistic: PlatformCategory = {\n id: res.data.id,\n orgId: args.orgId,\n dimension: args.dimension,\n name: args.name,\n slug: args.slug ?? null,\n parentId: args.parentId ?? null,\n isSystem: false,\n color: args.color ?? null,\n icon: args.icon ?? null,\n metadata: null,\n position: null,\n };\n const prev = catByDim.get(args.dimension);\n const existing = prev?.categories ?? [];\n if (!existing.some((c) => c.id === optimistic.id)) {\n setCat(args.dimension, {\n status: \"ready\",\n categories: [...existing, optimistic],\n fetchedAt: prev?.fetchedAt ?? Date.now(),\n error: null,\n });\n }\n await loadCategories(args.dimension, { force: true });\n return { ok: true, id: res.data.id };\n },\n\n async updateCategory(args) {\n const res = await categories.update(args);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await loadCategories(args.dimension, { force: true });\n return { ok: true, id: res.data.id };\n },\n\n async reparentCategory(args) {\n const res = await categories.reparent(args);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await loadCategories(args.dimension, { force: true });\n return { ok: true, id: res.data.id };\n },\n\n async deleteCategory(args) {\n const res = await categories.delete(args.id);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await loadCategories(args.dimension, { force: true });\n return { ok: true, id: res.data.id };\n },\n\n // ── comments (W6) ────────────────────────────────────────────────────\n getComments(type, id) {\n if (!type || !id) return IDLE_COMMENTS;\n return cmtByKey.get(associationsKey(type, id)) ?? IDLE_COMMENTS;\n },\n\n loadComments,\n\n subscribeComments(key, cb) {\n let subs = cmtSubs.get(key);\n if (!subs) {\n subs = new Set();\n cmtSubs.set(key, subs);\n }\n subs.add(cb);\n return () => {\n subs.delete(cb);\n if (subs.size === 0) cmtSubs.delete(key);\n };\n },\n\n async addComment(args) {\n const res = await comments.add(args);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await loadComments(args.entityType, args.entityId, { force: true });\n return { ok: true, id: res.data.id };\n },\n\n async editComment(args) {\n const res = await comments.edit(args.id, args.body);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await loadComments(args.entityType, args.entityId, { force: true });\n return { ok: true, id: args.id };\n },\n\n async deleteComment(args) {\n const res = await comments.remove(args.id);\n if (isAssociationsRpcErr(res)) {\n return { ok: false, error: res.error.message };\n }\n await loadComments(args.entityType, args.entityId, { force: true });\n return { ok: true, id: args.id };\n },\n\n invalidateComments(type, id) {\n const key = associationsKey(type, id);\n if (cmtByKey.delete(key)) notifyCmt(key);\n },\n\n // ── seams ────────────────────────────────────────────────────────────\n titles,\n favorites,\n candidates,\n entityRows,\n helpers,\n registry,\n services: { associations, categories, comments },\n registerEntityOverlay: registry.registerEntityOverlay,\n errorSink,\n dataSource,\n identity: config.identity,\n };\n}\n","// core/edgeClassifier.ts — @ai-matrx/associations/core\n//\n// THE canonical classifier for `platform.associations` edges: is an edge\n// CONTENT (\"this container holds that resource\") or STRUCTURE (membership,\n// context tagging, org attachment)? Ported behavior-verbatim from\n// matrx-frontend `features/scopes/service/associationEdges.ts` (associations\n// extraction W2, 2026-08-29); the host `Json` type becomes `unknown` (the\n// packaging standard's JSON-boundary rule).\n//\n// Every surface that lists \"what's attached to X\" must use this ONE\n// predicate. The old pattern — each consumer keeping its own whitelist of\n// allowed source tokens — silently dropped every newly registered entity\n// type. An EXCLUSION list inverts that: any registered token is content\n// unless it is structural, so a new token participates everywhere with zero\n// code changes.\n//\n// Structural edges are:\n// • container-membership edges (`thread → war_room`, marked\n// `metadata.membership: true`) — the thread is IN the room, not held BY it;\n// • scope / scope_type edges — context tagging, owned by the scopes system;\n// • organization edges — org attachment, owned by iam/memberships;\n// • container tokens themselves (`thread`, `war_room`) appearing as a\n// source — a container is never another container's content.\n\n/** Source tokens that are structure, never container content. */\nexport const NON_CONTENT_SOURCE_TYPES: ReadonlySet<string> = new Set([\n \"thread\",\n \"war_room\",\n \"scope\",\n \"scope_type\",\n \"organization\",\n]);\n\n/** True when edge metadata marks a container-membership edge. */\nexport function isMembershipMetadata(metadata: unknown): boolean {\n return (\n typeof metadata === \"object\" &&\n metadata !== null &&\n !Array.isArray(metadata) &&\n (metadata as Record<string, unknown>).membership === true\n );\n}\n\n/**\n * True when an edge into a container represents CONTENT the container holds.\n * `sourceType` is the edge's raw `source_type` token; `metadata` the edge's\n * jsonb (pass it when available so membership edges are excluded even if a\n * structural token is ever missed).\n */\nexport function isContentSourceEdge(\n sourceType: string,\n metadata?: unknown,\n): boolean {\n if (NON_CONTENT_SOURCE_TYPES.has(sourceType)) return false;\n if (isMembershipMetadata(metadata)) return false;\n return true;\n}\n","// core/categoryHierarchy.ts — @ai-matrx/associations/core\n//\n// The canonical two-level display order for one category facet — ported\n// VERBATIM from matrx-frontend `features/scopes/utils/categoryHierarchy.ts`\n// (W4 completion, 2026-08-29). Pure data → data, React-free, so it lives in\n// /core beside the category service; the `CategorySelect` /\n// `CategoryTagPicker` faces are its measured consumers.\n\nimport type { PlatformCategory } from \"../edges\";\n\nexport interface CategoryHierarchyItem {\n category: PlatformCategory;\n depth: 0 | 1;\n parent: PlatformCategory | null;\n displayName: string;\n}\n\nexport interface CategoryHierarchy {\n items: CategoryHierarchyItem[];\n roots: PlatformCategory[];\n hasHierarchy: boolean;\n}\n\n/**\n * Turns the RPC's ordered flat rows into the canonical two-level display order.\n * Flat facets retain their exact input order. Invalid/orphaned rows remain\n * visible at the root; the database guard prevents new ones from being made.\n */\nexport function buildCategoryHierarchy(\n categories: PlatformCategory[],\n): CategoryHierarchy {\n const byId = new Map(categories.map((category) => [category.id, category]));\n const hasHierarchy = categories.some(\n (category) => category.parentId !== null && byId.has(category.parentId),\n );\n\n if (!hasHierarchy) {\n return {\n items: categories.map((category) => ({\n category,\n depth: 0,\n parent: null,\n displayName: category.name,\n })),\n roots: categories.filter((category) => category.parentId === null),\n hasHierarchy: false,\n };\n }\n\n const roots = categories.filter(\n (category) => category.parentId === null || !byId.has(category.parentId),\n );\n const childrenByParent = new Map<string, PlatformCategory[]>();\n for (const category of categories) {\n if (!category.parentId || !byId.has(category.parentId)) continue;\n const children = childrenByParent.get(category.parentId) ?? [];\n children.push(category);\n childrenByParent.set(category.parentId, children);\n }\n\n const items: CategoryHierarchyItem[] = [];\n const seen = new Set<string>();\n for (const root of roots) {\n items.push({\n category: root,\n depth: 0,\n parent: null,\n displayName: root.name,\n });\n seen.add(root.id);\n\n for (const child of childrenByParent.get(root.id) ?? []) {\n items.push({\n category: child,\n depth: 1,\n parent: root,\n displayName: `${root.name} / ${child.name}`,\n });\n seen.add(child.id);\n }\n }\n\n // Loud database guards make this fallback unreachable for valid data, but a\n // picker must never hide an identity merely because older data is malformed.\n for (const category of categories) {\n if (seen.has(category.id)) continue;\n items.push({\n category,\n depth: 0,\n parent: null,\n displayName: category.name,\n });\n }\n\n return {\n items,\n roots: categories.filter((category) => category.parentId === null),\n hasHierarchy: true,\n };\n}\n"],"mappings":"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","names":["out","err","ok","err","data","error","ok","err","ok","err","ok","err"]}
|