@ai-matrx/data 0.26.1 → 0.28.0

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/dist/db.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/db/guarded-update.ts","../src/db/read-all-rows.ts","../src/db/merge-json-column.ts","../src/db/auth-retry.ts","../src/db/auth-cookie.ts","../src/db/active-org-cookie.ts","../src/db/realtime.ts","../src/db/oauth-refresh-transport.ts","../src/db/write-failure.ts","../src/db/write-one.ts","../src/db/record-unavailable.ts","../src/db/doors.ts"],"sourcesContent":["/**\n * guardedUpdate — the platform optimistic-concurrency contract for\n * direct-Supabase writes.\n *\n * Cross-repo system-of-record:\n * common-docs/systems/architecture/optimistic-concurrency/FEATURE.md — read it\n * before touching this feature in ANY repo.\n *\n * The revision token is the canonical `version` int column (bumped by the\n * `platform._touch_row` trigger on every UPDATE). A guarded write is a\n * compare-and-swap: `.eq(\"version\", expectedVersion)` on the UPDATE, then\n * classify 0 rows as conflict-vs-gone by re-reading the row. This helper owns\n * the classification and the typed result so every feature reports conflicts\n * the same way — it deliberately takes the two queries as callbacks because\n * each feature already has its own schema-scoped client, column list, and\n * narrowing filters (`.is(\"deleted_at\", null)` etc.).\n *\n * Usage:\n * const result = await guardedUpdate({\n * expectedVersion: page.version,\n * applyUpdate: ({ expectedVersion, nextVersion }) =>\n * db.from(\"page\")\n * .update({ ...patch, version: nextVersion })\n * .eq(\"id\", pageId)\n * .eq(\"version\", expectedVersion)\n * .select(PAGE_COLUMNS)\n * .maybeSingle(),\n * fetchCurrent: () =>\n * db.from(\"page\").select(PAGE_COLUMNS).eq(\"id\", pageId).maybeSingle(),\n * });\n * switch (result.status) { \"saved\" | \"conflict\" | \"not_found\" ... }\n *\n * Rules (same as the server side):\n * - Opt-in per write. No expectedVersion in hand (the surface never read\n * `version`)? Then the surface cannot opt in — fix the read first.\n * - SET `version: nextVersion` in the update payload: the trigger recomputes\n * the identical value on canonical tables and it keeps the CAS sound on\n * tables without the trigger.\n * - Never invent a second token (no updated_at comparisons in new code).\n * - On conflict, surface the merge/refresh choice to the user — never silently\n * overwrite (`currentRow`/`currentVersion` are returned for exactly that).\n *\n * THE PHANTOM CONFLICT, and `rebase` (2026-09-13). `version` moves on EVERY\n * update of the row — a desktop sync stamping `file_path`, an ingest job\n * writing metadata, a folder move — not only on the fields this editor edits.\n * A client that missed such a bump (its realtime echo was suppressed, its tab\n * was asleep, the write landed under its own actor) will CAS on a stale\n * number, miss, and be shown \"someone else changed this\" for a row whose\n * edited fields are byte-identical to the base it started from. That is not a\n * conflict; it is a version the client never learned. A conflict means the\n * OTHER side changed something you are editing.\n *\n * So a caller that knows its edit base passes `rebase.isPhantom(currentRow)`:\n * \"do the fields I edit, as the server holds them now, still equal the base\n * my edit was made against?\" When it answers yes, the helper retries the\n * write ONCE against the current version and returns `saved` with\n * `rebasedFrom` naming both numbers. A second miss, or a `no`, is a real\n * conflict and is returned exactly as before. No caller that does not pass\n * `rebase` changes behaviour.\n */\nimport type { MaybeSingleResponse } from \"../index\";\n\nexport interface VersionedRow {\n version: number;\n}\n\nexport interface RebasedFrom {\n /** The stale number the caller sent. */\n expectedVersion: number;\n /** The number the row actually held; the retry CAS'd on it. */\n currentVersion: number;\n}\n\nexport type GuardedUpdateResult<Row extends VersionedRow> =\n | {\n status: \"saved\";\n row: Row;\n /** Present when the write landed only after a phantom-conflict rebase. */\n rebasedFrom?: RebasedFrom;\n }\n | { status: \"conflict\"; currentRow: Row; currentVersion: number }\n | { status: \"not_found\" };\n\nexport interface GuardedUpdateRebase<Row extends VersionedRow> {\n /**\n * Given the row the server holds NOW (after a CAS missed), answer whether\n * every field this edit touches still equals the base the edit was made\n * against. `true` means nobody changed what we are changing — the version\n * moved for some other column — and the write is retried against\n * `currentRow.version`. Consulted again on EVERY miss, because the writer\n * that bumped the row once may bump it again (matrx-local stamps\n * `file_path` and then `last_device_id` as two UPDATEs).\n */\n isPhantom: (currentRow: Row) => boolean;\n /** Maximum retries after the first miss. Default 3. */\n maxRetries?: number;\n}\n\nexport interface GuardedUpdateArgs<Row extends VersionedRow> {\n /** The `version` the edit was based on — from the read that fed the UI. */\n expectedVersion: number;\n /**\n * Run the UPDATE with `.eq(\"version\", expectedVersion)` and\n * `version: nextVersion` in the payload, ending in `.select(...).maybeSingle()`.\n */\n applyUpdate: (guard: {\n expectedVersion: number;\n nextVersion: number;\n }) => PromiseLike<MaybeSingleResponse<Row>>;\n /** Re-read the row by primary key alone (no version filter), `.maybeSingle()`. */\n fetchCurrent: () => PromiseLike<MaybeSingleResponse<Row>>;\n /** Opt-in phantom-conflict recovery. See the header. */\n rebase?: GuardedUpdateRebase<Row>;\n}\n\nexport async function guardedUpdate<Row extends VersionedRow>(\n args: GuardedUpdateArgs<Row>,\n): Promise<GuardedUpdateResult<Row>> {\n const { expectedVersion, applyUpdate, fetchCurrent, rebase } = args;\n const updated = await applyUpdate({\n expectedVersion,\n nextVersion: expectedVersion + 1,\n });\n if (updated.error) throw updated.error;\n if (updated.data) return { status: \"saved\", row: updated.data };\n\n const current = await fetchCurrent();\n if (current.error) throw current.error;\n if (!current.data) return { status: \"not_found\" };\n let currentRow = current.data;\n let currentVersion = currentRow.version;\n\n if (rebase === undefined) {\n return { status: \"conflict\", currentRow, currentVersion };\n }\n\n // The number moved; if nothing we edit did, retry on the number the row\n // holds — and ask again on every miss, bounded, because the writer that\n // bumped it once may bump it again. The CAS keeps every retry safe: a real\n // change between the read and the retry misses and is re-read, and\n // `isPhantom` then sees it.\n const maxRetries = rebase.maxRetries ?? 3;\n for (let attempt = 0; attempt < maxRetries; attempt += 1) {\n if (\n !Number.isSafeInteger(currentVersion) ||\n currentVersion === expectedVersion ||\n !rebase.isPhantom(currentRow)\n ) {\n return { status: \"conflict\", currentRow, currentVersion };\n }\n const retried = await applyUpdate({\n expectedVersion: currentVersion,\n nextVersion: currentVersion + 1,\n });\n if (retried.error) throw retried.error;\n if (retried.data) {\n return {\n status: \"saved\",\n row: retried.data,\n rebasedFrom: { expectedVersion, currentVersion },\n };\n }\n const after = await fetchCurrent();\n if (after.error) throw after.error;\n if (!after.data) return { status: \"not_found\" };\n currentRow = after.data;\n currentVersion = currentRow.version;\n }\n\n return { status: \"conflict\", currentRow, currentVersion };\n}\n","/**\n * readAllRows — the ONE way to read a LIST YOU INTEND TO TREAT AS COMPLETE.\n *\n * THE BUG THIS EXISTS TO KILL (FOUND_DEFECTS D190)\n * ------------------------------------------------\n * PostgREST caps every response at `db-max-rows` (1000 on Matrx Main). It does\n * not error. It returns HTTP 206 and a `Content-Range: 0-999/4185` header, and\n * `supabase-js` hands you a perfectly successful-looking array of 1000 rows.\n *\n * If that array is only rendered, nothing is wrong — the user sees a screenful.\n * If that array is used to DECIDE SOMETHING, it is a silent, confident lie:\n *\n * - `rows.find(...)` → \"no such row\" (it exists, it was row 1200)\n * - `set.has(...)` → \"not registered\" (…)\n * - set subtraction → \"stale, delete it\" ← this one DELETES LIVE DATA\n * - `a.length === b.length` → \"out of sync\"\n *\n * Measured 2026-08-14: `public._schema_migrations` held 1611 rows,\n * `scripts/check-migrations.ts` saw 1000, and reported the 5 newest migrations\n * UNAPPLIED to a release that had just applied them — hard-blocking every\n * `--strict` release. Same day: `ui.ui_surface_value` held 4185 rows and fed a\n * `deleteStale` set-subtraction in the surface manifest sync.\n *\n * THE RULE\n * --------\n * An **existence check, a diff, a set subtraction, or a completeness/`.length`\n * comparison MUST read through `readAllRows`** (or `readAllRowsRest`). A bare\n * `.select()` is only acceptable when a short list is an acceptable answer —\n * i.e. you are rendering, sampling, or previewing.\n *\n * This helper refuses to guess. It pages to the declared total and, if it\n * cannot prove it collected every row, it THROWS instead of returning a\n * confidently wrong partial list. Callers that would rather skip a check than\n * assert a wrong one use `tryReadAllRows`, which logs loudly and returns null.\n *\n * USAGE (supabase-js)\n * -------------------\n * const rows = await readAllRows<Row>(\n * ({ from, to }) =>\n * sb.schema(\"ui\").from(\"ui_surface_value\")\n * .select(\"surface_name, name\", { count: \"exact\" }) // count REQUIRED\n * .order(\"id\", { ascending: true }) // stable order REQUIRED\n * .range(from, to),\n * { label: \"ui.ui_surface_value\" },\n * );\n *\n * Two things the caller owns and this helper cannot check for you:\n * 1. `{ count: \"exact\" }` — without it there is no total to verify against,\n * and the read throws rather than trusting a full-looking page.\n * 2. A **stable total order** (`.order()` on a unique-ish column). Paging an\n * unordered relation can repeat and skip rows between requests — you would\n * collect the right COUNT of rows and still miss one.\n */\n\n/** The shape every supabase-js `.range()` call resolves to. */\nexport interface PagedReadResult<T> {\n data: T[] | null;\n error: { message: string } | null;\n count?: number | null;\n}\n\n/**\n * A factory that runs ONE page. It must be a factory, not a builder: a\n * supabase-js query is a single-use thenable, so paging needs a fresh one per\n * request.\n */\nexport type PagedReadQuery<T> = (range: {\n from: number;\n to: number;\n}) => PromiseLike<PagedReadResult<T>>;\n\nexport interface ReadAllRowsOptions {\n /** `schema.table` (or RPC name) — appears in every error. Required: a silent truncation is unfindable without it. */\n label: string;\n /** Rows per request. Must not exceed the server's `db-max-rows` (1000 here). */\n pageSize?: number;\n /** Runaway guard. A read past this throws rather than looping forever. */\n maxRows?: number;\n}\n\nconst DEFAULT_PAGE_SIZE = 1000;\nconst DEFAULT_MAX_ROWS = 500_000;\n\n/** Thrown when the full set provably could not be collected. Never swallow this into an empty list. */\nexport class IncompleteReadError extends Error {\n readonly label: string;\n readonly collected: number;\n readonly expected: number | null;\n\n // Explicit fields, not constructor parameter properties: consumers compile\n // this source under `erasableSyntaxOnly` (workflow-studio, dashboard), which\n // forbids the shorthand.\n constructor(\n label: string,\n collected: number,\n expected: number | null,\n detail: string,\n ) {\n super(\n `readAllRows(${label}): ${detail} — collected ${collected}` +\n (expected === null ? \"\" : ` of ${expected}`) +\n \". Refusing to return a partial list: a truncated read used for an \" +\n \"existence/diff decision produces a confidently WRONG answer.\",\n );\n this.label = label;\n this.collected = collected;\n this.expected = expected;\n this.name = \"IncompleteReadError\";\n }\n}\n\n/**\n * Read EVERY row, or throw. See the file header for the contract.\n *\n * @throws IncompleteReadError when the collected count cannot be proven complete.\n * @throws Error on any underlying query error.\n */\nexport async function readAllRows<T>(\n query: PagedReadQuery<T>,\n opts: ReadAllRowsOptions,\n): Promise<T[]> {\n const pageSize = opts.pageSize ?? DEFAULT_PAGE_SIZE;\n const maxRows = opts.maxRows ?? DEFAULT_MAX_ROWS;\n const rows: T[] = [];\n let total: number | null = null;\n\n for (let from = 0; ; from += pageSize) {\n const res = await query({ from, to: from + pageSize - 1 });\n if (res.error) {\n throw new Error(\n `readAllRows(${opts.label}): query failed — ${res.error.message}`,\n );\n }\n const page = res.data ?? [];\n rows.push(...page);\n if (typeof res.count === \"number\") total = res.count;\n\n // No total on the first request means the caller omitted `{ count: \"exact\" }`.\n // A full-looking page is exactly what truncation looks like, so we cannot\n // accept it. A short first page is provably everything.\n if (total === null) {\n if (page.length < pageSize) return rows;\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n null,\n 'the query returned no count — pass { count: \"exact\" } to select() so ' +\n \"completeness can be verified\",\n );\n }\n\n if (rows.length >= total) break;\n if (page.length === 0) {\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n total,\n \"a page came back empty before the declared total was reached\",\n );\n }\n if (rows.length > maxRows) {\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n total,\n `exceeded the ${maxRows}-row safety limit`,\n );\n }\n }\n\n if (rows.length !== total) {\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n total,\n \"final row count does not match the total the server reported\",\n );\n }\n return rows;\n}\n\n/**\n * Same contract, but a provably-incomplete read returns `null` after SCREAMING\n * instead of throwing. For gate scripts that would rather SKIP a check than\n * assert a wrong verdict (`check-migrations.ts` is the exemplar). A `null`\n * return must never be coerced to `[]`.\n */\nexport async function tryReadAllRows<T>(\n query: PagedReadQuery<T>,\n opts: ReadAllRowsOptions,\n): Promise<T[] | null> {\n try {\n return await readAllRows(query, opts);\n } catch (err) {\n console.error(\n `[readAllRows] INCOMPLETE READ of ${opts.label} — check skipped rather ` +\n `than answered wrongly: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Raw-REST variant — for scripts that talk to PostgREST with `fetch`\n * and have no supabase-js client (they read `.env` directly).\n * ------------------------------------------------------------------ */\n\nexport interface ReadAllRowsRestOptions extends ReadAllRowsOptions {\n /** Supabase project URL, with or without a trailing slash. */\n url: string;\n /** apikey / bearer token. */\n key: string;\n /**\n * Path + query AFTER `/rest/v1/`, e.g.\n * `definition?select=name,parameters&order=name.asc`.\n * It MUST carry a stable `order=` — see the file header.\n */\n path: string;\n /** Postgres schema for the `Accept-Profile` header (the db.matrxserver.com proxy defaults to `api`). */\n schema?: string;\n}\n\n/**\n * Read EVERY row over raw REST, or throw. Uses `Range` headers and verifies the\n * collected count against the total in `Content-Range: 0-999/4185`.\n */\nexport async function readAllRowsRest<T>(\n opts: ReadAllRowsRestOptions,\n): Promise<T[]> {\n const pageSize = opts.pageSize ?? DEFAULT_PAGE_SIZE;\n const maxRows = opts.maxRows ?? DEFAULT_MAX_ROWS;\n const endpoint = `${opts.url.replace(/\\/$/, \"\")}/rest/v1/${opts.path}`;\n const rows: T[] = [];\n let total: number | null = null;\n\n for (let from = 0; ; from += pageSize) {\n const res = await fetch(endpoint, {\n headers: {\n apikey: opts.key,\n Authorization: `Bearer ${opts.key}`,\n Accept: \"application/json\",\n ...(opts.schema ? { \"Accept-Profile\": opts.schema } : {}),\n // Without this PostgREST answers `Content-Range: 0-999/*` — a page with\n // no total, which is unverifiable and therefore refused below. This is\n // the REST twin of supabase-js's `{ count: \"exact\" }`.\n Prefer: \"count=exact\",\n Range: `${from}-${from + pageSize - 1}`,\n \"Range-Unit\": \"items\",\n },\n });\n if (!res.ok && res.status !== 206) {\n throw new Error(\n `readAllRowsRest(${opts.label}): HTTP ${res.status} — ${await res.text()}`,\n );\n }\n const page = (await res.json()) as T[];\n rows.push(...page);\n\n // `Content-Range: 0-999/4185` — the part after the slash is the true total.\n // `*` means the server declined to count; treat it as unverifiable.\n const totalPart = res.headers.get(\"content-range\")?.split(\"/\")[1];\n if (totalPart && totalPart !== \"*\") total = Number(totalPart);\n\n if (total === null) {\n if (page.length < pageSize) return rows;\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n null,\n \"the server reported no total in Content-Range, and the page came back full\",\n );\n }\n if (rows.length >= total) break;\n if (page.length === 0) {\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n total,\n \"a page came back empty before the declared total was reached\",\n );\n }\n if (rows.length > maxRows) {\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n total,\n `exceeded the ${maxRows}-row safety limit`,\n );\n }\n }\n\n if (rows.length !== total) {\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n total,\n \"final row count does not match Content-Range's total\",\n );\n }\n return rows;\n}\n\n/** `tryReadAllRows` for the REST variant. */\nexport async function tryReadAllRowsRest<T>(\n opts: ReadAllRowsRestOptions,\n): Promise<T[] | null> {\n try {\n return await readAllRowsRest<T>(opts);\n } catch (err) {\n console.error(\n `[readAllRowsRest] INCOMPLETE READ of ${opts.label} — check skipped ` +\n `rather than answered wrongly: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n}\n","/**\n * mergeJsonColumn — the platform primitive for \"merge a value into a row's\n * JSONB column, from the browser, without losing a concurrent writer's keys\".\n *\n * Why this exists (matrx-frontend FOUND_DEFECTS D151): persisting a paid AI\n * result almost always means read-modify-write on an existing jsonb column\n * (`metadata`, `dynamic_content`, `settings`) — that is a lost-update race the\n * moment two surfaces write different keys of the same object. Every feature\n * that needed it was about to hand-roll the same read → spread → write, so it\n * is built ONCE here on the canonical optimistic-concurrency contract\n * (`guardedUpdate` — CAS on the `version` column) with a bounded\n * re-read-and-remerge retry, because an append/merge is exactly the conflict a\n * caller can resolve automatically.\n *\n * This is NOT a second concurrency token or a second write path: it composes\n * `guardedUpdate`, and it never compares `updated_at`.\n *\n * Usage:\n * await mergeJsonColumn<Row>({\n * fetchCurrent: () =>\n * db.from(\"study_session\").select(\"id, version, metadata\")\n * .eq(\"id\", sessionId).maybeSingle(),\n * readColumn: (row) => row.metadata,\n * merge: (current) => ({ ...current, coach_tips: [...prior, entry] }),\n * applyUpdate: ({ value, expectedVersion, nextVersion }) =>\n * db.from(\"study_session\")\n * .update({ metadata: value, version: nextVersion })\n * .eq(\"id\", sessionId).eq(\"version\", expectedVersion)\n * .select(\"id, version, metadata\").maybeSingle(),\n * });\n *\n * Never throws for a normal outcome — it returns a typed status so a persist\n * failure can be reported without taking down the surface that triggered it.\n */\nimport type { MaybeSingleResponse } from \"../index\";\nimport { guardedUpdate, type VersionedRow } from \"./guarded-update\";\n\n/**\n * A jsonb object column's value, normalized — never null, never an array.\n *\n * Typed over `unknown`, NOT this package's strict `Json`: the origin module was\n * typed against the HOST's generated `Json` type, and Supabase type generation\n * commonly emits `type Json = unknown` (the flagship host does). Requiring the\n * strict recursive `Json` here forced a cast at every real call site — the\n * merge callback's inputs and outputs go straight to/from a jsonb column the\n * host has already typed, so the honest boundary type is `unknown`.\n */\nexport type JsonObject = Record<string, unknown>;\n\nexport type MergeJsonColumnResult<Row extends VersionedRow> =\n | { status: \"saved\"; row: Row }\n /** The row is gone / not visible under RLS — nothing to merge into. */\n | { status: \"not_found\" }\n /** Every attempt lost the CAS race; the caller's value was NOT written. */\n | { status: \"conflict\" }\n /** A transport/PostgREST failure. The error is returned, never swallowed. */\n | { status: \"error\"; error: unknown };\n\nexport interface MergeJsonColumnArgs<Row extends VersionedRow> {\n /** Read the row by primary key — must select `version` and the json column. */\n fetchCurrent: () => PromiseLike<MaybeSingleResponse<Row>>;\n /** Pick the json column off a fetched row. */\n readColumn: (row: Row) => unknown;\n /**\n * Produce the column's next value from its CURRENT value. Re-invoked on each\n * retry with freshly-read data, so it must be a pure function of `current`.\n */\n merge: (current: JsonObject) => JsonObject;\n /**\n * Run the guarded UPDATE: set the column to `value` plus `version: nextVersion`,\n * filtered by `.eq(\"version\", expectedVersion)`, ending in `.select(...).maybeSingle()`.\n */\n applyUpdate: (next: {\n value: JsonObject;\n expectedVersion: number;\n nextVersion: number;\n }) => PromiseLike<MaybeSingleResponse<Row>>;\n /** How many CAS attempts before giving up. Default 3. */\n attempts?: number;\n}\n\n/** Normalize a jsonb column read to a plain object (null / array / scalar → {}). */\nexport function asJsonObject(value: unknown): JsonObject {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return {};\n return value as JsonObject;\n}\n\nexport async function mergeJsonColumn<Row extends VersionedRow>(\n args: MergeJsonColumnArgs<Row>,\n): Promise<MergeJsonColumnResult<Row>> {\n const attempts = Math.max(args.attempts ?? 3, 1);\n try {\n for (let attempt = 0; attempt < attempts; attempt++) {\n const current = await args.fetchCurrent();\n if (current.error) return { status: \"error\", error: current.error };\n if (!current.data) return { status: \"not_found\" };\n\n const next = args.merge(asJsonObject(args.readColumn(current.data)));\n const result = await guardedUpdate<Row>({\n expectedVersion: current.data.version,\n applyUpdate: ({ expectedVersion, nextVersion }) =>\n args.applyUpdate({ value: next, expectedVersion, nextVersion }),\n fetchCurrent: args.fetchCurrent,\n });\n if (result.status === \"saved\") return { status: \"saved\", row: result.row };\n if (result.status === \"not_found\") return { status: \"not_found\" };\n // Conflict: someone else wrote between our read and our write. Re-read and\n // re-merge — that is exactly what makes a merge safe to retry.\n }\n return { status: \"conflict\" };\n } catch (e) {\n return { status: \"error\", error: e };\n }\n}\n","/**\n * Session-retry — one primitive for the class of failure where a browser\n * operation reached PostgREST with NO user JWT even though the app believes a\n * user is signed in (the auth session was momentarily unavailable — refresh in\n * flight, storage read mid-rewrite, cookie chunk swap). The request then\n * executes as `anon`, and every RPC that resolves an owner answers with an\n * authorization error that has nothing to do with the user's actual\n * permissions.\n *\n * This fired for real (matrx-frontend, 2026-08-15): artifact materialization\n * lost a react artifact, and the browser console blamed \"cannot create another\n * user's personal organization\" — an organization the caller was never\n * creating. The DB edge answers honestly (`28000 not authenticated`); this is\n * the client half that makes a momentary blip recoverable instead of losing\n * the write.\n *\n * Deliberately NOT a general retry-on-error wrapper: it retries EXACTLY ONE\n * cause (no authenticated session) EXACTLY ONCE, after asking the auth client\n * to re-resolve the session. Anything else — RLS denials, constraint\n * violations, network errors — is returned untouched, because retrying those\n * is how a client turns one failure into a storm.\n *\n * The host injects its auth client through `SessionSource` (a supabase-js\n * client's `auth` satisfies it structurally) and, optionally, a diagnostics\n * sink; the default sink is `console.error` — honest, never silent.\n */\n\n/** The shape every supabase-js call returns, narrowed to what we inspect. */\nexport interface AuthRetryableResult<T> {\n data: T;\n error: { code?: string | null; message?: string | null } | null;\n status?: number;\n}\n\n/** The slice of an auth client this primitive needs (structural). */\nexport interface SessionSource {\n getSession(): Promise<{\n data: { session: { access_token?: string | null } | null };\n error: unknown | null;\n }>;\n}\n\nexport class SessionUnavailableError extends Error {\n readonly code = \"PGRST301\";\n\n constructor() {\n super(\"Your session expired\");\n this.name = \"SessionUnavailableError\";\n }\n}\n\n/**\n * True when the DB refused because the request carried no authenticated user.\n * `28000` is the SQLSTATE our authenticated-only RPCs raise; the message tests\n * cover RPCs that raise the same condition without setting ERRCODE, plus\n * PostgREST's own response when an anonymous request reaches an\n * authenticated-only RPC.\n */\nexport function isMissingSessionError(\n error: { code?: string | null; message?: string | null } | null | undefined,\n status?: number,\n): boolean {\n if (!error) return false;\n // PostgREST emits PGRST301 when JWT verification fails, including an\n // expired access token. It is the same session boundary as the shapes below.\n if (error.code === \"PGRST301\") return true;\n if (error.code === \"28000\") return true;\n const message = error.message?.toLowerCase();\n if (message?.startsWith(\"not authenticated\")) return true;\n return (\n status === 401 &&\n error.code === \"42501\" &&\n message?.startsWith(\"permission denied for function \") === true\n );\n}\n\nexport interface CreateSessionRetryOptions {\n /** The host's auth client (e.g. `supabase.auth`). */\n auth: SessionSource;\n /** Diagnostics sink for the two recovery screams. Default: `console.error`. */\n log?: (message: string, detail?: unknown) => void;\n}\n\n/**\n * Build the host-bound retry runner. The returned function runs a call; if it\n * fails purely because no session reached the server, it re-resolves the\n * session and runs it ONCE more.\n *\n * The operation must be idempotent — reads are safe, and write callers use an\n * upsert keyed on a natural key, so the retry can only land the same row.\n *\n * Returns the second attempt's result when a retry happened, else the first.\n * `retried` / `sessionRecovered` are reported so callers can log the truth\n * instead of a generic \"failed to persist\".\n *\n * @throws SessionUnavailableError before touching the network when the browser\n * already knows the session is gone — executing during that gap creates a\n * guaranteed anonymous 401 and turns ordinary session expiry into a product\n * error.\n */\nexport function createSessionRetry(options: CreateSessionRetryOptions) {\n const log =\n options.log ??\n ((m: string, d?: unknown) => {\n // Only forward a detail that exists — console.error(m, undefined)\n // renders a trailing \"undefined\" in every real console, and hosts\n // asserting on the call see a phantom second argument.\n if (d === undefined) console.error(m);\n else console.error(m, d);\n });\n\n return async function runWithSessionRetry<T>(\n // PromiseLike, not Promise: a supabase-js query builder is a thenable, so\n // callers can hand the builder straight back without an extra await.\n run: () => PromiseLike<AuthRetryableResult<T>>,\n ): Promise<\n AuthRetryableResult<T> & { retried: boolean; sessionRecovered: boolean }\n > {\n const { data: initialSession, error: initialSessionError } =\n await options.auth.getSession();\n if (!initialSession.session?.access_token || initialSessionError) {\n throw new SessionUnavailableError();\n }\n\n const first = await run();\n if (!isMissingSessionError(first.error, first.status)) {\n return { ...first, retried: false, sessionRecovered: false };\n }\n\n // getSession() re-reads the persisted session and refreshes it when\n // expired — the cheapest way to ask \"do we actually have a user right now?\"\n const { data, error: sessionError } = await options.auth.getSession();\n const recovered = Boolean(data.session?.access_token) && !sessionError;\n if (!recovered) {\n log(\n \"[authRetry] an operation reached the database with no authenticated session and the session could NOT be recovered — the user is signed out or their session expired. The operation was not retried.\",\n sessionError ?? first.error,\n );\n return { ...first, retried: false, sessionRecovered: false };\n }\n\n log(\n \"[authRetry] an operation reached the database with no authenticated session; the session re-resolved and the operation is being retried once. This is a recovery firing, which means a real session-availability bug got past the proactive layer.\",\n );\n const second = await run();\n return { ...second, retried: true, sessionRecovered: true };\n };\n}\n","/**\n * Shared auth-cookie options for EVERY Supabase client an application\n * constructs (browser, server, middleware, OAuth callbacks). All construction\n * sites MUST pass these options — a client using the default cookie name\n * cannot see the session the others wrote.\n *\n * WHY (the 2026-07 Matrx deployment split): one login must work on every\n * subdomain of the platform's apex (e.g. app.example.com, manage.example.com),\n * so on those hosts the auth cookie is issued domain-wide\n * (`Domain=.example.com`) instead of Supabase's default host-only cookie.\n *\n * The cookie is also RENAMED (default `sb-<project-ref>-auth-token` →\n * `sb-matrx-auth`): re-issuing an existing host-only cookie as domain-wide\n * under the SAME name leaves two same-name cookies in the browser (different\n * Domain attributes = distinct cookies), and whichever the browser sends\n * first wins — auth flaps. A new name makes the transition deterministic:\n * every user re-logs-in exactly once and the old cookie expires unused.\n * The `sb-` prefix is kept on purpose — cleanup paths that scrub session\n * cookies delete by that prefix.\n *\n * The Domain attribute is ONLY set on real apex hosts. localhost and preview\n * hosts get a host-only cookie — a browser rejects any Set-Cookie whose\n * Domain does not cover the current host, so setting it unconditionally would\n * silently break auth everywhere else.\n *\n * The apex domain is a VALUE the host passes in (never read from an env var\n * here): `createAuthCookie({ apexDomain: \"aimatrx.com\" })`.\n *\n * THE RENAME MIGRATION (0.5.0 — moved in from matrx-frontend, where it was\n * 44 lines of host code every other consumer would have had to re-derive):\n * replacing the auth authority (a new Supabase project) means a NEW cookie\n * name, and a tab still running the OLD bundle keeps writing the OLD name for\n * days. `migrateLegacyCookies` seeds the new storage key from the old one\n * ONLY when the new key is absent — never overwriting a live session — and\n * `isCurrentCookie` recognizes both the base name and Supabase's numbered\n * chunk suffixes (`<name>.0`, `<name>.1`, …), which a naive `startsWith`\n * check gets wrong for any cookie that merely shares the prefix.\n */\n\n/** Structurally compatible with @supabase/ssr's CookieOptionsWithName. */\nexport interface AuthCookieOptions {\n name: string;\n /** Remote hosts require HTTPS; loopback development remains usable over HTTP. */\n secure: boolean;\n domain?: string;\n}\n\n/** A cookie as read from a request — name + value, nothing else needed. */\nexport interface AuthCookieValue {\n name: string;\n value: string;\n}\n\nexport const DEFAULT_AUTH_COOKIE_NAME = \"sb-matrx-auth\";\n\nexport interface CreateAuthCookieArgs {\n /** The apex domain one login must span (e.g. `\"aimatrx.com\"`). */\n apexDomain: string;\n /** Override only for a second, unrelated deployment — never per-app. */\n cookieName?: string;\n /**\n * The storage key a PREVIOUS auth authority used. When present, cookies\n * under this name are seeded onto `cookieName` (absent-only) by\n * `migrateLegacyCookies`, and the middleware binding clears them at the\n * scope this host issued them on.\n */\n legacyCookieName?: string;\n}\n\nexport interface AuthCookie {\n cookieName: string;\n /** The superseded storage key, when this deployment has one. */\n legacyCookieName: string | undefined;\n /**\n * Cookie options for the host serving the current request.\n * @param host `Host` header or `window.location.hostname` (port tolerated).\n */\n optionsForHost(host: string | null | undefined): AuthCookieOptions;\n /** Browser variant — resolves the host from `window` (SSR-safe). */\n browserOptions(): AuthCookieOptions;\n /**\n * Is this cookie name the CURRENT auth cookie — base name or one of\n * Supabase's numbered chunks (`<name>.0`)? A prefix test is wrong: it\n * matches `<name>.anything`, including unrelated cookies.\n */\n isCurrentCookie(name: string): boolean;\n /**\n * Cookies to seed under the current name, derived from the legacy name.\n * Returns `[]` when any current cookie already exists (never overwrite a\n * live session) or when no legacy name is configured.\n */\n migrateLegacyCookies(\n cookies: readonly AuthCookieValue[],\n ): AuthCookieValue[];\n /**\n * THE POISONED-JAR READ. A browser can hold the SAME auth cookie name twice\n * — once host-only, once at `.apex` — because different Domain attributes\n * make distinct cookies, and it sends both in one `Cookie` header. Every\n * reassembler downstream (`@supabase/ssr`'s `combineChunks`) resolves a\n * chunk with `find()`, i.e. FIRST WINS, and the browser decides the order.\n * An empty shadow that sorts first therefore reassembles to `\"\"` and every\n * server read answers anonymous while the tab is signed in.\n *\n * This collapses each auth-cookie NAME to one entry, preferring the first\n * NON-EMPTY value. Non-auth cookies pass through untouched, in order.\n *\n * A `Cookie` header carries no Domain, so which scope a value came from is\n * genuinely unknowable here — non-empty-wins is the strongest correct rule\n * available, and `@supabase/ssr` already refuses a chunk set that decodes\n * incoherently. `shadowedNames` names every auth cookie that arrived more\n * than once, so the caller can EXPIRE the losing scope instead of leaving\n * the user to clear cookies by hand.\n *\n * THE SECOND POISON, AND IT IS AN IDENTITY LEAK: one storage key arriving\n * BOTH unchunked (`<name>`) and chunked (`<name>.0`, `<name>.1`). These are\n * DIFFERENT cookie names, so the per-name collapse above cannot see them,\n * and `@supabase/ssr`'s `combineChunks` returns the UNCHUNKED value the\n * moment it is non-empty — it never even reads the chunks. A stale base\n * cookie therefore shadows a freshly written chunked pair, and every read\n * resolves the PREVIOUS person while the new session sits unread beside it.\n * That is a different user's session being served, not merely a logout.\n *\n * `applyServerStorage` never writes that shape — it removes every chunk-like\n * sibling of whatever it writes — so a jar holding both is RESIDUE from a\n * removal that did not land (see `middlewareSession`: a two-scope removal\n * collapses on `ResponseCookies`, which is how this residue is made).\n *\n * WHICH COPY IS NEWER IS UNKNOWABLE HERE, and both directions of residue are\n * producible, so preferring either shape is a coin flip on WHOSE SESSION TO\n * SERVE. This drops the whole family from the read instead: nobody is signed\n * in, every name in it is returned in `ambiguousNames` to be expired, and the\n * host's honest-screen banner says so with the one action that fixes it. A\n * wrong sign-out is recoverable in one click; a wrong identity is not.\n */\n reconcile(cookies: readonly AuthCookieValue[]): ReconciledAuthCookies;\n}\n\n/** The outcome of {@link AuthCookie.reconcile}. */\nexport interface ReconciledAuthCookies {\n /** One entry per name; auth names resolved to their non-empty value. */\n cookies: AuthCookieValue[];\n /** Auth cookie names that arrived more than once (i.e. at two scopes). */\n shadowedNames: string[];\n /**\n * Auth cookie names belonging to a storage key that arrived UNCHUNKED AND\n * CHUNKED at once — see {@link AuthCookie.reconcile}. Their values have been\n * dropped from `cookies`, and they must be expired on EVERY host, including\n * the ones that issue a host-only cookie: unlike a two-scope shadow there is\n * no copy here that could be the good one.\n */\n ambiguousNames: string[];\n /** The storage keys that arrived in both shapes. Named for the scream. */\n ambiguousKeys: string[];\n /** `true` when the jar is split and needs healing. */\n split: boolean;\n}\n\n/**\n * Parse a raw `Cookie` request header, **PRESERVING DUPLICATES AND ORDER**.\n *\n * 🚨 THIS IS THE ONLY WAY TO SEE A SPLIT JAR. Next's `RequestCookies` (and the\n * `cookies()` store built on it) parses the header into a Map keyed by NAME,\n * so two same-name cookies at two Domain scopes collapse to ONE before any\n * application code runs — and the survivor is whichever the browser happened\n * to send LAST. Measured against the real class:\n *\n * \"sb-…-v2.0=; sb-…-v2.0=base64-REAL\" -> [{ value: \"base64-REAL\" }] works\n * \"sb-…-v2.0=base64-REAL; sb-…-v2.0=\" -> [{ value: \"\" }] anonymous\n *\n * That coin flip IS the production break, and it is invisible from the\n * collapsed jar: reconciliation over `getAll()` is a no-op no matter how\n * carefully it is written. Every door must therefore reconcile over THIS.\n */\nexport function parseCookieHeader(\n header: string | null | undefined,\n): AuthCookieValue[] {\n if (!header) return [];\n const out: AuthCookieValue[] = [];\n for (const pair of header.split(\";\")) {\n const eq = pair.indexOf(\"=\");\n // A valueless segment is a name with an empty value — exactly the shadow\n // this exists to catch — so it must not be skipped.\n const name = (eq === -1 ? pair : pair.slice(0, eq)).trim();\n if (!name) continue;\n const raw = eq === -1 ? \"\" : pair.slice(eq + 1).trim();\n let value = raw;\n try {\n value = decodeURIComponent(raw);\n } catch {\n // A malformed escape is not a reason to lose the cookie; Next's parser\n // keeps the raw text too.\n }\n out.push({ name, value });\n }\n return out;\n}\n\n/**\n * Is `name` the storage key itself or one of its numbered chunks? The same\n * membership test `@supabase/ssr`'s `isChunkLike` uses, so a family is defined\n * here exactly as the writer defines it. A bare `startsWith` is wrong: it also\n * matches `<key>.anything`, i.e. unrelated cookies.\n */\nfunction belongsToStorageKey(name: string, storageKey: string): boolean {\n if (name === storageKey) return true;\n if (!name.startsWith(`${storageKey}.`)) return false;\n return /^(0|[1-9][0-9]*)$/.test(name.slice(storageKey.length + 1));\n}\n\n/** `<from>` → `<to>`, carrying Supabase's numbered chunk suffix across. */\nfunction renamedCookie(\n cookie: AuthCookieValue,\n from: string,\n to: string,\n): AuthCookieValue | null {\n if (cookie.name === from) return { ...cookie, name: to };\n const prefix = `${from}.`;\n if (!cookie.name.startsWith(prefix)) return null;\n const chunk = cookie.name.slice(prefix.length);\n if (!/^(0|[1-9][0-9]*)$/.test(chunk)) return null;\n return { ...cookie, name: `${to}.${chunk}` };\n}\n\nexport function createAuthCookie(args: CreateAuthCookieArgs): AuthCookie {\n const cookieName = args.cookieName ?? DEFAULT_AUTH_COOKIE_NAME;\n const legacyCookieName = args.legacyCookieName;\n const apex = args.apexDomain.toLowerCase();\n\n const optionsForHost = (\n host: string | null | undefined,\n ): AuthCookieOptions => {\n const normalized = (host ?? \"\").toLowerCase();\n const hostname = normalized.startsWith(\"[\")\n ? normalized.slice(1, normalized.indexOf(\"]\"))\n : normalized === \"::1\" ? normalized : normalized.split(\":\")[0] ?? \"\";\n const loopback = hostname === \"localhost\" || hostname.endsWith(\".localhost\") ||\n hostname === \"::1\" || /^127(?:\\.(?:0|[1-9]\\d{0,2})){3}$/.test(hostname) &&\n hostname.split(\".\").every((part) => Number(part) <= 255);\n const secure = !loopback;\n const onApex = hostname === apex || hostname.endsWith(`.${apex}`);\n return onApex\n ? { name: cookieName, domain: `.${apex}`, secure }\n : { name: cookieName, secure };\n };\n\n const isCurrentCookie = (name: string): boolean =>\n belongsToStorageKey(name, cookieName);\n\n const isAuthCookie = (name: string): boolean =>\n isCurrentCookie(name) ||\n (legacyCookieName !== undefined &&\n (name === legacyCookieName || name.startsWith(`${legacyCookieName}.`)));\n\n const reconcile = (\n cookies: readonly AuthCookieValue[],\n ): ReconciledAuthCookies => {\n const seen = new Map<string, number>();\n const out: AuthCookieValue[] = [];\n const shadowed = new Set<string>();\n\n for (const cookie of cookies) {\n const at = seen.get(cookie.name);\n if (at === undefined) {\n seen.set(cookie.name, out.length);\n out.push({ name: cookie.name, value: cookie.value });\n continue;\n }\n if (!isAuthCookie(cookie.name)) continue; // non-auth: first wins, as before\n shadowed.add(cookie.name);\n const held = out[at];\n // Non-empty wins. Later non-empty values do NOT displace an earlier\n // non-empty one — with no scope information, churning the choice would\n // make reassembly non-deterministic across requests.\n if (held !== undefined && held.value.length === 0) {\n out[at] = { name: cookie.name, value: cookie.value };\n }\n }\n\n // THE FAMILY PASS. A storage key may arrive unchunked AND chunked at once;\n // those are different NAMES, so the collapse above cannot have seen it.\n // `combineChunks` would take the unchunked value and never read the chunks,\n // which serves whichever person's session happens to be sitting in the base\n // cookie. Refuse the family instead of guessing — see `reconcile`'s docs.\n const ambiguous = new Set<string>();\n const ambiguousKeys: string[] = [];\n const byName = new Map(out.map((cookie) => [cookie.name, cookie] as const));\n const storageKeys = [cookieName, ...(legacyCookieName ? [legacyCookieName] : [])];\n for (const storageKey of storageKeys) {\n const unchunked = byName.get(storageKey);\n const firstChunk = byName.get(`${storageKey}.0`);\n if (!unchunked?.value || !firstChunk?.value) continue;\n ambiguousKeys.push(storageKey);\n for (const { name } of out) {\n if (belongsToStorageKey(name, storageKey)) ambiguous.add(name);\n }\n }\n\n const resolved =\n ambiguous.size === 0\n ? out\n : out.filter(({ name }) => !ambiguous.has(name));\n\n const shadowedNames = [...shadowed];\n const ambiguousNames = [...ambiguous];\n return {\n cookies: resolved,\n shadowedNames,\n ambiguousNames,\n ambiguousKeys,\n split: shadowedNames.length > 0 || ambiguousNames.length > 0,\n };\n };\n\n return {\n cookieName,\n legacyCookieName,\n optionsForHost,\n reconcile,\n browserOptions: () =>\n optionsForHost(\n typeof window !== \"undefined\" ? window.location.hostname : null,\n ),\n isCurrentCookie,\n migrateLegacyCookies: (cookies) => {\n if (!legacyCookieName) return [];\n if (cookies.some(({ name }) => isCurrentCookie(name))) return [];\n return cookies.flatMap((cookie) => {\n const renamed = renamedCookie(cookie, legacyCookieName, cookieName);\n return renamed ? [renamed] : [];\n });\n },\n };\n}\n","/**\n * THE ACTIVE-ORGANIZATION COOKIE — one browser-stored \"which organization am I\n * acting in\" shared by EVERY Matrx web surface on the same apex.\n *\n * WHY (2026-09-08, the Workflow Studio `organization_not_selected` incident):\n * the main app (www.aimatrx.com) remembered the last active organization in\n * its own IndexedDB/localStorage cache; Workflow Studio (workflows.aimatrx.com)\n * remembered its own choice under `matrx_studio_org`; the admin dashboard\n * under `matrx_dashboard_org`. Three origins, three memories, and a person who\n * had been working in one organization for weeks opened Studio and was\n * refused on every request until they picked again — a choice they had\n * already made. Browser storage is per-origin; a cookie issued at the apex\n * (`Domain=.aimatrx.com`) is the ONE browser-stored value every subdomain can\n * read, exactly how the platform already shares its login (see\n * `auth-cookie.ts`). Cookies also ignore ports, so localhost:3000 and\n * localhost:3101 share it in development.\n *\n * WHAT IT IS, AND IS NOT:\n * - It is the FIRST rung of the canonical resolution order (stored selection\n * → sole membership → make the user pick; a saved default is display-only;\n * ruling: common-docs/projects/no-db-assigned-org/PLAN.md row EX-T05). A\n * consumer still validates the stored id against live membership and\n * drops it when the membership is gone — this module stores, it never\n * decides.\n * - It is IDENTITY-KEYED: the value carries the user id it was written for,\n * and `read(userId)` answers null for anybody else. A second person\n * signing in on the same browser must never inherit the first person's\n * workspace (the same rule the sync engine applies to every persisted\n * slice). Sign-out calls `clear()` on top of that.\n * - It is NOT a security boundary. The server admits a request only when\n * the `X-Organization-Id` it carries is a verified membership of the\n * bearer; this cookie only remembers which of those the person chose.\n * - It is NOT httpOnly — hosts read and write it from the browser. Nothing\n * secret is in it.\n *\n * The Domain attribute is set ONLY on a real apex host (the same rule and the\n * same reason as the auth cookie: a browser silently rejects a Set-Cookie\n * whose Domain does not cover the current host). Studio runs on TWO apexes\n * (workflows.aimatrx.com and studio.app.matrxserver.com), so this takes a\n * list; the first apex that covers the host wins.\n */\n\nimport { parseCookieHeader, type AuthCookieValue } from \"./auth-cookie\";\nimport { isUuidShape } from \"@ai-matrx/kit/uuid\";\n\nexport const DEFAULT_ACTIVE_ORG_COOKIE_NAME = \"matrx-active-org\";\n\n/** One year — the same horizon the platform's other preference cookies use. */\nexport const DEFAULT_ACTIVE_ORG_COOKIE_MAX_AGE = 60 * 60 * 24 * 365;\n\nexport interface ActiveOrgCookieOptions {\n name: string;\n domain?: string;\n}\n\n/** The stored fact: WHO chose WHICH organization. */\nexport interface ActiveOrgSelection {\n userId: string;\n organizationId: string;\n}\n\nexport interface CreateActiveOrgCookieArgs {\n /**\n * The apex domains one selection must span, e.g.\n * `[\"aimatrx.com\", \"matrxserver.com\"]`. Order matters only when two apexes\n * could cover one host, which they never should.\n */\n apexDomains: readonly string[];\n /** Override only for a second, unrelated deployment — never per-app. */\n cookieName?: string;\n /** Lifetime in seconds. Defaults to one year. */\n maxAgeSeconds?: number;\n}\n\nexport interface ActiveOrgCookie {\n cookieName: string;\n /**\n * Cookie options for the host serving the current request.\n * @param host `Host` header or `window.location.hostname` (port tolerated).\n */\n optionsForHost(host: string | null | undefined): ActiveOrgCookieOptions;\n /**\n * The organization `userId` last chose, from a raw `Cookie` request header\n * (SSR) — or null when nothing is stored, the value is malformed, or it\n * belongs to a different person.\n */\n readFromCookieHeader(\n header: string | null | undefined,\n userId: string | null | undefined,\n ): string | null;\n /** Browser read of the same fact from `document.cookie`. SSR-safe (null). */\n read(userId: string | null | undefined): string | null;\n /**\n * Record `userId`'s choice in the browser at the scope `optionsForHost`\n * decides for this host. A previous host-only copy is expired first so the\n * jar never holds two same-name cookies at two scopes (whichever the\n * browser sent first would win — see `auth-cookie.ts` on split jars).\n */\n write(selection: ActiveOrgSelection): void;\n /**\n * Forget the selection in the browser — at EVERY scope this host could have\n * issued it (domain-wide and host-only), so sign-out cannot leave a copy\n * behind for the next person.\n */\n clear(): void;\n /**\n * A `Set-Cookie` header value recording `selection` for `host` (null →\n * an expiring cookie). For servers that want to write it; browsers use\n * `write`.\n */\n serialize(\n host: string | null | undefined,\n selection: ActiveOrgSelection | null,\n secure?: boolean,\n ): string;\n}\n\n/** `<userId>:<organizationId>` — two UUIDs, one separator. */\nexport function encodeActiveOrgSelection(selection: ActiveOrgSelection): string {\n if (!isUuidShape(selection.userId) || !isUuidShape(selection.organizationId)) {\n throw new Error(\n \"encodeActiveOrgSelection: userId and organizationId must both be UUIDs.\",\n );\n }\n return `${selection.userId.toLowerCase()}:${selection.organizationId.toLowerCase()}`;\n}\n\n/** Inverse of {@link encodeActiveOrgSelection}. Null for anything malformed. */\nexport function decodeActiveOrgSelection(\n raw: string | null | undefined,\n): ActiveOrgSelection | null {\n if (!raw) return null;\n const parts = raw.split(\":\");\n if (parts.length !== 2) return null;\n const [userId, organizationId] = parts as [string, string];\n if (!isUuidShape(userId) || !isUuidShape(organizationId)) return null;\n return {\n userId: userId.toLowerCase(),\n organizationId: organizationId.toLowerCase(),\n };\n}\n\nfunction selectionFor(\n cookies: readonly AuthCookieValue[],\n cookieName: string,\n userId: string | null | undefined,\n): string | null {\n if (!userId) return null;\n const wanted = userId.toLowerCase();\n // Duplicates are possible (two Domain scopes) and arrive in browser order;\n // the first copy that belongs to THIS person wins, and a copy belonging to\n // anybody else is simply not an answer.\n for (const cookie of cookies) {\n if (cookie.name !== cookieName) continue;\n const decoded = decodeActiveOrgSelection(cookie.value);\n if (decoded && decoded.userId === wanted) return decoded.organizationId;\n }\n return null;\n}\n\nfunction attributes(\n options: ActiveOrgCookieOptions,\n maxAge: number,\n secure: boolean,\n): string {\n const parts = [`Path=/`, `Max-Age=${maxAge}`, `SameSite=Lax`];\n if (options.domain) parts.push(`Domain=${options.domain}`);\n if (secure) parts.push(\"Secure\");\n return parts.join(\"; \");\n}\n\nfunction hasDocument(): boolean {\n return typeof document !== \"undefined\" && typeof document.cookie === \"string\";\n}\n\nexport function createActiveOrgCookie(\n args: CreateActiveOrgCookieArgs,\n): ActiveOrgCookie {\n const cookieName = args.cookieName ?? DEFAULT_ACTIVE_ORG_COOKIE_NAME;\n const maxAge = args.maxAgeSeconds ?? DEFAULT_ACTIVE_ORG_COOKIE_MAX_AGE;\n const apexes = args.apexDomains.map((apex) => apex.toLowerCase());\n\n const optionsForHost = (\n host: string | null | undefined,\n ): ActiveOrgCookieOptions => {\n const hostname = (host ?? \"\").split(\":\")[0]?.toLowerCase() ?? \"\";\n const apex = apexes.find(\n (candidate) => hostname === candidate || hostname.endsWith(`.${candidate}`),\n );\n return apex ? { name: cookieName, domain: `.${apex}` } : { name: cookieName };\n };\n\n const serialize = (\n host: string | null | undefined,\n selection: ActiveOrgSelection | null,\n secure = false,\n ): string => {\n const options = optionsForHost(host);\n if (!selection) {\n return `${cookieName}=; ${attributes(options, 0, secure)}`;\n }\n return `${cookieName}=${encodeActiveOrgSelection(selection)}; ${attributes(options, maxAge, secure)}`;\n };\n\n const browserHost = (): string | null =>\n typeof window !== \"undefined\" ? window.location.hostname : null;\n const browserSecure = (): boolean =>\n typeof window !== \"undefined\" && window.location.protocol === \"https:\";\n\n const expireHostOnly = (secure: boolean): void => {\n document.cookie = `${cookieName}=; ${attributes({ name: cookieName }, 0, secure)}`;\n };\n\n return {\n cookieName,\n optionsForHost,\n serialize,\n readFromCookieHeader: (header, userId) =>\n selectionFor(parseCookieHeader(header), cookieName, userId),\n read: (userId) => {\n if (!hasDocument()) return null;\n return selectionFor(parseCookieHeader(document.cookie), cookieName, userId);\n },\n write: (selection) => {\n if (!hasDocument()) return;\n const host = browserHost();\n const secure = browserSecure();\n // Writing domain-wide on an apex host: retire any host-only copy first\n // so exactly one cookie under this name exists afterwards.\n if (optionsForHost(host).domain) expireHostOnly(secure);\n document.cookie = serialize(host, selection, secure);\n },\n clear: () => {\n if (!hasDocument()) return;\n const host = browserHost();\n const secure = browserSecure();\n expireHostOnly(secure);\n if (optionsForHost(host).domain) {\n document.cookie = serialize(host, null, secure);\n }\n },\n };\n}\n","/**\n * Realtime channel hygiene — RE-EXPORT ONLY. The canonical home is\n * `@ai-matrx/realtime`.\n *\n * Channel NAMING belongs to the realtime package (its work order, R1): it owns\n * the channel-naming registry, and `uniqueChannelTopic` is the React-19\n * double-invoked-effect collision guard that registry hands out. This package\n * kept the only copy while `@ai-matrx/realtime` was unpublished; that copy is\n * now DELETED and this module forwards, so the two can never drift and the\n * `#`-suffixed instance topics a Matrx app opens all come from one counter.\n *\n * Why forwarding matters and a second copy would not do: the old\n * implementation kept its sequence in a module-level `let`. With unsplit dual\n * ESM/CJS output a module can be instantiated twice in one process, so two\n * counters both starting at 1 hand out the same \"unique\" topic twice — exactly\n * the collision the function exists to prevent. The realtime package keeps the\n * counter in a `globalThis` slot (`Symbol.for`) and proves it across module\n * graphs in its packed-tarball canary.\n *\n * `@ai-matrx/realtime` is the deeper layer (zero runtime dependencies; it does\n * not and must not depend on `@ai-matrx/data`), so this direction keeps the\n * sibling graph acyclic — `node scripts/check_ts_sibling_graph.mjs`.\n *\n * New realtime work should not reach for this at all: declare a channel\n * namespace with `defineChannelNamespace` and let the manager assign the\n * instance topic. This export exists for the call sites that have not yet\n * migrated off hand-rolled `.channel(` blocks.\n */\n\nexport { uniqueChannelTopic } from \"@ai-matrx/realtime\";\n","/**\n * OAuth-aware transport for a Supabase auth-js client.\n *\n * Supabase's ordinary GoTrue refresh endpoint is `/auth/v1/token`, while a\n * session minted for a registered OAuth client must refresh at\n * `/auth/v1/oauth/token` and include that client id. auth-js owns session\n * storage, locking, rotation and notifications; this module changes only the\n * one outbound refresh request after proving that its refresh token belongs to\n * an allowlisted OAuth client. It never calls `auth.getSession()`.\n */\n\nexport interface OAuthRefreshStorage {\n getItem(key: string): string | null | Promise<string | null>;\n}\n\nexport interface CreateOAuthRefreshFetchArgs {\n /** The exact Supabase project origin, e.g. `https://db.matrxserver.com`. */\n supabaseUrl: string;\n /** The same auth storage auth-js uses. */\n storage: OAuthRefreshStorage;\n /** The auth-js storage key containing the persisted session JSON. */\n storageKey: string;\n /** Public OAuth client ids this host is intentionally allowed to refresh. */\n oauthClientIds: readonly string[];\n /** Injectable only for tests and non-browser hosts. */\n fetch?: typeof globalThis.fetch;\n}\n\ninterface StoredSession {\n access_token?: unknown;\n refresh_token?: unknown;\n user?: unknown;\n}\n\ninterface JwtClaims {\n sub?: unknown;\n client_id?: unknown;\n exp?: unknown;\n}\n\nfunction object(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction text(value: unknown): string | null {\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\n/** Decode routing metadata only. The server remains the authentication authority. */\nexport function decodeOAuthRefreshClaims(token: string): JwtClaims | null {\n const payload = token.split(\".\")[1];\n if (!payload) return null;\n try {\n const normalized = payload.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized + \"=\".repeat((4 - (normalized.length % 4)) % 4);\n const json = typeof atob === \"function\"\n ? atob(padded)\n : Buffer.from(padded, \"base64\").toString(\"utf8\");\n return object(JSON.parse(json)) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction isOrdinaryRefreshRequest(input: RequestInfo | URL, init: RequestInit | undefined, origin: string): boolean {\n const request = input instanceof Request ? input : null;\n const url = new URL(request?.url ?? String(input), origin);\n const method = (init?.method ?? request?.method ?? \"GET\").toUpperCase();\n return method === \"POST\" &&\n url.origin === origin &&\n url.pathname === \"/auth/v1/token\" &&\n url.searchParams.get(\"grant_type\") === \"refresh_token\";\n}\n\nasync function refreshTokenFrom(input: RequestInfo | URL, init: RequestInit | undefined): Promise<string | null> {\n let body = init?.body;\n // auth-js currently supplies init.body, but accepting a Request keeps this a\n // transparent Fetch transport for callers that put the body on the Request.\n // clone() is essential: consuming the original body would break normal fetch.\n if (body === undefined && input instanceof Request) body = await input.clone().text();\n if (body instanceof URLSearchParams) return body.get(\"refresh_token\");\n if (typeof body !== \"string\") return null;\n try {\n return text(object(JSON.parse(body))?.refresh_token);\n } catch {\n return new URLSearchParams(body).get(\"refresh_token\");\n }\n}\n\nfunction rewrittenInit(input: RequestInfo | URL, init: RequestInit | undefined, headers: Headers, body: URLSearchParams): RequestInit {\n const request = input instanceof Request ? input : null;\n const copied: RequestInit = {\n // init takes precedence, just as native fetch does. Copying Request fields\n // preserves the public Fetch contract after replacing its body.\n method: \"POST\",\n headers,\n body,\n };\n const inherited = {\n credentials: init?.credentials ?? request?.credentials,\n cache: init?.cache ?? request?.cache,\n redirect: init?.redirect ?? request?.redirect,\n referrer: init?.referrer ?? request?.referrer,\n referrerPolicy: init?.referrerPolicy ?? request?.referrerPolicy,\n integrity: init?.integrity ?? request?.integrity,\n keepalive: init?.keepalive ?? request?.keepalive,\n signal: init?.signal ?? request?.signal,\n };\n for (const [key, value] of Object.entries(inherited)) {\n if (value !== undefined) Object.assign(copied, { [key]: value });\n }\n return copied;\n}\n\nasync function storedSession(storage: OAuthRefreshStorage, key: string): Promise<StoredSession | null> {\n const raw = await storage.getItem(key);\n if (!raw) return null;\n try {\n return object(JSON.parse(raw)) as StoredSession | null;\n } catch {\n return null;\n }\n}\n\nfunction sameSubject(previousAccessToken: string, refreshedAccessToken: string, clientId: string): boolean {\n const previous = decodeOAuthRefreshClaims(previousAccessToken);\n const refreshed = decodeOAuthRefreshClaims(refreshedAccessToken);\n return text(previous?.sub) !== null && previous?.sub === refreshed?.sub && previous?.client_id === clientId && refreshed?.client_id === clientId;\n}\n\nfunction retryableRefusal(message: string): Response {\n // auth-js treats 5xx responses as retryable and keeps its persisted session.\n // A 400 would make an expired client clear the identity we intentionally did\n // not send to GoTrue (unknown client or storage mismatch).\n return new Response(JSON.stringify({ error: \"temporarily_unavailable\", error_description: message }), {\n status: 503,\n headers: { \"content-type\": \"application/json\", \"retry-after\": \"1\" },\n });\n}\n\nasync function normalizeOAuthResponse(\n response: Response,\n session: StoredSession,\n clientId: string,\n): Promise<Response> {\n if (!response.ok) return response;\n const previousAccessToken = text(session.access_token);\n const previousUser = session.user;\n const previousSubject = previousAccessToken ? text(decodeOAuthRefreshClaims(previousAccessToken)?.sub) : null;\n if (!previousAccessToken || !previousSubject || text(object(previousUser)?.id) !== previousSubject) {\n return retryableRefusal(\"Stored OAuth identity does not match its credential. Restore the account connection.\");\n }\n let payload: Record<string, unknown> | null = null;\n try {\n payload = object(await response.clone().json());\n } catch {\n return retryableRefusal(\"OAuth refresh returned an invalid response.\");\n }\n const refreshedAccessToken = text(payload?.access_token);\n if (!payload || !refreshedAccessToken || !sameSubject(previousAccessToken, refreshedAccessToken, clientId)) {\n return retryableRefusal(\"OAuth refresh returned a credential for an unexpected identity or client.\");\n }\n if (payload.user !== undefined && text(object(payload.user)?.id) !== previousSubject) {\n return retryableRefusal(\"OAuth refresh returned a user that does not match its credential.\");\n }\n if (payload.user === undefined) payload.user = previousUser;\n if (text(payload.refresh_token) === null) payload.refresh_token = session.refresh_token;\n const headers = new Headers(response.headers);\n headers.set(\"content-type\", \"application/json\");\n return new Response(JSON.stringify(payload), {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n\nasync function replacementAfterRejectedRefresh(\n response: Response,\n storage: OAuthRefreshStorage,\n storageKey: string,\n previous: StoredSession,\n clientId: string,\n): Promise<Response> {\n if (response.status !== 400 && response.status !== 401) return response;\n const replacement = await storedSession(storage, storageKey);\n const previousRefresh = text(previous.refresh_token);\n const replacementRefresh = text(replacement?.refresh_token);\n const previousAccess = text(previous.access_token);\n const replacementAccess = text(replacement?.access_token);\n if (!replacement || !previousRefresh || !replacementRefresh || replacementRefresh === previousRefresh ||\n !previousAccess || !replacementAccess || !sameSubject(previousAccess, replacementAccess, clientId) ||\n replacement.user === undefined) return response;\n return new Response(JSON.stringify(replacement), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n}\n\n/**\n * Returns a fetch implementation suitable for `createClient(..., { global:\n * { fetch } })`. Normal sessions and unrelated requests pass through exactly.\n */\nexport function createOAuthRefreshFetch(args: CreateOAuthRefreshFetchArgs): typeof globalThis.fetch {\n const origin = new URL(args.supabaseUrl).origin;\n const upstream = args.fetch ?? globalThis.fetch;\n const allowed = new Set(args.oauthClientIds);\n\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n if (!isOrdinaryRefreshRequest(input, init, origin)) return upstream(input, init);\n const refreshToken = await refreshTokenFrom(input, init);\n const session = await storedSession(args.storage, args.storageKey);\n const storedRefreshToken = text(session?.refresh_token);\n const accessToken = text(session?.access_token);\n const clientId = accessToken ? text(decodeOAuthRefreshClaims(accessToken)?.client_id) : null;\n if (!session || !clientId) {\n return upstream(input, init);\n }\n if (!allowed.has(clientId)) return retryableRefusal(\"This OAuth client is not allowed to refresh in this host.\");\n // This is an OAuth-owned session, but the caller did not send the refresh\n // token that storage associates with it. Forwarding that unknown token to\n // GoTrue's ordinary endpoint could refresh a different actor; auth-js will\n // re-read its stored session after the typed refusal instead.\n if (!refreshToken || refreshToken !== storedRefreshToken) {\n return retryableRefusal(\"OAuth refresh token no longer matches the stored session; resolve the session again.\");\n }\n\n const request = input instanceof Request ? input : null;\n const headers = new Headers(init?.headers ?? request?.headers);\n headers.set(\"content-type\", \"application/x-www-form-urlencoded\");\n const body = new URLSearchParams({ grant_type: \"refresh_token\", refresh_token: refreshToken, client_id: clientId });\n const response = await upstream(`${origin}/auth/v1/oauth/token`, rewrittenInit(input, init, headers, body));\n const adopted = await replacementAfterRejectedRefresh(response, args.storage, args.storageKey, session, clientId);\n const responseSession = adopted === response ? session : (await storedSession(args.storage, args.storageKey)) ?? session;\n return normalizeOAuthResponse(adopted, responseSession, clientId);\n };\n}\n","// @ai-matrx/data/db — write-failure: a failed write is said in words, with a remedy.\n// Ported verbatim from matrx-frontend `lib/errors/writeFailure.ts` (which now re-exports this\n// module, so `WriteRefusedError` is ONE class everywhere and every `instanceof` keeps working).\n//\n//\n// A FAILED WRITE IS SAID IN WORDS, WITH A REMEDY — NEVER AS METHOD, PATH AND STATUS.\n//\n// VERIFIER-21 injected a 500 on a schedule's Pause and the person read:\n// PATCH /scheduler/tasks/2be9cc7c… 500 — \"injected failure\"\n// That is a developer's log line on a customer's screen. The rule (a screen never lies, and\n// nothing fails silently): a failure says what did not happen, why in plain words, and what to\n// do — \"Could not pause this schedule. The server refused the request. Try again or open the\n// schedule's activity.\" No status code, method or path on screen (VERIFIER-23 #6 caught the toast\n// still reading \"(500)\") — the technical line is kept on the error (`technical`) for diagnostics.\n//\n// Two pieces, one per side of the wire:\n// - `WriteRefusedError` — what a hand-rolled fetch client throws for a non-2xx answer. Its\n// `message` is already a sentence, so a caller that renders `err.message` is honest too.\n// - `describeWriteFailure(err, { action, remedy })` — the words for ANY error (this one,\n// `BackendApiError`, a network failure), and `toastWriteFailure` puts them on screen.\n\n/** A non-2xx answer from a server, with the words already chosen. */\nexport class WriteRefusedError extends Error {\n readonly status: number;\n /** What the server said for a person, when it said something a person can read. */\n readonly serverMessage: string | null;\n /** The developer line (method, path, status, body) — for diagnostics, never for the screen. */\n readonly technical: string;\n\n constructor(args: { status: number; serverMessage?: string | null; technical: string }) {\n super(refusalSentence(args.status, args.serverMessage ?? null));\n this.name = \"WriteRefusedError\";\n this.status = args.status;\n this.serverMessage = args.serverMessage ?? null;\n this.technical = args.technical;\n }\n}\n\n/** Pull a human sentence out of a FastAPI-style error body, or null when there is none. */\nexport function serverMessageFromBody(body: unknown): string | null {\n if (!body || typeof body !== \"object\") return null;\n const b = body as Record<string, unknown>;\n const detail = b.detail;\n const pick = (v: unknown): string | null => (typeof v === \"string\" && v.trim() !== \"\" ? v.trim() : null);\n if (detail && typeof detail === \"object\" && !Array.isArray(detail)) {\n const d = detail as Record<string, unknown>;\n return pick(d.user_message) ?? pick(d.message);\n }\n return pick(b.user_message) ?? pick(detail) ?? pick(b.message);\n}\n\nconst LOOKS_TECHNICAL =\n /(^|\\s)(GET|POST|PUT|PATCH|DELETE)\\s+\\/|https?:\\/\\/|\\bHTTP \\d{3}\\b|Traceback|Exception\\b|permission denied for|violates|row-level security|\\brelation \"|\\bcolumn \"|\\bfunction .* does not exist|\\bPGRST\\d+|\\bJWT\\b|duplicate key|syntax error|invalid input syntax|JSON object requested|rows returned|\\bnull value in column|\\bundefined\\b|\\bat [\\w.]+ \\(/i;\n\n/**\n * THE STORE'S OWN WORDS, WHEN IT SAID SOME (lane HANDOVER, 2026-09-27). A door that refuses raises a\n * sentence for a person — `You can see this record, but \"Allergies\" is not yours to change.` — or the\n * same sentence behind its own name (`cat_write: this category is not yours to change.`). Postgres's\n * native refusals (`permission denied for table …`, `new row violates …`) are never that. This hands\n * back the door's sentence, capitalised and ended, or null when the text is not a person's words.\n * test@test.com's refused Allergies edit read \"Permission denied\" because the scopes mapper threw\n * the door's sentence away for a fixed string.\n */\nexport function personSentence(text: unknown): string | null {\n if (typeof text !== \"string\") return null;\n let said = text.trim();\n const named = /^[a-z][a-z0-9_]*[a-z0-9]: (.+)$/s.exec(said);\n if (named) said = (named[1] ?? \"\").trim().replace(/^[a-z]/, (c) => c.toUpperCase());\n if (said.length < 8 || LOOKS_TECHNICAL.test(said) || !/^[A-Z\"“']/.test(said) || !/\\s/.test(said)) return null;\n return /[.!?][\"”']?$/.test(said) ? said : `${said}.`;\n}\n\n/**\n * A PostgREST / Postgres refusal (a supabase-js `PostgrestError`, or a server action that passed one\n * through): `{ code, message, details, hint }`. Its `message` is the database's own line\n * (\"new row violates row-level security policy for table …\") — never words for a person.\n */\nfunction isPostgrestShaped(err: unknown): err is { code: string; message?: string } {\n if (!err || typeof err !== \"object\") return false;\n const code = (err as { code?: unknown }).code;\n return typeof code === \"string\" && /^(PGRST\\d{3}|[0-9A-Z]{5})$/.test(code) && !(\"status\" in err && typeof (err as { status?: unknown }).status === \"number\");\n}\n\n/** A `WriteRefusedError` (or subclass) after Redux Toolkit serialized it. */\nfunction isSerializedRefusal(err: unknown): err is { name: string; message: string } {\n if (!err || typeof err !== \"object\" || err instanceof Error) return false;\n const e = err as { name?: unknown; message?: unknown };\n if (typeof e.message !== \"string\" || e.message.trim() === \"\") return false;\n if (e.name === \"WriteRefusedError\" || e.name === \"WriteDidNotLandError\") return true;\n // A thunk that threw a plain `new Error(<the store's sentence>)` crosses `.unwrap()` as\n // `{ name: \"Error\", message }` (lane HANDOVER, 2026-09-27: a member's refused context value read\n // \"Failed to save\" while the store had said \"…is not yours to change.\"). Its words are a person's\n // sentence when they do not read as technical.\n return e.name === \"Error\" && !LOOKS_TECHNICAL.test(e.message);\n}\n\nfunction postgrestSentence(code: string): string {\n if (code === \"42501\" || code === \"PGRST301\" || code === \"PGRST302\") return \"You do not have permission to do this.\";\n if (code === \"PGRST303\" || code === \"PGRST300\") return \"Your sign-in has expired. Sign in again, then try again.\";\n if (code === \"PGRST116\") return \"It is no longer there — it may have been deleted.\";\n if (code === \"23505\") return \"Something with the same name or key already exists.\";\n if (code === \"23503\") return \"It refers to something that no longer exists.\";\n if (code === \"23514\" || code === \"23502\" || code === \"22P02\") return \"The database would not accept that value.\";\n if (code === \"57014\") return \"The database took too long to answer.\";\n if (code === \"40001\" || code === \"40P01\") return \"It changed while you were working. Reload to see the latest.\";\n return \"The database refused it.\";\n}\n\n/**\n * A direct Supabase write that matched no row answers WITHOUT an error (RLS filters the row out,\n * or it is gone), so the screen would say \"saved\" over nothing. Pass the `.select()` rows of an\n * update/upsert: zero rows is a refusal, said in words.\n */\nexport function assertWriteLanded<T>(rows: T[] | T | null | undefined, technical: string): void {\n const n = Array.isArray(rows) ? rows.length : rows == null ? 0 : 1;\n if (n > 0) return;\n throw new WriteRefusedError({\n status: 403,\n serverMessage: \"Nothing was saved: you may not have permission to change this, or it no longer exists.\",\n technical: `${technical} matched 0 rows`,\n });\n}\n\nfunction refusalSentence(status: number, serverMessage: string | null): string {\n const said = serverMessage && !LOOKS_TECHNICAL.test(serverMessage) ? serverMessage : null;\n if (status === 401) return \"Your sign-in has expired. Sign in again, then try again.\";\n if (status === 403) return said ?? \"You do not have permission to do this.\";\n if (status === 404) return said ?? \"It is no longer there — it may have been deleted.\";\n if (status === 409 || status === 412) return said ?? \"It changed while you were working. Reload to see the latest.\";\n // A 5xx body is the server's own failure text, not a sentence for a person.\n // No status code, method or path on screen — that is a developer's log line, kept on\n // `technical` for diagnostics only (GATES-TAIL, VERIFIER-23 #6: the toast still read \"(500)\").\n if (status >= 500) return \"The server refused the request.\";\n if (said) return `The server said: ${said.replace(/\\.?$/, \".\")}`;\n return \"The server did not accept it.\";\n}\n\nexport interface WriteFailureWords {\n /** \"Could not pause this schedule.\" */\n title: string;\n /** Why, in words, then the remedy. */\n description: string;\n}\n\n/**\n * The words for a failed write. `action` completes \"Could not …\" (\"pause this schedule\");\n * `remedy` is what to do next (\"Try again or open the schedule's activity.\").\n */\nexport function describeWriteFailure(\n err: unknown,\n { action, remedy = \"Try again.\" }: { action: string; remedy?: string },\n): WriteFailureWords {\n const title = `Could not ${action}.`;\n let why: string;\n if (err instanceof WriteRefusedError) {\n why = err.message;\n } else if (isSerializedRefusal(err)) {\n // A refusal that crossed a Redux thunk: `.unwrap()` rejects with a plain\n // `{ name, message }`, and its words are already a sentence for a person.\n why = /[.!?][\"”']?$/.test(err.message.trim()) ? err.message.trim() : `${err.message.trim()}.`;\n } else if (isPostgrestShaped(err)) {\n // A door's own sentence beats the code's generic one; Postgres's native prose never shows.\n why = personSentence(err.message) ?? postgrestSentence(err.code);\n } else if (err && typeof err === \"object\" && \"status\" in err && typeof (err as { status: unknown }).status === \"number\") {\n const e = err as { status: number; userMessage?: unknown };\n why = refusalSentence(e.status, typeof e.userMessage === \"string\" ? e.userMessage : null);\n } else if (err instanceof TypeError || (err instanceof Error && /Failed to fetch|NetworkError|Load failed/i.test(err.message))) {\n why = \"The server could not be reached. Check your connection.\";\n } else if (err instanceof Error && err.message && !LOOKS_TECHNICAL.test(err.message)) {\n why = err.message.replace(/\\.?$/, \".\");\n } else if (typeof err === \"string\" && err.trim() && !LOOKS_TECHNICAL.test(err)) {\n // A server action's `{ success: false, error: \"<text>\" }` — words only when they read as words.\n why = err.trim().replace(/\\.?$/, \".\");\n } else {\n why = \"Something went wrong on our side.\";\n }\n return { title, description: `${why} ${remedy}`.trim() };\n}\n","/**\n * @ai-matrx/data/db — writeOne: THE single-record write that PROVES it landed.\n *\n * Ported verbatim from matrx-frontend `utils/supabase/writeOne.ts` (which now\n * re-exports this module, so `WriteDidNotLandError` is ONE class everywhere).\n *\n * THE CLASS (flashcards, 2026-09-25). PostgREST answers an `.update()` or\n * `.delete()` that row-level security filters to zero rows with\n * `{ data: [], error: null }` — status 200, no error. A caller that judges\n * success by `error == null` therefore tells the person \"Card deleted\" while\n * nothing happened. The same is true when the row is already gone. Nothing\n * fails silently: zero rows written is a refusal, and it is said in words.\n *\n * USE IT for every write aimed at ONE record (`.eq(\"id\", …)`):\n *\n * await writeOne(\n * supabase.from(\"notes\").update({ label }).eq(\"id\", noteId).select(\"id\"),\n * { action: \"rename\", noun: \"note\" },\n * );\n *\n * - The builder MUST end in `.select(...)` — that is what makes PostgREST\n * return the rows it actually wrote. Select only what you need (`\"id\"` is\n * fine); the first written row is returned.\n * - A database error is thrown AS IS (the PostgrestError), so existing error\n * handling and `describeWriteFailure` keep working.\n * - Zero rows throws `WriteDidNotLandError` — a `WriteRefusedError` whose\n * message is already a sentence for a person:\n * \"Nothing was deleted: this card no longer exists, or your access does not\n * allow deleting it.\"\n * - `tryWriteOne` is the same check for result-style services that never\n * throw: it returns `{ row, error }`.\n *\n * TWO MODES for writes that carry an extra condition (coordinator ruling,\n * 2026-09-25):\n *\n * - IDEMPOTENT (`alreadyDone`): an archive filtered `.is(\"deleted_at\", null)`\n * writes zero rows when the record is ALREADY archived — and also when RLS\n * refused. On zero rows the primitive re-reads the row by id: visible and\n * already in the target state → success (the re-read row is returned);\n * invisible or still live → the plain refusal.\n *\n * - COMPARE-AND-SET (`compareAndSet: true`): `.eq(\"status\", \"pending\")`,\n * `.is(\"answered_at\", null)`… zero rows means someone else got there first.\n * That is still told to the person: \"This answer was already handled —\n * refresh to see the latest.\" (`WriteDidNotLandError.reason === \"taken\"`).\n *\n * Optimistic-concurrency edits with a `version` token use `guardedUpdate`\n * from `@ai-matrx/data/db`, which classifies zero rows as conflict or gone.\n * A bulk `.in(...)` write is not a single-record write.\n *\n * Guard: `pnpm check:single-record-writes` (scripts/check-single-record-writes.ts)\n * fails on a new single-record update/delete that judges success by error alone.\n */\nimport { PostgrestError } from \"@supabase/supabase-js\";\nimport { WriteRefusedError } from \"./write-failure\";\n\n/** The verb the person asked for. Drives the refusal sentence. */\nexport type WriteOneAction =\n | \"save\"\n | \"update\"\n | \"rename\"\n | \"move\"\n | \"delete\"\n | \"remove\"\n | \"archive\"\n | \"restore\"\n | \"publish\"\n | \"unpublish\"\n | \"change\";\n\nexport interface WriteOneOptions<Row = unknown> {\n /** What the person asked for: \"delete\", \"save\", \"archive\"… */\n action: WriteOneAction;\n /** What it is, in the person's words: \"card\", \"note\", \"saved view\". */\n noun: string;\n /**\n * Idempotent mode. On zero rows, `reread()` the record by id (end it in\n * `.maybeSingle()`); when it is visible and `isDone(row)`, the write is a\n * success and that row is returned. Otherwise the plain refusal.\n */\n alreadyDone?: {\n reread: () => PromiseLike<{ data: Row | null; error: unknown }>;\n isDone: (row: Row) => boolean;\n };\n /** Compare-and-set mode: zero rows means someone else got there first. */\n compareAndSet?: boolean;\n}\n\n/** Why nothing was written: refused/gone, or another writer took it first. */\nexport type WriteDidNotLandReason = \"refused\" | \"taken\";\n\nconst PAST: Record<WriteOneAction, string> = {\n save: \"saved\",\n update: \"updated\",\n rename: \"renamed\",\n move: \"moved\",\n delete: \"deleted\",\n remove: \"removed\",\n archive: \"archived\",\n restore: \"restored\",\n publish: \"published\",\n unpublish: \"unpublished\",\n change: \"changed\",\n};\n\nconst GERUND: Record<WriteOneAction, string> = {\n save: \"saving\",\n update: \"updating\",\n rename: \"renaming\",\n move: \"moving\",\n delete: \"deleting\",\n remove: \"removing\",\n archive: \"archiving\",\n restore: \"restoring\",\n publish: \"publishing\",\n unpublish: \"unpublishing\",\n change: \"changing\",\n};\n\n/** Zero rows were written: the record is gone, or the person may not change it. */\nexport class WriteDidNotLandError extends WriteRefusedError {\n readonly action: WriteOneAction;\n readonly noun: string;\n readonly reason: WriteDidNotLandReason;\n\n constructor(\n { action, noun }: Pick<WriteOneOptions, \"action\" | \"noun\">,\n reason: WriteDidNotLandReason = \"refused\",\n ) {\n super({\n status: reason === \"taken\" ? 409 : 403,\n serverMessage:\n reason === \"taken\"\n ? `This ${noun} was already handled — refresh to see the latest.`\n : `Nothing was ${PAST[action]}: this ${noun} no longer exists, or your access does not allow ${GERUND[action]} it.`,\n technical:\n reason === \"taken\"\n ? `writeOne(${action} ${noun}) compare-and-set matched 0 rows — another writer got there first`\n : `writeOne(${action} ${noun}) matched 0 rows — RLS refused or the row is gone`,\n });\n this.name = \"WriteDidNotLandError\";\n this.action = action;\n this.noun = noun;\n this.reason = reason;\n }\n}\n\n/** Structural shape of an awaited supabase-js builder that ended in `.select()`. */\ninterface RowsResponse<Row> {\n data: Row[] | null;\n error: unknown;\n}\n\n/**\n * Run a single-record write and prove it landed. Returns the first written\n * row; throws the database error as is, or `WriteDidNotLandError` on zero rows.\n */\nexport async function writeOne<Row>(\n write: PromiseLike<RowsResponse<Row>>,\n options: WriteOneOptions<Row>,\n): Promise<Row> {\n const { data, error } = await write;\n if (error) throw error;\n if (Array.isArray(data) && data.length > 0) return data[0] as Row;\n\n if (options.alreadyDone) {\n const current = await options.alreadyDone.reread();\n if (current.error) throw current.error;\n const row = Array.isArray(current.data) ? (current.data[0] as Row | undefined) : current.data;\n if (row && options.alreadyDone.isDone(row)) return row;\n }\n throw new WriteDidNotLandError(options, options.compareAndSet ? \"taken\" : \"refused\");\n}\n\nexport type TryWriteOneResult<Row> =\n | { row: Row; error: null }\n | { row: null; error: Error };\n\n/** `writeOne` for services that return results instead of throwing. */\nexport async function tryWriteOne<Row>(\n write: PromiseLike<RowsResponse<Row>>,\n options: WriteOneOptions<Row>,\n): Promise<TryWriteOneResult<Row>> {\n try {\n return { row: await writeOne(write, options), error: null };\n } catch (caught) {\n if (caught instanceof Error) return { row: null, error: caught };\n // PostgREST responses can be plain objects. Keep their structured refusal\n // intact instead of turning code/details/hint into an opaque Error cause.\n if (caught && typeof caught === \"object\" && \"code\" in caught &&\n typeof caught.code === \"string\" && \"message\" in caught &&\n typeof caught.message === \"string\") {\n return { row: null, error: new PostgrestError({\n code: caught.code,\n message: caught.message,\n details: \"details\" in caught && typeof caught.details === \"string\" ? caught.details : \"\",\n hint: \"hint\" in caught && typeof caught.hint === \"string\" ? caught.hint : \"\",\n }) };\n }\n const message =\n caught && typeof caught === \"object\" && \"message\" in caught && typeof caught.message === \"string\"\n ? caught.message\n : String(caught);\n const error = new Error(message);\n (error as Error & { cause?: unknown }).cause = caught;\n return { row: null, error };\n }\n}\n\n/**\n * The HTTP status a route handler answers with for a failed write: the\n * refusal's own status (403 refused / 409 taken) for `WriteDidNotLandError`,\n * Database authorization/not-found/conflict codes retain their HTTP meaning;\n * unknown failures remain 500. Server twin of the client's toast path.\n */\nexport function writeFailureStatus(error: unknown): number {\n if (error instanceof WriteDidNotLandError) return error.status;\n if (error && typeof error === \"object\" && \"code\" in error) {\n if (error.code === \"42501\") return 403;\n if (error.code === \"PGRST301\" || error.code === \"PGRST302\" || error.code === \"PGRST303\") return 401;\n if (error.code === \"PGRST116\") return 404;\n if (error.code === \"23505\" || error.code === \"40001\" || error.code === \"40P01\") return 409;\n }\n return 500;\n}\n\n/**\n * Several single-record writes where some did not land. The message names how\n * many of how many failed and why (the first reason); `failures` keeps each\n * record id with its own sentence so a screen can mark exactly those rows.\n */\nexport class BulkWriteError extends Error {\n readonly failures: { id: string; message: string }[];\n readonly attempted: number;\n\n constructor(failures: { id: string; message: string }[], attempted: number) {\n super(\n `${failures.length} of ${attempted} ${attempted === 1 ? \"change was\" : \"changes were\"} not saved. ${failures[0]?.message ?? \"\"}`.trim(),\n );\n this.name = \"BulkWriteError\";\n this.failures = failures;\n this.attempted = attempted;\n }\n}\n\nexport type WriteOneRowResult<Row> =\n | { data: Row; error: null }\n | { data: null; error: PostgrestError };\n\n/**\n * The drop-in for `.update(…).eq(\"id\", …).select(…).single()` (and the\n * `.maybeSingle()` twin whose caller never looks at `data`): same\n * `{ data, error }` shape, same `PostgrestError` type, same `PGRST116` code on\n * zero rows — but the message is the person's sentence (\"Nothing was updated:\n * this deal no longer exists, or your access does not allow updating it.\")\n * instead of PostgREST's \"JSON object requested, multiple (or no) rows\n * returned\", which every screen rendered as a vague failure.\n *\n * const { data, error } = await writeOneRow(\n * db.from(\"deal\").update(patch).eq(\"id\", id).select(\"*\"),\n * { action: \"update\", noun: \"deal\" },\n * );\n *\n * Guard: `pnpm check:single-record-writes` flags the bare `.select().single()`\n * shape on a write.\n */\nexport async function writeOneRow<Row>(\n write: PromiseLike<RowsResponse<Row>>,\n options: Pick<WriteOneOptions, \"action\" | \"noun\" | \"compareAndSet\">,\n): Promise<WriteOneRowResult<Row>> {\n const { data, error } = await write;\n if (error) {\n if (error instanceof PostgrestError) return { data: null, error };\n const e = error as { message?: unknown; details?: unknown; hint?: unknown; code?: unknown };\n return {\n data: null,\n error: new PostgrestError({\n message: typeof e.message === \"string\" ? e.message : String(error),\n details: typeof e.details === \"string\" ? e.details : \"\",\n hint: typeof e.hint === \"string\" ? e.hint : \"\",\n code: typeof e.code === \"string\" ? e.code : \"\",\n }),\n };\n }\n const rows = Array.isArray(data) ? data : [];\n if (rows.length === 1) return { data: rows[0] as Row, error: null };\n const refusal = new WriteDidNotLandError(options, options.compareAndSet ? \"taken\" : \"refused\");\n return {\n data: null,\n error: new PostgrestError({\n message:\n rows.length === 0\n ? refusal.serverMessage ?? refusal.message\n : `${rows.length} records matched where one ${options.noun} was expected, and all of them were changed. Reload to see the result.`,\n details: rows.length === 0 ? refusal.technical : `writeOneRow(${options.action} ${options.noun}) matched ${rows.length} rows`,\n hint: \"\",\n code: \"PGRST116\",\n }),\n };\n}\n","/**\n * @ai-matrx/data/db — record-unavailable: THE one shape for \"a single-record\n * read came back with zero rows\".\n *\n * Ported from matrx-frontend `lib/records/recordUnavailable.ts`, which keeps\n * its capture helpers (`recordUnavailable`, `resolveRecordUnavailableCapture`)\n * and re-exports this class — so `RecordUnavailableError` is ONE class across\n * the app and `@ai-matrx/chat`, and every `instanceof` keeps working.\n *\n * Zero rows is at least three different situations: the row was soft-deleted,\n * the row is alive but this reader's access (org membership / permission\n * grant) does not reach it, or the id is stale/wrong. Asserting deletion for\n * all three is what D133 cost — two agent-review items were rejected as \"site\n * deleted or is no longer accessible\" while the brand AND site were live and\n * un-deleted; the null was RLS.\n *\n * So `deleted` is claimed ONLY when a probe proved it. Everything else is\n * `unknown` and says both possibilities out loud. Never construct the error\n * directly at a read site: the host's `recordUnavailable(...)` builds it AND\n * captures it — the capture is the loud half of the contract.\n */\n\n/** `deleted` is PROVEN (a probe read the row and saw `deleted_at`). */\nexport type RecordUnavailableReason = \"deleted\" | \"unknown\";\n\n/** The truth an access resolver can add after the initial ambiguous read failure. */\nexport type RecordUnavailableResolution =\n \"denied\" | \"deleted\" | \"missing\" | \"signed-out\" | \"ok\";\n\nexport class RecordUnavailableError extends Error {\n readonly entity: string;\n readonly reason: RecordUnavailableReason;\n readonly recordId?: string | undefined;\n /**\n * Canonical entity token, when the read site knows it. With a token AND a\n * recordId the renderer stops describing the ambiguity and ASKS the platform\n * instead — an access gate resolves which of the four it really is.\n * Without one, honest ambiguity is still the best available answer.\n */\n readonly token?: string | undefined;\n /** Diagnostics identity for reconciling this exact capture in place. */\n captureId?: string | undefined;\n /** Last truth written to diagnostics; avoids duplicate reconciliation. */\n captureResolution: RecordUnavailableReason | RecordUnavailableResolution;\n\n constructor(input: {\n entity: string;\n reason: RecordUnavailableReason;\n recordId?: string | undefined;\n token?: string | undefined;\n }) {\n super(recordUnavailableMessage(input.entity, input.reason));\n this.name = \"RecordUnavailableError\";\n this.entity = input.entity;\n this.reason = input.reason;\n this.recordId = input.recordId;\n this.token = input.token;\n this.captureResolution = input.reason;\n }\n}\n\nexport function recordUnavailableMessage(\n entity: string,\n reason: RecordUnavailableReason,\n): string {\n if (reason === \"deleted\") {\n return `This ${entity} was deleted, so it can no longer be opened.`;\n }\n return `We couldn't open this ${entity}. It may have been deleted, or it may belong to an organization you don't have access to.`;\n}\n\nexport function isRecordUnavailableError(\n value: unknown,\n): value is RecordUnavailableError {\n return value instanceof RecordUnavailableError;\n}\n","/**\n * @ai-matrx/data — THE doors: one way to talk to the database.\n *\n * `createDb` owns the connection (wrapping the app's existing Supabase client\n * during migration — data never opens a second auth client or socket), the\n * session (handed to `@ai-matrx/api` as its `user` credential through\n * `db.credentials`) and the organization binding. Every operation is a\n * standalone function over a DESCRIPTOR that each app generates locally from the\n * ONE database description (`matrx-data generate`), so the rules ride the\n * descriptor's flags — read from the live table registry — never a call site's\n * memory:\n *\n * - organization (the access ladder): an entity insert takes the explicit\n * `organization_id`, else the active organization; a CHILD insert\n * (`org.rule === \"parent\"`) never takes the active organization — the\n * database's `inherit_org_from_parent` fills it from the parent, so adding to\n * a record in another organization works; reads NEVER read the active\n * organization; service doors have no binding (organization is required);\n * - complete reads: `listAll` pages past PostgREST's 1,000-row cap\n * (`readAllRows`) and throws on a short read; `page` is the explicit window;\n * - versioned tables: `update` takes `{ expectedVersion }` (guarded, conflict\n * returned) or `{ overwrite: true }` — explicit either way;\n * - lifecycle: `remove` soft-deletes where the table has `deleted_at`; an\n * archive-only table refuses `remove` (use `archive`); a hard delete exists\n * only where the table has neither;\n * - the door set by registry type (entity/detail all · ledger read/list/insert ·\n * reference/system read/list · restricted service-only · deprecated none),\n * narrowed by `client_read_only` / `client_deletes_refused` — refused BEFORE\n * the wire with a sentence that names the rule;\n * - service role: `createServiceDb` throws in a browser bundle;\n * - a table chosen at runtime: `tableByName(index, \"schema.table\")` over the\n * generated flags index — loosely typed, same rules.\n */\nimport { readAllRows } from \"./read-all-rows\";\nimport { guardedUpdate } from \"./guarded-update\";\n\n// ─── descriptors (what `matrx-data generate` emits) ─────────────────────────\n\n/** Registry type (`platform.entity_types.type`); null = untyped or no registry row. */\nexport type TableType = \"entity\" | \"detail\" | \"ledger\" | \"reference\" | \"system\" | \"restricted\" | \"deprecated\";\n\nexport type OrgRule =\n | { readonly rule: \"binding\" }\n | { readonly rule: \"parent\"; readonly parent: string; readonly via: string }\n | { readonly rule: \"column\" }\n | { readonly rule: \"none\" };\n\n/** Phantom carrier for the generated row types — never present at runtime. */\ndeclare const ROW: unique symbol;\n\nexport interface TableDescriptor<Row = Record<string, unknown>, Insert = Record<string, unknown>, Update = Partial<Insert>> {\n readonly schema: string;\n readonly name: string;\n readonly kind: \"table\" | \"view\" | \"materialized_view\";\n readonly type: TableType | null;\n readonly pk: readonly string[];\n readonly org: OrgRule;\n readonly versioned: boolean;\n readonly softDelete: boolean;\n /** The archive column, when the table archives instead of (or as well as) soft-deleting. */\n readonly archive: \"archived_at\" | \"is_archived\" | null;\n readonly readOnly: boolean;\n readonly deletesRefused: boolean;\n readonly readOnlyColumns: readonly string[];\n readonly listScope: string | null;\n readonly realtime: boolean;\n /**\n * The table has a `created_by` column. A signed-in insert that omits it is stamped with the\n * session's person (row security on tables like `workbench.notes` refuses an insert whose\n * `created_by` is not `auth.uid()`). Optional: descriptors generated before 0.25.0 lack it.\n */\n readonly createdBy?: boolean;\n readonly [ROW]?: { row: Row; insert: Insert; update: Update };\n}\n\nexport interface FunctionDescriptor<Args = Record<string, unknown>, Result = unknown> {\n readonly schema: string;\n readonly name: string;\n readonly roles: readonly (\"anon\" | \"authenticated\" | \"service_role\")[];\n readonly registered: boolean;\n readonly [ROW]?: { args: Args; result: Result };\n}\n\nexport type RowOf<T> = T extends TableDescriptor<infer R, any, any> ? R : never;\nexport type InsertOf<T> = T extends TableDescriptor<any, infer I, any> ? I : never;\nexport type UpdateOf<T> = T extends TableDescriptor<any, any, infer U> ? U : never;\nexport type ArgsOf<F> = F extends FunctionDescriptor<infer A, any> ? A : never;\nexport type ResultOf<F> = F extends FunctionDescriptor<any, infer R> ? R : never;\n\n// ─── the connection ─────────────────────────────────────────────────────────\n\ninterface PostgrestError {\n message: string;\n code?: string;\n details?: string | null;\n hint?: string | null;\n}\ninterface Resp<T> {\n data: T | null;\n error: PostgrestError | null;\n count?: number | null;\n}\n/** The slice of a supabase-js query builder the doors use (structural — any supabase-js 2.x client). */\nexport interface QueryLike extends PromiseLike<Resp<any>> {\n select(columns?: string, opts?: { count?: \"exact\" | \"planned\" | \"estimated\"; head?: boolean }): QueryLike;\n insert(values: unknown): QueryLike;\n update(values: unknown): QueryLike;\n delete(): QueryLike;\n eq(column: string, value: unknown): QueryLike;\n is(column: string, value: null | boolean): QueryLike;\n order(column: string, opts?: { ascending?: boolean }): QueryLike;\n range(from: number, to: number): QueryLike;\n maybeSingle(): PromiseLike<Resp<any>>;\n single(): PromiseLike<Resp<any>>;\n}\n/** The slice of a supabase-js client the doors use. */\nexport interface SupabaseLike {\n schema(name: string): {\n from(table: string): QueryLike;\n rpc(fn: string, args?: Record<string, unknown>, opts?: { count?: \"exact\" | \"planned\" | \"estimated\" }): PromiseLike<Resp<any>>;\n };\n auth?: {\n getSession(): Promise<{ data: { session: { access_token: string; user?: { id: string } | null } | null } }>;\n onAuthStateChange(cb: (event: string, session: unknown) => void): { data: { subscription: { unsubscribe(): void } } };\n };\n}\n\n/** The credential shape `@ai-matrx/api`'s `CredentialsPort` accepts (structural; data owns the session). */\nexport interface UserCredentialsPort {\n get(): Promise<{ kind: \"user\"; accessToken: string } | null>;\n onChange?(cb: () => void): () => void;\n}\n\nexport interface Db {\n readonly client: SupabaseLike;\n readonly role: \"user\" | \"service\";\n /** The active organization — where NEW entity rows are saved. Never a read filter. */\n activeOrganization(): string | null;\n /** The session as `@ai-matrx/api`'s `user` credential (one sign-in feeds both lanes). */\n readonly credentials: UserCredentialsPort;\n}\n\nexport interface CreateDbOptions {\n /** The app's existing Supabase client (browser, RSC, route or the host's chat client). */\n client: SupabaseLike;\n /** Where new entity rows are saved. Read lazily on every insert; never consulted by a read. */\n organization?: () => string | null | undefined;\n}\n\nfunction credentialsOf(client: SupabaseLike): UserCredentialsPort {\n return {\n async get() {\n if (!client.auth) return null;\n const { data } = await client.auth.getSession();\n return data.session ? { kind: \"user\", accessToken: data.session.access_token } : null;\n },\n onChange(cb) {\n if (!client.auth) return () => {};\n const { data } = client.auth.onAuthStateChange(() => cb());\n return () => data.subscription.unsubscribe();\n },\n };\n}\n\n/** The one database connection for a signed-in (or anonymous) person. */\nexport function createDb(options: CreateDbOptions): Db {\n const { client, organization } = options;\n return {\n client,\n role: \"user\",\n activeOrganization: () => organization?.() ?? null,\n credentials: credentialsOf(client),\n };\n}\n\n/**\n * Service-role doors — servers only. No session, no binding: every entity insert\n * names its organization. Throws in a browser bundle.\n */\nexport function createServiceDb(options: { client: SupabaseLike }): Db {\n if (typeof (globalThis as { window?: unknown }).window !== \"undefined\") {\n throw new DoorRefusedError(\"createServiceDb\", \"the service role never runs in a browser\");\n }\n return { client: options.client, role: \"service\", activeOrganization: () => null, credentials: credentialsOf(options.client) };\n}\n\n// ─── refusals ───────────────────────────────────────────────────────────────\n\nexport class DoorRefusedError extends Error {\n constructor(\n readonly door: string,\n readonly reason: string,\n ) {\n super(`${door}: ${reason}`);\n this.name = \"DoorRefusedError\";\n }\n}\n\nexport class DatabaseError extends Error {\n constructor(\n readonly door: string,\n readonly cause: PostgrestError,\n ) {\n super(`${door}: ${cause.message}${cause.code ? ` (${cause.code})` : \"\"}`);\n this.name = \"DatabaseError\";\n }\n}\n\ntype Op = \"read\" | \"insert\" | \"update\" | \"remove\" | \"archive\";\nconst CLIENT_DOORS: Record<TableType, readonly Op[]> = {\n entity: [\"read\", \"insert\", \"update\", \"remove\", \"archive\"],\n detail: [\"read\", \"insert\", \"update\", \"remove\", \"archive\"],\n ledger: [\"read\", \"insert\"],\n reference: [\"read\"],\n system: [\"read\"],\n restricted: [],\n deprecated: [],\n};\n\nconst qualified = (t: { schema: string; name: string }) => `${t.schema}.${t.name}`;\n\n/** Refuse before the wire when the descriptor's rules do not open this door. */\nexport function assertDoor(db: Db, table: TableDescriptor<any, any, any>, op: Op): void {\n const door = `${op} ${qualified(table)}`;\n if (table.type === \"deprecated\") throw new DoorRefusedError(door, \"the table is deprecated — no door opens on it\");\n if (table.kind !== \"table\" && op !== \"read\") throw new DoorRefusedError(door, `a ${table.kind.replace(\"_\", \" \")} is read-only`);\n if (db.role === \"service\") return;\n if (table.type && !CLIENT_DOORS[table.type].includes(op))\n throw new DoorRefusedError(door, `a ${table.type} table opens only ${CLIENT_DOORS[table.type].join(\", \") || \"service\"} doors to a client`);\n if (op !== \"read\" && table.readOnly) throw new DoorRefusedError(door, \"the table is read-only to clients (client_read_only)\");\n if (op === \"remove\" && table.deletesRefused) throw new DoorRefusedError(door, \"clients may not delete from this table (client_deletes_refused)\");\n}\n\nfunction check<T>(door: string, res: Resp<T>): T {\n if (res.error) throw new DatabaseError(door, res.error);\n return res.data as T;\n}\n\nconst from = (db: Db, t: TableDescriptor<any, any, any>) => db.client.schema(t.schema).from(t.name);\n\nfunction byPk(q: QueryLike, t: TableDescriptor<any, any, any>, id: unknown): QueryLike {\n if (t.pk.length === 1) return q.eq(t.pk[0] as string, id);\n const key = id as Record<string, unknown>;\n return t.pk.reduce((acc, col) => acc.eq(col, key[col]), q);\n}\n\n// ─── reads (never the active organization; soft-deleted rows excluded unless asked) ─\n\ntype Col<R> = Extract<keyof R, string>;\n\n/** The typed filter a `Where` callback receives — column names and values checked against the row. */\nexport interface Filter<R> {\n eq<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;\n neq<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;\n gt<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;\n gte<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;\n lt<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;\n lte<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;\n like(column: Col<R>, pattern: string): Filter<R>;\n ilike(column: Col<R>, pattern: string): Filter<R>;\n in<K extends Col<R>>(column: K, values: readonly NonNullable<R[K]>[]): Filter<R>;\n is(column: Col<R>, value: null | boolean): Filter<R>;\n contains(column: Col<R>, value: unknown): Filter<R>;\n overlaps(column: Col<R>, value: unknown): Filter<R>;\n textSearch(column: Col<R>, query: string, opts?: { type?: \"plain\" | \"phrase\" | \"websearch\"; config?: string }): Filter<R>;\n /** PostgREST's raw `or` grammar (`\"pinned.eq.true,starred.eq.true\"`). */\n or(filters: string, opts?: { referencedTable?: string }): Filter<R>;\n not(column: Col<R>, operator: string, value: unknown): Filter<R>;\n}\n\n/** A filter callback — the same builder `readAllRows` callers write today, typed to the row. */\nexport type Where<R = any> = (q: Filter<R>) => Filter<R>;\n\nexport interface ReadOptions<C> {\n /** Only these columns (the result is typed to them). Default every column. */\n columns?: readonly C[];\n /** Include soft-deleted rows (default: excluded on tables with `deleted_at`). */\n includeDeleted?: boolean;\n}\n\nconst selectOf = (columns?: readonly string[]) => (columns && columns.length ? columns.join(\",\") : \"*\");\n\nfunction live(q: any, table: TableDescriptor<any, any, any>, includeDeleted?: boolean): any {\n return table.softDelete && !includeDeleted ? q.is(\"deleted_at\", null) : q;\n}\n\nfunction ordered(q: any, table: TableDescriptor<any, any, any>, orderBy?: string, ascending = true): any {\n // The FULL primary key, so paging is stable on composite keys.\n const cols = orderBy ? [orderBy, ...table.pk.filter((c) => c !== orderBy)] : table.pk.length ? table.pk : [\"id\"];\n return cols.reduce((acc: any, c) => acc.order(c, { ascending }), q);\n}\n\n/** One row by primary key (a composite key takes `{ col: value }`), or null. */\nexport async function read<R, I, U, C extends Col<R> = Col<R>>(\n db: Db,\n table: TableDescriptor<R, I, U>,\n id: unknown,\n opts: ReadOptions<C> = {},\n): Promise<Pick<R, C> | null> {\n assertDoor(db, table, \"read\");\n const q = live(byPk(from(db, table).select(selectOf(opts.columns)), table, id), table, opts.includeDeleted);\n return check(`read ${qualified(table)}`, await q.maybeSingle());\n}\n\n/** EVERY matching row, paged past the 1,000-row cap (ordered by the full key); throws on a short read. */\nexport async function listAll<R, I, U, C extends Col<R> = Col<R>>(\n db: Db,\n table: TableDescriptor<R, I, U>,\n where?: Where<R>,\n opts: ReadOptions<C> & { orderBy?: Col<R>; pageSize?: number; maxRows?: number } = {},\n): Promise<Pick<R, C>[]> {\n assertDoor(db, table, \"read\");\n return readAllRows<Pick<R, C>>(\n ({ from: lo, to: hi }) => {\n let q: any = live(from(db, table).select(selectOf(opts.columns), { count: \"exact\" }), table, opts.includeDeleted);\n if (where) q = where(q);\n // The database's own error (code, details) reaches the caller as a DatabaseError,\n // exactly like every other door — never a re-worded readAllRows message.\n return Promise.resolve(ordered(q, table, opts.orderBy).range(lo, hi)).then((res: Resp<any>) => {\n if (res.error) throw new DatabaseError(`listAll ${qualified(table)}`, res.error);\n return res;\n });\n },\n {\n label: `listAll ${qualified(table)}`,\n ...(opts.pageSize !== undefined ? { pageSize: opts.pageSize } : {}),\n ...(opts.maxRows !== undefined ? { maxRows: opts.maxRows } : {}),\n },\n );\n}\n\n/** One explicit window (`from`..`to`, inclusive) plus the exact total. */\nexport async function page<R, I, U, C extends Col<R> = Col<R>>(\n db: Db,\n table: TableDescriptor<R, I, U>,\n window: ReadOptions<C> & { from: number; to: number; where?: Where<R>; orderBy?: Col<R>; ascending?: boolean },\n): Promise<{ rows: Pick<R, C>[]; total: number | null }> {\n assertDoor(db, table, \"read\");\n let q: any = live(from(db, table).select(selectOf(window.columns), { count: \"exact\" }), table, window.includeDeleted);\n if (window.where) q = window.where(q);\n const res = await ordered(q, table, window.orderBy, window.ascending ?? true).range(window.from, window.to);\n return { rows: check(`page ${qualified(table)}`, res) ?? [], total: res.count ?? null };\n}\n\n/** The exact count of matching rows (no rows transferred). */\nexport async function count<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, where?: Where<R>, opts: { includeDeleted?: boolean } = {}): Promise<number> {\n assertDoor(db, table, \"read\");\n let q: any = live(from(db, table).select(\"*\", { count: \"exact\", head: true }), table, opts.includeDeleted);\n if (where) q = where(q);\n const res = await q;\n check(`count ${qualified(table)}`, res);\n return res.count ?? 0;\n}\n\n// ─── writes ─────────────────────────────────────────────────────────────────\n\nfunction withOrganization(db: Db, table: TableDescriptor<any, any, any>, values: Record<string, unknown>): Record<string, unknown> {\n const door = `insert ${qualified(table)}`;\n const org = table.org;\n if (org.rule === \"parent\" && values[org.via] != null) {\n // A child row: its organization is its parent's. Never the active organization —\n // `inherit_org_from_parent` fills organization_id; an explicit one is checked by\n // `refuse_org_foreign_to_parent`. So adding to a record in another organization works.\n return values;\n }\n if (org.rule === \"binding\" || org.rule === \"parent\") {\n // An entity row, or a row whose optional parent is absent (a note outside any folder),\n // is saved in the named organization, else the active one.\n if (values.organization_id != null) return values;\n const active = db.activeOrganization();\n if (!active) {\n throw new DoorRefusedError(\n door,\n db.role === \"service\" ? \"a service insert names its organization_id\" : \"no organization: pass organization_id or bind createDb({ organization })\",\n );\n }\n return { ...values, organization_id: active };\n }\n return values;\n}\n\n/** Insert one row (or many) and return what the database stored. */\nexport async function insert<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, values: I): Promise<R>;\nexport async function insert<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, values: readonly I[]): Promise<R[]>;\nexport async function insert(db: Db, table: TableDescriptor<any, any, any>, values: unknown): Promise<unknown> {\n assertDoor(db, table, \"insert\");\n const many = Array.isArray(values);\n let rows = (many ? values : [values]).map((v) => withOrganization(db, table, v as Record<string, unknown>));\n if (table.createdBy && db.role === \"user\" && rows.some((r) => r.created_by == null) && db.client.auth) {\n // Stamp the signed-in person (no session: sent as given, and row security answers).\n const { data } = await db.client.auth.getSession();\n const person = data.session?.user?.id;\n if (person) rows = rows.map((r) => (r.created_by == null ? { ...r, created_by: person } : r));\n }\n const res = await from(db, table).insert(rows).select(\"*\");\n const stored = check(`insert ${qualified(table)}`, res) as unknown[];\n return many ? stored : stored[0];\n}\n\n/** Every write on a versioned table is explicit: `{ expectedVersion }` (guarded) or `{ overwrite: true }`. */\nexport type UpdateGuard = { expectedVersion: number } | { overwrite: true };\n\nexport type WriteResult<R> =\n | { status: \"saved\"; row: R; rebasedFrom?: { expectedVersion: number; currentVersion: number } }\n | { status: \"conflict\"; currentRow: R; currentVersion: number }\n | { status: \"not_found\" };\n\n/** The one guarded write every update-shaped door goes through. */\nasync function writeRow<R>(db: Db, table: TableDescriptor<any, any, any>, id: unknown, values: Record<string, unknown>, door: string, guard?: UpdateGuard): Promise<WriteResult<R>> {\n const expected = guard && \"expectedVersion\" in guard ? guard.expectedVersion : undefined;\n if (expected !== undefined && !table.versioned) {\n throw new DoorRefusedError(door, \"expectedVersion on a table that is not versioned — nothing would guard it; pass no guard\");\n }\n if (table.versioned && expected === undefined && !(guard && \"overwrite\" in guard && guard.overwrite)) {\n throw new DoorRefusedError(door, \"a versioned table takes { expectedVersion } or { overwrite: true }\");\n }\n if (expected !== undefined) {\n return (await guardedUpdate<any>({\n expectedVersion: expected,\n applyUpdate: ({ expectedVersion, nextVersion }) =>\n byPk(from(db, table).update({ ...values, version: nextVersion }), table, id).eq(\"version\", expectedVersion).select(\"*\").maybeSingle(),\n fetchCurrent: () => byPk(from(db, table).select(\"*\"), table, id).maybeSingle(),\n })) as WriteResult<R>;\n }\n const row = check(door, await byPk(from(db, table).update(values), table, id).select(\"*\").maybeSingle());\n return row ? { status: \"saved\", row } : { status: \"not_found\" };\n}\n\n/**\n * Update one row by primary key. On a versioned table the guard is required:\n * `{ expectedVersion }` (a conflict comes back, never a silent overwrite) or\n * `{ overwrite: true }`; on an unversioned table `expectedVersion` is refused.\n */\nexport async function update<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, patch: U, guard?: UpdateGuard): Promise<WriteResult<R>> {\n assertDoor(db, table, \"update\");\n const door = `update ${qualified(table)}`;\n const values = patch as Record<string, unknown>;\n if (db.role === \"user\") {\n const blocked = table.readOnlyColumns.filter((c) => c in values);\n if (blocked.length) throw new DoorRefusedError(door, `read-only to clients: ${blocked.join(\", \")}`);\n }\n return writeRow<R>(db, table, id, values, door, guard);\n}\n\n/**\n * Remove one row the way the table removes: soft delete (`deleted_at`) where it\n * has one; an archive-only table refuses (use `archive`); a hard delete only where\n * the table has neither. Guarded like `update` on a versioned table.\n */\nexport async function remove<R, I, U>(\n db: Db,\n table: TableDescriptor<R, I, U>,\n id: unknown,\n guard?: UpdateGuard,\n): Promise<{ status: \"soft_deleted\" | \"deleted\" | \"not_found\" } | { status: \"conflict\"; currentVersion: number }> {\n assertDoor(db, table, \"remove\");\n const door = `remove ${qualified(table)}`;\n if (table.softDelete) {\n const res = await writeRow<R>(db, table, id, { deleted_at: new Date().toISOString() }, door, guard);\n return res.status === \"saved\" ? { status: \"soft_deleted\" } : res.status === \"conflict\" ? { status: \"conflict\", currentVersion: res.currentVersion } : res;\n }\n if (table.archive) throw new DoorRefusedError(door, \"this table archives instead of deleting — use archive()\");\n const expected = guard && \"expectedVersion\" in guard ? guard.expectedVersion : undefined;\n if (expected !== undefined && !table.versioned) throw new DoorRefusedError(door, \"expectedVersion on a table that is not versioned\");\n if (table.versioned && expected === undefined && !(guard && \"overwrite\" in guard)) {\n throw new DoorRefusedError(door, \"a versioned table takes { expectedVersion } or { overwrite: true }\");\n }\n let q = byPk(from(db, table).delete(), table, id);\n if (expected !== undefined) q = q.eq(\"version\", expected);\n const rows = check(door, await q.select(\"*\")) as unknown[] | null;\n if (rows && rows.length) return { status: \"deleted\" };\n if (expected !== undefined) {\n const current = check(door, await byPk(from(db, table).select(\"version\"), table, id).maybeSingle()) as { version: number } | null;\n if (current) return { status: \"conflict\", currentVersion: current.version };\n }\n return { status: \"not_found\" };\n}\n\n/** Archive (or, with `restore`, bring back) one row by the table's archive column. Guarded like `update`. */\nexport async function archive<R, I, U>(\n db: Db,\n table: TableDescriptor<R, I, U>,\n id: unknown,\n opts: { restore?: boolean; guard?: UpdateGuard } = {},\n): Promise<WriteResult<R>> {\n assertDoor(db, table, \"archive\");\n const door = `${opts.restore ? \"restore\" : \"archive\"} ${qualified(table)}`;\n let values: Record<string, unknown>;\n if (table.archive === \"archived_at\") values = { archived_at: opts.restore ? null : new Date().toISOString() };\n else if (table.archive === \"is_archived\") values = { is_archived: !opts.restore };\n else if (table.softDelete && opts.restore) values = { deleted_at: null };\n else throw new DoorRefusedError(door, \"the table has no archive column\");\n return writeRow<R>(db, table, id, values, door, opts.guard);\n}\n\n/** Bring back an archived or soft-deleted row. */\nexport const restore = <R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, guard?: UpdateGuard) =>\n archive(db, table, id, guard ? { restore: true, guard } : { restore: true });\n\n// ─── functions ──────────────────────────────────────────────────────────────\n\n/** Call a database function through its generated door (PostgREST chooses an overload by argument names). */\nexport async function call<F extends FunctionDescriptor<any, any>>(db: Db, fn: F, args: ArgsOf<F>): Promise<ResultOf<F>> {\n const door = `call ${fn.schema}.${fn.name}`;\n const role = db.role === \"service\" ? \"service_role\" : \"authenticated\";\n if (!fn.roles.includes(role) && !(role === \"authenticated\" && fn.roles.includes(\"anon\"))) {\n throw new DoorRefusedError(door, `not executable by ${role} (executable by: ${fn.roles.join(\", \") || \"nobody\"})`);\n }\n return check(door, await db.client.schema(fn.schema).rpc(fn.name, args as Record<string, unknown>));\n}\n\n/** One ordering column of a set-returning function's rows (PostgREST `order`). */\nexport type CallOrder = string | { column: string; ascending?: boolean; nullsFirst?: boolean };\n\n/**\n * EVERY row a set-returning function answers, paged past the 1,000-row cap by\n * `range` over a stable `order` (name enough columns to make it total — end on a key);\n * throws a `DatabaseError` with the database's own error, or `IncompleteReadError` on a short read.\n */\nexport async function callAll<F extends FunctionDescriptor<any, any>>(\n db: Db,\n fn: F,\n args: ArgsOf<F>,\n opts: { order: readonly CallOrder[]; pageSize?: number; maxRows?: number },\n): Promise<ResultOf<F> extends readonly (infer Row)[] ? Row[] : ResultOf<F>[]> {\n const door = `callAll ${fn.schema}.${fn.name}`;\n const role = db.role === \"service\" ? \"service_role\" : \"authenticated\";\n if (!fn.roles.includes(role) && !(role === \"authenticated\" && fn.roles.includes(\"anon\"))) {\n throw new DoorRefusedError(door, `not executable by ${role} (executable by: ${fn.roles.join(\", \") || \"nobody\"})`);\n }\n if (!opts.order.length) throw new DoorRefusedError(door, \"a paged read needs an order (end on a key) — pages over no order can skip or repeat rows\");\n return readAllRows<any>(\n ({ from: lo, to: hi }) => {\n let q: any = db.client.schema(fn.schema).rpc(fn.name, args as Record<string, unknown>, { count: \"exact\" });\n for (const o of opts.order) {\n q = typeof o === \"string\" ? q.order(o) : q.order(o.column, { ascending: o.ascending ?? true, ...(o.nullsFirst !== undefined ? { nullsFirst: o.nullsFirst } : {}) });\n }\n return Promise.resolve(q.range(lo, hi)).then((res: Resp<any>) => {\n if (res.error) throw new DatabaseError(door, res.error);\n return res;\n });\n },\n { label: door, ...(opts.pageSize !== undefined ? { pageSize: opts.pageSize } : {}), ...(opts.maxRows !== undefined ? { maxRows: opts.maxRows } : {}) },\n ) as never;\n}\n\n// ─── a table chosen at runtime ──────────────────────────────────────────────\n\n/** One schema's flags (`<schema>.flags.ts` from `matrx-data generate --flags-index`): \"schema.table\" → descriptor. */\nexport type FlagsIndex = Readonly<Record<string, TableDescriptor>>;\n/** Per-schema loaders (`flags-index.ts`): only the schema a runtime name names is loaded (pay-only). */\nexport type FlagLoaders = Readonly<Record<string, () => Promise<FlagsIndex>>>;\n\n/** The door for a table whose name arrives at runtime — loosely typed, the same rules. */\nexport function tableByName(index: FlagsIndex, name: string): TableDescriptor {\n const t = index[name];\n if (!t) throw new DoorRefusedError(`tableByName ${name}`, \"no such table in the database description (schema-qualify it: schema.table)\");\n return t;\n}\n\n/** `tableByName` over per-schema loaders: loads only the named schema's flags. */\nexport async function loadTableByName(loaders: FlagLoaders, name: string): Promise<TableDescriptor> {\n const schema = name.slice(0, name.indexOf(\".\"));\n const load = schema ? loaders[schema] : undefined;\n if (!load) throw new DoorRefusedError(`tableByName ${name}`, \"no such schema in the database description (schema-qualify it: schema.table)\");\n return tableByName(await load(), name);\n}\n\n// ─── realtime ───────────────────────────────────────────────────────────────\n\n/** The `postgres_changes` filter for a table — only published tables have one (an unpublished table delivers nothing). */\nexport function changesOf(table: TableDescriptor<any, any, any>): { schema: string; table: string } {\n if (!table.realtime) throw new DoorRefusedError(`changesOf ${qualified(table)}`, \"the table is not in the supabase_realtime publication\");\n return { schema: table.schema, table: table.name };\n}\n"],"mappings":"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","names":["from","page","from","text","window"]}
1
+ {"version":3,"sources":["../src/db/guarded-update.ts","../src/db/read-all-rows.ts","../src/db/merge-json-column.ts","../src/db/auth-retry.ts","../src/db/auth-cookie.ts","../src/db/active-org-cookie.ts","../src/db/realtime.ts","../src/db/oauth-refresh-transport.ts","../src/db/write-failure.ts","../src/db/write-one.ts","../src/db/record-unavailable.ts","../src/db/doors.ts"],"sourcesContent":["/**\n * guardedUpdate — the platform optimistic-concurrency contract for\n * direct-Supabase writes.\n *\n * Cross-repo system-of-record:\n * common-docs/systems/architecture/optimistic-concurrency/FEATURE.md — read it\n * before touching this feature in ANY repo.\n *\n * The revision token is the canonical `version` int column (bumped by the\n * `platform._touch_row` trigger on every UPDATE). A guarded write is a\n * compare-and-swap: `.eq(\"version\", expectedVersion)` on the UPDATE, then\n * classify 0 rows as conflict-vs-gone by re-reading the row. This helper owns\n * the classification and the typed result so every feature reports conflicts\n * the same way — it deliberately takes the two queries as callbacks because\n * each feature already has its own schema-scoped client, column list, and\n * narrowing filters (`.is(\"deleted_at\", null)` etc.).\n *\n * Usage:\n * const result = await guardedUpdate({\n * expectedVersion: page.version,\n * applyUpdate: ({ expectedVersion, nextVersion }) =>\n * db.from(\"page\")\n * .update({ ...patch, version: nextVersion })\n * .eq(\"id\", pageId)\n * .eq(\"version\", expectedVersion)\n * .select(PAGE_COLUMNS)\n * .maybeSingle(),\n * fetchCurrent: () =>\n * db.from(\"page\").select(PAGE_COLUMNS).eq(\"id\", pageId).maybeSingle(),\n * });\n * switch (result.status) { \"saved\" | \"conflict\" | \"not_found\" ... }\n *\n * Rules (same as the server side):\n * - Opt-in per write. No expectedVersion in hand (the surface never read\n * `version`)? Then the surface cannot opt in — fix the read first.\n * - SET `version: nextVersion` in the update payload: the trigger recomputes\n * the identical value on canonical tables and it keeps the CAS sound on\n * tables without the trigger.\n * - Never invent a second token (no updated_at comparisons in new code).\n * - On conflict, surface the merge/refresh choice to the user — never silently\n * overwrite (`currentRow`/`currentVersion` are returned for exactly that).\n *\n * THE PHANTOM CONFLICT, and `rebase` (2026-09-13). `version` moves on EVERY\n * update of the row — a desktop sync stamping `file_path`, an ingest job\n * writing metadata, a folder move — not only on the fields this editor edits.\n * A client that missed such a bump (its realtime echo was suppressed, its tab\n * was asleep, the write landed under its own actor) will CAS on a stale\n * number, miss, and be shown \"someone else changed this\" for a row whose\n * edited fields are byte-identical to the base it started from. That is not a\n * conflict; it is a version the client never learned. A conflict means the\n * OTHER side changed something you are editing.\n *\n * So a caller that knows its edit base passes `rebase.isPhantom(currentRow)`:\n * \"do the fields I edit, as the server holds them now, still equal the base\n * my edit was made against?\" When it answers yes, the helper retries the\n * write ONCE against the current version and returns `saved` with\n * `rebasedFrom` naming both numbers. A second miss, or a `no`, is a real\n * conflict and is returned exactly as before. No caller that does not pass\n * `rebase` changes behaviour.\n */\nimport type { MaybeSingleResponse } from \"../index\";\n\nexport interface VersionedRow {\n version: number;\n}\n\nexport interface RebasedFrom {\n /** The stale number the caller sent. */\n expectedVersion: number;\n /** The number the row actually held; the retry CAS'd on it. */\n currentVersion: number;\n}\n\nexport type GuardedUpdateResult<Row extends VersionedRow> =\n | {\n status: \"saved\";\n row: Row;\n /** Present when the write landed only after a phantom-conflict rebase. */\n rebasedFrom?: RebasedFrom;\n }\n | { status: \"conflict\"; currentRow: Row; currentVersion: number }\n | { status: \"not_found\" };\n\nexport interface GuardedUpdateRebase<Row extends VersionedRow> {\n /**\n * Given the row the server holds NOW (after a CAS missed), answer whether\n * every field this edit touches still equals the base the edit was made\n * against. `true` means nobody changed what we are changing — the version\n * moved for some other column — and the write is retried against\n * `currentRow.version`. Consulted again on EVERY miss, because the writer\n * that bumped the row once may bump it again (matrx-local stamps\n * `file_path` and then `last_device_id` as two UPDATEs).\n */\n isPhantom: (currentRow: Row) => boolean;\n /** Maximum retries after the first miss. Default 3. */\n maxRetries?: number;\n}\n\nexport interface GuardedUpdateArgs<Row extends VersionedRow> {\n /** The `version` the edit was based on — from the read that fed the UI. */\n expectedVersion: number;\n /**\n * Run the UPDATE with `.eq(\"version\", expectedVersion)` and\n * `version: nextVersion` in the payload, ending in `.select(...).maybeSingle()`.\n */\n applyUpdate: (guard: {\n expectedVersion: number;\n nextVersion: number;\n }) => PromiseLike<MaybeSingleResponse<Row>>;\n /** Re-read the row by primary key alone (no version filter), `.maybeSingle()`. */\n fetchCurrent: () => PromiseLike<MaybeSingleResponse<Row>>;\n /** Opt-in phantom-conflict recovery. See the header. */\n rebase?: GuardedUpdateRebase<Row>;\n}\n\nexport async function guardedUpdate<Row extends VersionedRow>(\n args: GuardedUpdateArgs<Row>,\n): Promise<GuardedUpdateResult<Row>> {\n const { expectedVersion, applyUpdate, fetchCurrent, rebase } = args;\n const updated = await applyUpdate({\n expectedVersion,\n nextVersion: expectedVersion + 1,\n });\n if (updated.error) throw updated.error;\n if (updated.data) return { status: \"saved\", row: updated.data };\n\n const current = await fetchCurrent();\n if (current.error) throw current.error;\n if (!current.data) return { status: \"not_found\" };\n let currentRow = current.data;\n let currentVersion = currentRow.version;\n\n if (rebase === undefined) {\n return { status: \"conflict\", currentRow, currentVersion };\n }\n\n // The number moved; if nothing we edit did, retry on the number the row\n // holds — and ask again on every miss, bounded, because the writer that\n // bumped it once may bump it again. The CAS keeps every retry safe: a real\n // change between the read and the retry misses and is re-read, and\n // `isPhantom` then sees it.\n const maxRetries = rebase.maxRetries ?? 3;\n for (let attempt = 0; attempt < maxRetries; attempt += 1) {\n if (\n !Number.isSafeInteger(currentVersion) ||\n currentVersion === expectedVersion ||\n !rebase.isPhantom(currentRow)\n ) {\n return { status: \"conflict\", currentRow, currentVersion };\n }\n const retried = await applyUpdate({\n expectedVersion: currentVersion,\n nextVersion: currentVersion + 1,\n });\n if (retried.error) throw retried.error;\n if (retried.data) {\n return {\n status: \"saved\",\n row: retried.data,\n rebasedFrom: { expectedVersion, currentVersion },\n };\n }\n const after = await fetchCurrent();\n if (after.error) throw after.error;\n if (!after.data) return { status: \"not_found\" };\n currentRow = after.data;\n currentVersion = currentRow.version;\n }\n\n return { status: \"conflict\", currentRow, currentVersion };\n}\n","/**\n * readAllRows — the ONE way to read a LIST YOU INTEND TO TREAT AS COMPLETE.\n *\n * THE BUG THIS EXISTS TO KILL (FOUND_DEFECTS D190)\n * ------------------------------------------------\n * PostgREST caps every response at `db-max-rows` (1000 on Matrx Main). It does\n * not error. It returns HTTP 206 and a `Content-Range: 0-999/4185` header, and\n * `supabase-js` hands you a perfectly successful-looking array of 1000 rows.\n *\n * If that array is only rendered, nothing is wrong — the user sees a screenful.\n * If that array is used to DECIDE SOMETHING, it is a silent, confident lie:\n *\n * - `rows.find(...)` → \"no such row\" (it exists, it was row 1200)\n * - `set.has(...)` → \"not registered\" (…)\n * - set subtraction → \"stale, delete it\" ← this one DELETES LIVE DATA\n * - `a.length === b.length` → \"out of sync\"\n *\n * Measured 2026-08-14: `public._schema_migrations` held 1611 rows,\n * `scripts/check-migrations.ts` saw 1000, and reported the 5 newest migrations\n * UNAPPLIED to a release that had just applied them — hard-blocking every\n * `--strict` release. Same day: `ui.ui_surface_value` held 4185 rows and fed a\n * `deleteStale` set-subtraction in the surface manifest sync.\n *\n * THE RULE\n * --------\n * An **existence check, a diff, a set subtraction, or a completeness/`.length`\n * comparison MUST read through `readAllRows`** (or `readAllRowsRest`). A bare\n * `.select()` is only acceptable when a short list is an acceptable answer —\n * i.e. you are rendering, sampling, or previewing.\n *\n * This helper refuses to guess. It pages to the declared total and, if it\n * cannot prove it collected every row, it THROWS instead of returning a\n * confidently wrong partial list. Callers that would rather skip a check than\n * assert a wrong one use `tryReadAllRows`, which logs loudly and returns null.\n *\n * USAGE (supabase-js)\n * -------------------\n * const rows = await readAllRows<Row>(\n * ({ from, to }) =>\n * sb.schema(\"ui\").from(\"ui_surface_value\")\n * .select(\"surface_name, name\", { count: \"exact\" }) // count REQUIRED\n * .order(\"id\", { ascending: true }) // stable order REQUIRED\n * .range(from, to),\n * { label: \"ui.ui_surface_value\" },\n * );\n *\n * Two things the caller owns and this helper cannot check for you:\n * 1. `{ count: \"exact\" }` — without it there is no total to verify against,\n * and the read throws rather than trusting a full-looking page.\n * 2. A **stable total order** (`.order()` on a unique-ish column). Paging an\n * unordered relation can repeat and skip rows between requests — you would\n * collect the right COUNT of rows and still miss one.\n */\n\n/** The shape every supabase-js `.range()` call resolves to. */\nexport interface PagedReadResult<T> {\n data: T[] | null;\n error: { message: string } | null;\n count?: number | null;\n}\n\n/**\n * A factory that runs ONE page. It must be a factory, not a builder: a\n * supabase-js query is a single-use thenable, so paging needs a fresh one per\n * request.\n */\nexport type PagedReadQuery<T> = (range: {\n from: number;\n to: number;\n}) => PromiseLike<PagedReadResult<T>>;\n\nexport interface ReadAllRowsOptions {\n /** `schema.table` (or RPC name) — appears in every error. Required: a silent truncation is unfindable without it. */\n label: string;\n /** Rows per request. Must not exceed the server's `db-max-rows` (1000 here). */\n pageSize?: number;\n /** Runaway guard. A read past this throws rather than looping forever. */\n maxRows?: number;\n}\n\nconst DEFAULT_PAGE_SIZE = 1000;\nconst DEFAULT_MAX_ROWS = 500_000;\n\n/** Thrown when the full set provably could not be collected. Never swallow this into an empty list. */\nexport class IncompleteReadError extends Error {\n readonly label: string;\n readonly collected: number;\n readonly expected: number | null;\n\n // Explicit fields, not constructor parameter properties: consumers compile\n // this source under `erasableSyntaxOnly` (workflow-studio, dashboard), which\n // forbids the shorthand.\n constructor(\n label: string,\n collected: number,\n expected: number | null,\n detail: string,\n ) {\n super(\n `readAllRows(${label}): ${detail} — collected ${collected}` +\n (expected === null ? \"\" : ` of ${expected}`) +\n \". Refusing to return a partial list: a truncated read used for an \" +\n \"existence/diff decision produces a confidently WRONG answer.\",\n );\n this.label = label;\n this.collected = collected;\n this.expected = expected;\n this.name = \"IncompleteReadError\";\n }\n}\n\n/**\n * Read EVERY row, or throw. See the file header for the contract.\n *\n * @throws IncompleteReadError when the collected count cannot be proven complete.\n * @throws Error on any underlying query error.\n */\nexport async function readAllRows<T>(\n query: PagedReadQuery<T>,\n opts: ReadAllRowsOptions,\n): Promise<T[]> {\n const pageSize = opts.pageSize ?? DEFAULT_PAGE_SIZE;\n const maxRows = opts.maxRows ?? DEFAULT_MAX_ROWS;\n const rows: T[] = [];\n let total: number | null = null;\n\n for (let from = 0; ; from += pageSize) {\n const res = await query({ from, to: from + pageSize - 1 });\n if (res.error) {\n throw new Error(\n `readAllRows(${opts.label}): query failed — ${res.error.message}`,\n );\n }\n const page = res.data ?? [];\n rows.push(...page);\n if (typeof res.count === \"number\") total = res.count;\n\n // No total on the first request means the caller omitted `{ count: \"exact\" }`.\n // A full-looking page is exactly what truncation looks like, so we cannot\n // accept it. A short first page is provably everything.\n if (total === null) {\n if (page.length < pageSize) return rows;\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n null,\n 'the query returned no count — pass { count: \"exact\" } to select() so ' +\n \"completeness can be verified\",\n );\n }\n\n if (rows.length >= total) break;\n if (page.length === 0) {\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n total,\n \"a page came back empty before the declared total was reached\",\n );\n }\n if (rows.length > maxRows) {\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n total,\n `exceeded the ${maxRows}-row safety limit`,\n );\n }\n }\n\n if (rows.length !== total) {\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n total,\n \"final row count does not match the total the server reported\",\n );\n }\n return rows;\n}\n\n/**\n * Same contract, but a provably-incomplete read returns `null` after SCREAMING\n * instead of throwing. For gate scripts that would rather SKIP a check than\n * assert a wrong verdict (`check-migrations.ts` is the exemplar). A `null`\n * return must never be coerced to `[]`.\n */\nexport async function tryReadAllRows<T>(\n query: PagedReadQuery<T>,\n opts: ReadAllRowsOptions,\n): Promise<T[] | null> {\n try {\n return await readAllRows(query, opts);\n } catch (err) {\n console.error(\n `[readAllRows] INCOMPLETE READ of ${opts.label} — check skipped rather ` +\n `than answered wrongly: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Raw-REST variant — for scripts that talk to PostgREST with `fetch`\n * and have no supabase-js client (they read `.env` directly).\n * ------------------------------------------------------------------ */\n\nexport interface ReadAllRowsRestOptions extends ReadAllRowsOptions {\n /** Supabase project URL, with or without a trailing slash. */\n url: string;\n /** apikey / bearer token. */\n key: string;\n /**\n * Path + query AFTER `/rest/v1/`, e.g.\n * `definition?select=name,parameters&order=name.asc`.\n * It MUST carry a stable `order=` — see the file header.\n */\n path: string;\n /** Postgres schema for the `Accept-Profile` header (the db.matrxserver.com proxy defaults to `api`). */\n schema?: string;\n}\n\n/**\n * Read EVERY row over raw REST, or throw. Uses `Range` headers and verifies the\n * collected count against the total in `Content-Range: 0-999/4185`.\n */\nexport async function readAllRowsRest<T>(\n opts: ReadAllRowsRestOptions,\n): Promise<T[]> {\n const pageSize = opts.pageSize ?? DEFAULT_PAGE_SIZE;\n const maxRows = opts.maxRows ?? DEFAULT_MAX_ROWS;\n const endpoint = `${opts.url.replace(/\\/$/, \"\")}/rest/v1/${opts.path}`;\n const rows: T[] = [];\n let total: number | null = null;\n\n for (let from = 0; ; from += pageSize) {\n const res = await fetch(endpoint, {\n headers: {\n apikey: opts.key,\n Authorization: `Bearer ${opts.key}`,\n Accept: \"application/json\",\n ...(opts.schema ? { \"Accept-Profile\": opts.schema } : {}),\n // Without this PostgREST answers `Content-Range: 0-999/*` — a page with\n // no total, which is unverifiable and therefore refused below. This is\n // the REST twin of supabase-js's `{ count: \"exact\" }`.\n Prefer: \"count=exact\",\n Range: `${from}-${from + pageSize - 1}`,\n \"Range-Unit\": \"items\",\n },\n });\n if (!res.ok && res.status !== 206) {\n throw new Error(\n `readAllRowsRest(${opts.label}): HTTP ${res.status} — ${await res.text()}`,\n );\n }\n const page = (await res.json()) as T[];\n rows.push(...page);\n\n // `Content-Range: 0-999/4185` — the part after the slash is the true total.\n // `*` means the server declined to count; treat it as unverifiable.\n const totalPart = res.headers.get(\"content-range\")?.split(\"/\")[1];\n if (totalPart && totalPart !== \"*\") total = Number(totalPart);\n\n if (total === null) {\n if (page.length < pageSize) return rows;\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n null,\n \"the server reported no total in Content-Range, and the page came back full\",\n );\n }\n if (rows.length >= total) break;\n if (page.length === 0) {\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n total,\n \"a page came back empty before the declared total was reached\",\n );\n }\n if (rows.length > maxRows) {\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n total,\n `exceeded the ${maxRows}-row safety limit`,\n );\n }\n }\n\n if (rows.length !== total) {\n throw new IncompleteReadError(\n opts.label,\n rows.length,\n total,\n \"final row count does not match Content-Range's total\",\n );\n }\n return rows;\n}\n\n/** `tryReadAllRows` for the REST variant. */\nexport async function tryReadAllRowsRest<T>(\n opts: ReadAllRowsRestOptions,\n): Promise<T[] | null> {\n try {\n return await readAllRowsRest<T>(opts);\n } catch (err) {\n console.error(\n `[readAllRowsRest] INCOMPLETE READ of ${opts.label} — check skipped ` +\n `rather than answered wrongly: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n}\n","/**\n * mergeJsonColumn — the platform primitive for \"merge a value into a row's\n * JSONB column, from the browser, without losing a concurrent writer's keys\".\n *\n * Why this exists (matrx-frontend FOUND_DEFECTS D151): persisting a paid AI\n * result almost always means read-modify-write on an existing jsonb column\n * (`metadata`, `dynamic_content`, `settings`) — that is a lost-update race the\n * moment two surfaces write different keys of the same object. Every feature\n * that needed it was about to hand-roll the same read → spread → write, so it\n * is built ONCE here on the canonical optimistic-concurrency contract\n * (`guardedUpdate` — CAS on the `version` column) with a bounded\n * re-read-and-remerge retry, because an append/merge is exactly the conflict a\n * caller can resolve automatically.\n *\n * This is NOT a second concurrency token or a second write path: it composes\n * `guardedUpdate`, and it never compares `updated_at`.\n *\n * Usage:\n * await mergeJsonColumn<Row>({\n * fetchCurrent: () =>\n * db.from(\"study_session\").select(\"id, version, metadata\")\n * .eq(\"id\", sessionId).maybeSingle(),\n * readColumn: (row) => row.metadata,\n * merge: (current) => ({ ...current, coach_tips: [...prior, entry] }),\n * applyUpdate: ({ value, expectedVersion, nextVersion }) =>\n * db.from(\"study_session\")\n * .update({ metadata: value, version: nextVersion })\n * .eq(\"id\", sessionId).eq(\"version\", expectedVersion)\n * .select(\"id, version, metadata\").maybeSingle(),\n * });\n *\n * Never throws for a normal outcome — it returns a typed status so a persist\n * failure can be reported without taking down the surface that triggered it.\n */\nimport type { MaybeSingleResponse } from \"../index\";\nimport { guardedUpdate, type VersionedRow } from \"./guarded-update\";\n\n/**\n * A jsonb object column's value, normalized — never null, never an array.\n *\n * Typed over `unknown`, NOT this package's strict `Json`: the origin module was\n * typed against the HOST's generated `Json` type, and Supabase type generation\n * commonly emits `type Json = unknown` (the flagship host does). Requiring the\n * strict recursive `Json` here forced a cast at every real call site — the\n * merge callback's inputs and outputs go straight to/from a jsonb column the\n * host has already typed, so the honest boundary type is `unknown`.\n */\nexport type JsonObject = Record<string, unknown>;\n\nexport type MergeJsonColumnResult<Row extends VersionedRow> =\n | { status: \"saved\"; row: Row }\n /** The row is gone / not visible under RLS — nothing to merge into. */\n | { status: \"not_found\" }\n /** Every attempt lost the CAS race; the caller's value was NOT written. */\n | { status: \"conflict\" }\n /** A transport/PostgREST failure. The error is returned, never swallowed. */\n | { status: \"error\"; error: unknown };\n\nexport interface MergeJsonColumnArgs<Row extends VersionedRow> {\n /** Read the row by primary key — must select `version` and the json column. */\n fetchCurrent: () => PromiseLike<MaybeSingleResponse<Row>>;\n /** Pick the json column off a fetched row. */\n readColumn: (row: Row) => unknown;\n /**\n * Produce the column's next value from its CURRENT value. Re-invoked on each\n * retry with freshly-read data, so it must be a pure function of `current`.\n */\n merge: (current: JsonObject) => JsonObject;\n /**\n * Run the guarded UPDATE: set the column to `value` plus `version: nextVersion`,\n * filtered by `.eq(\"version\", expectedVersion)`, ending in `.select(...).maybeSingle()`.\n */\n applyUpdate: (next: {\n value: JsonObject;\n expectedVersion: number;\n nextVersion: number;\n }) => PromiseLike<MaybeSingleResponse<Row>>;\n /** How many CAS attempts before giving up. Default 3. */\n attempts?: number;\n}\n\n/** Normalize a jsonb column read to a plain object (null / array / scalar → {}). */\nexport function asJsonObject(value: unknown): JsonObject {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return {};\n return value as JsonObject;\n}\n\nexport async function mergeJsonColumn<Row extends VersionedRow>(\n args: MergeJsonColumnArgs<Row>,\n): Promise<MergeJsonColumnResult<Row>> {\n const attempts = Math.max(args.attempts ?? 3, 1);\n try {\n for (let attempt = 0; attempt < attempts; attempt++) {\n const current = await args.fetchCurrent();\n if (current.error) return { status: \"error\", error: current.error };\n if (!current.data) return { status: \"not_found\" };\n\n const next = args.merge(asJsonObject(args.readColumn(current.data)));\n const result = await guardedUpdate<Row>({\n expectedVersion: current.data.version,\n applyUpdate: ({ expectedVersion, nextVersion }) =>\n args.applyUpdate({ value: next, expectedVersion, nextVersion }),\n fetchCurrent: args.fetchCurrent,\n });\n if (result.status === \"saved\") return { status: \"saved\", row: result.row };\n if (result.status === \"not_found\") return { status: \"not_found\" };\n // Conflict: someone else wrote between our read and our write. Re-read and\n // re-merge — that is exactly what makes a merge safe to retry.\n }\n return { status: \"conflict\" };\n } catch (e) {\n return { status: \"error\", error: e };\n }\n}\n","/**\n * Session-retry — one primitive for the class of failure where a browser\n * operation reached PostgREST with NO user JWT even though the app believes a\n * user is signed in (the auth session was momentarily unavailable — refresh in\n * flight, storage read mid-rewrite, cookie chunk swap). The request then\n * executes as `anon`, and every RPC that resolves an owner answers with an\n * authorization error that has nothing to do with the user's actual\n * permissions.\n *\n * This fired for real (matrx-frontend, 2026-08-15): artifact materialization\n * lost a react artifact, and the browser console blamed \"cannot create another\n * user's personal organization\" — an organization the caller was never\n * creating. The DB edge answers honestly (`28000 not authenticated`); this is\n * the client half that makes a momentary blip recoverable instead of losing\n * the write.\n *\n * Deliberately NOT a general retry-on-error wrapper: it retries EXACTLY ONE\n * cause (no authenticated session) EXACTLY ONCE, after asking the auth client\n * to re-resolve the session. Anything else — RLS denials, constraint\n * violations, network errors — is returned untouched, because retrying those\n * is how a client turns one failure into a storm.\n *\n * The host injects its auth client through `SessionSource` (a supabase-js\n * client's `auth` satisfies it structurally) and, optionally, a diagnostics\n * sink; the default sink is `console.error` — honest, never silent.\n */\n\n/** The shape every supabase-js call returns, narrowed to what we inspect. */\nexport interface AuthRetryableResult<T> {\n data: T;\n error: { code?: string | null; message?: string | null } | null;\n status?: number;\n}\n\n/** The slice of an auth client this primitive needs (structural). */\nexport interface SessionSource {\n getSession(): Promise<{\n data: { session: { access_token?: string | null } | null };\n error: unknown | null;\n }>;\n}\n\nexport class SessionUnavailableError extends Error {\n readonly code = \"PGRST301\";\n\n constructor() {\n super(\"Your session expired\");\n this.name = \"SessionUnavailableError\";\n }\n}\n\n/**\n * True when the DB refused because the request carried no authenticated user.\n * `28000` is the SQLSTATE our authenticated-only RPCs raise; the message tests\n * cover RPCs that raise the same condition without setting ERRCODE, plus\n * PostgREST's own response when an anonymous request reaches an\n * authenticated-only RPC.\n */\nexport function isMissingSessionError(\n error: { code?: string | null; message?: string | null } | null | undefined,\n status?: number,\n): boolean {\n if (!error) return false;\n // PostgREST emits PGRST301 when JWT verification fails, including an\n // expired access token. It is the same session boundary as the shapes below.\n if (error.code === \"PGRST301\") return true;\n if (error.code === \"28000\") return true;\n const message = error.message?.toLowerCase();\n if (message?.startsWith(\"not authenticated\")) return true;\n return (\n status === 401 &&\n error.code === \"42501\" &&\n message?.startsWith(\"permission denied for function \") === true\n );\n}\n\nexport interface CreateSessionRetryOptions {\n /** The host's auth client (e.g. `supabase.auth`). */\n auth: SessionSource;\n /** Diagnostics sink for the two recovery screams. Default: `console.error`. */\n log?: (message: string, detail?: unknown) => void;\n}\n\n/**\n * Build the host-bound retry runner. The returned function runs a call; if it\n * fails purely because no session reached the server, it re-resolves the\n * session and runs it ONCE more.\n *\n * The operation must be idempotent — reads are safe, and write callers use an\n * upsert keyed on a natural key, so the retry can only land the same row.\n *\n * Returns the second attempt's result when a retry happened, else the first.\n * `retried` / `sessionRecovered` are reported so callers can log the truth\n * instead of a generic \"failed to persist\".\n *\n * @throws SessionUnavailableError before touching the network when the browser\n * already knows the session is gone — executing during that gap creates a\n * guaranteed anonymous 401 and turns ordinary session expiry into a product\n * error.\n */\nexport function createSessionRetry(options: CreateSessionRetryOptions) {\n const log =\n options.log ??\n ((m: string, d?: unknown) => {\n // Only forward a detail that exists — console.error(m, undefined)\n // renders a trailing \"undefined\" in every real console, and hosts\n // asserting on the call see a phantom second argument.\n if (d === undefined) console.error(m);\n else console.error(m, d);\n });\n\n return async function runWithSessionRetry<T>(\n // PromiseLike, not Promise: a supabase-js query builder is a thenable, so\n // callers can hand the builder straight back without an extra await.\n run: () => PromiseLike<AuthRetryableResult<T>>,\n ): Promise<\n AuthRetryableResult<T> & { retried: boolean; sessionRecovered: boolean }\n > {\n const { data: initialSession, error: initialSessionError } =\n await options.auth.getSession();\n if (!initialSession.session?.access_token || initialSessionError) {\n throw new SessionUnavailableError();\n }\n\n const first = await run();\n if (!isMissingSessionError(first.error, first.status)) {\n return { ...first, retried: false, sessionRecovered: false };\n }\n\n // getSession() re-reads the persisted session and refreshes it when\n // expired — the cheapest way to ask \"do we actually have a user right now?\"\n const { data, error: sessionError } = await options.auth.getSession();\n const recovered = Boolean(data.session?.access_token) && !sessionError;\n if (!recovered) {\n log(\n \"[authRetry] an operation reached the database with no authenticated session and the session could NOT be recovered — the user is signed out or their session expired. The operation was not retried.\",\n sessionError ?? first.error,\n );\n return { ...first, retried: false, sessionRecovered: false };\n }\n\n log(\n \"[authRetry] an operation reached the database with no authenticated session; the session re-resolved and the operation is being retried once. This is a recovery firing, which means a real session-availability bug got past the proactive layer.\",\n );\n const second = await run();\n return { ...second, retried: true, sessionRecovered: true };\n };\n}\n","/**\n * Shared auth-cookie options for EVERY Supabase client an application\n * constructs (browser, server, middleware, OAuth callbacks). All construction\n * sites MUST pass these options — a client using the default cookie name\n * cannot see the session the others wrote.\n *\n * WHY (the 2026-07 Matrx deployment split): one login must work on every\n * subdomain of the platform's apex (e.g. app.example.com, manage.example.com),\n * so on those hosts the auth cookie is issued domain-wide\n * (`Domain=.example.com`) instead of Supabase's default host-only cookie.\n *\n * The cookie is also RENAMED (default `sb-<project-ref>-auth-token` →\n * `sb-matrx-auth`): re-issuing an existing host-only cookie as domain-wide\n * under the SAME name leaves two same-name cookies in the browser (different\n * Domain attributes = distinct cookies), and whichever the browser sends\n * first wins — auth flaps. A new name makes the transition deterministic:\n * every user re-logs-in exactly once and the old cookie expires unused.\n * The `sb-` prefix is kept on purpose — cleanup paths that scrub session\n * cookies delete by that prefix.\n *\n * The Domain attribute is ONLY set on real apex hosts. localhost and preview\n * hosts get a host-only cookie — a browser rejects any Set-Cookie whose\n * Domain does not cover the current host, so setting it unconditionally would\n * silently break auth everywhere else.\n *\n * The apex domain is a VALUE the host passes in (never read from an env var\n * here): `createAuthCookie({ apexDomain: \"aimatrx.com\" })`.\n *\n * THE RENAME MIGRATION (0.5.0 — moved in from matrx-frontend, where it was\n * 44 lines of host code every other consumer would have had to re-derive):\n * replacing the auth authority (a new Supabase project) means a NEW cookie\n * name, and a tab still running the OLD bundle keeps writing the OLD name for\n * days. `migrateLegacyCookies` seeds the new storage key from the old one\n * ONLY when the new key is absent — never overwriting a live session — and\n * `isCurrentCookie` recognizes both the base name and Supabase's numbered\n * chunk suffixes (`<name>.0`, `<name>.1`, …), which a naive `startsWith`\n * check gets wrong for any cookie that merely shares the prefix.\n */\n\n/** Structurally compatible with @supabase/ssr's CookieOptionsWithName. */\nexport interface AuthCookieOptions {\n name: string;\n /** Remote hosts require HTTPS; loopback development remains usable over HTTP. */\n secure: boolean;\n domain?: string;\n}\n\n/** A cookie as read from a request — name + value, nothing else needed. */\nexport interface AuthCookieValue {\n name: string;\n value: string;\n}\n\nexport const DEFAULT_AUTH_COOKIE_NAME = \"sb-matrx-auth\";\n\nexport interface CreateAuthCookieArgs {\n /** The apex domain one login must span (e.g. `\"aimatrx.com\"`). */\n apexDomain: string;\n /** Override only for a second, unrelated deployment — never per-app. */\n cookieName?: string;\n /**\n * The storage key a PREVIOUS auth authority used. When present, cookies\n * under this name are seeded onto `cookieName` (absent-only) by\n * `migrateLegacyCookies`, and the middleware binding clears them at the\n * scope this host issued them on.\n */\n legacyCookieName?: string;\n}\n\nexport interface AuthCookie {\n cookieName: string;\n /** The superseded storage key, when this deployment has one. */\n legacyCookieName: string | undefined;\n /**\n * Cookie options for the host serving the current request.\n * @param host `Host` header or `window.location.hostname` (port tolerated).\n */\n optionsForHost(host: string | null | undefined): AuthCookieOptions;\n /** Browser variant — resolves the host from `window` (SSR-safe). */\n browserOptions(): AuthCookieOptions;\n /**\n * Is this cookie name the CURRENT auth cookie — base name or one of\n * Supabase's numbered chunks (`<name>.0`)? A prefix test is wrong: it\n * matches `<name>.anything`, including unrelated cookies.\n */\n isCurrentCookie(name: string): boolean;\n /**\n * Cookies to seed under the current name, derived from the legacy name.\n * Returns `[]` when any current cookie already exists (never overwrite a\n * live session) or when no legacy name is configured.\n */\n migrateLegacyCookies(\n cookies: readonly AuthCookieValue[],\n ): AuthCookieValue[];\n /**\n * THE POISONED-JAR READ. A browser can hold the SAME auth cookie name twice\n * — once host-only, once at `.apex` — because different Domain attributes\n * make distinct cookies, and it sends both in one `Cookie` header. Every\n * reassembler downstream (`@supabase/ssr`'s `combineChunks`) resolves a\n * chunk with `find()`, i.e. FIRST WINS, and the browser decides the order.\n * An empty shadow that sorts first therefore reassembles to `\"\"` and every\n * server read answers anonymous while the tab is signed in.\n *\n * This collapses each auth-cookie NAME to one entry, preferring the first\n * NON-EMPTY value. Non-auth cookies pass through untouched, in order.\n *\n * A `Cookie` header carries no Domain, so which scope a value came from is\n * genuinely unknowable here — non-empty-wins is the strongest correct rule\n * available, and `@supabase/ssr` already refuses a chunk set that decodes\n * incoherently. `shadowedNames` names every auth cookie that arrived more\n * than once, so the caller can EXPIRE the losing scope instead of leaving\n * the user to clear cookies by hand.\n *\n * THE SECOND POISON, AND IT IS AN IDENTITY LEAK: one storage key arriving\n * BOTH unchunked (`<name>`) and chunked (`<name>.0`, `<name>.1`). These are\n * DIFFERENT cookie names, so the per-name collapse above cannot see them,\n * and `@supabase/ssr`'s `combineChunks` returns the UNCHUNKED value the\n * moment it is non-empty — it never even reads the chunks. A stale base\n * cookie therefore shadows a freshly written chunked pair, and every read\n * resolves the PREVIOUS person while the new session sits unread beside it.\n * That is a different user's session being served, not merely a logout.\n *\n * `applyServerStorage` never writes that shape — it removes every chunk-like\n * sibling of whatever it writes — so a jar holding both is RESIDUE from a\n * removal that did not land (see `middlewareSession`: a two-scope removal\n * collapses on `ResponseCookies`, which is how this residue is made).\n *\n * WHICH COPY IS NEWER IS UNKNOWABLE HERE, and both directions of residue are\n * producible, so preferring either shape is a coin flip on WHOSE SESSION TO\n * SERVE. This drops the whole family from the read instead: nobody is signed\n * in, every name in it is returned in `ambiguousNames` to be expired, and the\n * host's honest-screen banner says so with the one action that fixes it. A\n * wrong sign-out is recoverable in one click; a wrong identity is not.\n */\n reconcile(cookies: readonly AuthCookieValue[]): ReconciledAuthCookies;\n}\n\n/** The outcome of {@link AuthCookie.reconcile}. */\nexport interface ReconciledAuthCookies {\n /** One entry per name; auth names resolved to their non-empty value. */\n cookies: AuthCookieValue[];\n /** Auth cookie names that arrived more than once (i.e. at two scopes). */\n shadowedNames: string[];\n /**\n * Auth cookie names belonging to a storage key that arrived UNCHUNKED AND\n * CHUNKED at once — see {@link AuthCookie.reconcile}. Their values have been\n * dropped from `cookies`, and they must be expired on EVERY host, including\n * the ones that issue a host-only cookie: unlike a two-scope shadow there is\n * no copy here that could be the good one.\n */\n ambiguousNames: string[];\n /** The storage keys that arrived in both shapes. Named for the scream. */\n ambiguousKeys: string[];\n /** `true` when the jar is split and needs healing. */\n split: boolean;\n}\n\n/**\n * Parse a raw `Cookie` request header, **PRESERVING DUPLICATES AND ORDER**.\n *\n * 🚨 THIS IS THE ONLY WAY TO SEE A SPLIT JAR. Next's `RequestCookies` (and the\n * `cookies()` store built on it) parses the header into a Map keyed by NAME,\n * so two same-name cookies at two Domain scopes collapse to ONE before any\n * application code runs — and the survivor is whichever the browser happened\n * to send LAST. Measured against the real class:\n *\n * \"sb-…-v2.0=; sb-…-v2.0=base64-REAL\" -> [{ value: \"base64-REAL\" }] works\n * \"sb-…-v2.0=base64-REAL; sb-…-v2.0=\" -> [{ value: \"\" }] anonymous\n *\n * That coin flip IS the production break, and it is invisible from the\n * collapsed jar: reconciliation over `getAll()` is a no-op no matter how\n * carefully it is written. Every door must therefore reconcile over THIS.\n */\nexport function parseCookieHeader(\n header: string | null | undefined,\n): AuthCookieValue[] {\n if (!header) return [];\n const out: AuthCookieValue[] = [];\n for (const pair of header.split(\";\")) {\n const eq = pair.indexOf(\"=\");\n // A valueless segment is a name with an empty value — exactly the shadow\n // this exists to catch — so it must not be skipped.\n const name = (eq === -1 ? pair : pair.slice(0, eq)).trim();\n if (!name) continue;\n const raw = eq === -1 ? \"\" : pair.slice(eq + 1).trim();\n let value = raw;\n try {\n value = decodeURIComponent(raw);\n } catch {\n // A malformed escape is not a reason to lose the cookie; Next's parser\n // keeps the raw text too.\n }\n out.push({ name, value });\n }\n return out;\n}\n\n/**\n * Is `name` the storage key itself or one of its numbered chunks? The same\n * membership test `@supabase/ssr`'s `isChunkLike` uses, so a family is defined\n * here exactly as the writer defines it. A bare `startsWith` is wrong: it also\n * matches `<key>.anything`, i.e. unrelated cookies.\n */\nfunction belongsToStorageKey(name: string, storageKey: string): boolean {\n if (name === storageKey) return true;\n if (!name.startsWith(`${storageKey}.`)) return false;\n return /^(0|[1-9][0-9]*)$/.test(name.slice(storageKey.length + 1));\n}\n\n/** `<from>` → `<to>`, carrying Supabase's numbered chunk suffix across. */\nfunction renamedCookie(\n cookie: AuthCookieValue,\n from: string,\n to: string,\n): AuthCookieValue | null {\n if (cookie.name === from) return { ...cookie, name: to };\n const prefix = `${from}.`;\n if (!cookie.name.startsWith(prefix)) return null;\n const chunk = cookie.name.slice(prefix.length);\n if (!/^(0|[1-9][0-9]*)$/.test(chunk)) return null;\n return { ...cookie, name: `${to}.${chunk}` };\n}\n\nexport function createAuthCookie(args: CreateAuthCookieArgs): AuthCookie {\n const cookieName = args.cookieName ?? DEFAULT_AUTH_COOKIE_NAME;\n const legacyCookieName = args.legacyCookieName;\n const apex = args.apexDomain.toLowerCase();\n\n const optionsForHost = (\n host: string | null | undefined,\n ): AuthCookieOptions => {\n const normalized = (host ?? \"\").toLowerCase();\n const hostname = normalized.startsWith(\"[\")\n ? normalized.slice(1, normalized.indexOf(\"]\"))\n : normalized === \"::1\" ? normalized : normalized.split(\":\")[0] ?? \"\";\n const loopback = hostname === \"localhost\" || hostname.endsWith(\".localhost\") ||\n hostname === \"::1\" || /^127(?:\\.(?:0|[1-9]\\d{0,2})){3}$/.test(hostname) &&\n hostname.split(\".\").every((part) => Number(part) <= 255);\n const secure = !loopback;\n const onApex = hostname === apex || hostname.endsWith(`.${apex}`);\n return onApex\n ? { name: cookieName, domain: `.${apex}`, secure }\n : { name: cookieName, secure };\n };\n\n const isCurrentCookie = (name: string): boolean =>\n belongsToStorageKey(name, cookieName);\n\n const isAuthCookie = (name: string): boolean =>\n isCurrentCookie(name) ||\n (legacyCookieName !== undefined &&\n (name === legacyCookieName || name.startsWith(`${legacyCookieName}.`)));\n\n const reconcile = (\n cookies: readonly AuthCookieValue[],\n ): ReconciledAuthCookies => {\n const seen = new Map<string, number>();\n const out: AuthCookieValue[] = [];\n const shadowed = new Set<string>();\n\n for (const cookie of cookies) {\n const at = seen.get(cookie.name);\n if (at === undefined) {\n seen.set(cookie.name, out.length);\n out.push({ name: cookie.name, value: cookie.value });\n continue;\n }\n if (!isAuthCookie(cookie.name)) continue; // non-auth: first wins, as before\n shadowed.add(cookie.name);\n const held = out[at];\n // Non-empty wins. Later non-empty values do NOT displace an earlier\n // non-empty one — with no scope information, churning the choice would\n // make reassembly non-deterministic across requests.\n if (held !== undefined && held.value.length === 0) {\n out[at] = { name: cookie.name, value: cookie.value };\n }\n }\n\n // THE FAMILY PASS. A storage key may arrive unchunked AND chunked at once;\n // those are different NAMES, so the collapse above cannot have seen it.\n // `combineChunks` would take the unchunked value and never read the chunks,\n // which serves whichever person's session happens to be sitting in the base\n // cookie. Refuse the family instead of guessing — see `reconcile`'s docs.\n const ambiguous = new Set<string>();\n const ambiguousKeys: string[] = [];\n const byName = new Map(out.map((cookie) => [cookie.name, cookie] as const));\n const storageKeys = [cookieName, ...(legacyCookieName ? [legacyCookieName] : [])];\n for (const storageKey of storageKeys) {\n const unchunked = byName.get(storageKey);\n const firstChunk = byName.get(`${storageKey}.0`);\n if (!unchunked?.value || !firstChunk?.value) continue;\n ambiguousKeys.push(storageKey);\n for (const { name } of out) {\n if (belongsToStorageKey(name, storageKey)) ambiguous.add(name);\n }\n }\n\n const resolved =\n ambiguous.size === 0\n ? out\n : out.filter(({ name }) => !ambiguous.has(name));\n\n const shadowedNames = [...shadowed];\n const ambiguousNames = [...ambiguous];\n return {\n cookies: resolved,\n shadowedNames,\n ambiguousNames,\n ambiguousKeys,\n split: shadowedNames.length > 0 || ambiguousNames.length > 0,\n };\n };\n\n return {\n cookieName,\n legacyCookieName,\n optionsForHost,\n reconcile,\n browserOptions: () =>\n optionsForHost(\n typeof window !== \"undefined\" ? window.location.hostname : null,\n ),\n isCurrentCookie,\n migrateLegacyCookies: (cookies) => {\n if (!legacyCookieName) return [];\n if (cookies.some(({ name }) => isCurrentCookie(name))) return [];\n return cookies.flatMap((cookie) => {\n const renamed = renamedCookie(cookie, legacyCookieName, cookieName);\n return renamed ? [renamed] : [];\n });\n },\n };\n}\n","/**\n * THE ACTIVE-ORGANIZATION COOKIE — one browser-stored \"which organization am I\n * acting in\" shared by EVERY Matrx web surface on the same apex.\n *\n * WHY (2026-09-08, the Workflow Studio `organization_not_selected` incident):\n * the main app (www.aimatrx.com) remembered the last active organization in\n * its own IndexedDB/localStorage cache; Workflow Studio (workflows.aimatrx.com)\n * remembered its own choice under `matrx_studio_org`; the admin dashboard\n * under `matrx_dashboard_org`. Three origins, three memories, and a person who\n * had been working in one organization for weeks opened Studio and was\n * refused on every request until they picked again — a choice they had\n * already made. Browser storage is per-origin; a cookie issued at the apex\n * (`Domain=.aimatrx.com`) is the ONE browser-stored value every subdomain can\n * read, exactly how the platform already shares its login (see\n * `auth-cookie.ts`). Cookies also ignore ports, so localhost:3000 and\n * localhost:3101 share it in development.\n *\n * WHAT IT IS, AND IS NOT:\n * - It is the FIRST rung of the canonical resolution order (stored selection\n * → sole membership → make the user pick; a saved default is display-only;\n * ruling: common-docs/projects/no-db-assigned-org/PLAN.md row EX-T05). A\n * consumer still validates the stored id against live membership and\n * drops it when the membership is gone — this module stores, it never\n * decides.\n * - It is IDENTITY-KEYED: the value carries the user id it was written for,\n * and `read(userId)` answers null for anybody else. A second person\n * signing in on the same browser must never inherit the first person's\n * workspace (the same rule the sync engine applies to every persisted\n * slice). Sign-out calls `clear()` on top of that.\n * - It is NOT a security boundary. The server admits a request only when\n * the `X-Organization-Id` it carries is a verified membership of the\n * bearer; this cookie only remembers which of those the person chose.\n * - It is NOT httpOnly — hosts read and write it from the browser. Nothing\n * secret is in it.\n *\n * The Domain attribute is set ONLY on a real apex host (the same rule and the\n * same reason as the auth cookie: a browser silently rejects a Set-Cookie\n * whose Domain does not cover the current host). Studio runs on TWO apexes\n * (workflows.aimatrx.com and studio.app.matrxserver.com), so this takes a\n * list; the first apex that covers the host wins.\n */\n\nimport { parseCookieHeader, type AuthCookieValue } from \"./auth-cookie\";\nimport { isUuidShape } from \"@ai-matrx/kit/uuid\";\n\nexport const DEFAULT_ACTIVE_ORG_COOKIE_NAME = \"matrx-active-org\";\n\n/** One year — the same horizon the platform's other preference cookies use. */\nexport const DEFAULT_ACTIVE_ORG_COOKIE_MAX_AGE = 60 * 60 * 24 * 365;\n\nexport interface ActiveOrgCookieOptions {\n name: string;\n domain?: string;\n}\n\n/** The stored fact: WHO chose WHICH organization. */\nexport interface ActiveOrgSelection {\n userId: string;\n organizationId: string;\n}\n\nexport interface CreateActiveOrgCookieArgs {\n /**\n * The apex domains one selection must span, e.g.\n * `[\"aimatrx.com\", \"matrxserver.com\"]`. Order matters only when two apexes\n * could cover one host, which they never should.\n */\n apexDomains: readonly string[];\n /** Override only for a second, unrelated deployment — never per-app. */\n cookieName?: string;\n /** Lifetime in seconds. Defaults to one year. */\n maxAgeSeconds?: number;\n}\n\nexport interface ActiveOrgCookie {\n cookieName: string;\n /**\n * Cookie options for the host serving the current request.\n * @param host `Host` header or `window.location.hostname` (port tolerated).\n */\n optionsForHost(host: string | null | undefined): ActiveOrgCookieOptions;\n /**\n * The organization `userId` last chose, from a raw `Cookie` request header\n * (SSR) — or null when nothing is stored, the value is malformed, or it\n * belongs to a different person.\n */\n readFromCookieHeader(\n header: string | null | undefined,\n userId: string | null | undefined,\n ): string | null;\n /** Browser read of the same fact from `document.cookie`. SSR-safe (null). */\n read(userId: string | null | undefined): string | null;\n /**\n * Record `userId`'s choice in the browser at the scope `optionsForHost`\n * decides for this host. A previous host-only copy is expired first so the\n * jar never holds two same-name cookies at two scopes (whichever the\n * browser sent first would win — see `auth-cookie.ts` on split jars).\n */\n write(selection: ActiveOrgSelection): void;\n /**\n * Forget the selection in the browser — at EVERY scope this host could have\n * issued it (domain-wide and host-only), so sign-out cannot leave a copy\n * behind for the next person.\n */\n clear(): void;\n /**\n * A `Set-Cookie` header value recording `selection` for `host` (null →\n * an expiring cookie). For servers that want to write it; browsers use\n * `write`.\n */\n serialize(\n host: string | null | undefined,\n selection: ActiveOrgSelection | null,\n secure?: boolean,\n ): string;\n}\n\n/** `<userId>:<organizationId>` — two UUIDs, one separator. */\nexport function encodeActiveOrgSelection(selection: ActiveOrgSelection): string {\n if (!isUuidShape(selection.userId) || !isUuidShape(selection.organizationId)) {\n throw new Error(\n \"encodeActiveOrgSelection: userId and organizationId must both be UUIDs.\",\n );\n }\n return `${selection.userId.toLowerCase()}:${selection.organizationId.toLowerCase()}`;\n}\n\n/** Inverse of {@link encodeActiveOrgSelection}. Null for anything malformed. */\nexport function decodeActiveOrgSelection(\n raw: string | null | undefined,\n): ActiveOrgSelection | null {\n if (!raw) return null;\n const parts = raw.split(\":\");\n if (parts.length !== 2) return null;\n const [userId, organizationId] = parts as [string, string];\n if (!isUuidShape(userId) || !isUuidShape(organizationId)) return null;\n return {\n userId: userId.toLowerCase(),\n organizationId: organizationId.toLowerCase(),\n };\n}\n\nfunction selectionFor(\n cookies: readonly AuthCookieValue[],\n cookieName: string,\n userId: string | null | undefined,\n): string | null {\n if (!userId) return null;\n const wanted = userId.toLowerCase();\n // Duplicates are possible (two Domain scopes) and arrive in browser order;\n // the first copy that belongs to THIS person wins, and a copy belonging to\n // anybody else is simply not an answer.\n for (const cookie of cookies) {\n if (cookie.name !== cookieName) continue;\n const decoded = decodeActiveOrgSelection(cookie.value);\n if (decoded && decoded.userId === wanted) return decoded.organizationId;\n }\n return null;\n}\n\nfunction attributes(\n options: ActiveOrgCookieOptions,\n maxAge: number,\n secure: boolean,\n): string {\n const parts = [`Path=/`, `Max-Age=${maxAge}`, `SameSite=Lax`];\n if (options.domain) parts.push(`Domain=${options.domain}`);\n if (secure) parts.push(\"Secure\");\n return parts.join(\"; \");\n}\n\nfunction hasDocument(): boolean {\n return typeof document !== \"undefined\" && typeof document.cookie === \"string\";\n}\n\nexport function createActiveOrgCookie(\n args: CreateActiveOrgCookieArgs,\n): ActiveOrgCookie {\n const cookieName = args.cookieName ?? DEFAULT_ACTIVE_ORG_COOKIE_NAME;\n const maxAge = args.maxAgeSeconds ?? DEFAULT_ACTIVE_ORG_COOKIE_MAX_AGE;\n const apexes = args.apexDomains.map((apex) => apex.toLowerCase());\n\n const optionsForHost = (\n host: string | null | undefined,\n ): ActiveOrgCookieOptions => {\n const hostname = (host ?? \"\").split(\":\")[0]?.toLowerCase() ?? \"\";\n const apex = apexes.find(\n (candidate) => hostname === candidate || hostname.endsWith(`.${candidate}`),\n );\n return apex ? { name: cookieName, domain: `.${apex}` } : { name: cookieName };\n };\n\n const serialize = (\n host: string | null | undefined,\n selection: ActiveOrgSelection | null,\n secure = false,\n ): string => {\n const options = optionsForHost(host);\n if (!selection) {\n return `${cookieName}=; ${attributes(options, 0, secure)}`;\n }\n return `${cookieName}=${encodeActiveOrgSelection(selection)}; ${attributes(options, maxAge, secure)}`;\n };\n\n const browserHost = (): string | null =>\n typeof window !== \"undefined\" ? window.location.hostname : null;\n const browserSecure = (): boolean =>\n typeof window !== \"undefined\" && window.location.protocol === \"https:\";\n\n const expireHostOnly = (secure: boolean): void => {\n document.cookie = `${cookieName}=; ${attributes({ name: cookieName }, 0, secure)}`;\n };\n\n return {\n cookieName,\n optionsForHost,\n serialize,\n readFromCookieHeader: (header, userId) =>\n selectionFor(parseCookieHeader(header), cookieName, userId),\n read: (userId) => {\n if (!hasDocument()) return null;\n return selectionFor(parseCookieHeader(document.cookie), cookieName, userId);\n },\n write: (selection) => {\n if (!hasDocument()) return;\n const host = browserHost();\n const secure = browserSecure();\n // Writing domain-wide on an apex host: retire any host-only copy first\n // so exactly one cookie under this name exists afterwards.\n if (optionsForHost(host).domain) expireHostOnly(secure);\n document.cookie = serialize(host, selection, secure);\n },\n clear: () => {\n if (!hasDocument()) return;\n const host = browserHost();\n const secure = browserSecure();\n expireHostOnly(secure);\n if (optionsForHost(host).domain) {\n document.cookie = serialize(host, null, secure);\n }\n },\n };\n}\n","/**\n * Realtime channel hygiene — RE-EXPORT ONLY. The canonical home is\n * `@ai-matrx/realtime`.\n *\n * Channel NAMING belongs to the realtime package (its work order, R1): it owns\n * the channel-naming registry, and `uniqueChannelTopic` is the React-19\n * double-invoked-effect collision guard that registry hands out. This package\n * kept the only copy while `@ai-matrx/realtime` was unpublished; that copy is\n * now DELETED and this module forwards, so the two can never drift and the\n * `#`-suffixed instance topics a Matrx app opens all come from one counter.\n *\n * Why forwarding matters and a second copy would not do: the old\n * implementation kept its sequence in a module-level `let`. With unsplit dual\n * ESM/CJS output a module can be instantiated twice in one process, so two\n * counters both starting at 1 hand out the same \"unique\" topic twice — exactly\n * the collision the function exists to prevent. The realtime package keeps the\n * counter in a `globalThis` slot (`Symbol.for`) and proves it across module\n * graphs in its packed-tarball canary.\n *\n * `@ai-matrx/realtime` is the deeper layer (zero runtime dependencies; it does\n * not and must not depend on `@ai-matrx/data`), so this direction keeps the\n * sibling graph acyclic — `node scripts/check_ts_sibling_graph.mjs`.\n *\n * New realtime work should not reach for this at all: declare a channel\n * namespace with `defineChannelNamespace` and let the manager assign the\n * instance topic. This export exists for the call sites that have not yet\n * migrated off hand-rolled `.channel(` blocks.\n */\n\nexport { uniqueChannelTopic } from \"@ai-matrx/realtime\";\n","/**\n * OAuth-aware transport for a Supabase auth-js client.\n *\n * Supabase's ordinary GoTrue refresh endpoint is `/auth/v1/token`, while a\n * session minted for a registered OAuth client must refresh at\n * `/auth/v1/oauth/token` and include that client id. auth-js owns session\n * storage, locking, rotation and notifications; this module changes only the\n * one outbound refresh request after proving that its refresh token belongs to\n * an allowlisted OAuth client. It never calls `auth.getSession()`.\n */\n\nexport interface OAuthRefreshStorage {\n getItem(key: string): string | null | Promise<string | null>;\n}\n\nexport interface CreateOAuthRefreshFetchArgs {\n /** The exact Supabase project origin, e.g. `https://db.matrxserver.com`. */\n supabaseUrl: string;\n /** The same auth storage auth-js uses. */\n storage: OAuthRefreshStorage;\n /** The auth-js storage key containing the persisted session JSON. */\n storageKey: string;\n /** Public OAuth client ids this host is intentionally allowed to refresh. */\n oauthClientIds: readonly string[];\n /** Injectable only for tests and non-browser hosts. */\n fetch?: typeof globalThis.fetch;\n}\n\ninterface StoredSession {\n access_token?: unknown;\n refresh_token?: unknown;\n user?: unknown;\n}\n\ninterface JwtClaims {\n sub?: unknown;\n client_id?: unknown;\n exp?: unknown;\n}\n\nfunction object(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction text(value: unknown): string | null {\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\n/** Decode routing metadata only. The server remains the authentication authority. */\nexport function decodeOAuthRefreshClaims(token: string): JwtClaims | null {\n const payload = token.split(\".\")[1];\n if (!payload) return null;\n try {\n const normalized = payload.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized + \"=\".repeat((4 - (normalized.length % 4)) % 4);\n const json = typeof atob === \"function\"\n ? atob(padded)\n : Buffer.from(padded, \"base64\").toString(\"utf8\");\n return object(JSON.parse(json)) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction isOrdinaryRefreshRequest(input: RequestInfo | URL, init: RequestInit | undefined, origin: string): boolean {\n const request = input instanceof Request ? input : null;\n const url = new URL(request?.url ?? String(input), origin);\n const method = (init?.method ?? request?.method ?? \"GET\").toUpperCase();\n return method === \"POST\" &&\n url.origin === origin &&\n url.pathname === \"/auth/v1/token\" &&\n url.searchParams.get(\"grant_type\") === \"refresh_token\";\n}\n\nasync function refreshTokenFrom(input: RequestInfo | URL, init: RequestInit | undefined): Promise<string | null> {\n let body = init?.body;\n // auth-js currently supplies init.body, but accepting a Request keeps this a\n // transparent Fetch transport for callers that put the body on the Request.\n // clone() is essential: consuming the original body would break normal fetch.\n if (body === undefined && input instanceof Request) body = await input.clone().text();\n if (body instanceof URLSearchParams) return body.get(\"refresh_token\");\n if (typeof body !== \"string\") return null;\n try {\n return text(object(JSON.parse(body))?.refresh_token);\n } catch {\n return new URLSearchParams(body).get(\"refresh_token\");\n }\n}\n\nfunction rewrittenInit(input: RequestInfo | URL, init: RequestInit | undefined, headers: Headers, body: URLSearchParams): RequestInit {\n const request = input instanceof Request ? input : null;\n const copied: RequestInit = {\n // init takes precedence, just as native fetch does. Copying Request fields\n // preserves the public Fetch contract after replacing its body.\n method: \"POST\",\n headers,\n body,\n };\n const inherited = {\n credentials: init?.credentials ?? request?.credentials,\n cache: init?.cache ?? request?.cache,\n redirect: init?.redirect ?? request?.redirect,\n referrer: init?.referrer ?? request?.referrer,\n referrerPolicy: init?.referrerPolicy ?? request?.referrerPolicy,\n integrity: init?.integrity ?? request?.integrity,\n keepalive: init?.keepalive ?? request?.keepalive,\n signal: init?.signal ?? request?.signal,\n };\n for (const [key, value] of Object.entries(inherited)) {\n if (value !== undefined) Object.assign(copied, { [key]: value });\n }\n return copied;\n}\n\nasync function storedSession(storage: OAuthRefreshStorage, key: string): Promise<StoredSession | null> {\n const raw = await storage.getItem(key);\n if (!raw) return null;\n try {\n return object(JSON.parse(raw)) as StoredSession | null;\n } catch {\n return null;\n }\n}\n\nfunction sameSubject(previousAccessToken: string, refreshedAccessToken: string, clientId: string): boolean {\n const previous = decodeOAuthRefreshClaims(previousAccessToken);\n const refreshed = decodeOAuthRefreshClaims(refreshedAccessToken);\n return text(previous?.sub) !== null && previous?.sub === refreshed?.sub && previous?.client_id === clientId && refreshed?.client_id === clientId;\n}\n\nfunction retryableRefusal(message: string): Response {\n // auth-js treats 5xx responses as retryable and keeps its persisted session.\n // A 400 would make an expired client clear the identity we intentionally did\n // not send to GoTrue (unknown client or storage mismatch).\n return new Response(JSON.stringify({ error: \"temporarily_unavailable\", error_description: message }), {\n status: 503,\n headers: { \"content-type\": \"application/json\", \"retry-after\": \"1\" },\n });\n}\n\nasync function normalizeOAuthResponse(\n response: Response,\n session: StoredSession,\n clientId: string,\n): Promise<Response> {\n if (!response.ok) return response;\n const previousAccessToken = text(session.access_token);\n const previousUser = session.user;\n const previousSubject = previousAccessToken ? text(decodeOAuthRefreshClaims(previousAccessToken)?.sub) : null;\n if (!previousAccessToken || !previousSubject || text(object(previousUser)?.id) !== previousSubject) {\n return retryableRefusal(\"Stored OAuth identity does not match its credential. Restore the account connection.\");\n }\n let payload: Record<string, unknown> | null = null;\n try {\n payload = object(await response.clone().json());\n } catch {\n return retryableRefusal(\"OAuth refresh returned an invalid response.\");\n }\n const refreshedAccessToken = text(payload?.access_token);\n if (!payload || !refreshedAccessToken || !sameSubject(previousAccessToken, refreshedAccessToken, clientId)) {\n return retryableRefusal(\"OAuth refresh returned a credential for an unexpected identity or client.\");\n }\n if (payload.user !== undefined && text(object(payload.user)?.id) !== previousSubject) {\n return retryableRefusal(\"OAuth refresh returned a user that does not match its credential.\");\n }\n if (payload.user === undefined) payload.user = previousUser;\n if (text(payload.refresh_token) === null) payload.refresh_token = session.refresh_token;\n const headers = new Headers(response.headers);\n headers.set(\"content-type\", \"application/json\");\n return new Response(JSON.stringify(payload), {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n\nasync function replacementAfterRejectedRefresh(\n response: Response,\n storage: OAuthRefreshStorage,\n storageKey: string,\n previous: StoredSession,\n clientId: string,\n): Promise<Response> {\n if (response.status !== 400 && response.status !== 401) return response;\n const replacement = await storedSession(storage, storageKey);\n const previousRefresh = text(previous.refresh_token);\n const replacementRefresh = text(replacement?.refresh_token);\n const previousAccess = text(previous.access_token);\n const replacementAccess = text(replacement?.access_token);\n if (!replacement || !previousRefresh || !replacementRefresh || replacementRefresh === previousRefresh ||\n !previousAccess || !replacementAccess || !sameSubject(previousAccess, replacementAccess, clientId) ||\n replacement.user === undefined) return response;\n return new Response(JSON.stringify(replacement), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n}\n\n/**\n * Returns a fetch implementation suitable for `createClient(..., { global:\n * { fetch } })`. Normal sessions and unrelated requests pass through exactly.\n */\nexport function createOAuthRefreshFetch(args: CreateOAuthRefreshFetchArgs): typeof globalThis.fetch {\n const origin = new URL(args.supabaseUrl).origin;\n const upstream = args.fetch ?? globalThis.fetch;\n const allowed = new Set(args.oauthClientIds);\n\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n if (!isOrdinaryRefreshRequest(input, init, origin)) return upstream(input, init);\n const refreshToken = await refreshTokenFrom(input, init);\n const session = await storedSession(args.storage, args.storageKey);\n const storedRefreshToken = text(session?.refresh_token);\n const accessToken = text(session?.access_token);\n const clientId = accessToken ? text(decodeOAuthRefreshClaims(accessToken)?.client_id) : null;\n if (!session || !clientId) {\n return upstream(input, init);\n }\n if (!allowed.has(clientId)) return retryableRefusal(\"This OAuth client is not allowed to refresh in this host.\");\n // This is an OAuth-owned session, but the caller did not send the refresh\n // token that storage associates with it. Forwarding that unknown token to\n // GoTrue's ordinary endpoint could refresh a different actor; auth-js will\n // re-read its stored session after the typed refusal instead.\n if (!refreshToken || refreshToken !== storedRefreshToken) {\n return retryableRefusal(\"OAuth refresh token no longer matches the stored session; resolve the session again.\");\n }\n\n const request = input instanceof Request ? input : null;\n const headers = new Headers(init?.headers ?? request?.headers);\n headers.set(\"content-type\", \"application/x-www-form-urlencoded\");\n const body = new URLSearchParams({ grant_type: \"refresh_token\", refresh_token: refreshToken, client_id: clientId });\n const response = await upstream(`${origin}/auth/v1/oauth/token`, rewrittenInit(input, init, headers, body));\n const adopted = await replacementAfterRejectedRefresh(response, args.storage, args.storageKey, session, clientId);\n const responseSession = adopted === response ? session : (await storedSession(args.storage, args.storageKey)) ?? session;\n return normalizeOAuthResponse(adopted, responseSession, clientId);\n };\n}\n","// @ai-matrx/data/db — write-failure: a failed write is said in words, with a remedy.\n// Ported verbatim from matrx-frontend `lib/errors/writeFailure.ts` (which now re-exports this\n// module, so `WriteRefusedError` is ONE class everywhere and every `instanceof` keeps working).\n//\n//\n// A FAILED WRITE IS SAID IN WORDS, WITH A REMEDY — NEVER AS METHOD, PATH AND STATUS.\n//\n// VERIFIER-21 injected a 500 on a schedule's Pause and the person read:\n// PATCH /scheduler/tasks/2be9cc7c… 500 — \"injected failure\"\n// That is a developer's log line on a customer's screen. The rule (a screen never lies, and\n// nothing fails silently): a failure says what did not happen, why in plain words, and what to\n// do — \"Could not pause this schedule. The server refused the request. Try again or open the\n// schedule's activity.\" No status code, method or path on screen (VERIFIER-23 #6 caught the toast\n// still reading \"(500)\") — the technical line is kept on the error (`technical`) for diagnostics.\n//\n// Two pieces, one per side of the wire:\n// - `WriteRefusedError` — what a hand-rolled fetch client throws for a non-2xx answer. Its\n// `message` is already a sentence, so a caller that renders `err.message` is honest too.\n// - `describeWriteFailure(err, { action, remedy })` — the words for ANY error (this one,\n// `BackendApiError`, a network failure), and `toastWriteFailure` puts them on screen.\n\n/** A non-2xx answer from a server, with the words already chosen. */\nexport class WriteRefusedError extends Error {\n readonly status: number;\n /** What the server said for a person, when it said something a person can read. */\n readonly serverMessage: string | null;\n /** The developer line (method, path, status, body) — for diagnostics, never for the screen. */\n readonly technical: string;\n\n constructor(args: { status: number; serverMessage?: string | null; technical: string }) {\n super(refusalSentence(args.status, args.serverMessage ?? null));\n this.name = \"WriteRefusedError\";\n this.status = args.status;\n this.serverMessage = args.serverMessage ?? null;\n this.technical = args.technical;\n }\n}\n\n/** Pull a human sentence out of a FastAPI-style error body, or null when there is none. */\nexport function serverMessageFromBody(body: unknown): string | null {\n if (!body || typeof body !== \"object\") return null;\n const b = body as Record<string, unknown>;\n const detail = b.detail;\n const pick = (v: unknown): string | null => (typeof v === \"string\" && v.trim() !== \"\" ? v.trim() : null);\n if (detail && typeof detail === \"object\" && !Array.isArray(detail)) {\n const d = detail as Record<string, unknown>;\n return pick(d.user_message) ?? pick(d.message);\n }\n return pick(b.user_message) ?? pick(detail) ?? pick(b.message);\n}\n\nconst LOOKS_TECHNICAL =\n /(^|\\s)(GET|POST|PUT|PATCH|DELETE)\\s+\\/|https?:\\/\\/|\\bHTTP \\d{3}\\b|Traceback|Exception\\b|permission denied for|violates|row-level security|\\brelation \"|\\bcolumn \"|\\bfunction .* does not exist|\\bPGRST\\d+|\\bJWT\\b|duplicate key|syntax error|invalid input syntax|JSON object requested|rows returned|\\bnull value in column|\\bundefined\\b|\\bat [\\w.]+ \\(/i;\n\n/**\n * THE STORE'S OWN WORDS, WHEN IT SAID SOME (lane HANDOVER, 2026-09-27). A door that refuses raises a\n * sentence for a person — `You can see this record, but \"Allergies\" is not yours to change.` — or the\n * same sentence behind its own name (`cat_write: this category is not yours to change.`). Postgres's\n * native refusals (`permission denied for table …`, `new row violates …`) are never that. This hands\n * back the door's sentence, capitalised and ended, or null when the text is not a person's words.\n * test@test.com's refused Allergies edit read \"Permission denied\" because the scopes mapper threw\n * the door's sentence away for a fixed string.\n */\nexport function personSentence(text: unknown): string | null {\n if (typeof text !== \"string\") return null;\n let said = text.trim();\n const named = /^[a-z][a-z0-9_]*[a-z0-9]: (.+)$/s.exec(said);\n if (named) said = (named[1] ?? \"\").trim().replace(/^[a-z]/, (c) => c.toUpperCase());\n if (said.length < 8 || LOOKS_TECHNICAL.test(said) || !/^[A-Z\"“']/.test(said) || !/\\s/.test(said)) return null;\n return /[.!?][\"”']?$/.test(said) ? said : `${said}.`;\n}\n\n/**\n * A PostgREST / Postgres refusal (a supabase-js `PostgrestError`, or a server action that passed one\n * through): `{ code, message, details, hint }`. Its `message` is the database's own line\n * (\"new row violates row-level security policy for table …\") — never words for a person.\n */\nfunction isPostgrestShaped(err: unknown): err is { code: string; message?: string } {\n if (!err || typeof err !== \"object\") return false;\n const code = (err as { code?: unknown }).code;\n return typeof code === \"string\" && /^(PGRST\\d{3}|[0-9A-Z]{5})$/.test(code) && !(\"status\" in err && typeof (err as { status?: unknown }).status === \"number\");\n}\n\n/** A `WriteRefusedError` (or subclass) after Redux Toolkit serialized it. */\nfunction isSerializedRefusal(err: unknown): err is { name: string; message: string } {\n if (!err || typeof err !== \"object\" || err instanceof Error) return false;\n const e = err as { name?: unknown; message?: unknown };\n if (typeof e.message !== \"string\" || e.message.trim() === \"\") return false;\n if (e.name === \"WriteRefusedError\" || e.name === \"WriteDidNotLandError\") return true;\n // A thunk that threw a plain `new Error(<the store's sentence>)` crosses `.unwrap()` as\n // `{ name: \"Error\", message }` (lane HANDOVER, 2026-09-27: a member's refused context value read\n // \"Failed to save\" while the store had said \"…is not yours to change.\"). Its words are a person's\n // sentence when they do not read as technical.\n return e.name === \"Error\" && !LOOKS_TECHNICAL.test(e.message);\n}\n\nfunction postgrestSentence(code: string): string {\n if (code === \"42501\" || code === \"PGRST301\" || code === \"PGRST302\") return \"You do not have permission to do this.\";\n if (code === \"PGRST303\" || code === \"PGRST300\") return \"Your sign-in has expired. Sign in again, then try again.\";\n if (code === \"PGRST116\") return \"It is no longer there — it may have been deleted.\";\n if (code === \"23505\") return \"Something with the same name or key already exists.\";\n if (code === \"23503\") return \"It refers to something that no longer exists.\";\n if (code === \"23514\" || code === \"23502\" || code === \"22P02\") return \"The database would not accept that value.\";\n if (code === \"57014\") return \"The database took too long to answer.\";\n if (code === \"40001\" || code === \"40P01\") return \"It changed while you were working. Reload to see the latest.\";\n return \"The database refused it.\";\n}\n\n/**\n * A direct Supabase write that matched no row answers WITHOUT an error (RLS filters the row out,\n * or it is gone), so the screen would say \"saved\" over nothing. Pass the `.select()` rows of an\n * update/upsert: zero rows is a refusal, said in words.\n */\nexport function assertWriteLanded<T>(rows: T[] | T | null | undefined, technical: string): void {\n const n = Array.isArray(rows) ? rows.length : rows == null ? 0 : 1;\n if (n > 0) return;\n throw new WriteRefusedError({\n status: 403,\n serverMessage: \"Nothing was saved: you may not have permission to change this, or it no longer exists.\",\n technical: `${technical} matched 0 rows`,\n });\n}\n\nfunction refusalSentence(status: number, serverMessage: string | null): string {\n const said = serverMessage && !LOOKS_TECHNICAL.test(serverMessage) ? serverMessage : null;\n if (status === 401) return \"Your sign-in has expired. Sign in again, then try again.\";\n if (status === 403) return said ?? \"You do not have permission to do this.\";\n if (status === 404) return said ?? \"It is no longer there — it may have been deleted.\";\n if (status === 409 || status === 412) return said ?? \"It changed while you were working. Reload to see the latest.\";\n // A 5xx body is the server's own failure text, not a sentence for a person.\n // No status code, method or path on screen — that is a developer's log line, kept on\n // `technical` for diagnostics only (GATES-TAIL, VERIFIER-23 #6: the toast still read \"(500)\").\n if (status >= 500) return \"The server refused the request.\";\n if (said) return `The server said: ${said.replace(/\\.?$/, \".\")}`;\n return \"The server did not accept it.\";\n}\n\nexport interface WriteFailureWords {\n /** \"Could not pause this schedule.\" */\n title: string;\n /** Why, in words, then the remedy. */\n description: string;\n}\n\n/**\n * The words for a failed write. `action` completes \"Could not …\" (\"pause this schedule\");\n * `remedy` is what to do next (\"Try again or open the schedule's activity.\").\n */\nexport function describeWriteFailure(\n err: unknown,\n { action, remedy = \"Try again.\" }: { action: string; remedy?: string },\n): WriteFailureWords {\n const title = `Could not ${action}.`;\n let why: string;\n if (err instanceof WriteRefusedError) {\n why = err.message;\n } else if (isSerializedRefusal(err)) {\n // A refusal that crossed a Redux thunk: `.unwrap()` rejects with a plain\n // `{ name, message }`, and its words are already a sentence for a person.\n why = /[.!?][\"”']?$/.test(err.message.trim()) ? err.message.trim() : `${err.message.trim()}.`;\n } else if (isPostgrestShaped(err)) {\n // A door's own sentence beats the code's generic one; Postgres's native prose never shows.\n why = personSentence(err.message) ?? postgrestSentence(err.code);\n } else if (err && typeof err === \"object\" && \"status\" in err && typeof (err as { status: unknown }).status === \"number\") {\n const e = err as { status: number; userMessage?: unknown };\n why = refusalSentence(e.status, typeof e.userMessage === \"string\" ? e.userMessage : null);\n } else if (err instanceof TypeError || (err instanceof Error && /Failed to fetch|NetworkError|Load failed/i.test(err.message))) {\n why = \"The server could not be reached. Check your connection.\";\n } else if (err instanceof Error && err.message && !LOOKS_TECHNICAL.test(err.message)) {\n why = err.message.replace(/\\.?$/, \".\");\n } else if (typeof err === \"string\" && err.trim() && !LOOKS_TECHNICAL.test(err)) {\n // A server action's `{ success: false, error: \"<text>\" }` — words only when they read as words.\n why = err.trim().replace(/\\.?$/, \".\");\n } else {\n why = \"Something went wrong on our side.\";\n }\n return { title, description: `${why} ${remedy}`.trim() };\n}\n","/**\n * @ai-matrx/data/db — writeOne: THE single-record write that PROVES it landed.\n *\n * Ported verbatim from matrx-frontend `utils/supabase/writeOne.ts` (which now\n * re-exports this module, so `WriteDidNotLandError` is ONE class everywhere).\n *\n * THE CLASS (flashcards, 2026-09-25). PostgREST answers an `.update()` or\n * `.delete()` that row-level security filters to zero rows with\n * `{ data: [], error: null }` — status 200, no error. A caller that judges\n * success by `error == null` therefore tells the person \"Card deleted\" while\n * nothing happened. The same is true when the row is already gone. Nothing\n * fails silently: zero rows written is a refusal, and it is said in words.\n *\n * USE IT for every write aimed at ONE record (`.eq(\"id\", …)`):\n *\n * await writeOne(\n * supabase.from(\"notes\").update({ label }).eq(\"id\", noteId).select(\"id\"),\n * { action: \"rename\", noun: \"note\" },\n * );\n *\n * - The builder MUST end in `.select(...)` — that is what makes PostgREST\n * return the rows it actually wrote. Select only what you need (`\"id\"` is\n * fine); the first written row is returned.\n * - A database error is thrown AS IS (the PostgrestError), so existing error\n * handling and `describeWriteFailure` keep working.\n * - Zero rows throws `WriteDidNotLandError` — a `WriteRefusedError` whose\n * message is already a sentence for a person:\n * \"Nothing was deleted: this card no longer exists, or your access does not\n * allow deleting it.\"\n * - `tryWriteOne` is the same check for result-style services that never\n * throw: it returns `{ row, error }`.\n *\n * TWO MODES for writes that carry an extra condition (coordinator ruling,\n * 2026-09-25):\n *\n * - IDEMPOTENT (`alreadyDone`): an archive filtered `.is(\"deleted_at\", null)`\n * writes zero rows when the record is ALREADY archived — and also when RLS\n * refused. On zero rows the primitive re-reads the row by id: visible and\n * already in the target state → success (the re-read row is returned);\n * invisible or still live → the plain refusal.\n *\n * - COMPARE-AND-SET (`compareAndSet: true`): `.eq(\"status\", \"pending\")`,\n * `.is(\"answered_at\", null)`… zero rows means someone else got there first.\n * That is still told to the person: \"This answer was already handled —\n * refresh to see the latest.\" (`WriteDidNotLandError.reason === \"taken\"`).\n *\n * Optimistic-concurrency edits with a `version` token use `guardedUpdate`\n * from `@ai-matrx/data/db`, which classifies zero rows as conflict or gone.\n * A bulk `.in(...)` write is not a single-record write.\n *\n * Guard: `pnpm check:single-record-writes` (scripts/check-single-record-writes.ts)\n * fails on a new single-record update/delete that judges success by error alone.\n */\nimport { PostgrestError } from \"@supabase/supabase-js\";\nimport { WriteRefusedError } from \"./write-failure\";\n\n/** The verb the person asked for. Drives the refusal sentence. */\nexport type WriteOneAction =\n | \"save\"\n | \"update\"\n | \"rename\"\n | \"move\"\n | \"delete\"\n | \"remove\"\n | \"archive\"\n | \"restore\"\n | \"publish\"\n | \"unpublish\"\n | \"change\";\n\nexport interface WriteOneOptions<Row = unknown> {\n /** What the person asked for: \"delete\", \"save\", \"archive\"… */\n action: WriteOneAction;\n /** What it is, in the person's words: \"card\", \"note\", \"saved view\". */\n noun: string;\n /**\n * Idempotent mode. On zero rows, `reread()` the record by id (end it in\n * `.maybeSingle()`); when it is visible and `isDone(row)`, the write is a\n * success and that row is returned. Otherwise the plain refusal.\n */\n alreadyDone?: {\n reread: () => PromiseLike<{ data: Row | null; error: unknown }>;\n isDone: (row: Row) => boolean;\n };\n /** Compare-and-set mode: zero rows means someone else got there first. */\n compareAndSet?: boolean;\n}\n\n/** Why nothing was written: refused/gone, or another writer took it first. */\nexport type WriteDidNotLandReason = \"refused\" | \"taken\";\n\nconst PAST: Record<WriteOneAction, string> = {\n save: \"saved\",\n update: \"updated\",\n rename: \"renamed\",\n move: \"moved\",\n delete: \"deleted\",\n remove: \"removed\",\n archive: \"archived\",\n restore: \"restored\",\n publish: \"published\",\n unpublish: \"unpublished\",\n change: \"changed\",\n};\n\nconst GERUND: Record<WriteOneAction, string> = {\n save: \"saving\",\n update: \"updating\",\n rename: \"renaming\",\n move: \"moving\",\n delete: \"deleting\",\n remove: \"removing\",\n archive: \"archiving\",\n restore: \"restoring\",\n publish: \"publishing\",\n unpublish: \"unpublishing\",\n change: \"changing\",\n};\n\n/** Zero rows were written: the record is gone, or the person may not change it. */\nexport class WriteDidNotLandError extends WriteRefusedError {\n readonly action: WriteOneAction;\n readonly noun: string;\n readonly reason: WriteDidNotLandReason;\n\n constructor(\n { action, noun }: Pick<WriteOneOptions, \"action\" | \"noun\">,\n reason: WriteDidNotLandReason = \"refused\",\n ) {\n super({\n status: reason === \"taken\" ? 409 : 403,\n serverMessage:\n reason === \"taken\"\n ? `This ${noun} was already handled — refresh to see the latest.`\n : `Nothing was ${PAST[action]}: this ${noun} no longer exists, or your access does not allow ${GERUND[action]} it.`,\n technical:\n reason === \"taken\"\n ? `writeOne(${action} ${noun}) compare-and-set matched 0 rows — another writer got there first`\n : `writeOne(${action} ${noun}) matched 0 rows — RLS refused or the row is gone`,\n });\n this.name = \"WriteDidNotLandError\";\n this.action = action;\n this.noun = noun;\n this.reason = reason;\n }\n}\n\n/** Structural shape of an awaited supabase-js builder that ended in `.select()`. */\ninterface RowsResponse<Row> {\n data: Row[] | null;\n error: unknown;\n}\n\n/**\n * Run a single-record write and prove it landed. Returns the first written\n * row; throws the database error as is, or `WriteDidNotLandError` on zero rows.\n */\nexport async function writeOne<Row>(\n write: PromiseLike<RowsResponse<Row>>,\n options: WriteOneOptions<Row>,\n): Promise<Row> {\n const { data, error } = await write;\n if (error) throw error;\n if (Array.isArray(data) && data.length > 0) return data[0] as Row;\n\n if (options.alreadyDone) {\n const current = await options.alreadyDone.reread();\n if (current.error) throw current.error;\n const row = Array.isArray(current.data) ? (current.data[0] as Row | undefined) : current.data;\n if (row && options.alreadyDone.isDone(row)) return row;\n }\n throw new WriteDidNotLandError(options, options.compareAndSet ? \"taken\" : \"refused\");\n}\n\nexport type TryWriteOneResult<Row> =\n | { row: Row; error: null }\n | { row: null; error: Error };\n\n/** `writeOne` for services that return results instead of throwing. */\nexport async function tryWriteOne<Row>(\n write: PromiseLike<RowsResponse<Row>>,\n options: WriteOneOptions<Row>,\n): Promise<TryWriteOneResult<Row>> {\n try {\n return { row: await writeOne(write, options), error: null };\n } catch (caught) {\n if (caught instanceof Error) return { row: null, error: caught };\n // PostgREST responses can be plain objects. Keep their structured refusal\n // intact instead of turning code/details/hint into an opaque Error cause.\n if (caught && typeof caught === \"object\" && \"code\" in caught &&\n typeof caught.code === \"string\" && \"message\" in caught &&\n typeof caught.message === \"string\") {\n return { row: null, error: new PostgrestError({\n code: caught.code,\n message: caught.message,\n details: \"details\" in caught && typeof caught.details === \"string\" ? caught.details : \"\",\n hint: \"hint\" in caught && typeof caught.hint === \"string\" ? caught.hint : \"\",\n }) };\n }\n const message =\n caught && typeof caught === \"object\" && \"message\" in caught && typeof caught.message === \"string\"\n ? caught.message\n : String(caught);\n const error = new Error(message);\n (error as Error & { cause?: unknown }).cause = caught;\n return { row: null, error };\n }\n}\n\n/**\n * The HTTP status a route handler answers with for a failed write: the\n * refusal's own status (403 refused / 409 taken) for `WriteDidNotLandError`,\n * Database authorization/not-found/conflict codes retain their HTTP meaning;\n * unknown failures remain 500. Server twin of the client's toast path.\n */\nexport function writeFailureStatus(error: unknown): number {\n if (error instanceof WriteDidNotLandError) return error.status;\n if (error && typeof error === \"object\" && \"code\" in error) {\n if (error.code === \"42501\") return 403;\n if (error.code === \"PGRST301\" || error.code === \"PGRST302\" || error.code === \"PGRST303\") return 401;\n if (error.code === \"PGRST116\") return 404;\n if (error.code === \"23505\" || error.code === \"40001\" || error.code === \"40P01\") return 409;\n }\n return 500;\n}\n\n/**\n * Several single-record writes where some did not land. The message names how\n * many of how many failed and why (the first reason); `failures` keeps each\n * record id with its own sentence so a screen can mark exactly those rows.\n */\nexport class BulkWriteError extends Error {\n readonly failures: { id: string; message: string }[];\n readonly attempted: number;\n\n constructor(failures: { id: string; message: string }[], attempted: number) {\n super(\n `${failures.length} of ${attempted} ${attempted === 1 ? \"change was\" : \"changes were\"} not saved. ${failures[0]?.message ?? \"\"}`.trim(),\n );\n this.name = \"BulkWriteError\";\n this.failures = failures;\n this.attempted = attempted;\n }\n}\n\nexport type WriteOneRowResult<Row> =\n | { data: Row; error: null }\n | { data: null; error: PostgrestError };\n\n/**\n * The drop-in for `.update(…).eq(\"id\", …).select(…).single()` (and the\n * `.maybeSingle()` twin whose caller never looks at `data`): same\n * `{ data, error }` shape, same `PostgrestError` type, same `PGRST116` code on\n * zero rows — but the message is the person's sentence (\"Nothing was updated:\n * this deal no longer exists, or your access does not allow updating it.\")\n * instead of PostgREST's \"JSON object requested, multiple (or no) rows\n * returned\", which every screen rendered as a vague failure.\n *\n * const { data, error } = await writeOneRow(\n * db.from(\"deal\").update(patch).eq(\"id\", id).select(\"*\"),\n * { action: \"update\", noun: \"deal\" },\n * );\n *\n * Guard: `pnpm check:single-record-writes` flags the bare `.select().single()`\n * shape on a write.\n */\nexport async function writeOneRow<Row>(\n write: PromiseLike<RowsResponse<Row>>,\n options: Pick<WriteOneOptions, \"action\" | \"noun\" | \"compareAndSet\">,\n): Promise<WriteOneRowResult<Row>> {\n const { data, error } = await write;\n if (error) {\n if (error instanceof PostgrestError) return { data: null, error };\n const e = error as { message?: unknown; details?: unknown; hint?: unknown; code?: unknown };\n return {\n data: null,\n error: new PostgrestError({\n message: typeof e.message === \"string\" ? e.message : String(error),\n details: typeof e.details === \"string\" ? e.details : \"\",\n hint: typeof e.hint === \"string\" ? e.hint : \"\",\n code: typeof e.code === \"string\" ? e.code : \"\",\n }),\n };\n }\n const rows = Array.isArray(data) ? data : [];\n if (rows.length === 1) return { data: rows[0] as Row, error: null };\n const refusal = new WriteDidNotLandError(options, options.compareAndSet ? \"taken\" : \"refused\");\n return {\n data: null,\n error: new PostgrestError({\n message:\n rows.length === 0\n ? refusal.serverMessage ?? refusal.message\n : `${rows.length} records matched where one ${options.noun} was expected, and all of them were changed. Reload to see the result.`,\n details: rows.length === 0 ? refusal.technical : `writeOneRow(${options.action} ${options.noun}) matched ${rows.length} rows`,\n hint: \"\",\n code: \"PGRST116\",\n }),\n };\n}\n","/**\n * @ai-matrx/data/db — record-unavailable: THE one shape for \"a single-record\n * read came back with zero rows\".\n *\n * Ported from matrx-frontend `lib/records/recordUnavailable.ts`, which keeps\n * its capture helpers (`recordUnavailable`, `resolveRecordUnavailableCapture`)\n * and re-exports this class — so `RecordUnavailableError` is ONE class across\n * the app and `@ai-matrx/chat`, and every `instanceof` keeps working.\n *\n * Zero rows is at least three different situations: the row was soft-deleted,\n * the row is alive but this reader's access (org membership / permission\n * grant) does not reach it, or the id is stale/wrong. Asserting deletion for\n * all three is what D133 cost — two agent-review items were rejected as \"site\n * deleted or is no longer accessible\" while the brand AND site were live and\n * un-deleted; the null was RLS.\n *\n * So `deleted` is claimed ONLY when a probe proved it. Everything else is\n * `unknown` and says both possibilities out loud. Never construct the error\n * directly at a read site: the host's `recordUnavailable(...)` builds it AND\n * captures it — the capture is the loud half of the contract.\n */\n\n/** `deleted` is PROVEN (a probe read the row and saw `deleted_at`). */\nexport type RecordUnavailableReason = \"deleted\" | \"unknown\";\n\n/** The truth an access resolver can add after the initial ambiguous read failure. */\nexport type RecordUnavailableResolution =\n \"denied\" | \"deleted\" | \"missing\" | \"signed-out\" | \"ok\";\n\nexport class RecordUnavailableError extends Error {\n readonly entity: string;\n readonly reason: RecordUnavailableReason;\n readonly recordId?: string | undefined;\n /**\n * Canonical entity token, when the read site knows it. With a token AND a\n * recordId the renderer stops describing the ambiguity and ASKS the platform\n * instead — an access gate resolves which of the four it really is.\n * Without one, honest ambiguity is still the best available answer.\n */\n readonly token?: string | undefined;\n /** Diagnostics identity for reconciling this exact capture in place. */\n captureId?: string | undefined;\n /** Last truth written to diagnostics; avoids duplicate reconciliation. */\n captureResolution: RecordUnavailableReason | RecordUnavailableResolution;\n\n constructor(input: {\n entity: string;\n reason: RecordUnavailableReason;\n recordId?: string | undefined;\n token?: string | undefined;\n }) {\n super(recordUnavailableMessage(input.entity, input.reason));\n this.name = \"RecordUnavailableError\";\n this.entity = input.entity;\n this.reason = input.reason;\n this.recordId = input.recordId;\n this.token = input.token;\n this.captureResolution = input.reason;\n }\n}\n\nexport function recordUnavailableMessage(\n entity: string,\n reason: RecordUnavailableReason,\n): string {\n if (reason === \"deleted\") {\n return `This ${entity} was deleted, so it can no longer be opened.`;\n }\n return `We couldn't open this ${entity}. It may have been deleted, or it may belong to an organization you don't have access to.`;\n}\n\nexport function isRecordUnavailableError(\n value: unknown,\n): value is RecordUnavailableError {\n return value instanceof RecordUnavailableError;\n}\n","/**\n * @ai-matrx/data — THE doors: one way to talk to the database.\n *\n * `createDb` owns the connection (wrapping the app's existing Supabase client\n * during migration — data never opens a second auth client or socket), the\n * session (handed to `@ai-matrx/api` as its `user` credential through\n * `db.credentials`) and the organization binding. Every operation is a\n * standalone function over a DESCRIPTOR that each app generates locally from the\n * ONE database description (`matrx-data generate`), so the rules ride the\n * descriptor's flags — read from the live table registry — never a call site's\n * memory:\n *\n * - organization (the access ladder): an entity insert takes the explicit\n * `organization_id`, else the active organization; a CHILD insert\n * (`org.rule === \"parent\"`) never takes the active organization — the\n * database's `inherit_org_from_parent` fills it from the parent, so adding to\n * a record in another organization works; reads NEVER read the active\n * organization; service doors have no binding (organization is required);\n * - complete reads: `listAll` pages past PostgREST's 1,000-row cap\n * (`readAllRows`) and throws on a short read; `page` is the explicit window;\n * - versioned tables: `update` takes `{ expectedVersion }` (guarded, conflict\n * returned) or `{ overwrite: true }` — explicit either way;\n * - lifecycle: `remove` soft-deletes where the table has `deleted_at`; an\n * archive-only table refuses `remove` (use `archive`); a hard delete exists\n * only where the table has neither;\n * - the door set by registry type (entity/detail all · ledger read/list/insert ·\n * reference/system read/list · restricted service-only · deprecated none),\n * narrowed by `client_read_only` / `client_deletes_refused` — refused BEFORE\n * the wire with a sentence that names the rule;\n * - service role: `createServiceDb` throws in a browser bundle;\n * - a table chosen at runtime: `tableByName(index, \"schema.table\")` over the\n * generated flags index — loosely typed, same rules.\n */\nimport { readAllRows } from \"./read-all-rows\";\nimport { guardedUpdate } from \"./guarded-update\";\n\n// ─── descriptors (what `matrx-data generate` emits) ─────────────────────────\n\n/** Registry type (`platform.entity_types.type`); null = untyped or no registry row. */\nexport type TableType = \"entity\" | \"detail\" | \"ledger\" | \"reference\" | \"system\" | \"restricted\" | \"deprecated\";\n\nexport type OrgRule =\n | { readonly rule: \"binding\" }\n | { readonly rule: \"parent\"; readonly parent: string; readonly via: string }\n | { readonly rule: \"column\" }\n | { readonly rule: \"none\" };\n\n/** Phantom carrier for the generated row types — never present at runtime. */\ndeclare const ROW: unique symbol;\n\nexport interface TableDescriptor<Row = Record<string, unknown>, Insert = Record<string, unknown>, Update = Partial<Insert>> {\n readonly schema: string;\n readonly name: string;\n readonly kind: \"table\" | \"view\" | \"materialized_view\";\n readonly type: TableType | null;\n readonly pk: readonly string[];\n readonly org: OrgRule;\n readonly versioned: boolean;\n readonly softDelete: boolean;\n /** The archive column, when the table archives instead of (or as well as) soft-deleting. */\n readonly archive: \"archived_at\" | \"is_archived\" | null;\n readonly readOnly: boolean;\n readonly deletesRefused: boolean;\n readonly readOnlyColumns: readonly string[];\n readonly listScope: string | null;\n readonly realtime: boolean;\n /**\n * The table has a `created_by` column. A signed-in insert that omits it is stamped with the\n * session's person (row security on tables like `workbench.notes` refuses an insert whose\n * `created_by` is not `auth.uid()`). Optional: descriptors generated before 0.25.0 lack it.\n */\n readonly createdBy?: boolean;\n readonly [ROW]?: { row: Row; insert: Insert; update: Update };\n}\n\nexport interface FunctionDescriptor<Args = Record<string, unknown>, Result = unknown> {\n readonly schema: string;\n readonly name: string;\n readonly roles: readonly (\"anon\" | \"authenticated\" | \"service_role\")[];\n readonly registered: boolean;\n readonly [ROW]?: { args: Args; result: Result };\n}\n\nexport type RowOf<T> = T extends TableDescriptor<infer R, any, any> ? R : never;\nexport type InsertOf<T> = T extends TableDescriptor<any, infer I, any> ? I : never;\nexport type UpdateOf<T> = T extends TableDescriptor<any, any, infer U> ? U : never;\nexport type ArgsOf<F> = F extends FunctionDescriptor<infer A, any> ? A : never;\nexport type ResultOf<F> = F extends FunctionDescriptor<any, infer R> ? R : never;\n\n// ─── the connection ─────────────────────────────────────────────────────────\n\ninterface PostgrestError {\n message: string;\n code?: string;\n details?: string | null;\n hint?: string | null;\n}\ninterface Resp<T> {\n data: T | null;\n error: PostgrestError | null;\n count?: number | null;\n}\n/** The slice of a supabase-js query builder the doors use (structural — any supabase-js 2.x client). */\nexport interface QueryLike extends PromiseLike<Resp<any>> {\n select(columns?: string, opts?: { count?: \"exact\" | \"planned\" | \"estimated\"; head?: boolean }): QueryLike;\n eq(column: string, value: unknown): QueryLike;\n is(column: string, value: null | boolean): QueryLike;\n order(column: string, opts?: { ascending?: boolean }): QueryLike;\n range(from: number, to: number): QueryLike;\n maybeSingle(): PromiseLike<Resp<any>>;\n single(): PromiseLike<Resp<any>>;\n}\n/** The slice of a supabase-js table builder (`client.schema(s).from(t)`) the doors use. */\nexport interface TableLike {\n select(columns?: string, opts?: { count?: \"exact\" | \"planned\" | \"estimated\"; head?: boolean }): QueryLike;\n insert(values: any): QueryLike;\n update(values: any): QueryLike;\n delete(): QueryLike;\n}\n/** The slice of a supabase-js client the doors use (a real `SupabaseClient` is assignable — doors.types.test.ts). */\nexport interface SupabaseLike {\n schema(name: string): {\n /**\n * A table builder (read as `TableLike` inside the doors). Typed `unknown` on purpose: matching\n * supabase-js's deep builder generics structurally costs TS2589 in every consumer.\n */\n from(table: string): unknown;\n rpc(fn: string, args?: Record<string, unknown>, opts?: { count?: \"exact\" | \"planned\" | \"estimated\" }): PromiseLike<Resp<any>>;\n };\n auth?: {\n getSession(): Promise<{ data: { session: { access_token: string; user?: { id: string } | null } | null } }>;\n onAuthStateChange(cb: (event: string, session: unknown) => void): { data: { subscription: { unsubscribe(): void } } };\n };\n}\n\n/** The credential shape `@ai-matrx/api`'s `CredentialsPort` accepts (structural; data owns the session). */\nexport interface UserCredentialsPort {\n get(): Promise<{ kind: \"user\"; accessToken: string } | null>;\n onChange?(cb: () => void): () => void;\n}\n\nexport interface Db {\n readonly client: SupabaseLike;\n readonly role: \"user\" | \"service\";\n /** The active organization — where NEW entity rows are saved. Never a read filter. */\n activeOrganization(): string | null;\n /** The session as `@ai-matrx/api`'s `user` credential (one sign-in feeds both lanes). */\n readonly credentials: UserCredentialsPort;\n}\n\nexport interface CreateDbOptions {\n /** The app's existing Supabase client (browser, RSC, route or the host's chat client). */\n client: SupabaseLike;\n /** Where new entity rows are saved. Read lazily on every insert; never consulted by a read. */\n organization?: () => string | null | undefined;\n}\n\nfunction credentialsOf(client: SupabaseLike): UserCredentialsPort {\n return {\n async get() {\n if (!client.auth) return null;\n const { data } = await client.auth.getSession();\n return data.session ? { kind: \"user\", accessToken: data.session.access_token } : null;\n },\n onChange(cb) {\n if (!client.auth) return () => {};\n const { data } = client.auth.onAuthStateChange(() => cb());\n return () => data.subscription.unsubscribe();\n },\n };\n}\n\n/** The one database connection for a signed-in (or anonymous) person. */\nexport function createDb(options: CreateDbOptions): Db {\n const { client, organization } = options;\n return {\n client,\n role: \"user\",\n activeOrganization: () => organization?.() ?? null,\n credentials: credentialsOf(client),\n };\n}\n\n/**\n * Service-role doors — servers only. No session, no binding: every entity insert\n * names its organization. Throws in a browser bundle.\n */\nexport function createServiceDb(options: { client: SupabaseLike }): Db {\n if (typeof (globalThis as { window?: unknown }).window !== \"undefined\") {\n throw new DoorRefusedError(\"createServiceDb\", \"the service role never runs in a browser\");\n }\n return { client: options.client, role: \"service\", activeOrganization: () => null, credentials: credentialsOf(options.client) };\n}\n\n// ─── refusals ───────────────────────────────────────────────────────────────\n\nexport class DoorRefusedError extends Error {\n constructor(\n readonly door: string,\n readonly reason: string,\n ) {\n super(`${door}: ${reason}`);\n this.name = \"DoorRefusedError\";\n }\n}\n\nexport class DatabaseError extends Error {\n constructor(\n readonly door: string,\n readonly cause: PostgrestError,\n ) {\n super(`${door}: ${cause.message}${cause.code ? ` (${cause.code})` : \"\"}`);\n this.name = \"DatabaseError\";\n }\n}\n\ntype Op = \"read\" | \"insert\" | \"update\" | \"remove\" | \"archive\";\nconst CLIENT_DOORS: Record<TableType, readonly Op[]> = {\n entity: [\"read\", \"insert\", \"update\", \"remove\", \"archive\"],\n detail: [\"read\", \"insert\", \"update\", \"remove\", \"archive\"],\n ledger: [\"read\", \"insert\"],\n reference: [\"read\"],\n system: [\"read\"],\n restricted: [],\n deprecated: [],\n};\n\nconst qualified = (t: { schema: string; name: string }) => `${t.schema}.${t.name}`;\n\n/** Refuse before the wire when the descriptor's rules do not open this door. */\nexport function assertDoor(db: Db, table: TableDescriptor<any, any, any>, op: Op): void {\n const door = `${op} ${qualified(table)}`;\n if (table.type === \"deprecated\") throw new DoorRefusedError(door, \"the table is deprecated — no door opens on it\");\n if (table.kind !== \"table\" && op !== \"read\") throw new DoorRefusedError(door, `a ${table.kind.replace(\"_\", \" \")} is read-only`);\n if (db.role === \"service\") return;\n if (table.type && !CLIENT_DOORS[table.type].includes(op))\n throw new DoorRefusedError(door, `a ${table.type} table opens only ${CLIENT_DOORS[table.type].join(\", \") || \"service\"} doors to a client`);\n if (op !== \"read\" && table.readOnly) throw new DoorRefusedError(door, \"the table is read-only to clients (client_read_only)\");\n if (op === \"remove\" && table.deletesRefused) throw new DoorRefusedError(door, \"clients may not delete from this table (client_deletes_refused)\");\n}\n\nfunction check<T>(door: string, res: Resp<T>): T {\n if (res.error) throw new DatabaseError(door, res.error);\n return res.data as T;\n}\n\nconst from = (db: Db, t: TableDescriptor<any, any, any>) => db.client.schema(t.schema).from(t.name) as TableLike;\n\nfunction byPk(q: QueryLike, t: TableDescriptor<any, any, any>, id: unknown): QueryLike {\n if (t.pk.length === 1) return q.eq(t.pk[0] as string, id);\n const key = id as Record<string, unknown>;\n return t.pk.reduce((acc, col) => acc.eq(col, key[col]), q);\n}\n\n// ─── reads (never the active organization; soft-deleted rows excluded unless asked) ─\n\ntype Col<R> = Extract<keyof R, string>;\n\n/** The typed filter a `Where` callback receives — column names and values checked against the row. */\nexport interface Filter<R> {\n eq<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;\n neq<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;\n gt<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;\n gte<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;\n lt<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;\n lte<K extends Col<R>>(column: K, value: NonNullable<R[K]>): Filter<R>;\n like(column: Col<R>, pattern: string): Filter<R>;\n ilike(column: Col<R>, pattern: string): Filter<R>;\n in<K extends Col<R>>(column: K, values: readonly NonNullable<R[K]>[]): Filter<R>;\n is(column: Col<R>, value: null | boolean): Filter<R>;\n contains(column: Col<R>, value: unknown): Filter<R>;\n overlaps(column: Col<R>, value: unknown): Filter<R>;\n textSearch(column: Col<R>, query: string, opts?: { type?: \"plain\" | \"phrase\" | \"websearch\"; config?: string }): Filter<R>;\n /** PostgREST's raw `or` grammar (`\"pinned.eq.true,starred.eq.true\"`). */\n or(filters: string, opts?: { referencedTable?: string }): Filter<R>;\n not(column: Col<R>, operator: string, value: unknown): Filter<R>;\n}\n\n/** A filter callback — the same builder `readAllRows` callers write today, typed to the row. */\nexport type Where<R = any> = (q: Filter<R>) => Filter<R>;\n\nexport interface ReadOptions<C> {\n /** Only these columns (the result is typed to them). Default every column. */\n columns?: readonly C[];\n /** Include soft-deleted rows (default: excluded on tables with `deleted_at`). */\n includeDeleted?: boolean;\n}\n\nconst selectOf = (columns?: readonly string[]) => (columns && columns.length ? columns.join(\",\") : \"*\");\n\nfunction live(q: any, table: TableDescriptor<any, any, any>, includeDeleted?: boolean): any {\n return table.softDelete && !includeDeleted ? q.is(\"deleted_at\", null) : q;\n}\n\nfunction ordered(q: any, table: TableDescriptor<any, any, any>, orderBy?: string, ascending = true): any {\n // The FULL primary key, so paging is stable on composite keys.\n const cols = orderBy ? [orderBy, ...table.pk.filter((c) => c !== orderBy)] : table.pk.length ? table.pk : [\"id\"];\n return cols.reduce((acc: any, c) => acc.order(c, { ascending }), q);\n}\n\n/** One row by primary key (a composite key takes `{ col: value }`), or null. */\nexport async function read<R, I, U, C extends Col<R> = Col<R>>(\n db: Db,\n table: TableDescriptor<R, I, U>,\n id: unknown,\n opts: ReadOptions<C> = {},\n): Promise<Pick<R, C> | null> {\n assertDoor(db, table, \"read\");\n const q = live(byPk(from(db, table).select(selectOf(opts.columns)), table, id), table, opts.includeDeleted);\n return check(`read ${qualified(table)}`, await q.maybeSingle());\n}\n\n/** EVERY matching row, paged past the 1,000-row cap (ordered by the full key); throws on a short read. */\nexport async function listAll<R, I, U, C extends Col<R> = Col<R>>(\n db: Db,\n table: TableDescriptor<R, I, U>,\n where?: Where<R>,\n opts: ReadOptions<C> & { orderBy?: Col<R>; pageSize?: number; maxRows?: number } = {},\n): Promise<Pick<R, C>[]> {\n assertDoor(db, table, \"read\");\n return readAllRows<Pick<R, C>>(\n ({ from: lo, to: hi }) => {\n let q: any = live(from(db, table).select(selectOf(opts.columns), { count: \"exact\" }), table, opts.includeDeleted);\n if (where) q = where(q);\n // The database's own error (code, details) reaches the caller as a DatabaseError,\n // exactly like every other door — never a re-worded readAllRows message.\n return Promise.resolve(ordered(q, table, opts.orderBy).range(lo, hi)).then((res: Resp<any>) => {\n if (res.error) throw new DatabaseError(`listAll ${qualified(table)}`, res.error);\n return res;\n });\n },\n {\n label: `listAll ${qualified(table)}`,\n ...(opts.pageSize !== undefined ? { pageSize: opts.pageSize } : {}),\n ...(opts.maxRows !== undefined ? { maxRows: opts.maxRows } : {}),\n },\n );\n}\n\n/** One explicit window (`from`..`to`, inclusive) plus the exact total. */\nexport async function page<R, I, U, C extends Col<R> = Col<R>>(\n db: Db,\n table: TableDescriptor<R, I, U>,\n window: ReadOptions<C> & { from: number; to: number; where?: Where<R>; orderBy?: Col<R>; ascending?: boolean },\n): Promise<{ rows: Pick<R, C>[]; total: number | null }> {\n assertDoor(db, table, \"read\");\n let q: any = live(from(db, table).select(selectOf(window.columns), { count: \"exact\" }), table, window.includeDeleted);\n if (window.where) q = window.where(q);\n const res = await ordered(q, table, window.orderBy, window.ascending ?? true).range(window.from, window.to);\n return { rows: check(`page ${qualified(table)}`, res) ?? [], total: res.count ?? null };\n}\n\n/** The exact count of matching rows (no rows transferred). */\nexport async function count<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, where?: Where<R>, opts: { includeDeleted?: boolean } = {}): Promise<number> {\n assertDoor(db, table, \"read\");\n let q: any = live(from(db, table).select(\"*\", { count: \"exact\", head: true }), table, opts.includeDeleted);\n if (where) q = where(q);\n const res = await q;\n check(`count ${qualified(table)}`, res);\n return res.count ?? 0;\n}\n\n// ─── writes ─────────────────────────────────────────────────────────────────\n\nfunction withOrganization(db: Db, table: TableDescriptor<any, any, any>, values: Record<string, unknown>): Record<string, unknown> {\n const door = `insert ${qualified(table)}`;\n const org = table.org;\n if (org.rule === \"parent\" && values[org.via] != null) {\n // A child row: its organization is its parent's. Never the active organization —\n // `inherit_org_from_parent` fills organization_id; an explicit one is checked by\n // `refuse_org_foreign_to_parent`. So adding to a record in another organization works.\n return values;\n }\n if (org.rule === \"binding\" || org.rule === \"parent\") {\n // An entity row, or a row whose optional parent is absent (a note outside any folder),\n // is saved in the named organization, else the active one.\n if (values.organization_id != null) return values;\n const active = db.activeOrganization();\n if (!active) {\n throw new DoorRefusedError(\n door,\n db.role === \"service\" ? \"a service insert names its organization_id\" : \"no organization: pass organization_id or bind createDb({ organization })\",\n );\n }\n return { ...values, organization_id: active };\n }\n return values;\n}\n\n/** Insert one row (or many) and return what the database stored. */\nexport async function insert<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, values: I): Promise<R>;\nexport async function insert<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, values: readonly I[]): Promise<R[]>;\nexport async function insert(db: Db, table: TableDescriptor<any, any, any>, values: unknown): Promise<unknown> {\n assertDoor(db, table, \"insert\");\n const many = Array.isArray(values);\n let rows = (many ? values : [values]).map((v) => withOrganization(db, table, v as Record<string, unknown>));\n if (table.createdBy && db.role === \"user\" && rows.some((r) => r.created_by == null) && db.client.auth) {\n // Stamp the signed-in person (no session: sent as given, and row security answers).\n const { data } = await db.client.auth.getSession();\n const person = data.session?.user?.id;\n if (person) rows = rows.map((r) => (r.created_by == null ? { ...r, created_by: person } : r));\n }\n const res = await from(db, table).insert(rows).select(\"*\");\n const stored = check(`insert ${qualified(table)}`, res) as unknown[];\n return many ? stored : stored[0];\n}\n\n/** Every write on a versioned table is explicit: `{ expectedVersion }` (guarded) or `{ overwrite: true }`. */\nexport type UpdateGuard = { expectedVersion: number } | { overwrite: true };\n\nexport type WriteResult<R> =\n | { status: \"saved\"; row: R; rebasedFrom?: { expectedVersion: number; currentVersion: number } }\n | { status: \"conflict\"; currentRow: R; currentVersion: number }\n | { status: \"not_found\" };\n\n/** The one guarded write every update-shaped door goes through. */\nasync function writeRow<R>(db: Db, table: TableDescriptor<any, any, any>, id: unknown, values: Record<string, unknown>, door: string, guard?: UpdateGuard): Promise<WriteResult<R>> {\n const expected = guard && \"expectedVersion\" in guard ? guard.expectedVersion : undefined;\n if (expected !== undefined && !table.versioned) {\n throw new DoorRefusedError(door, \"expectedVersion on a table that is not versioned — nothing would guard it; pass no guard\");\n }\n if (table.versioned && expected === undefined && !(guard && \"overwrite\" in guard && guard.overwrite)) {\n throw new DoorRefusedError(door, \"a versioned table takes { expectedVersion } or { overwrite: true }\");\n }\n if (expected !== undefined) {\n return (await guardedUpdate<any>({\n expectedVersion: expected,\n applyUpdate: ({ expectedVersion, nextVersion }) =>\n byPk(from(db, table).update({ ...values, version: nextVersion }), table, id).eq(\"version\", expectedVersion).select(\"*\").maybeSingle(),\n fetchCurrent: () => byPk(from(db, table).select(\"*\"), table, id).maybeSingle(),\n })) as WriteResult<R>;\n }\n const row = check(door, await byPk(from(db, table).update(values), table, id).select(\"*\").maybeSingle());\n return row ? { status: \"saved\", row } : { status: \"not_found\" };\n}\n\n/**\n * Update one row by primary key. On a versioned table the guard is required:\n * `{ expectedVersion }` (a conflict comes back, never a silent overwrite) or\n * `{ overwrite: true }`; on an unversioned table `expectedVersion` is refused.\n */\nexport async function update<R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, patch: U, guard?: UpdateGuard): Promise<WriteResult<R>> {\n assertDoor(db, table, \"update\");\n const door = `update ${qualified(table)}`;\n const values = patch as Record<string, unknown>;\n if (db.role === \"user\") {\n const blocked = table.readOnlyColumns.filter((c) => c in values);\n if (blocked.length) throw new DoorRefusedError(door, `read-only to clients: ${blocked.join(\", \")}`);\n }\n return writeRow<R>(db, table, id, values, door, guard);\n}\n\n/**\n * Remove one row the way the table removes: soft delete (`deleted_at`) where it\n * has one; an archive-only table refuses (use `archive`); a hard delete only where\n * the table has neither. Guarded like `update` on a versioned table.\n */\nexport async function remove<R, I, U>(\n db: Db,\n table: TableDescriptor<R, I, U>,\n id: unknown,\n guard?: UpdateGuard,\n): Promise<{ status: \"soft_deleted\" | \"deleted\" | \"not_found\" } | { status: \"conflict\"; currentVersion: number }> {\n assertDoor(db, table, \"remove\");\n const door = `remove ${qualified(table)}`;\n if (table.softDelete) {\n const res = await writeRow<R>(db, table, id, { deleted_at: new Date().toISOString() }, door, guard);\n return res.status === \"saved\" ? { status: \"soft_deleted\" } : res.status === \"conflict\" ? { status: \"conflict\", currentVersion: res.currentVersion } : res;\n }\n if (table.archive) throw new DoorRefusedError(door, \"this table archives instead of deleting — use archive()\");\n const expected = guard && \"expectedVersion\" in guard ? guard.expectedVersion : undefined;\n if (expected !== undefined && !table.versioned) throw new DoorRefusedError(door, \"expectedVersion on a table that is not versioned\");\n if (table.versioned && expected === undefined && !(guard && \"overwrite\" in guard)) {\n throw new DoorRefusedError(door, \"a versioned table takes { expectedVersion } or { overwrite: true }\");\n }\n let q = byPk(from(db, table).delete(), table, id);\n if (expected !== undefined) q = q.eq(\"version\", expected);\n const rows = check(door, await q.select(\"*\")) as unknown[] | null;\n if (rows && rows.length) return { status: \"deleted\" };\n if (expected !== undefined) {\n const current = check(door, await byPk(from(db, table).select(\"version\"), table, id).maybeSingle()) as { version: number } | null;\n if (current) return { status: \"conflict\", currentVersion: current.version };\n }\n return { status: \"not_found\" };\n}\n\n/** Archive (or, with `restore`, bring back) one row by the table's archive column. Guarded like `update`. */\nexport async function archive<R, I, U>(\n db: Db,\n table: TableDescriptor<R, I, U>,\n id: unknown,\n opts: { restore?: boolean; guard?: UpdateGuard } = {},\n): Promise<WriteResult<R>> {\n assertDoor(db, table, \"archive\");\n const door = `${opts.restore ? \"restore\" : \"archive\"} ${qualified(table)}`;\n let values: Record<string, unknown>;\n if (table.archive === \"archived_at\") values = { archived_at: opts.restore ? null : new Date().toISOString() };\n else if (table.archive === \"is_archived\") values = { is_archived: !opts.restore };\n else if (table.softDelete && opts.restore) values = { deleted_at: null };\n else throw new DoorRefusedError(door, \"the table has no archive column\");\n return writeRow<R>(db, table, id, values, door, opts.guard);\n}\n\n/** Bring back an archived or soft-deleted row. */\nexport const restore = <R, I, U>(db: Db, table: TableDescriptor<R, I, U>, id: unknown, guard?: UpdateGuard) =>\n archive(db, table, id, guard ? { restore: true, guard } : { restore: true });\n\n// ─── functions ──────────────────────────────────────────────────────────────\n\n/** Call a database function through its generated door (PostgREST chooses an overload by argument names). */\nexport async function call<F extends FunctionDescriptor<any, any>>(db: Db, fn: F, args: ArgsOf<F>): Promise<ResultOf<F>> {\n const door = `call ${fn.schema}.${fn.name}`;\n const role = db.role === \"service\" ? \"service_role\" : \"authenticated\";\n if (!fn.roles.includes(role) && !(role === \"authenticated\" && fn.roles.includes(\"anon\"))) {\n throw new DoorRefusedError(door, `not executable by ${role} (executable by: ${fn.roles.join(\", \") || \"nobody\"})`);\n }\n return check(door, await db.client.schema(fn.schema).rpc(fn.name, args as Record<string, unknown>));\n}\n\n/** One ordering column of a set-returning function's rows (PostgREST `order`). */\nexport type CallOrder = string | { column: string; ascending?: boolean; nullsFirst?: boolean };\n\n/**\n * EVERY row a set-returning function answers, paged past the 1,000-row cap by\n * `range` over a stable `order` (name enough columns to make it total — end on a key);\n * throws a `DatabaseError` with the database's own error, or `IncompleteReadError` on a short read.\n */\nexport async function callAll<F extends FunctionDescriptor<any, any>>(\n db: Db,\n fn: F,\n args: ArgsOf<F>,\n opts: { order: readonly CallOrder[]; pageSize?: number; maxRows?: number },\n): Promise<ResultOf<F> extends readonly (infer Row)[] ? Row[] : ResultOf<F>[]> {\n const door = `callAll ${fn.schema}.${fn.name}`;\n const role = db.role === \"service\" ? \"service_role\" : \"authenticated\";\n if (!fn.roles.includes(role) && !(role === \"authenticated\" && fn.roles.includes(\"anon\"))) {\n throw new DoorRefusedError(door, `not executable by ${role} (executable by: ${fn.roles.join(\", \") || \"nobody\"})`);\n }\n if (!opts.order.length) throw new DoorRefusedError(door, \"a paged read needs an order (end on a key) — pages over no order can skip or repeat rows\");\n return readAllRows<any>(\n ({ from: lo, to: hi }) => {\n let q: any = db.client.schema(fn.schema).rpc(fn.name, args as Record<string, unknown>, { count: \"exact\" });\n for (const o of opts.order) {\n q = typeof o === \"string\" ? q.order(o) : q.order(o.column, { ascending: o.ascending ?? true, ...(o.nullsFirst !== undefined ? { nullsFirst: o.nullsFirst } : {}) });\n }\n return Promise.resolve(q.range(lo, hi)).then((res: Resp<any>) => {\n if (res.error) throw new DatabaseError(door, res.error);\n return res;\n });\n },\n { label: door, ...(opts.pageSize !== undefined ? { pageSize: opts.pageSize } : {}), ...(opts.maxRows !== undefined ? { maxRows: opts.maxRows } : {}) },\n ) as never;\n}\n\n// ─── a table chosen at runtime ──────────────────────────────────────────────\n\n/** One schema's flags (`<schema>.flags.ts` from `matrx-data generate --flags-index`): \"schema.table\" → descriptor. */\nexport type FlagsIndex = Readonly<Record<string, TableDescriptor>>;\n/** Per-schema loaders (`flags-index.ts`): only the schema a runtime name names is loaded (pay-only). */\nexport type FlagLoaders = Readonly<Record<string, () => Promise<FlagsIndex>>>;\n\n/** The door for a table whose name arrives at runtime — loosely typed, the same rules. */\nexport function tableByName(index: FlagsIndex, name: string): TableDescriptor {\n const t = index[name];\n if (!t) throw new DoorRefusedError(`tableByName ${name}`, \"no such table in the database description (schema-qualify it: schema.table)\");\n return t;\n}\n\n/** `tableByName` over per-schema loaders: loads only the named schema's flags. */\nexport async function loadTableByName(loaders: FlagLoaders, name: string): Promise<TableDescriptor> {\n const schema = name.slice(0, name.indexOf(\".\"));\n const load = schema ? loaders[schema] : undefined;\n if (!load) throw new DoorRefusedError(`tableByName ${name}`, \"no such schema in the database description (schema-qualify it: schema.table)\");\n return tableByName(await load(), name);\n}\n\n// ─── realtime ───────────────────────────────────────────────────────────────\n\n/** The `postgres_changes` filter for a table — only published tables have one (an unpublished table delivers nothing). */\nexport function changesOf(table: TableDescriptor<any, any, any>): { schema: string; table: string } {\n if (!table.realtime) throw new DoorRefusedError(`changesOf ${qualified(table)}`, \"the table is not in the supabase_realtime publication\");\n return { schema: table.schema, table: table.name };\n}\n"],"mappings":"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","names":["from","page","from","text","window"]}