@palbase/backend 22.0.0 → 22.1.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/bin/palbase-backend.cjs +340 -22
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +2 -2
- package/dist/{chunk-QYOHMVUW.js → chunk-74XDEF5J.js} +338 -22
- package/dist/chunk-74XDEF5J.js.map +1 -0
- package/dist/{chunk-SSGAMC26.js → chunk-I3ON7MYF.js} +57 -5
- package/dist/chunk-I3ON7MYF.js.map +1 -0
- package/dist/{chunk-POYAFBLF.js → chunk-SQC5EIWY.js} +5 -3
- package/dist/chunk-SQC5EIWY.js.map +1 -0
- package/dist/db/index.cjs +60 -6
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.cts +2 -2
- package/dist/db/index.d.ts +2 -2
- package/dist/db/index.js +7 -3
- package/dist/{endpoint-B0LpZixz.d.cts → endpoint-BVT6jcVW.d.cts} +39 -7
- package/dist/{endpoint-B0LpZixz.d.ts → endpoint-BVT6jcVW.d.ts} +39 -7
- package/dist/engine/index.cjs +340 -22
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +4 -4
- package/dist/engine/index.d.ts +4 -4
- package/dist/engine/index.js +2 -2
- package/dist/{index-B4W6d2VJ.d.cts → index-BS1gW4nV.d.cts} +24 -25
- package/dist/{index-BGSCWlUa.d.cts → index-BqCiHao8.d.cts} +97 -7
- package/dist/{index-BCNtlG1w.d.ts → index-CCZqzych.d.ts} +24 -25
- package/dist/{index-g-EzitI-.d.ts → index-vwHoS0l2.d.ts} +97 -7
- package/dist/index.cjs +244 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +124 -9
- package/dist/index.d.ts +124 -9
- package/dist/index.js +186 -3
- package/dist/index.js.map +1 -1
- package/dist/openapi/index.d.cts +2 -2
- package/dist/openapi/index.d.ts +2 -2
- package/dist/{registry-Cw0YEYCg.d.cts → registry-BWttGlaT.d.cts} +1 -1
- package/dist/{registry-3BLYv4si.d.ts → registry-Bsuf-orT.d.ts} +1 -1
- package/docs/README.md +12 -7
- package/docs/endpoints.md +1 -1
- package/docs/errors.md +9 -0
- package/docs/llms-full.txt +22 -8
- package/package.json +1 -1
- package/dist/chunk-POYAFBLF.js.map +0 -1
- package/dist/chunk-QYOHMVUW.js.map +0 -1
- package/dist/chunk-SSGAMC26.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/bin/palbase-backend.ts","../../src/runtime.ts","../../src/db/tx-plan.ts","../../src/errors.ts","../../src/engine/config.ts","../../src/engine/auth.ts","../../src/engine/ratelimit.ts","../../src/engine/cache.ts","../../src/engine/db.ts","../../src/decorators/registry.ts","../../src/engine/router.ts","../../src/engine/upload.ts","../../src/engine/index.ts","../../src/decorators/controller.ts"],"sourcesContent":["#!/usr/bin/env bun\n/**\n * palbase-backend — run this project's backend.\n *\n * npm run dev → palbase-backend dev (reloads on change)\n * npm start → palbase-backend serve\n *\n * There is no scaffolding step and no server file to write. The project IS the\n * backend: every `controllers/*.controller.ts` is imported, which is what\n * registers it, and the engine is built around whatever registered.\n *\n * It is the same engine the deployed runtime builds — not a development\n * stand-in. A dev server that is a different program from the production one is\n * a source of \"works locally\" reports, and this one has no second implementation\n * to disagree with.\n */\nimport { readdir, stat } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport { createApp, loadConfig, BootRefused } from \"../engine/index.js\";\nimport { getRegisteredControllers } from \"../decorators/controller.js\";\n\nconst USAGE = `palbase-backend — run this project's backend\n\n palbase-backend serve start the backend\n palbase-backend dev start it and reload on change\n palbase-backend routes print the route table and exit\n\nConfiguration comes from the environment (a .env beside package.json is read):\n\n DATABASE_URL required — the stack's Postgres\n AUTH_JWKS_URL required — where your stack publishes its signing keys\n MODULE_BASE_URL where Documents/Storage/Notifications/Flags/Realtime live\n PALBASE_ANON_KEY publishable key, sent on module calls\n PALBASE_SERVICE_ROLE_KEY secret key, for privileged module calls\n PORT default 3000\n`;\n\nfunction die(message: string): never {\n console.error(message);\n process.exit(1);\n}\n\n/** Read a `.env` beside the project, without adding a dependency for it. */\nasync function loadDotEnv(root: string): Promise<void> {\n const file = Bun.file(join(root, \".env\"));\n if (!(await file.exists())) return;\n for (const raw of (await file.text()).split(\"\\n\")) {\n const line = raw.trim();\n if (!line || line.startsWith(\"#\")) continue;\n const eq = line.indexOf(\"=\");\n if (eq < 1) continue;\n const key = line.slice(0, eq).trim();\n // The environment wins: an exported value is the operator being explicit,\n // and a file quietly overriding it is how a \"why is it still pointing at\n // the old database\" hour begins.\n if (process.env[key] !== undefined) continue;\n let value = line.slice(eq + 1).trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n process.env[key] = value;\n }\n}\n\n/** Every `*.controller.ts` under `controllers/`, sorted, recursively. */\nasync function findControllers(root: string): Promise<string[]> {\n const dir = join(root, \"controllers\");\n try {\n if (!(await stat(dir)).isDirectory()) return [];\n } catch {\n return [];\n }\n const out: string[] = [];\n const walk = async (d: string): Promise<void> => {\n for (const entry of await readdir(d, { withFileTypes: true })) {\n const full = join(d, entry.name);\n if (entry.isDirectory()) await walk(full);\n else if (/\\.controller\\.(ts|js|mts|mjs)$/.test(entry.name)) out.push(full);\n }\n };\n await walk(dir);\n // Sorted so route precedence is the same on every machine.\n return out.sort();\n}\n\nasync function importSchema(root: string): Promise<unknown> {\n for (const candidate of [\"db/schema.ts\", \"db/schema.js\"]) {\n const path = join(root, candidate);\n try {\n await stat(path);\n return (await import(pathToFileURL(path).href)).default;\n } catch {\n // Not every project declares a schema; the typed `.tables` surface is\n // simply absent then.\n }\n }\n return undefined;\n}\n\nasync function main(): Promise<void> {\n const command = process.argv[2] ?? \"serve\";\n if (command === \"--help\" || command === \"-h\" || command === \"help\") {\n console.log(USAGE);\n return;\n }\n if (![\"serve\", \"dev\", \"routes\"].includes(command)) {\n die(`palbase-backend: unknown command \"${command}\".\\n\\n${USAGE}`);\n }\n if (typeof Bun === \"undefined\") {\n die(\n \"palbase-backend needs Bun: the engine serves `fetch` natively and opens its own\\n\" +\n \"Postgres pool through Bun.sql. Install it from https://bun.sh, then re-run.\",\n );\n }\n\n // `dev` is `serve` under Bun's watcher. Re-exec rather than reimplement:\n // one code path serves, and the reload is the runtime's job, not ours.\n if (command === \"dev\" && !process.env.PALBASE_WATCHING) {\n const self = Bun.fileURLToPath(import.meta.url);\n const child = Bun.spawn([\"bun\", \"--watch\", self, \"serve\"], {\n stdio: [\"inherit\", \"inherit\", \"inherit\"],\n env: { ...process.env, PALBASE_WATCHING: \"1\" },\n });\n process.exit(await child.exited);\n }\n\n const root = resolve(process.env.PALBASE_PROJECT_DIR ?? process.cwd());\n await loadDotEnv(root);\n\n const files = await findControllers(root);\n if (files.length === 0) {\n die(\n `palbase-backend: no controllers found under ${join(root, \"controllers\")}.\\n` +\n `A backend is its controllers — add one and run again:\\n\\n` +\n ` // controllers/hello.controller.ts\\n` +\n ` import { Controller, Get } from \"@palbase/backend\";\\n` +\n ` @Controller(\"/hello\")\\n` +\n ` class HelloController {\\n` +\n ` @Get(\"\") hi(): Promise<{ ok: boolean }> { return Promise.resolve({ ok: true }); }\\n` +\n ` }\\n`,\n );\n }\n\n // Importing IS the registration — the decorator records each class as it runs.\n for (const file of files) await import(pathToFileURL(file).href);\n const controllers = getRegisteredControllers();\n if (controllers.length === 0) {\n die(\n `palbase-backend: ${files.length} controller file(s) loaded but none registered.\\n` +\n `Every one of them is missing its @Controller decorator, or the files were\\n` +\n `compiled with decorators stripped. Nothing would answer, so this is fatal.`,\n );\n }\n\n let config;\n try {\n config = loadConfig(process.env as Record<string, string | undefined>);\n } catch (e) {\n if (e instanceof BootRefused) {\n die(\n `${e.message}\\n\\n` +\n `Put them in a .env beside package.json, or export them. A local stack\\n` +\n `(docker compose up) publishes both.`,\n );\n }\n throw e;\n }\n\n const app = await createApp({ config, controllers, schema: await importSchema(root) });\n\n if (command === \"routes\") {\n for (const route of app.routes) console.log(route.id);\n await app.shutdown();\n return;\n }\n\n Bun.serve({ port: config.port, idleTimeout: 60, fetch: app.handle });\n console.log(`palbase-backend listening on http://localhost:${config.port}`);\n console.log(` ${app.routes.length} endpoint(s) from ${files.length} controller file(s)`);\n for (const route of app.routes) console.log(` ${route.id}`);\n\n for (const signal of [\"SIGTERM\", \"SIGINT\"] as const) {\n process.on(signal, () => {\n void app.shutdown().finally(() => process.exit(0));\n });\n }\n}\n\n// Not a top-level await: this file is also emitted in a CommonJS flavour, where\n// one is a build error. The rejection handler is the point either way — an\n// unhandled one exits 0 on some runtimes, which would report a dead backend as\n// a successful start.\nmain().catch((e: unknown) => {\n console.error(e instanceof Error ? e.message : e);\n process.exit(1);\n});\n","/**\n * runtime.ts — request-scoped service singletons.\n *\n * The backend SDK no longer threads a `ctx` god-object through every handler.\n * Instead, controller methods import PascalCase service singletons directly:\n *\n * import { Controller, Post, Body, Database } from \"@palbase/backend\";\n *\n * \\@Controller(\"/todos\")\n * export default class TodosController {\n * \\@Post(\"\") create(\\@Body(CreateTodoBody) body: CreateTodoBody): unknown {\n * return Database.insert(\"todos\", { title: body.title });\n * }\n * }\n *\n * The singletons are thin Proxies. Every property access forwards to the live\n * client for the CURRENT request scope, resolved through {@link __getRuntime}.\n *\n * # Request-scope resolution (persistent app-server)\n *\n * The runtime is a long-running Node process that serves many concurrent\n * requests on one event loop (NOT a fresh subprocess per request). A single\n * module-global slot would let one in-flight request's services bleed into\n * another's. So the services are carried in an {@link AsyncLocalStorage} store\n * ({@link __requestALS}) that the runtime sets per request with\n * {@link __runWithRuntime}; every async continuation of that request reads its\n * own store. `__getRuntime` reads the ALS store first; the module-global slot\n * (set by {@link __setRuntime}) is only a fallback for callers that run OUTSIDE\n * an ALS scope (dev-server, unit tests, the legacy single-shot path). Because\n * each `br-<ref>` pod is single-tenant, there is no cross-tenant leakage; the\n * ALS store is what prevents cross-REQUEST leakage within the shared process.\n *\n * The seam that makes `import { Database } from \"@palbase/backend\"` resolve to\n * the runtime-injected client: `@palbase/backend` is marked esbuild-EXTERNAL\n * when the tenant bundle is built, and the package is installed globally in the\n * pod (NODE_PATH=/usr/local/lib/node_modules). So worker.js's\n * `require('@palbase/backend')` and the bundle's `import` resolve to ONE shared\n * module instance — the ALS store and `__setRuntime` slot on that instance are\n * visible to the singletons the bundle imported.\n */\n\nimport type { Buckets, BucketTypes } from \"./db/env.js\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type {\n DBClient,\n DBOps,\n CacheClient,\n Logger,\n PalbaseDocsClient,\n SecretsService,\n} from \"./endpoint.js\";\nimport type {\n PalbaseStorageClient,\n PalbaseBucketClient,\n PalbaseNotificationsClient,\n PalbaseFlagsClient,\n PalbaseFlagsServiceClient,\n PalbaseFlagContext,\n PalbaseFlagVariant,\n PalbaseFlag,\n PalbaseFlagValue,\n PalbaseSetOverrideResult,\n PalbaseRealtimeClient,\n} from \"./clients.js\";\nimport type { PalbaseResult } from \"./endpoint.js\";\nimport type {\n EnvTypedDatabase,\n EnvServiceDatabase,\n EnvTables,\n TxPlan,\n TxTables,\n} from \"./db/typed-db.js\";\nimport type { Materialized } from \"./db/tx-plan.js\";\nimport { TxPlanBuilder, runTxPlan } from \"./db/tx-plan.js\";\nimport type { PurchasesService } from \"./purchases/service.js\";\n\n/** The set of live clients the runtime injects per request scope.\n *\n * Realtime is BROADCAST-ONLY here (a stateless handler can push an event but\n * cannot hold a subscription socket — `subscribe()` lives on the client SDK).\n *\n * EXCLUDED on purpose: Functions, Links, Analytics, Auth. They are not\n * exposed as backend handler singletons (auth lives on the client SDK; the rest\n * are out of scope for backend endpoints). */\nexport interface RuntimeServices {\n Database: DBClient;\n Secrets: SecretsService;\n Documents: PalbaseDocsClient;\n Storage: PalbaseStorageClient;\n Cache: CacheClient;\n Log: Logger;\n Notifications: PalbaseNotificationsClient;\n Flags: PalbaseFlagsClient;\n Realtime: PalbaseRealtimeClient;\n Purchases: PurchasesService;\n}\n\n/**\n * The per-request ALS box.\n *\n * `runtime` is the service bundle. `userId` is the request's authenticated user\n * id, written by the runtime immediately after it assembles the request object\n * (worker.js: `requestALS.getStore().userId = pbReq.user?.id || null`) and\n * `null` on an anonymous request. It was already being written there for the\n * Flags client's auto-bind; declaring it here makes the existing contract typed\n * instead of implicit, which is what lets `currentSubjectId()` read a\n * server-owned identity rather than trusting anything the caller sent.\n */\nexport interface RequestStore {\n runtime: RuntimeServices;\n userId?: string | null;\n /** This request's id (`req_…`), written by the runtime. Used as the spend\n * idempotency scope when the caller supplied no `Idempotency-Key`. */\n requestId?: string;\n /** The caller's `Idempotency-Key` header, or `null` when absent. What makes a\n * client's retry replay its first result instead of charging twice. */\n idempotencyKey?: string | null;\n}\n\n/**\n * Per-request store. The persistent runtime runs each request inside\n * {@link __runWithRuntime}, so every async continuation of that request reads\n * its OWN `runtime` (and any other request-scoped fields the runtime adds).\n *\n * Exported with a `__` prefix so the runtime (worker.js) shares the SAME ALS\n * instance across the one module instance — two ALS instances would silently\n * not see each other's stores. NOT part of the public author-facing API.\n */\nexport const __requestALS = new AsyncLocalStorage<RequestStore>();\n\n/** Process-global fallback slot. Used only OUTSIDE an ALS scope (dev-server,\n * unit tests, legacy single-shot worker). Inside the persistent server every\n * request runs in {@link __requestALS}, which takes precedence. */\nlet runtime: RuntimeServices | null = null;\n\n/** Install the live clients in the process-global fallback slot.\n *\n * Persistent-server requests should use {@link __runWithRuntime} instead; this\n * remains for dev-server / tests / the legacy single-shot path that run without\n * an ALS scope. NOT part of the public author-facing API. */\nexport function __setRuntime(services: RuntimeServices): void {\n runtime = services;\n}\n\n/** Run `fn` with `services` bound as the request-scoped runtime.\n *\n * The persistent worker calls this once per request so concurrent requests\n * never share a services slot. NOT part of the public author-facing API. */\nexport function __runWithRuntime<T>(services: RuntimeServices, fn: () => T): T {\n return __requestALS.run({ runtime: services }, fn);\n}\n\n/** Read the live clients, throwing if accessed outside a request scope.\n *\n * Resolves the ALS store first (persistent server, per-request), then the\n * process-global fallback (dev-server / tests). NOT part of the public\n * author-facing API — used by the runtime and the singleton Proxies. */\nexport function __getRuntime(): RuntimeServices {\n const scoped = __requestALS.getStore();\n if (scoped) return scoped.runtime;\n if (runtime === null) {\n throw new Error(\n \"Palbase services accessed outside a request scope. The Database/Documents/… \" +\n \"singletons are only available inside an endpoint handler (or after the \" +\n \"runtime has called __runWithRuntime / __setRuntime).\",\n );\n }\n return runtime;\n}\n\n/**\n * Build a Proxy singleton that forwards every property access to the live\n * client named `key` on the current runtime.\n *\n * The single `as RuntimeServices[K]` is the only contained cast in the surface:\n * `Reflect.get` on a typed object returns `unknown` for a `string | symbol`\n * key, but `prop` is constrained to keys of the client interface at the call\n * sites (the exported singletons are typed below), so the forward is sound.\n */\nfunction makeServiceProxy<K extends keyof RuntimeServices>(key: K): RuntimeServices[K] {\n const handler: ProxyHandler<RuntimeServices[K]> = {\n get(_target, prop, receiver) {\n const client = __getRuntime()[key];\n const value = Reflect.get(client as object, prop, receiver) as unknown;\n // Bind methods to their owning client so `this` stays correct when the\n // author destructures or calls `Database.query(...)`.\n return typeof value === \"function\" ? value.bind(client) : value;\n },\n };\n // The Proxy target is irrelevant (all access goes through `get`); the cast\n // names the surface type the singleton presents to authors.\n return new Proxy({} as RuntimeServices[K], handler);\n}\n\n/**\n * Build the `.tables` accessor for the top-level `Database`. Each\n * `tables.<name>` access returns a small object that forwards the five CRUD ops\n * to the underlying client using `name` as the string table identifier. The\n * shapes are typed against the generated `palbase-env.d.ts` (`EnvTables`); at\n * runtime they are plain string-keyed calls, so no schema value is needed here.\n *\n * Returns `EnvTables` — TS cannot infer the mapped type through the Proxy, so\n * a single structural narrowing names the surface (the proxy returns a\n * correctly-shaped accessor for whatever string member is read).\n */\nfunction makeTablesAccessor(ops: () => DBOps): EnvTables {\n const tablesProxy = new Proxy(\n {},\n {\n get(_t, prop: string | symbol) {\n if (typeof prop !== \"string\") return undefined;\n const name = prop;\n return {\n insert: (data: Record<string, unknown>) => ops().insert(name, data),\n update: (id: string, data: Record<string, unknown>) => ops().update(name, id, data),\n delete: (id: string) => ops().delete(name, id),\n findById: (id: string) => ops().findById(name, id),\n findMany: (query?: Record<string, unknown>) => ops().findMany(name, query),\n };\n },\n },\n );\n return tablesProxy as EnvTables;\n}\n\n/** The raw string-keyed `DBClient` for the current request scope. */\nconst rawDatabase: DBClient = makeServiceProxy(\"Database\");\n\n/**\n * Wrap a raw `DBClient` into the typed `{ ...ops, tables, transaction }`\n * surface. The five string ops forward straight through; `tables` is the\n * env-typed accessor; `transaction` yields typed tables. Reused for both the\n * default (RLS-enforced) `Database` and the `asService()` sibling — each is\n * fed its own raw client (the default proxy vs `rawDatabase.asService()`).\n *\n * The `satisfies` pins the op surface so a missing/renamed op is a compile\n * error; the assembled object carries `tables`/`transaction` alongside.\n */\nfunction makeTypedSurface(raw: Omit<DBClient, \"asService\">): EnvServiceDatabase {\n const ops = {\n query: (sql: string, params?: unknown[]) => raw.query(sql, params),\n insert: (table: string, data: Record<string, unknown>) => raw.insert(table, data),\n update: (table: string, id: string, data: Record<string, unknown>) =>\n raw.update(table, id, data),\n delete: (table: string, id: string) => raw.delete(table, id),\n findById: (table: string, id: string) => raw.findById(table, id),\n findMany: (table: string, query?: Record<string, unknown>) => raw.findMany(table, query),\n } satisfies DBOps;\n return Object.assign(ops, {\n tables: makeTablesAccessor(() => raw),\n transaction<T>(\n fn: (tx: TxPlan) => T extends Promise<unknown> ? never : T,\n ): Promise<Materialized<T>> {\n // A FRESH builder per call: it holds this transaction's ops and its error\n // slot table, and the runtime serves concurrent requests on one event loop.\n // A shared builder would splice one request's writes into another's plan.\n const builder = new TxPlanBuilder();\n return runTxPlan(raw, makeTxTablesAccessor(builder), builder, fn) as Promise<\n Materialized<T>\n >;\n },\n });\n}\n\n/**\n * The transaction twin of {@link makeTablesAccessor}: `tables.<name>` yields the\n * table's PLAN operations, recorded into `builder` instead of sent one by one.\n *\n * Same Proxy shape and same reason for the single narrowing — TS cannot infer a\n * mapped type through a Proxy, so the cast names what the trap returns.\n */\nfunction makeTxTablesAccessor(builder: TxPlanBuilder): TxTables {\n const tablesProxy = new Proxy(\n {},\n {\n get(_t, prop: string | symbol) {\n if (typeof prop !== \"string\") return undefined;\n return builder.table(prop);\n },\n },\n );\n return tablesProxy as TxTables;\n}\n\n/**\n * The project's own Postgres (pgx, schema `env_<envId>`).\n *\n * Typed by default: `Database.tables.<name>.insert({...})` is typed against\n * the project's generated `palbase-env.d.ts` with NO import and NO generic.\n * The raw string ops (`query`/`insert`/`update`/`delete`/`findById`/`findMany`)\n * are also available for dynamic table names and read-only SQL.\n *\n * RLS is enforced by default (the runtime runs each op as `authenticated` with\n * the verified user's claims). To bypass RLS, call `Database.asService()` —\n * explicit and greppable — which runs as the `service_role` (BYPASSRLS).\n *\n * @example\n * import { Database } from \"@palbase/backend\";\n *\n * const todo = await Database.tables.todos.insert({ title: req.input.title });\n * todo.id; // string ✓\n * const rows = await Database.query(\"SELECT id FROM todos WHERE done = $1\", [false]);\n * const all = await Database.asService().tables.todos.findMany({}); // RLS bypass\n */\nexport const Database: EnvTypedDatabase = Object.assign(makeTypedSurface(rawDatabase), {\n /**\n * Lazily resolve the runtime's service-role sibling on each call. We do NOT\n * cache it: `rawDatabase.asService()` reads the CURRENT request scope through\n * the runtime proxy, and the per-request runtime injects a service client\n * bound to that request's identity headers — caching would leak one request's\n * sibling into another concurrent request.\n */\n asService(): EnvServiceDatabase {\n return makeTypedSurface(rawDatabase.asService());\n },\n});\n\n/** Firestore-like document client (PalDocs). */\nexport const Documents: PalbaseDocsClient = makeServiceProxy(\"Documents\");\n\n/**\n * `buckets.<name>` — the storage twin of `Database.tables.<name>`, and the same\n * mechanism: `config/storage.ts` generates a `Buckets` augmentation into\n * `palbase-env.d.ts`, so a bucket name is a property with no import and no\n * generic, and a typo is a compile error.\n *\n * The intermediate `.buckets` is there for the reason `.tables` is: bucket\n * names must not share a namespace with the client's own methods, or the day\n * somebody declares a bucket called `bucket` the surface breaks.\n */\nexport type EnvBuckets = {\n [K in keyof Buckets]: TypedBucketClient<Buckets[K] extends BucketTypes ? Buckets[K] : BucketTypes>;\n};\n\n/** One bucket, with its declared variant names in the type. */\nexport interface TypedBucketClient<B extends BucketTypes> extends Omit<PalbaseBucketClient, \"getPublicUrl\"> {\n /** The public URL for the object, or for one of THIS bucket's declared\n * renditions. A name the bucket does not declare is a compile error. */\n getPublicUrl(path: string, options?: { variant?: B[\"variants\"] }): string;\n}\n\nfunction makeBucketsAccessor(storage: () => PalbaseStorageClient): EnvBuckets {\n return new Proxy(\n {},\n {\n get(_t, prop: string | symbol) {\n if (typeof prop !== \"string\") return undefined;\n return storage().bucket(prop);\n },\n },\n ) as EnvBuckets;\n}\n\nconst rawStorage: PalbaseStorageClient = makeServiceProxy(\"Storage\");\n\n/**\n * Object storage: buckets, objects, renditions and signed URLs.\n *\n * `Storage.buckets.posts.upload(...)` is the typed path. `Storage.bucket(name)`\n * remains for a name computed at runtime — rare, and it gives up the typing,\n * which is the honest trade rather than a second blessed way to do it.\n */\nexport const Storage: PalbaseStorageClient & { buckets: EnvBuckets } = Object.assign(\n {\n // FORWARDED explicitly, not assigned onto the service proxy.\n //\n // `Object.assign(rawStorage, {buckets})` writes onto the proxy's TARGET, and\n // the proxy's only trap is `get`, which forwards every read to the module\n // client — so the property landed somewhere nothing reads and\n // `Storage.buckets.docs` was `undefined` in a deployed handler. It\n // typechecked, every test passed, and the live call answered\n // \"TypeError: undefined is not an object\". `Database` never had the bug\n // because it builds a plain surface the same way this now does.\n bucket: (name: string) => rawStorage.bucket(name),\n },\n { buckets: makeBucketsAccessor(() => rawStorage) },\n);\n\n/** JSON-typed cache (get/set/incr/getOrSet). */\nexport const Cache: CacheClient = makeServiceProxy(\"Cache\");\n\n\n/**\n * This tenant's secrets — API keys, provider credentials, signing material the\n * BACKEND owns.\n *\n * `await Secrets.get(\"STRIPE_KEY\")` in a handler. There is no `.env` to read\n * and no file to mount: a secret is written through the vault's authenticated\n * API (or the CLI/MCP that calls it), and this is how the deployed code reads\n * it back. A name this tenant has not set answers null — as does every name\n * the STACK holds, because no route returns a platform secret's value at all.\n */\nexport const Secrets: SecretsService = makeServiceProxy(\"Secrets\");\n\n/** Structured logger. */\nexport const Log: Logger = makeServiceProxy(\"Log\");\n\n/** Push / email / SMS / in-app notifications. */\nexport const Notifications: PalbaseNotificationsClient = makeServiceProxy(\"Notifications\");\n\n/**\n * Palstore purchases (entitlements + quota/credit spend).\n *\n * Reached by handlers through the `@RequireEntitlement` / `@Spend` decorators\n * rather than called directly in the common case; exposed as a singleton for\n * the cases the decorators deliberately do not cover (a dynamic spend count,\n * which must run BEFORE the billable side-effect).\n */\nexport const Purchases: PurchasesService = makeServiceProxy(\"Purchases\");\n\n/**\n * The raw runtime Flags client for the current request scope. Carries the\n * default-surface reads + `setOverride` AND the runtime's `asService()` sibling\n * (the br-pod's `buildFlagsClient` returns both). The default `Flags` singleton\n * below forwards reads + `setOverride` through here; `Flags.asService()`\n * forwards to this client's own `asService()`.\n */\nconst rawFlags: PalbaseFlagsClient = makeServiceProxy(\"Flags\");\n\n/**\n * Feature flags.\n *\n * Mirrors the `Database` / `Database.asService()` model. The default surface is\n * RLS-equivalent for flags: reads resolve against the CURRENT request user and\n * `Flags.setOverride(key, value)` writes an override for that same signed-in\n * user (no userId argument, no admin power). Cross-user admin writes\n * (`setOverrideForUser`, …) live behind `Flags.asService()` — explicit and\n * greppable, just like `Database.asService()`.\n *\n * @example\n * import { Flags } from \"@palbase/backend\";\n *\n * if (await Flags.isEnabled(\"new_checkout\")) { ... } // current user\n * await Flags.setOverride(\"new_checkout\", true); // current user\n * await Flags.asService().setOverrideForUser(\"u_9\", \"x\", true); // cross-user\n */\nexport const Flags: PalbaseFlagsClient = Object.assign(\n {\n isEnabled(\n flagName: string,\n context?: PalbaseFlagContext,\n ): Promise<PalbaseResult<boolean>> {\n return rawFlags.isEnabled(flagName, context);\n },\n getVariant(\n flagName: string,\n context?: PalbaseFlagContext,\n ): Promise<PalbaseResult<PalbaseFlagVariant>> {\n return rawFlags.getVariant(flagName, context);\n },\n getAll(context?: PalbaseFlagContext): Promise<PalbaseResult<PalbaseFlag[]>> {\n return rawFlags.getAll(context);\n },\n /**\n * Resolve a flag's value, with an optional fallback.\n *\n * FORWARDED as of 2026-08-15. This surface is written out by hand, method\n * by method, and `get` was missing from it — so the client implemented it,\n * thirty assertions covered it, and `Flags.get(\"x\")` was `undefined` in a\n * deployed handler. Exactly the shape of the `Storage.buckets` defect found\n * the same day: a hand-maintained forwarding list is a list somebody has to\n * remember to update.\n */\n get(\n flagName: string,\n defaultOrContext?: PalbaseFlagValue | PalbaseFlagContext,\n maybeContext?: PalbaseFlagContext,\n ): Promise<PalbaseResult<PalbaseFlagValue>> {\n return rawFlags.get(flagName, defaultOrContext, maybeContext);\n },\n setOverride(\n key: string,\n value: PalbaseFlagValue,\n ): Promise<PalbaseResult<PalbaseSetOverrideResult>> {\n return rawFlags.setOverride(key, value);\n },\n },\n {\n /**\n * Lazily resolve the runtime's cross-user sibling on each call. We do NOT\n * cache it: `rawFlags.asService()` reads the CURRENT request scope through\n * the runtime proxy, so caching would leak one request's sibling into\n * another concurrent request. Mirrors `Database.asService()`.\n */\n asService(): PalbaseFlagsServiceClient {\n return rawFlags.asService();\n },\n },\n);\n\n/**\n * The Realtime broadcast singleton for the current request scope. Backend-side\n * Realtime is BROADCAST-ONLY (a stateless handler can push but not subscribe —\n * `subscribe()` lives on the client SDK's `pb.realtime`). Fire-and-forget:\n * `broadcast` resolves once accepted (or with an `error`), never blocking the\n * handler on subscribers.\n *\n * @example\n * import { Realtime } from \"@palbase/backend\";\n *\n * await Realtime.broadcast(\"room:42\", \"message\", { text, from: user.id });\n */\nexport const Realtime: PalbaseRealtimeClient = makeServiceProxy(\"Realtime\");\n","/**\n * tx-plan.ts — `Database.transaction()` as a PLAN, not a pinned session.\n *\n * A transaction used to be a conversation: BEGIN, then one network round trip\n * per operation, then COMMIT. Each of those round trips cost ~4 ms and, because\n * the pooler runs in transaction mode, an open transaction pinned a Postgres\n * backend for the whole conversation. A 121-operation statement upload pinned\n * one backend for ~490 ms.\n *\n * So the callback no longer TALKS to the database. It DESCRIBES what should\n * happen; the description is serialised and sent once; the broker runs the whole\n * thing inside one transaction and answers once. Committing on return and\n * rolling back on throw is unchanged — that is the only property tenant code\n * actually asked for.\n *\n * The consequences, stated plainly, because they are the whole design:\n *\n * - The callback is SYNCHRONOUS. There is nothing to await: no statement has\n * run yet when it returns. `async` on the callback and `await` inside it are\n * both compile errors (see {@link TxPlan} and {@link NotAwaitable}).\n * - `insert()` does not hand back a row, it hands back {@link TxRows}. Reading\n * a field requires `.expectOne(err)` first, which makes \"what if the row\n * isn't there\" a question you cannot route around: it is the argument.\n * - A field read from a row is a {@link Ref} — a PROMISE OF A VALUE THE SERVER\n * WILL PRODUCE, not the value. It can be written into a later operation and\n * it can be returned from the callback (it is substituted for the real value\n * before `transaction()` resolves). It cannot be branched on. See the\n * \"Truthiness\" note below — this is the sharp edge of the whole design.\n * - Control flow that needs a real value must move OUT of the callback: read\n * before the transaction, or express the condition as a guard\n * (`updateWhere({ id, accepted_at: null }, …).expectOne(new Conflict(…))`)\n * which the server evaluates and which rolls the whole plan back.\n *\n * # Truthiness — the hole this file CANNOT close\n *\n * JavaScript does not let a Proxy trap truthiness. `if (ref)` takes the true\n * branch, always, for every Ref, and no `get` handler ever runs. `tsc` is silent\n * because a Ref is a perfectly good object. So:\n *\n * const pot = tx.tables.pots.select({ id }, { limit: 1 }).expectOne(e);\n * if (!pot.balance) { … } // ← ALWAYS false. Silently wrong data.\n *\n * What this file does close: coercion (`Symbol.toPrimitive`/`valueOf`/\n * `toString`), awaiting (`then` is a callable member with a non-thenable\n * signature, which is a *compile* error), serialisation (`toJSON`), and nesting\n * a Ref inside a literal value where the server would store it as data. What it\n * cannot close is a bare truthiness test. The real defence is the build-time\n * static analysis (`tx_analysis.js`, phase P4); until that ships, this hole is\n * open and this comment is the only warning.\n *\n * # Wire contract\n *\n * The JSON this file emits is consumed by\n * `modules/backend/internal/management/tx_program.go`. That decoder rejects\n * unknown fields at every level, so an op carries EXACTLY the fields its kind\n * takes. Everything here that looks like a needless restriction is one of the\n * server's rules made visible early:\n *\n * - `$ref` only points BACKWARDS, and only at an op statically known to yield\n * at most one row (insert, or a `one`/`atMost 1` guard, or `select limit 1`).\n * `.expectOne()` is what this file uses to satisfy that, always.\n * - `$expr` is a closed set: `inc`/`dec` (update only — they read the column's\n * current value) and `now()`.\n * - `update`/`delete` require a `where`; `insert` refuses one.\n * - `insertMany` rows must all set the same columns.\n * - ≤1000 ops, ≤5000 rows per insertMany, ≤8 MiB of JSON.\n *\n * Column keys are emitted SORTED, so the same callback always produces byte-\n * identical JSON. That is what lets the Go decoder be locked to golden files\n * this SDK emits (`testdata/tx_plan_golden/`).\n */\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\n/**\n * A plan handle was used as if it were a value: awaited, coerced to a string or\n * number, serialised, or nested inside another value.\n *\n * Thrown while the callback is still BUILDING the plan, so nothing has been sent\n * and nothing has been written.\n */\nexport class TxRefError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TxRefError\";\n }\n}\n\n/**\n * The plan the callback described cannot be sent: it breaks a rule the server\n * would reject, and rejecting it here names the line that wrote it instead of\n * returning a 400 about an op index.\n */\nexport class TxPlanError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TxPlanError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Wire types — mirror tx_program.go's decoder exactly.\n// ---------------------------------------------------------------------------\n\n/** A backwards reference to an earlier op's single-row result. */\nexport interface TxWireRef {\n $ref: { op: number; field: string };\n}\n\n/** A call from the server's closed function set. */\nexport interface TxWireExpr {\n $expr: { fn: \"inc\" | \"dec\"; by: number } | { fn: \"now\" };\n}\n\n/** One value in a `values`/`set`/`where` map: a literal, a `$ref` or a `$expr`. */\nexport type TxWireValue = TxWireRef | TxWireExpr | unknown;\n\n/** The tenant's declared expectation about an op's row count. `slot` indexes the\n * client-side error table — the error OBJECT never travels. */\nexport interface TxWireGuard {\n kind: \"one\" | \"none\" | \"atLeast\" | \"atMost\";\n n: number;\n slot: number;\n}\n\n/** One operation in the wire plan. Fields are omitted, never null: the decoder\n * rejects a field that does not belong to the op's kind. */\nexport interface TxWireOp {\n op: \"insert\" | \"insertMany\" | \"update\" | \"delete\" | \"select\";\n table: string;\n values?: Record<string, TxWireValue>;\n rows?: Record<string, TxWireValue>[];\n set?: Record<string, TxWireValue>;\n where?: Record<string, TxWireValue>;\n limit?: number;\n lock?: \"update\";\n guard?: TxWireGuard;\n}\n\n/** The plan the engine executes on the request's own transaction. */\nexport interface TxPlanBody {\n ops: TxWireOp[];\n}\n\n/** One op's outcome, positionally matched to the plan's ops. */\nexport interface TxPlanOpResult {\n rows: Record<string, unknown>[];\n rows_affected: number;\n}\n\n/** One result per op, in plan order. */\nexport interface TxPlanResponse {\n results: TxPlanOpResult[];\n}\n\n/**\n * The fields the runtime must copy from the broker's error envelope onto the\n * rejection it throws out of {@link DBClient.txPlan}.\n *\n * `slot` is the whole point: on a guard failure the server answers with the\n * INDEX of the expectation that did not hold, never with an error message of its\n * own, and this SDK maps that index back to the `Error` the callback handed to\n * `.expectOne(…)`. Without `slot` a guard failure degrades to a generic 409.\n */\nexport interface TxPlanRejection {\n status?: number;\n /** `tx_plan_invalid` | `tx_guard_failed` | `tx_ref_unresolved` | a pg class. */\n error_code?: string;\n /** Present only for `tx_guard_failed`: the client-side error table index. */\n slot?: number;\n /** Present on a database error: which op failed. */\n op?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Handle types\n// ---------------------------------------------------------------------------\n\ndeclare const refBrand: unique symbol;\ndeclare const rowBrand: unique symbol;\ndeclare const rowsBrand: unique symbol;\n\n/**\n * Makes a handle a compile error to `await`.\n *\n * `then` is declared as a CALLABLE member whose signature is not `PromiseLike`,\n * which is precisely the shape TypeScript rejects: `await handle` is TS1320 and\n * `async () => handle` is TS1058. A non-callable `then` would not do it — the\n * compiler simply ignores those.\n */\nexport interface NotAwaitable {\n /** Not a promise. Nothing here has run yet; there is nothing to await. */\n then(doNotAwaitAPlanHandle: \"a transaction plan is built synchronously\"): never;\n}\n\n/**\n * A value the SERVER will produce, standing in for a column of a row this plan\n * writes or reads.\n *\n * Legal uses: write it into a later operation's `values`/`set`/`where`, or\n * return it from the callback (it is replaced by the real value before\n * `transaction()` resolves).\n *\n * Illegal, and caught: `await`, `String(ref)`, `` `${ref}` ``, `ref + 1`,\n * `JSON.stringify(ref)`, burying it inside a jsonb object.\n *\n * Illegal, and NOT caught: `if (ref)`. See the truthiness note at the top.\n */\nexport interface Ref<T> extends NotAwaitable {\n readonly [refBrand]: T;\n}\n\n/** The brand carried by a single-row handle, and the seam `Materialized` reads\n * to turn `return st` into the whole row. */\nexport interface TxRowHandle<Row> extends NotAwaitable {\n readonly [rowBrand]: Row;\n}\n\n/**\n * A row this plan is known to produce exactly one of. Every property is a\n * {@link Ref}; returning the handle itself yields the whole row.\n *\n * Only `.expectOne(err)` produces one — which is the design: a row you can read\n * fields from is a row whose absence you have already answered for.\n */\nexport type TxRow<Row> = { readonly [K in keyof Row]: Ref<Row[K]> } & TxRowHandle<Row>;\n\n/**\n * The result of one operation, before any expectation is declared about it.\n *\n * Deliberately not a row and not a list: an operation's row count is not known\n * until the server runs it, so the only thing that can be said about it here is\n * an EXPECTATION. Declaring one is also the only way to get a readable row.\n *\n * At most one expectation per operation — the wire carries one guard per op, and\n * a second call throws rather than silently dropping the first.\n */\nexport interface TxRows<Row> extends NotAwaitable {\n readonly [rowsBrand]: Row;\n /**\n * Require exactly one row, and read it. On any other count the server rolls\n * the whole transaction back and this `error` is thrown to the caller.\n *\n * This is the only way to reach a row's fields, and the only shape a `$ref`\n * may point at.\n */\n expectOne(error: Error): TxRow<Row>;\n /** Require zero rows (e.g. \"this membership must not already exist\"). */\n expectNone(error: Error): void;\n /** Require at least `n` rows. */\n expectAtLeast(n: number, error: Error): void;\n /** Require at most `n` rows. */\n expectAtMost(n: number, error: Error): void;\n}\n\n/** `now()` — the server's clock, usable wherever a value is. */\nexport interface TxNow extends NotAwaitable {\n readonly $expr: { fn: \"now\" };\n}\n\n/** `inc(n)` / `dec(n)` — read the column's CURRENT value and write it back\n * changed. Only meaningful in an update's `set`, which is where the types allow\n * it and where the server allows it. */\nexport interface TxColumnExpr extends NotAwaitable {\n readonly $expr: { fn: \"inc\" | \"dec\"; by: number };\n}\n\n/**\n * Resolve a callback's return type against what actually comes back: every\n * {@link Ref} becomes its value, every {@link TxRow} becomes its row, and\n * anything else keeps its shape.\n *\n * A {@link TxRows} resolves to an explanatory string type rather than a row\n * list: it has no single answer to give, and saying so in the type is louder\n * than a runtime throw.\n */\nexport type Materialized<T> = T extends Ref<infer U>\n ? U\n : T extends TxRowHandle<infer R>\n ? R\n : T extends TxRows<unknown>\n ? \"a TxRows cannot leave the transaction callback — read a row with .expectOne(err) first\"\n : T extends Date\n ? T\n : T extends object\n ? { [K in keyof T]: Materialized<T[K]> }\n : T;\n\n// ---------------------------------------------------------------------------\n// Author-facing value types\n// ---------------------------------------------------------------------------\n\n/** A value written by an INSERT: a literal, an earlier row's field, or `now()`.\n * `inc`/`dec` are absent on purpose — they read a current value, and an inserted\n * row has none. */\nexport type TxInsertValue<V> = V | Ref<V> | TxNow;\n\n/** A value written by an UPDATE's `set`: everything an insert takes, plus the\n * read-modify-write expressions. */\nexport type TxSetValue<V> = V | Ref<V> | TxNow | TxColumnExpr;\n\n/** An insert payload: the table's insert shape, with refs and `now()` allowed. */\nexport type TxInsertShape<Insert> = { [K in keyof Insert]: TxInsertValue<Insert[K]> };\n\n/** An update's `set`: any subset of the insert shape, with expressions allowed. */\nexport type TxSetShape<Insert> = { [K in keyof Insert]?: TxSetValue<Insert[K]> };\n\n/**\n * A filter. Every entry is an equality test and they are AND-ed; a `null`\n * becomes `IS NULL`, which is what makes `{ accepted_at: null }` a usable\n * \"not yet accepted\" guard rather than a clause that matches nothing.\n */\nexport type TxWhere<Row> = { [K in keyof Row]?: Row[K] | Ref<Row[K]> };\n\n/** Options for a plan `select`. */\nexport interface TxSelectOptions {\n /** Cap the rows read. */\n limit?: number;\n /** Take a real `FOR UPDATE` row lock for the rest of the transaction. */\n lock?: \"update\";\n}\n\n/** One table, as the plan sees it. */\nexport interface TxTable<Row, Insert> {\n /** Insert one row. Returns a handle — call `.expectOne(err)` to read fields. */\n insert(values: TxInsertShape<Insert>): TxRows<Row>;\n /**\n * Insert many rows in ONE statement. Every row must set the same columns\n * (a row that omits one would silently take the column's default).\n *\n * An empty list writes nothing and sends nothing.\n */\n insertMany(rows: readonly TxInsertShape<Insert>[]): TxRows<Row>;\n /**\n * Update every row matching `where`. The filter comes first because it is the\n * dangerous half: an update whose `where` you got wrong rewrites rows you\n * never looked at. The server refuses an update with no `where` at all.\n */\n updateWhere(where: TxWhere<Row>, set: TxSetShape<Insert>): TxRows<Row>;\n /** Delete every row matching `where`. The server refuses an unfiltered delete. */\n deleteWhere(where: TxWhere<Row>): TxRows<Row>;\n /** Read rows, optionally locking them for the rest of the transaction. */\n select(where?: TxWhere<Row>, options?: TxSelectOptions): TxRows<Row>;\n}\n\n/**\n * The handle a transaction callback receives.\n *\n * It carries tables and nothing else: no `query`, no `findById`, no `asService`.\n * A read whose value the plan does not write belongs OUTSIDE the transaction,\n * where it costs one round trip and can be branched on like an ordinary value.\n */\nexport interface TxPlanHandle<TTables> {\n tables: TTables;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — expressions\n// ---------------------------------------------------------------------------\n\n/** Internal marker read by the serialiser. */\nconst EXPR = Symbol.for(\"palbase.tx.expr\");\nconst REF = Symbol.for(\"palbase.tx.ref\");\nconst ROW = Symbol.for(\"palbase.tx.row\");\nconst ROWS = Symbol.for(\"palbase.tx.rows\");\n\ninterface RefDescriptor {\n op: number;\n field: string;\n}\n\n/** Property reads that must not silently produce a value on a plan handle.\n * `then` is the one that matters for correctness (it makes `await` a compile\n * error AND stops a handle from being adopted by a promise); the rest turn a\n * silent wrong answer — `\"[object Object]\"`, `NaN`, `{}` — into a thrown one. */\nconst TRAPPED_PROPS: readonly (string | symbol)[] = [\n \"then\",\n \"valueOf\",\n \"toString\",\n \"toJSON\",\n Symbol.toPrimitive,\n];\n\nfunction trap(prop: string | symbol, what: string, hint: string): never {\n const name = typeof prop === \"symbol\" ? prop.description ?? String(prop) : prop;\n throw new TxRefError(\n `${what} was used as a value (via \\`${name}\\`). Nothing in a transaction ` +\n `callback has run yet, so there is no value to read. ${hint}`,\n );\n}\n\n/** The server's `now()`. */\nexport function now(): TxNow {\n return makeExpr({ fn: \"now\" }) as TxNow;\n}\n\n/** Add `by` to the column's current value. Only valid in an update's `set`. */\nexport function inc(by: number): TxColumnExpr {\n assertFiniteNumber(by, \"inc\");\n return makeExpr({ fn: \"inc\", by }) as TxColumnExpr;\n}\n\n/** Subtract `by` from the column's current value. Only valid in an update's `set`. */\nexport function dec(by: number): TxColumnExpr {\n assertFiniteNumber(by, \"dec\");\n return makeExpr({ fn: \"dec\", by }) as TxColumnExpr;\n}\n\nfunction assertFiniteNumber(by: number, fn: string): void {\n if (typeof by !== \"number\" || !Number.isFinite(by)) {\n // JSON has no NaN/Infinity: they would serialise to `null` and the server\n // would reject the plan with an unhelpful decode error.\n throw new TxPlanError(`${fn}() needs a finite number, got ${String(by)}`);\n }\n}\n\nfunction makeExpr(expr: TxWireExpr[\"$expr\"]): unknown {\n return new Proxy(\n { [EXPR]: expr } as Record<string | symbol, unknown>,\n {\n get(target, prop) {\n if (prop === EXPR) return target[EXPR];\n if (TRAPPED_PROPS.includes(prop)) {\n trap(prop, \"A plan expression\", \"Write it into an operation instead.\");\n }\n return undefined;\n },\n },\n );\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — refs and row handles\n// ---------------------------------------------------------------------------\n\nfunction makeRef(op: number, field: string): unknown {\n const target: Record<string | symbol, unknown> = { [REF]: { op, field } satisfies RefDescriptor };\n return new Proxy(target, {\n get(t, prop) {\n if (prop === REF) return t[REF];\n if (TRAPPED_PROPS.includes(prop)) {\n trap(\n prop,\n `\\`${field}\\` of a row this transaction has not written yet`,\n \"Pass it to another operation in the same plan, or return it from the \" +\n \"callback and read it after `transaction()` resolves.\",\n );\n }\n return undefined;\n },\n });\n}\n\nfunction makeRowHandle(op: number): unknown {\n const target: Record<string | symbol, unknown> = { [ROW]: op };\n return new Proxy(target, {\n get(t, prop) {\n if (prop === ROW) return t[ROW];\n if (TRAPPED_PROPS.includes(prop)) {\n trap(\n prop,\n \"A row this transaction has not written yet\",\n \"Read one of its columns to reference it, or return the row from the \" +\n \"callback and read it after `transaction()` resolves.\",\n );\n }\n if (typeof prop === \"symbol\") return undefined;\n return makeRef(op, prop);\n },\n });\n}\n\nfunction refDescriptor(v: unknown): RefDescriptor | null {\n if (typeof v !== \"object\" || v === null) return null;\n const d = (v as Record<symbol, unknown>)[REF];\n return isRefDescriptor(d) ? d : null;\n}\n\nfunction isRefDescriptor(d: unknown): d is RefDescriptor {\n return (\n typeof d === \"object\" &&\n d !== null &&\n typeof (d as RefDescriptor).op === \"number\" &&\n typeof (d as RefDescriptor).field === \"string\"\n );\n}\n\nfunction rowOpIndex(v: unknown): number | null {\n if (typeof v !== \"object\" || v === null) return null;\n const op = (v as Record<symbol, unknown>)[ROW];\n return typeof op === \"number\" ? op : null;\n}\n\nfunction exprOf(v: unknown): TxWireExpr[\"$expr\"] | null {\n if (typeof v !== \"object\" || v === null) return null;\n const e = (v as Record<symbol, unknown>)[EXPR];\n return typeof e === \"object\" && e !== null ? (e as TxWireExpr[\"$expr\"]) : null;\n}\n\nfunction isRowsHandle(v: unknown): boolean {\n return typeof v === \"object\" && v !== null && (v as Record<symbol, unknown>)[ROWS] !== undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — value encoding\n// ---------------------------------------------------------------------------\n\n/**\n * Encode one value of a `values`/`set`/`where` map.\n *\n * The nesting check is not defensive tidiness. The server treats `$ref` as a\n * tagged value only at the TOP of a column's value; a ref buried inside a jsonb\n * payload is just data, and would be stored as the literal object\n * `{\"$ref\":{...}}` — a write that succeeds, commits, and is wrong. So a nested\n * handle is a hard error here, where the line that wrote it is still on the\n * stack.\n */\nfunction encodeValue(value: unknown, column: string, allowColumnExpr: boolean): TxWireValue {\n const ref = refDescriptor(value);\n if (ref) return { $ref: { op: ref.op, field: ref.field } } satisfies TxWireRef;\n\n const expr = exprOf(value);\n if (expr) {\n if (expr.fn !== \"now\" && !allowColumnExpr) {\n throw new TxPlanError(\n `\\`${column}\\`: ${expr.fn}() reads the column's current value, so it is ` +\n `only valid in updateWhere(where, set).`,\n );\n }\n return { $expr: expr } satisfies TxWireExpr;\n }\n\n if (rowOpIndex(value) !== null) {\n throw new TxPlanError(\n `\\`${column}\\`: a row handle is not a value. Read the column you meant ` +\n `(e.g. \\`row.id\\`).`,\n );\n }\n if (isRowsHandle(value)) {\n throw new TxPlanError(\n `\\`${column}\\`: an operation result is not a value. Declare an expectation ` +\n `first (\\`.expectOne(err)\\`) and read a column from the row.`,\n );\n }\n\n assertNoNestedHandles(value, column);\n return value;\n}\n\nfunction assertNoNestedHandles(value: unknown, column: string): void {\n if (typeof value !== \"object\" || value === null) return;\n if (value instanceof Date) return;\n if (refDescriptor(value) || exprOf(value) || rowOpIndex(value) !== null || isRowsHandle(value)) {\n throw new TxPlanError(\n `\\`${column}\\`: a plan handle is nested inside a value. The server would ` +\n `store it as literal JSON, not resolve it. Put the reference directly in ` +\n `the column.`,\n );\n }\n if (Array.isArray(value)) {\n for (const item of value) assertNoNestedHandles(item, column);\n return;\n }\n for (const item of Object.values(value as Record<string, unknown>)) {\n assertNoNestedHandles(item, column);\n }\n}\n\n/**\n * Encode a column map, dropping `undefined` and emitting keys SORTED.\n *\n * Sorting is what makes the same callback produce byte-identical JSON every\n * time, which is what lets the Go decoder be locked to goldens this SDK emits.\n * Dropping `undefined` mirrors what `JSON.stringify` would do anyway, but does\n * it where the resulting column list is still checkable.\n */\nfunction encodeMap(\n map: Record<string, unknown>,\n allowColumnExpr: boolean,\n): Record<string, TxWireValue> {\n const out: Record<string, TxWireValue> = {};\n for (const key of Object.keys(map).sort()) {\n const value = map[key];\n if (value === undefined) continue;\n out[key] = encodeValue(value, key, allowColumnExpr);\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — the builder\n// ---------------------------------------------------------------------------\n\n/** How many rows an op can produce, as far as the CLIENT can tell before it\n * runs. Only the empty `insertMany` is knowable, and knowing it is what lets a\n * doomed expectation fail on the line that declared it. */\nconst SKIPPED_OP = -1;\n\nclass TxRowsImpl<Row> implements TxRows<Row> {\n // Present so `isRowsHandle` recognises the object; never read for its value.\n readonly [ROWS] = true;\n // Phantom: the type brand that stops a bare object passing as a TxRows. Never\n // present at run time, which is what `declare` says.\n declare readonly [rowsBrand]: Row;\n private guarded = false;\n\n constructor(\n private readonly builder: TxPlanBuilder,\n private readonly opIndex: number,\n private readonly what: string,\n ) {}\n\n // The type-level `await` guard made real: TS rejects `await rows` at compile\n // time, and reaching this means someone called `.then(...)` by hand.\n then(): never {\n throw new TxRefError(\n `${this.what} cannot be awaited: a transaction callback builds a plan, it ` +\n `does not run statements. Remove the \\`await\\`.`,\n );\n }\n\n expectOne(error: Error): TxRow<Row> {\n this.declareGuard(\"one\", 1, error);\n if (this.opIndex === SKIPPED_OP) throw error;\n return makeRowHandle(this.opIndex) as TxRow<Row>;\n }\n\n expectNone(error: Error): void {\n this.declareGuard(\"none\", 0, error);\n }\n\n expectAtLeast(n: number, error: Error): void {\n assertGuardCount(n, \"expectAtLeast\");\n this.declareGuard(\"atLeast\", n, error);\n if (this.opIndex === SKIPPED_OP && n > 0) throw error;\n }\n\n expectAtMost(n: number, error: Error): void {\n assertGuardCount(n, \"expectAtMost\");\n this.declareGuard(\"atMost\", n, error);\n }\n\n private declareGuard(kind: TxWireGuard[\"kind\"], n: number, error: Error): void {\n if (!(error instanceof Error)) {\n // The error object is the ONLY thing that describes this failure to the\n // caller — the server sends back an index, never a message.\n throw new TxPlanError(\n `${this.what}: an expectation needs the Error to throw when it does not ` +\n `hold (e.g. \\`.expect…(new Conflict(\"already accepted\"))\\`).`,\n );\n }\n if (this.guarded) {\n throw new TxPlanError(\n `${this.what} already has an expectation. One operation carries one ` +\n `expectation; declare the second one on its own operation.`,\n );\n }\n this.guarded = true;\n if (this.opIndex === SKIPPED_OP) return;\n this.builder.attachGuard(this.opIndex, kind, n, error);\n }\n}\n\nfunction assertGuardCount(n: number, fn: string): void {\n if (!Number.isInteger(n) || n < 0) {\n throw new TxPlanError(`${fn}(n) needs a non-negative integer, got ${String(n)}`);\n }\n}\n\n/** Bounds mirrored from tx_program.go so an over-sized plan is named here rather\n * than rejected as an opaque 400 after it has crossed the network. */\nconst MAX_OPS = 1000;\nconst MAX_ROWS = 5000;\n\n/**\n * Accumulates ops and the client-side error table while the callback runs.\n *\n * Exported for the runtime and for tests that need the serialised plan without\n * a server; author code never sees it.\n */\nexport class TxPlanBuilder {\n private readonly ops: TxWireOp[] = [];\n /** Errors handed to expectations, indexed by the `slot` the server echoes. */\n private readonly slots: Error[] = [];\n\n /** The table surface handed to the callback. Untyped here; the public\n * `transaction()` signatures put the schema types on top. */\n table(name: string): TxTable<Record<string, unknown>, Record<string, unknown>> {\n return {\n insert: (values) => {\n const encoded = encodeMap(values as Record<string, unknown>, false);\n if (Object.keys(encoded).length === 0) {\n throw new TxPlanError(`${name}.insert() needs at least one column`);\n }\n return this.push({ op: \"insert\", table: name, values: encoded }, `${name}.insert()`);\n },\n\n insertMany: (rows) => {\n if (rows.length === 0) {\n // Nothing to write. Emitting an op would be a guaranteed 400 (the\n // server requires rows), and refusing outright would punish the\n // ordinary \"filtered every candidate out\" case.\n return new TxRowsImpl(this, SKIPPED_OP, `${name}.insertMany()`);\n }\n if (rows.length > MAX_ROWS) {\n throw new TxPlanError(\n `${name}.insertMany() has ${rows.length} rows; the limit is ${MAX_ROWS}. ` +\n `Split the write across requests.`,\n );\n }\n const encoded = rows.map((row) => encodeMap(row as Record<string, unknown>, false));\n assertUniformRows(encoded, name);\n return this.push({ op: \"insertMany\", table: name, rows: encoded }, `${name}.insertMany()`);\n },\n\n updateWhere: (where, set) => {\n const encodedWhere = encodeMap(where as Record<string, unknown>, false);\n const encodedSet = encodeMap(set as Record<string, unknown>, true);\n if (Object.keys(encodedWhere).length === 0) {\n throw new TxPlanError(\n `${name}.updateWhere() needs a filter. An update with no filter ` +\n `rewrites the whole table.`,\n );\n }\n if (Object.keys(encodedSet).length === 0) {\n throw new TxPlanError(`${name}.updateWhere() needs at least one column to set`);\n }\n return this.push(\n { op: \"update\", table: name, set: encodedSet, where: encodedWhere },\n `${name}.updateWhere()`,\n );\n },\n\n deleteWhere: (where) => {\n const encodedWhere = encodeMap(where as Record<string, unknown>, false);\n if (Object.keys(encodedWhere).length === 0) {\n throw new TxPlanError(\n `${name}.deleteWhere() needs a filter. A delete with no filter empties ` +\n `the table.`,\n );\n }\n return this.push(\n { op: \"delete\", table: name, where: encodedWhere },\n `${name}.deleteWhere()`,\n );\n },\n\n select: (where, options) => {\n const op: TxWireOp = { op: \"select\", table: name };\n const encodedWhere = encodeMap((where ?? {}) as Record<string, unknown>, false);\n if (Object.keys(encodedWhere).length > 0) op.where = encodedWhere;\n if (options?.limit !== undefined) {\n if (!Number.isInteger(options.limit) || options.limit < 0) {\n throw new TxPlanError(\n `${name}.select(): limit needs a non-negative integer, got ${String(options.limit)}`,\n );\n }\n op.limit = options.limit;\n }\n if (options?.lock !== undefined) op.lock = options.lock;\n return this.push(op, `${name}.select()`);\n },\n };\n }\n\n private push(op: TxWireOp, what: string): TxRows<Record<string, unknown>> {\n if (this.ops.length >= MAX_OPS) {\n throw new TxPlanError(\n `this transaction has ${MAX_OPS} operations, which is the limit. Use ` +\n `insertMany() for bulk writes, or split the work across requests.`,\n );\n }\n const index = this.ops.length;\n this.ops.push(op);\n return new TxRowsImpl(this, index, what);\n }\n\n /** Attach an expectation to an op and record its error in the slot table. */\n attachGuard(opIndex: number, kind: TxWireGuard[\"kind\"], n: number, error: Error): void {\n const op = this.ops[opIndex];\n // Unreachable: the index came from `push`. A loud failure beats a silently\n // unguarded write if that ever stops being true.\n if (!op) throw new TxPlanError(`internal: expectation on unknown operation ${opIndex}`);\n const slot = this.slots.length;\n this.slots.push(error);\n op.guard = { kind, n, slot };\n }\n\n /** The serialisable plan. Empty when the callback described no writes. */\n body(): TxPlanBody {\n return { ops: this.ops };\n }\n\n /** The error the server's `slot` selects, or `null` when it names one this\n * plan never declared (a server/client disagreement, not a tenant error). */\n errorForSlot(slot: number): Error | null {\n return this.slots[slot] ?? null;\n }\n}\n\nfunction assertUniformRows(rows: Record<string, TxWireValue>[], table: string): void {\n const first = rows[0];\n if (!first) return;\n const want = Object.keys(first);\n const wantKey = want.join(\",\");\n for (let i = 1; i < rows.length; i++) {\n const got = Object.keys(rows[i] as Record<string, TxWireValue>);\n if (got.join(\",\") !== wantKey) {\n // One statement, one column list. A ragged row would take the DB default\n // for the column it omitted — a write that succeeds and is wrong.\n throw new TxPlanError(\n `${table}.insertMany(): every row must set the same columns. Row 0 sets ` +\n `[${want.join(\", \")}] but row ${i} sets [${got.join(\", \")}]. ` +\n `(A property set to \\`undefined\\` counts as absent — use \\`null\\`.)`,\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — materialisation\n// ---------------------------------------------------------------------------\n\n/**\n * Replace every handle in the callback's return value with what the server\n * actually produced.\n *\n * Walks arrays and PLAIN objects only. Class instances (a Date, a Zod schema, a\n * domain object) are returned untouched — recursing into them would rebuild them\n * as bare objects, and nothing inside one can be a handle that this SDK created.\n */\nexport function materializeResult(value: unknown, results: TxPlanOpResult[]): unknown {\n const ref = refDescriptor(value);\n if (ref) {\n const row = rowOf(results, ref.op, `\\`${ref.field}\\``);\n if (!(ref.field in row)) {\n throw new TxPlanError(\n `the transaction's operation ${ref.op} returned no column \\`${ref.field}\\`.`,\n );\n }\n return row[ref.field];\n }\n\n const rowOp = rowOpIndex(value);\n if (rowOp !== null) return rowOf(results, rowOp, \"a row\");\n\n if (isRowsHandle(value)) {\n throw new TxPlanError(\n \"an operation result cannot be returned from a transaction callback: its \" +\n \"row count is not known until the plan runs. Declare an expectation \" +\n \"(`.expectOne(err)`) and return the row, or a column of it.\",\n );\n }\n\n if (Array.isArray(value)) return value.map((item) => materializeResult(item, results));\n\n if (isPlainObject(value)) {\n const out: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) out[key] = materializeResult(item, results);\n return out;\n }\n\n return value;\n}\n\nfunction rowOf(results: TxPlanOpResult[], opIndex: number, what: string): Record<string, unknown> {\n const result = results[opIndex];\n if (!result) {\n throw new TxPlanError(\n `the transaction returned no result for operation ${opIndex}, so ${what} ` +\n `cannot be read.`,\n );\n }\n const row = result.rows[0];\n if (!row) {\n // Unreachable through the public API: a handle only exists behind an\n // `expectOne`, and the server rolls back rather than answering 200 with a\n // guard unmet. Loud, because the alternative is `undefined` in tenant data.\n throw new TxPlanError(\n `the transaction's operation ${opIndex} returned no row, so ${what} cannot ` +\n `be read.`,\n );\n }\n return row;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — the driver\n// ---------------------------------------------------------------------------\n\n/** What {@link runTxPlan} needs from the runtime: one call, one transaction. */\nexport interface TxPlanTransport {\n txPlan(plan: TxPlanBody): Promise<TxPlanResponse>;\n}\n\n/**\n * Build the plan, send it, and resolve the callback's return value.\n *\n * A callback that throws never reaches the network: there is nothing to roll\n * back because nothing was sent. A callback that describes no writes also skips\n * the round trip entirely.\n *\n * The RETURN type is `unknown` here on purpose. `Materialized<T>` is a compile-\n * time rewrite of the callback's return type, and it belongs on the public\n * `transaction()` signatures where `T` is inferred from the author's callback;\n * threading it through this driver as well would mean inferring `T` twice, from\n * two different positions, and reconciling them. The public wrappers narrow\n * once, at the seam where the value types were erased anyway.\n */\nexport async function runTxPlan<TTables>(\n transport: TxPlanTransport,\n tables: TTables,\n builder: TxPlanBuilder,\n fn: (tx: TxPlanHandle<TTables>) => unknown,\n): Promise<unknown> {\n const returned = fn({ tables });\n const body = builder.body();\n if (body.ops.length === 0) {\n return materializeResult(returned, []);\n }\n\n let response: TxPlanResponse;\n try {\n response = await transport.txPlan(body);\n } catch (err) {\n throw translateRejection(err, builder);\n }\n return materializeResult(returned, response.results);\n}\n\n/**\n * Turn the broker's rejection back into the tenant's own error.\n *\n * The server never sees the `Error` an expectation was given — only its slot\n * index — so this is the only place the intended error can be produced. A\n * rejection this SDK does not recognise passes through untouched: inventing an\n * error for it would hide the real failure.\n */\nfunction translateRejection(err: unknown, builder: TxPlanBuilder): unknown {\n if (typeof err !== \"object\" || err === null) return err;\n const rejection = err as TxPlanRejection;\n if (rejection.error_code !== \"tx_guard_failed\" || typeof rejection.slot !== \"number\") {\n return err;\n }\n return builder.errorForSlot(rejection.slot) ?? err;\n}\n","/** HTTP error with structured error response format.\n *\n * The base class for the throwable error classes (`PalError`, `Conflict`,\n * `NotFound`, …). Construct one directly with `throw new HttpError(404,\n * \"todo_not_found\", \"No such todo\")`, or throw a named subclass\n * (`throw new NotFound(\"todo not found\")`). The runtime catches any `HttpError`\n * and emits the standard envelope; on the wire (and to iOS) it surfaces as\n * `BackendError.server(code, status, message, requestId)`.\n *\n * The optional `data` field carries a structured payload alongside the\n * standard envelope — for errors that need to ship extra context\n * (e.g. `new Conflict(\"locked\", \"title_locked\", { retryAfter: 30 })`). It rides\n * through to the iOS typed enum's associated value.\n */\n/**\n * The brand that identifies an HttpError ACROSS SDK instances.\n *\n * A process legitimately holds more than one copy of this SDK — the runtime\n * loads the engine from its own node_modules while the tenant's bundle carries\n * an inlined copy, which is why the controller registry and the error registry\n * are both anchored on `Symbol.for`. The one place that did not follow the\n * pattern was the engine's catch: `err instanceof HttpError` compares CLASS\n * IDENTITY, so a `throw new NotFound()` from the bundle's copy did not match\n * the engine's copy and every typed error in every deployed backend degraded to\n * `500 internal_error`. Measured through the edge on a real deploy: a route\n * throwing `NotFound` answered 500 while the runtime's own log printed the\n * error object with `status: 404` right beside it.\n *\n * `Symbol.for` puts this in the cross-realm registry, so every copy of the SDK\n * agrees on it by VALUE rather than by identity.\n */\nexport const HTTP_ERROR_BRAND: unique symbol = Symbol.for(\"palbase.backend.httpError\");\n\n/**\n * Whether a thrown value is an HttpError from ANY copy of this SDK.\n *\n * The shape is checked as well as the brand: the brand says \"this claims to be\n * one of ours\", the fields say the envelope can actually be built from it, and\n * a half-formed object must fall through to the 500 path rather than produce a\n * malformed response.\n */\nexport function isHttpError(err: unknown): err is HttpError {\n if (typeof err !== \"object\" || err === null) return false;\n const e = err as Record<PropertyKey, unknown>;\n return (\n e[HTTP_ERROR_BRAND] === true &&\n typeof e.status === \"number\" &&\n typeof e.error === \"string\" &&\n typeof e.errorDescription === \"string\"\n );\n}\n\nexport class HttpError extends Error {\n public readonly status: number;\n public readonly error: string;\n public readonly errorDescription: string;\n public readonly data?: unknown;\n /** See {@link HTTP_ERROR_BRAND} — how the engine recognises this across SDK copies. */\n public readonly [HTTP_ERROR_BRAND] = true;\n\n constructor(status: number, error: string, errorDescription: string, data?: unknown) {\n super(errorDescription);\n this.name = \"HttpError\";\n this.status = status;\n this.error = error;\n this.errorDescription = errorDescription;\n if (data !== undefined) {\n this.data = data;\n }\n }\n\n /**\n * Serialize to the standard Palbase error response format.\n * The `requestId` is injected by the runtime layer from the request context.\n * When called without arguments (e.g. JSON.stringify), request_id is omitted.\n * When `data` is set, it is appended as a strict-superset field.\n */\n toJSON(requestId?: string): {\n error: string;\n error_description: string;\n status: number;\n request_id?: string;\n data?: unknown;\n } {\n const result: {\n error: string;\n error_description: string;\n status: number;\n request_id?: string;\n data?: unknown;\n } = {\n error: this.error,\n error_description: this.errorDescription,\n status: this.status,\n };\n if (requestId) {\n result.request_id = requestId;\n }\n if (this.data !== undefined) {\n result.data = this.data;\n }\n return result;\n }\n}\n\n/**\n * Throw with a custom HTTP status + wire code. The general-purpose escape hatch\n * when none of the named classes (`Conflict`/`NotFound`/…) fits.\n *\n * @example\n * throw new PalError(418, \"teapot\", \"I'm a teapot\");\n */\nexport class PalError extends HttpError {\n constructor(status: number, code: string, description: string, data?: unknown) {\n super(status, code, description, data);\n this.name = \"PalError\";\n }\n}\n\n/** Base for the named status classes. Each subclass fixes its HTTP status; the\n * `code` defaults to the class's canonical wire code (overridable), and the\n * `message` defaults to a human-readable label (overridable). */\nabstract class NamedHttpError extends HttpError {\n protected constructor(\n status: number,\n defaultCode: string,\n name: string,\n message?: string,\n code?: string,\n data?: unknown,\n ) {\n super(status, code ?? defaultCode, message ?? defaultMessage(name), data);\n this.name = name;\n }\n}\n\n/** Derive a default human-readable message from a class name\n * (\"NotFound\" → \"Not found\", \"TooManyRequests\" → \"Too many requests\"). */\nfunction defaultMessage(name: string): string {\n const spaced = name.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\");\n return spaced.charAt(0).toUpperCase() + spaced.slice(1).toLowerCase();\n}\n\n/**\n * 400 — the request was malformed or failed validation. Carries a fixed typed\n * payload: `new BadRequest({ fields: [{ field: \"email\", message: \"invalid\" }] })`.\n * The shape is declared once in the SDK so codegen surfaces `error.data.fields`\n * typed on the client.\n */\nexport class BadRequest extends NamedHttpError {\n public declare readonly data: BadRequestData;\n constructor(data: BadRequestData, message?: string) {\n super(400, \"bad_request\", \"BadRequest\", message, undefined, data);\n }\n}\n\n/** 401 — the caller is not authenticated. */\nexport class Unauthorized extends NamedHttpError {\n constructor(message?: string, code?: string, data?: unknown) {\n super(401, \"unauthorized\", \"Unauthorized\", message, code, data);\n }\n}\n\n/** 403 — the caller is authenticated but not allowed. */\nexport class Forbidden extends NamedHttpError {\n constructor(message?: string, code?: string, data?: unknown) {\n super(403, \"forbidden\", \"Forbidden\", message, code, data);\n }\n}\n\n/** 404 — the requested resource does not exist. */\nexport class NotFound extends NamedHttpError {\n constructor(message?: string, code?: string, data?: unknown) {\n super(404, \"not_found\", \"NotFound\", message, code, data);\n }\n}\n\n/** 409 — the request conflicts with the current state. */\nexport class Conflict extends NamedHttpError {\n constructor(message?: string, code?: string, data?: unknown) {\n super(409, \"conflict\", \"Conflict\", message, code, data);\n }\n}\n\n/** A single field-level validation failure carried by {@link BadRequest}. */\nexport interface FieldError {\n /** The offending field's name (dotted path for nested fields). */\n field: string;\n /** Human-readable reason the field failed. */\n message: string;\n}\n\n/** The fixed, typed payload {@link BadRequest} ships. */\nexport interface BadRequestData {\n /** The fields that failed validation. */\n fields: FieldError[];\n}\n\n/** The fixed, typed payload {@link TooManyRequests} ships. */\nexport interface TooManyRequestsData {\n /** Seconds the caller should wait before retrying. */\n retryAfter: number;\n}\n\n/**\n * 429 — the caller has exceeded the rate limit. Carries a fixed typed payload:\n * `new TooManyRequests({ retryAfter: 30 })`. The shape is declared once in the\n * SDK (error-registry pre-seed) so codegen surfaces `error.data.retryAfter`\n * typed on the client — no per-project definition needed.\n */\nexport class TooManyRequests extends NamedHttpError {\n public declare readonly data: TooManyRequestsData;\n constructor(data: TooManyRequestsData, message?: string) {\n super(429, \"too_many_requests\", \"TooManyRequests\", message, undefined, data);\n }\n}\n","/**\n * engine/config.ts — settings from the environment, and the gate that refuses\n * to boot without them.\n *\n * A mandatory module that is not configured must stop the process, by name.\n * The failure this prevents is the expensive one: a stack that boots, passes\n * its probes, and answers 500 on first contact — where the missing value is\n * discovered by a customer rather than by the operator who could fix it.\n *\n * Database and Auth are mandatory. That is a product decision (2026-08-14), not\n * a technical necessity: a backend whose data layer or whose notion of \"who is\n * calling\" is undefined has nothing safe to do with a request.\n */\n\n/** Everything the engine needs to serve. Built once, at boot, never re-read. */\nexport interface EngineConfig {\n /** Postgres connection string. MANDATORY. */\n databaseUrl: string;\n /** Where this stack publishes its token signing keys. MANDATORY. */\n authJwksUrl: string;\n /** When set, a token whose `iss` differs is rejected. */\n authIssuer?: string;\n /** Base URL of the module surface (`/v1/*`, `/auth/*`). Empty ⇒ module\n * singletons throw a named error on first use rather than silently no-op. */\n moduleBaseUrl: string;\n /**\n * The address CLIENTS reach this stack at — `https://<ref>.palbase.studio` in\n * the cloud, whatever domain the certificate is for when self-hosted.\n *\n * NOT `moduleBaseUrl`, and the distinction is the whole point: that one is\n * this process's internal route to palsvc (`http://127.0.0.1:8080`), which\n * resolves nowhere outside the pod. A public object URL has to survive\n * leaving the response body, so it cannot be built from the internal one.\n *\n * Only the operator knows this value, so only the operator sets it\n * (`PALBASE_PUBLIC_ORIGIN`). Empty ⇒ `Storage…getPublicUrl()` throws a named\n * error, the same way an unconfigured module does.\n */\n publicOrigin: string;\n /** Shared secret storage signs its internal upload calls with. Empty means\n * uploads are not wired, and those calls are refused. */\n uploadSecret: string;\n /** Publishable key, sent as `apikey` on module calls. */\n anonKey: string;\n /** Secret key. Used for privileged module calls. */\n serviceRoleKey: string;\n /** HMAC the realtime broadcast token is signed with. Empty ⇒ broadcast\n * returns a clear `realtime_unconfigured` error instead of failing silently. */\n realtimeSecret: string;\n port: number;\n /** The Postgres role each request is bound to. RLS policies are written\n * against it, so changing it changes who the database thinks is asking. */\n dbRole: string;\n /**\n * The Postgres role `Database.asService()` is bound to. It is the one that\n * carries BYPASSRLS, which is the whole of what \"as service\" means — a name\n * pointing at a role without it does not fail, it returns fewer rows.\n *\n * Configurable for the same reason `dbRole` is, and beside it on purpose: a\n * stack that renames one of the pair must rename both, or the request and its\n * service sibling stop being two identities of the same installation.\n */\n dbServiceRole: string;\n poolMax: number;\n}\n\n/** Thrown when a mandatory module is unconfigured. Carries the missing names. */\nexport class BootRefused extends Error {\n readonly missing: readonly string[];\n constructor(missing: readonly string[], message: string) {\n super(message);\n this.name = \"BootRefused\";\n this.missing = missing;\n }\n}\n\nconst MANDATORY: ReadonlyArray<{ key: string; what: string }> = [\n { key: \"DATABASE_URL\", what: \"the stack's Postgres (Database module)\" },\n { key: \"AUTH_JWKS_URL\", what: \"where this stack publishes its token signing keys (Auth module)\" },\n];\n\n/**\n * Read the engine's settings, or refuse.\n *\n * @throws {BootRefused} naming every missing mandatory value at once — one\n * restart per missing variable is a bad way to learn what a stack needs.\n */\nexport function loadConfig(env: Record<string, string | undefined>): EngineConfig {\n const missing = MANDATORY.filter((m) => !env[m.key]?.trim()).map((m) => m.key);\n if (missing.length > 0) {\n const detail = MANDATORY.filter((m) => missing.includes(m.key))\n .map((m) => ` ${m.key.padEnd(16)}${m.what}`)\n .join(\"\\n\");\n throw new BootRefused(\n missing,\n `boot refused: mandatory module not configured — missing ${missing.join(\", \")}.\\n${detail}`,\n );\n }\n\n const port = Number(env.PORT ?? 3000);\n if (!Number.isInteger(port) || port < 0 || port > 65535) {\n throw new BootRefused([], `boot refused: PORT is not a valid port number (got ${env.PORT}).`);\n }\n const poolMax = Number(env.DB_POOL_MAX ?? 10);\n if (!Number.isInteger(poolMax) || poolMax < 1) {\n throw new BootRefused([], `boot refused: DB_POOL_MAX must be a positive integer (got ${env.DB_POOL_MAX}).`);\n }\n\n return {\n databaseUrl: env.DATABASE_URL!.trim(),\n authJwksUrl: env.AUTH_JWKS_URL!.trim(),\n authIssuer: env.AUTH_ISSUER?.trim() || undefined,\n moduleBaseUrl: (env.MODULE_BASE_URL ?? \"\").replace(/\\/+$/, \"\"),\n publicOrigin: (env.PALBASE_PUBLIC_ORIGIN ?? \"\").trim().replace(/\\/+$/, \"\"),\n // The secret storage signs its two internal calls with (authorize, and the\n // completion that runs an @Upload handler). Empty means uploads are not\n // wired, and both calls REFUSE — an unsigned completion would let anyone\n // who knows a route path invent an upload that never happened.\n uploadSecret: env.PALBASE_UPLOAD_SECRET ?? \"\",\n anonKey: env.PALBASE_ANON_KEY ?? \"\",\n serviceRoleKey: env.PALBASE_SERVICE_ROLE_KEY ?? \"\",\n realtimeSecret: env.REALTIME_INGESTION_SECRET ?? \"\",\n port,\n dbRole: env.DB_ROLE ?? \"backend_authenticated\",\n // Verified against the stack that provisions them, not from memory: the six\n // roles and their attributes are declared in v2/internal/migrate/provision.go\n // (`roleBackendServiceRole = \"backend_service_role\"`, NOLOGIN BYPASSRLS),\n // and the live database agrees (pg_roles.rolbypassrls = true).\n dbServiceRole: env.DB_SERVICE_ROLE ?? \"backend_service_role\",\n poolMax,\n };\n}\n","/**\n * engine/auth.ts — verifying the stack's own access tokens.\n *\n * The engine does this itself rather than trusting a header stamped upstream.\n * In the isolate architecture a gateway verified the token and the runtime read\n * the result; a backend that boots on its own has no such upstream, so the\n * verification lives here — against the keys the stack publishes.\n *\n * Deliberately narrow: ES256 over P-256, which is what palauth mints. An\n * unrecognised `alg` is refused rather than accommodated, because the classic\n * JWT break is a verifier that is helpful about algorithms.\n */\n\n/** A JSON Web Key, narrowed to the EC keys this verifier accepts. */\ninterface EcJwk {\n kid: string;\n kty: string;\n crv: string;\n x: string;\n y: string;\n}\n\n/** The claims the engine reads. Everything else rides along untyped. */\nexport interface VerifiedClaims extends Record<string, unknown> {\n sub?: string;\n role?: string;\n email?: string;\n email_verified?: boolean;\n exp?: number;\n iss?: string;\n}\n\nfunction b64urlToBytes(s: string): Uint8Array<ArrayBuffer> {\n const pad = s.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const full = pad.padEnd(Math.ceil(pad.length / 4) * 4, \"=\");\n const bin = atob(full);\n // Backed by a plain ArrayBuffer so the result satisfies BufferSource — a\n // Uint8Array over ArrayBufferLike could be shared memory, which the WebCrypto\n // signatures reject.\n const out = new Uint8Array(new ArrayBuffer(bin.length));\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nexport interface AuthVerifierOptions {\n jwksUrl: string;\n issuer?: string;\n /** Injectable for tests; defaults to global fetch. */\n fetchImpl?: typeof fetch;\n /** How long a fetched keyset is trusted before it is fetched again. A key\n * rotation must become visible without a restart, and an unknown `kid` must\n * not be able to force a fetch per request (that is a free DoS lever). */\n keysetTtlMs?: number;\n}\n\nexport class AuthVerifier {\n private keys = new Map<string, CryptoKey>();\n private fetchedAt = 0;\n private inflight: Promise<void> | null = null;\n private readonly jwksUrl: string;\n private readonly issuer?: string;\n private readonly fetchImpl: typeof fetch;\n private readonly ttl: number;\n\n constructor(opts: AuthVerifierOptions) {\n this.jwksUrl = opts.jwksUrl;\n this.issuer = opts.issuer;\n this.fetchImpl = opts.fetchImpl ?? ((...a: Parameters<typeof fetch>) => fetch(...a));\n this.ttl = opts.keysetTtlMs ?? 5 * 60_000;\n }\n\n /** Fetch the keyset at most once per TTL, and at most once concurrently. */\n private async refresh(): Promise<void> {\n if (this.inflight) return this.inflight;\n this.inflight = (async () => {\n try {\n const res = await this.fetchImpl(this.jwksUrl);\n if (!res.ok) return;\n const body = (await res.json()) as { keys?: EcJwk[] };\n const next = new Map<string, CryptoKey>();\n for (const jwk of body.keys ?? []) {\n if (jwk.kty !== \"EC\" || jwk.crv !== \"P-256\") continue;\n try {\n next.set(\n jwk.kid,\n await crypto.subtle.importKey(\n \"jwk\",\n { kty: \"EC\", crv: jwk.crv, x: jwk.x, y: jwk.y, ext: true },\n { name: \"ECDSA\", namedCurve: \"P-256\" },\n true,\n [\"verify\"],\n ),\n );\n } catch {\n // A single malformed key must not blind the verifier to the rest.\n }\n }\n if (next.size > 0) {\n this.keys = next;\n this.fetchedAt = Date.now();\n }\n } finally {\n this.inflight = null;\n }\n })();\n return this.inflight;\n }\n\n private async key(kid: string): Promise<CryptoKey | null> {\n const stale = Date.now() - this.fetchedAt > this.ttl;\n if (!this.keys.has(kid) || stale) await this.refresh();\n return this.keys.get(kid) ?? null;\n }\n\n /**\n * Verify an `Authorization` header value.\n *\n * @returns the verified claims, or `null` for absent / malformed / expired /\n * wrong-issuer / bad-signature. One `null` for every failure on purpose:\n * the caller answers 401 either way, and a detailed reason is an oracle.\n */\n async verify(authorization: string | null | undefined): Promise<VerifiedClaims | null> {\n if (!authorization || !authorization.startsWith(\"Bearer \")) return null;\n const parts = authorization.slice(7).trim().split(\".\");\n if (parts.length !== 3) return null;\n const h = parts[0];\n const p = parts[1];\n const sig = parts[2];\n if (h === undefined || p === undefined || sig === undefined) return null;\n\n let header: { alg?: string; kid?: string };\n let claims: VerifiedClaims;\n try {\n header = JSON.parse(new TextDecoder().decode(b64urlToBytes(h)));\n claims = JSON.parse(new TextDecoder().decode(b64urlToBytes(p)));\n } catch {\n return null;\n }\n // `none`, `HS256`-with-the-public-key, and friends all die here.\n if (header.alg !== \"ES256\" || !header.kid) return null;\n\n const key = await this.key(header.kid);\n if (!key) return null;\n\n let ok = false;\n try {\n ok = await crypto.subtle.verify(\n { name: \"ECDSA\", hash: \"SHA-256\" },\n key,\n b64urlToBytes(sig),\n new TextEncoder().encode(`${h}.${p}`),\n );\n } catch {\n return null;\n }\n if (!ok) return null;\n if (typeof claims.exp === \"number\" && claims.exp * 1000 <= Date.now()) return null;\n if (this.issuer && claims.iss !== this.issuer) return null;\n return claims;\n }\n}\n\n/** What a route demands, after the route's own spec and the controller's\n * default have been reconciled. */\nexport interface EffectiveAuth {\n required: boolean;\n role?: string;\n verifiedEmail: boolean;\n}\n\n/**\n * Reconcile route-level and controller-level auth.\n *\n * The route's own spec wins when it says anything at all; otherwise the\n * controller's default applies; when NEITHER speaks, the answer is `required`.\n * That last clause is the whole point — a route that forgot to declare must be\n * closed, not open. (Measured: an engine that only read the route level served\n * a controller marked `auth: false` as 401, and would have served the reverse\n * mistake as an open endpoint.)\n */\nexport function effectiveAuth(routeAuth: unknown, controllerAuth: unknown): EffectiveAuth {\n const spec = routeAuth !== undefined ? routeAuth : controllerAuth;\n if (spec === false) return { required: false, verifiedEmail: false };\n if (spec === true || spec === undefined || spec === null) return { required: true, verifiedEmail: false };\n if (typeof spec !== \"object\") return { required: true, verifiedEmail: false };\n\n const o = spec as { required?: unknown; role?: unknown; verifiedEmail?: unknown };\n const role = typeof o.role === \"string\" && o.role.trim() !== \"\" ? o.role.trim() : undefined;\n return {\n required: o.required !== false,\n role,\n verifiedEmail: o.verifiedEmail === true,\n };\n}\n","/**\n * engine/ratelimit.ts — the customer's own per-route limit, enforced here.\n *\n * This is the PRODUCT feature (`@Get(\"/x\", { rateLimit: { max, window } })`),\n * not a quota the platform imposes. It runs in this process, on this pod,\n * because the route table lives here: the edge proxies by path and has never\n * seen a route's options, so teaching it would mean shipping the table twice\n * and keeping the copies in step.\n *\n * Fixed window, in memory. A single-tenant backend is the whole stack rather\n * than a shard of it, so \"in process\" is not an approximation. A restart\n * forgets the window, which for an endpoint guard fails in the right\n * direction: it forgives, it never invents a refusal.\n */\n\nexport interface RateLimitRule {\n max: number;\n /** Seconds. */\n window: number;\n}\n\ninterface Bucket {\n count: number;\n resetAt: number;\n}\n\nexport class RateLimiter {\n private buckets = new Map<string, Bucket>();\n /** Bound on distinct keys held, so an attacker cycling identities cannot\n * grow this map without limit. On overflow the oldest windows are dropped —\n * forgiving, consistent with the restart behaviour above. */\n constructor(private readonly maxKeys = 100_000) {}\n\n /**\n * Identify the caller: the signed-in user when the route resolved one,\n * otherwise the address the edge forwarded. Callers the edge did not\n * identify share one bucket — deliberately conservative, since the\n * alternative is a limit anyone resets by omitting a header.\n */\n static key(routeId: string, userId: string | undefined, headers: Headers): string {\n if (userId) return `${routeId}\\x00u:${userId}`;\n const fwd = headers.get(\"x-forwarded-for\");\n const addr = (fwd ? (fwd.split(\",\")[0] ?? \"\") : (headers.get(\"x-real-ip\") ?? \"\")).trim();\n return `${routeId}\\x00a:${addr || \"anonymous\"}`;\n }\n\n /**\n * @returns `null` when the request may proceed, or the number of seconds to\n * wait (never 0 — a caller told to wait 0 comes straight back to the same\n * refusal).\n */\n check(rule: RateLimitRule | undefined, key: string, now: number): number | null {\n if (!rule || !(rule.max > 0) || !(rule.window > 0)) return null;\n\n const bucket = this.buckets.get(key);\n if (!bucket || now >= bucket.resetAt) {\n if (this.buckets.size >= this.maxKeys) this.evict(now);\n this.buckets.set(key, { count: 1, resetAt: now + rule.window * 1000 });\n return null;\n }\n if (bucket.count < rule.max) {\n bucket.count++;\n return null;\n }\n return Math.max(1, Math.ceil((bucket.resetAt - now) / 1000));\n }\n\n /** Drop expired windows; if none are expired, drop the earliest-resetting\n * quarter so the map cannot wedge at the ceiling. */\n private evict(now: number): void {\n let dropped = 0;\n for (const [k, b] of this.buckets) {\n if (now >= b.resetAt) {\n this.buckets.delete(k);\n dropped++;\n }\n }\n if (dropped > 0) return;\n const byReset = [...this.buckets.entries()].sort((a, b) => a[1].resetAt - b[1].resetAt);\n for (let i = 0; i < Math.ceil(byReset.length / 4); i++) {\n const victim = byReset[i];\n if (victim) this.buckets.delete(victim[0]);\n }\n }\n\n /** Test seam. */\n get size(): number {\n return this.buckets.size;\n }\n}\n","/**\n * engine/cache.ts — the cache, in this process's own memory.\n *\n * A stack that serves one tenant has nobody to share a cache with; palsvc drew\n * exactly this conclusion for itself when it dropped Redis, and a backend that\n * reaches over a network for a hash map is paying a round trip for nothing.\n *\n * JSON-typed, matching `CacheClient`: values round-trip as whatever was stored.\n */\nimport type { CacheClient } from \"../endpoint.js\";\n\ninterface Entry {\n value: unknown;\n /** Epoch ms, or 0 for \"no expiry\". */\n expiresAt: number;\n}\n\nexport interface MemoryCacheOptions {\n /** Bound on entries held. On overflow the soonest-to-expire are dropped. */\n maxEntries?: number;\n /** Injectable clock, for tests. */\n now?: () => number;\n}\n\n/**\n * Build an in-process cache.\n *\n * `getOrSet` is single-flight: concurrent misses on one key share one fill, so\n * a cold key under load does not become N identical expensive calls.\n */\nexport function makeMemoryCache(opts: MemoryCacheOptions = {}): CacheClient {\n const maxEntries = opts.maxEntries ?? 50_000;\n const now = opts.now ?? (() => Date.now());\n const store = new Map<string, Entry>();\n const inflight = new Map<string, Promise<unknown>>();\n\n const live = (key: string): Entry | undefined => {\n const e = store.get(key);\n if (!e) return undefined;\n if (e.expiresAt !== 0 && e.expiresAt <= now()) {\n store.delete(key);\n return undefined;\n }\n return e;\n };\n\n const evict = () => {\n const t = now();\n let dropped = 0;\n for (const [k, e] of store) {\n if (e.expiresAt !== 0 && e.expiresAt <= t) {\n store.delete(k);\n dropped++;\n }\n }\n if (dropped > 0) return;\n // Nothing expired: drop the soonest-to-expire quarter (entries with no\n // expiry sort last, so an unbounded writer sheds its own oldest first).\n const order = [...store.entries()].sort(\n (a, b) => (a[1].expiresAt || Infinity) - (b[1].expiresAt || Infinity),\n );\n for (let i = 0; i < Math.ceil(order.length / 4); i++) {\n const victim = order[i];\n if (victim) store.delete(victim[0]);\n }\n };\n\n const set = async (key: string, value: unknown, ttl?: number): Promise<void> => {\n if (store.size >= maxEntries && !store.has(key)) evict();\n store.set(key, { value, expiresAt: ttl && ttl > 0 ? now() + ttl * 1000 : 0 });\n };\n\n return {\n async get<T = unknown>(key: string): Promise<T | null> {\n const e = live(key);\n return e ? (e.value as T) : null;\n },\n set,\n async del(key: string): Promise<void> {\n store.delete(key);\n },\n async incr(key: string): Promise<number> {\n const e = live(key);\n const next = (typeof e?.value === \"number\" ? e.value : 0) + 1;\n store.set(key, { value: next, expiresAt: e?.expiresAt ?? 0 });\n return next;\n },\n async getOrSet<T>(key: string, ttl: number, fn: () => Promise<T> | T): Promise<T> {\n const hit = live(key);\n if (hit) return hit.value as T;\n\n const running = inflight.get(key);\n if (running) return running as Promise<T>;\n\n const fill = (async () => {\n try {\n const value = await fn();\n await set(key, value, ttl);\n return value;\n } finally {\n inflight.delete(key);\n }\n })();\n inflight.set(key, fill);\n return fill as Promise<T>;\n },\n };\n}\n","/**\n * engine/db.ts — a real pooled connection, and the identity every request is\n * bound to inside it.\n *\n * # Why one transaction per request\n *\n * In the isolate architecture every `Database.*` call was its own HTTP hop to a\n * capability surface, so two writes in one handler could not be atomic — a\n * handler that wrote and then threw left the first write behind. Here the whole\n * request runs inside one transaction: it commits when the handler returns and\n * rolls back when it throws. Atomicity stops being something the author has to\n * ask for.\n *\n * # Why it opens lazily\n *\n * A handler that touches no table must cost no round trip. Opening eagerly cost\n * four (BEGIN + bind + … + COMMIT) on endpoints that never query — measured at\n * 1,243 rps against 31,579 for the same endpoint once the open became lazy.\n *\n * # How the caller's identity reaches RLS\n *\n * One statement, not three:\n *\n * select set_config('role',$1,true),\n * set_config('search_path','public',true),\n * set_config('request.jwt.claims',$2,true)\n *\n * `set_config(..., is_local => true)` is transaction-scoped exactly like\n * `SET LOCAL`, but takes BOUND PARAMETERS, which `SET LOCAL` cannot. So the\n * role and the caller's claims travel as parameters — user identity is never\n * spliced into SQL text — and `auth.uid()` resolves inside RLS policies, which\n * means the row filter is enforced by Postgres rather than by our code.\n */\nimport type { DBClient, DBOps } from \"../endpoint.js\";\nimport type {\n TxPlanBody,\n TxPlanOpResult,\n TxPlanResponse,\n TxWireExpr,\n TxWireOp,\n TxWireRef,\n TxWireValue,\n} from \"../db/tx-plan.js\";\n\n/** The slice of a SQL driver the engine uses. `Bun.sql` satisfies it. */\nexport interface SqlDriver {\n /** Run a parameterised statement. */\n unsafe(sql: string, params?: unknown[]): Promise<unknown>;\n /** Open a transaction; the driver commits when `cb` resolves and rolls back\n * when it rejects. */\n begin<T>(cb: (tx: SqlTx) => Promise<T>): Promise<T>;\n}\n\nexport interface SqlTx {\n unsafe(sql: string, params?: unknown[]): Promise<unknown>;\n savepoint<T>(cb: (sp: SqlTx) => Promise<T>): Promise<T>;\n}\n\ntype Row = Record<string, unknown>;\n\n/** Quote an identifier. Table and column names reach here from the schema and\n * from handler arguments; neither is allowed to become syntax. */\nexport function quoteIdent(name: string): string {\n return `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\nconst BIND_SQL =\n \"select set_config('role',$1,true), set_config('search_path','public',true), set_config('request.jwt.claims',$2,true)\";\n\n/**\n * A transaction that does not exist until somebody reads or writes.\n *\n * `begin(cb)` is callback-scoped, so to hold one open across a whole request\n * the callback parks on a promise this object controls: `commit()` resolves it\n * (the driver commits), `rollback()` rejects it (the driver rolls back). A\n * request that never touches the database never enters the callback at all.\n */\nexport function createLazyTransaction(\n sql: SqlDriver,\n role: string,\n claimsJson: string,\n options: { lockTimeout?: string } = {},\n) {\n const { lockTimeout } = options;\n // `lock_timeout` travels as a BOUND parameter like the other two, so a value\n // from configuration can never become SQL text.\n const bindSql = lockTimeout ? `${BIND_SQL}, set_config('lock_timeout',$3,true)` : BIND_SQL;\n const bindParams = lockTimeout ? [role, claimsJson, lockTimeout] : [role, claimsJson];\n\n let opening: Promise<SqlTx> | null = null;\n let release: (() => void) | null = null;\n let fail: ((e: unknown) => void) | null = null;\n let settled: Promise<unknown> | null = null;\n\n const ensure = (): Promise<SqlTx> => {\n if (opening) return opening;\n opening = new Promise<SqlTx>((resolveTx, rejectTx) => {\n const parked = new Promise<void>((res, rej) => {\n release = res;\n fail = rej;\n });\n settled = sql\n .begin(async (tx) => {\n await tx.unsafe(bindSql, bindParams);\n resolveTx(tx);\n await parked;\n })\n .catch((e: unknown) => {\n // Both paths matter: a caller awaiting `ensure()` must see the\n // failure, and `commit()` must not hang waiting for a dead driver.\n rejectTx(e);\n throw e;\n });\n });\n return opening;\n };\n\n return {\n ensure,\n get opened(): boolean {\n return opening !== null;\n },\n async commit(): Promise<void> {\n if (!opening) return;\n release!();\n await settled;\n },\n async rollback(reason: unknown): Promise<void> {\n if (!opening) return;\n fail!(reason);\n // The rejection is the mechanism, not an error to report twice.\n await settled?.catch(() => undefined);\n },\n };\n}\n\nexport type LazyTransaction = ReturnType<typeof createLazyTransaction>;\n\n/** Either a live driver transaction or the lazy holder above. */\ntype TxLike = SqlTx | LazyTransaction;\n\nconst resolveTx = async (tx: TxLike): Promise<SqlTx> =>\n typeof (tx as LazyTransaction).ensure === \"function\"\n ? await (tx as LazyTransaction).ensure()\n : (tx as SqlTx);\n\n/**\n * What a row LOOKS like to the code that reads it.\n *\n * The driver hands back a `Date` for every timestamp column, while the typed\n * surface this SDK generates for the same table says `string` — and so does the\n * response schema derived from a handler's return type, and so does the JSON on\n * the wire. So a handler that returned a row straight from `Database.tables.x`\n * failed its OWN declared type: measured on 2026-08-16, `POST /todos` answered\n * 500 `output_invalid` with \"expected string, received date\" for `created_at`,\n * from code that had done nothing wrong.\n *\n * ISO-8601, because that is what the schema, the generated client and every\n * JSON reader already agree on.\n */\nfunction asWireValue(value: unknown): unknown {\n if (value instanceof Date) return value.toISOString();\n if (Array.isArray(value)) return value.map(asWireValue);\n return value;\n}\n\n/** Every row a caller receives passes through here. */\nfunction asWireRow<T>(row: T): T {\n if (row === null || typeof row !== \"object\") return row;\n const out: Row = {};\n for (const [key, value] of Object.entries(row as Row)) out[key] = asWireValue(value);\n return out as T;\n}\n\nfunction asWireRows(rows: Row[]): Row[] {\n return rows.map((row) => asWireRow(row));\n}\n\n/** The six string-keyed operations, plus an interactive `transaction`. */\nexport function createOps(tx: TxLike) {\n const at = () => resolveTx(tx);\n\n const ops = {\n async query(sql: string, params: unknown[] = []): Promise<Row[]> {\n return asWireRows((await (await at()).unsafe(sql, params)) as Row[]);\n },\n\n async insert(table: string, data: Row): Promise<Row> {\n const cols = Object.keys(data);\n if (cols.length === 0) throw new Error(`insert into ${table}: no columns given`);\n const placeholders = cols.map((_, i) => `$${i + 1}`).join(\", \");\n const sql =\n `INSERT INTO ${quoteIdent(table)} (${cols.map(quoteIdent).join(\", \")}) ` +\n `VALUES (${placeholders}) RETURNING *`;\n const rows = (await (await at()).unsafe(sql, cols.map((c) => data[c]))) as Row[];\n const inserted = rows[0];\n if (!inserted) {\n // RETURNING * with no row back means the write was filtered away — an\n // RLS WITH CHECK that rejected it, most often. Silence here would hand\n // the author `undefined` and a 500 three lines later.\n throw new Error(\n `insert into ${table} returned no row — the write was rejected (an RLS policy, most likely).`,\n );\n }\n return asWireRow(inserted);\n },\n\n async update(table: string, id: string, data: Row): Promise<Row | null> {\n const cols = Object.keys(data);\n if (cols.length === 0) return ops.findById(table, id);\n const assignments = cols.map((c, i) => `${quoteIdent(c)} = $${i + 1}`).join(\", \");\n const sql = `UPDATE ${quoteIdent(table)} SET ${assignments} WHERE id = $${cols.length + 1} RETURNING *`;\n const rows = (await (await at()).unsafe(sql, [...cols.map((c) => data[c]), id])) as Row[];\n return rows[0] ? asWireRow(rows[0]) : null;\n },\n\n async delete(table: string, id: string): Promise<void> {\n await (await at()).unsafe(`DELETE FROM ${quoteIdent(table)} WHERE id = $1`, [id]);\n },\n\n async findById(table: string, id: string): Promise<Row | null> {\n const rows = (await (await at()).unsafe(\n `SELECT * FROM ${quoteIdent(table)} WHERE id = $1`,\n [id],\n )) as Row[];\n return rows[0] ? asWireRow(rows[0]) : null;\n },\n\n async findMany(table: string, query: Row = {}): Promise<Row[]> {\n const cols = Object.keys(query);\n const where = cols.length\n ? ` WHERE ${cols.map((c, i) => `${quoteIdent(c)} = $${i + 1}`).join(\" AND \")}`\n : \"\";\n return asWireRows((await (await at()).unsafe(\n `SELECT * FROM ${quoteIdent(table)}${where}`,\n cols.map((c) => query[c]),\n )) as Row[]);\n },\n\n /** A real SAVEPOINT inside the request's transaction. */\n async transaction<T>(cb: (t: unknown) => Promise<T>): Promise<T> {\n const live = await at();\n return live.savepoint(async (sp) => cb(withTables(createOps(sp), currentSchema)));\n },\n\n /**\n * Execute a whole transaction plan — what `Database.transaction(fn)` builds.\n *\n * WHY IT RUNS HERE. The platform used to carry a complete implementation\n * of this at `/internal-api/db/tx`, for tenant code that ran in an isolate\n * with no connection of its own. Running the plan there means running it on\n * a DIFFERENT connection: a transaction would not see the uncommitted\n * writes of the request that started it, and the two would hold separate\n * RLS bindings of the same identity. In this stack the tenant's code and\n * the connection share a process, so the plan runs on the request's own\n * transaction inside one SAVEPOINT — and that surface was removed on\n * 2026-08-15, once this was the last thing that could have called it.\n *\n * Until 2026-08-15 it ran NOWHERE: `runTxPlan` called `transport.txPlan` and\n * nothing here implemented it, so a live handler answered\n * \"transport.txPlan is not a function\" while every test that covered\n * transactions passed against a mock that did implement it.\n */\n async txPlan(plan: TxPlanBody): Promise<TxPlanResponse> {\n const live = await at();\n // ONE savepoint for the whole plan: a failed expectation must undo the\n // transaction the author wrote, and nothing outside it.\n return live.savepoint(async (sp) => {\n const results: TxPlanOpResult[] = [];\n for (const op of plan.ops) {\n const rows = await runPlanOp(sp, op, results);\n const result: TxPlanOpResult = { rows, rows_affected: rows.length };\n results.push(result);\n assertGuard(op, result);\n }\n return { results };\n });\n },\n } satisfies DBOps & Record<string, unknown>;\n\n return ops;\n}\n\n/** The schema whose table names the typed `.tables` surface is built from. */\nlet currentSchema: { tables?: Record<string, { name?: string }> } = {};\n\n/** Install the project's `defineSchema()` result. Called once at boot. */\nexport function setSchema(schema: unknown): void {\n const s = schema as { default?: unknown } | undefined;\n currentSchema = ((s && \"default\" in s ? s.default : s) ?? {}) as typeof currentSchema;\n}\n\n/**\n * Merge the typed `.tables` accessor onto a raw op surface.\n *\n * Mirrors what the pod runtime does, including the recursive application to the\n * transaction callback: without it `tx.tables.rooms.insert(...)` throws\n * \"Cannot read properties of undefined\".\n */\nexport function withTables<T extends ReturnType<typeof createOps>>(\n ops: T,\n schema: { tables?: Record<string, { name?: string }> } = currentSchema,\n): T & { tables: Record<string, unknown> } {\n const tables: Record<string, unknown> = {};\n for (const key of Object.keys(schema.tables ?? {})) {\n const name = schema.tables?.[key]?.name ?? key;\n tables[key] = {\n insert: (data: Row) => ops.insert(name, data),\n update: (id: string, data: Row) => ops.update(name, id, data),\n delete: (id: string) => ops.delete(name, id),\n findById: (id: string) => ops.findById(name, id),\n findMany: (query?: Row) => ops.findMany(name, query ?? {}),\n };\n }\n const base: Record<string, unknown> = Object.create(null);\n return Object.assign(base, ops, { tables });\n}\n\n// ── the two identities one request may speak with ──────────────────────────\n\n/**\n * How long a statement on the SERVICE transaction may wait for a row lock.\n *\n * The bound exists because `asService()` runs in a SECOND transaction on a\n * SECOND connection (see {@link createRequestDatabase} for why it must). A\n * handler that writes a row through `Database.*` and then touches the same row\n * through `Database.asService()` is waiting on a lock held by a transaction\n * that cannot commit until the handler returns — a wait that can never end.\n * Unbounded, that hangs the request AND holds two pool connections for as long\n * as the process lives; a few of those and the runtime stops answering at all.\n *\n * 5s, from the two numbers around it: a healthy contended write resolves in\n * milliseconds, and the edge cuts a tenant request at 60s\n * (v2/deploy/envoy/routes.yaml, the catch-all route).\n * So the failure arrives as a legible error at the caller instead of a 504 with\n * both connections still held.\n */\nconst SERVICE_LOCK_TIMEOUT = \"5s\";\n\n/** Postgres raises 55P03 (lock_not_available) when `lock_timeout` fires. */\nfunction isLockTimeout(e: unknown): boolean {\n const code = (e as { code?: unknown } | null)?.code;\n const message = String((e as { message?: unknown } | null)?.message ?? \"\");\n return code === \"55P03\" || /lock timeout/i.test(message);\n}\n\n/**\n * Wrap a driver so a lock timeout says what actually happened.\n *\n * \"canceling statement due to lock timeout\" is true and useless: the author's\n * two surfaces are two transactions, which is the one thing the message cannot\n * tell them. Applied recursively through `savepoint`, so `transaction()` and\n * `txPlan` inside the service surface answer the same way.\n */\nfunction diagnosingDriver(sql: SqlDriver): SqlDriver {\n const explain = (e: unknown): unknown =>\n isLockTimeout(e)\n ? new Error(\n \"Database.asService() waited too long for a row lock. It runs in its OWN transaction, so a \" +\n \"row this request already wrote through Database.* is locked against it until the request \" +\n \"commits — a wait that cannot end. Do that row's work on one surface or the other. \" +\n `(${String((e as { message?: unknown } | null)?.message ?? e)})`,\n )\n : e;\n\n const wrapTx = (tx: SqlTx): SqlTx => ({\n async unsafe(text: string, params?: unknown[]) {\n try {\n return await tx.unsafe(text, params);\n } catch (e) {\n throw explain(e);\n }\n },\n savepoint<T>(cb: (sp: SqlTx) => Promise<T>) {\n return tx.savepoint((sp) => cb(wrapTx(sp)));\n },\n });\n\n return {\n unsafe: (text: string, params?: unknown[]) => sql.unsafe(text, params),\n begin: <T>(cb: (tx: SqlTx) => Promise<T>) => sql.begin((tx) => cb(wrapTx(tx))),\n };\n}\n\n/** The two transactions a request may hold, and the single `Database` over them. */\nexport interface RequestDatabase {\n /** What the engine injects as the request's `Database` singleton. */\n readonly client: DBClient;\n /** Commit whatever was opened. Called once, after the handler returns. */\n commit(): Promise<void>;\n /** Roll back whatever was opened. Called once, when the handler throws. */\n rollback(reason: unknown): Promise<void>;\n}\n\n/**\n * The `Database` one request sees: RLS-enforced by default, with the\n * service-role sibling behind `asService()`.\n *\n * # Why the sibling cannot ride the request's own transaction\n *\n * The role reaches Postgres ONCE, in the BEGIN's bind statement, and it is\n * transaction-scoped. So a sibling built on the same transaction runs as\n * `backend_authenticated` no matter what it is called — RLS still filters every\n * row and `asService()` silently means nothing. That is the failure mode worth\n * naming: it does not throw, it does not log, it simply returns the caller's own\n * rows where the author asked for everyone's, and a handler that trusts it\n * (`if (existing) throw new Conflict()`) makes the wrong decision on data it was\n * never shown.\n *\n * The obvious repair — re-issue `set_config('role', …)` around each service op\n * — is worse than the bug. Two statements are not one: `Promise.all([\n * Database.query(…), Database.asService().query(…) ])` interleaves them on the\n * single connection, and the user's query can execute between the service's\n * set-role and its own statement. That is RLS silently OFF on the DEFAULT path,\n * which is precisely the direction a security seam must never fail.\n *\n * So the service surface gets its own transaction, on its own connection, bound\n * to the service role at BEGIN. The identity separation is physical: no\n * statement of either surface can change what the other runs as.\n *\n * # What that costs, stated plainly\n *\n * - **One extra connection per request that uses it**, and only then: the second\n * transaction is lazy exactly like the first, so `asService()` called and\n * never used opens nothing.\n * - **Called twice, it is the same surface** — one transaction per REQUEST, not\n * per call — so a handler cannot leak connections by reaching for it in a\n * loop.\n * - **The two are not atomic with each other.** Both settle with the request\n * (commit when the handler returns, roll back when it throws), but they settle\n * as two transactions: if the second COMMIT fails, the first has already\n * landed. The request's own work commits first, so the failure that survives\n * is never \"the audit row exists and the thing it audits does not\".\n * - **They can wait on each other's locks.** Bounded in the service direction by\n * {@link SERVICE_LOCK_TIMEOUT}; in the other direction — a `Database.*` write\n * to a row `asService()` has already written — the wait is the request's own,\n * and the answer is not to write one row from both surfaces.\n *\n * # Claims travel unchanged\n *\n * The service transaction carries the SAME `request.jwt.claims` as the user's.\n * `asService()` changes what the caller may TOUCH, not who they are, so\n * `auth.uid()` still resolves inside a trigger or a column default. It is also\n * the fail-closed direction: a service role provisioned WITHOUT `BYPASSRLS`\n * (measured live on 2026-08-13, created by hand during a diagnosis) is not named\n * by any policy, so it reads zero rows instead of quietly reading everyone's.\n */\nexport function createRequestDatabase(\n sql: SqlDriver,\n identity: { role: string; serviceRole: string; claimsJson: string },\n): RequestDatabase {\n const tx = createLazyTransaction(sql, identity.role, identity.claimsJson);\n\n // Opened on FIRST use and shared by every later `asService()` call.\n let serviceTx: LazyTransaction | null = null;\n let serviceClient: Omit<DBClient, \"asService\"> | null = null;\n\n const asService = (): Omit<DBClient, \"asService\"> => {\n if (serviceClient === null) {\n serviceTx = createLazyTransaction(\n diagnosingDriver(sql),\n identity.serviceRole,\n identity.claimsJson,\n { lockTimeout: SERVICE_LOCK_TIMEOUT },\n );\n // No `asService` on it: the type says `Omit<DBClient, \"asService\">` and so\n // does the object, so a second bypass is neither typeable nor callable.\n serviceClient = withTables(createOps(serviceTx));\n }\n return serviceClient;\n };\n\n return {\n client: Object.assign(withTables(createOps(tx)), { asService }),\n async commit(): Promise<void> {\n // The request's declared work first; see \"not atomic with each other\".\n await tx.commit();\n await serviceTx?.commit();\n },\n async rollback(reason: unknown): Promise<void> {\n await tx.rollback(reason);\n await serviceTx?.rollback(reason);\n },\n };\n}\n\n\n// ── the transaction plan executor ──────────────────────────────────────────\n//\n// The plan is a closed little language: five op kinds, equality-only filters,\n// and three value forms (a literal, a `$ref` to an earlier op's row, an\n// `$expr`). It is built by `TxPlanBuilder` in this same package, so the\n// executor's job is to run it faithfully rather than to defend against it —\n// with one exception that still matters: identifiers reach SQL as text, so\n// every table and column name goes through `quoteIdent`, exactly as the six\n// single-statement ops above do.\n\n/** Collects bound parameters so a value is never spliced into SQL text. */\nclass Args {\n readonly values: unknown[] = [];\n bind(value: unknown): string {\n this.values.push(value);\n return `$${this.values.length}`;\n }\n}\n\nfunction isRef(v: unknown): v is TxWireRef {\n return typeof v === \"object\" && v !== null && \"$ref\" in v;\n}\nfunction isExpr(v: unknown): v is TxWireExpr {\n return typeof v === \"object\" && v !== null && \"$expr\" in v;\n}\n\n/**\n * Render one value into SQL, binding whatever is data.\n *\n * `column` is only used by `inc`/`dec`, which read the column they write.\n */\nfunction renderValue(\n value: TxWireValue,\n column: string,\n args: Args,\n results: TxPlanOpResult[],\n): string {\n if (isRef(value)) {\n const source = results[value.$ref.op];\n const row = source?.rows[0];\n if (!row || !(value.$ref.field in row)) {\n throw Object.assign(new Error(`op ${value.$ref.op} has no column \"${value.$ref.field}\" to reference`), {\n error_code: \"tx_ref_unresolved\",\n });\n }\n return args.bind(row[value.$ref.field]);\n }\n if (isExpr(value)) {\n const fn = value.$expr;\n if (fn.fn === \"now\") return \"now()\";\n const operator = fn.fn === \"inc\" ? \"+\" : \"-\";\n // The column is an identifier; the operand is BOUND. This is the one place\n // the tenant's digits could otherwise have reached SQL text.\n return `${quoteIdent(column)} ${operator} ${args.bind(fn.by)}`;\n }\n return args.bind(value);\n}\n\n/**\n * Render a WHERE clause.\n *\n * A null is compared with IS NULL, never `= NULL`: the latter is never true, so\n * a filter written that way silently matches nothing.\n */\nfunction renderWhere(\n where: Record<string, TxWireValue> | undefined,\n args: Args,\n results: TxPlanOpResult[],\n): string {\n const cols = Object.keys(where ?? {});\n if (cols.length === 0) return \"\";\n const terms = cols.map((c) => {\n const v = (where as Record<string, TxWireValue>)[c];\n if (v === null) return `${quoteIdent(c)} IS NULL`;\n return `${quoteIdent(c)} = ${renderValue(v, c, args, results)}`;\n });\n return ` WHERE ${terms.join(\" AND \")}`;\n}\n\nasync function runPlanOp(\n sp: SqlTx,\n op: TxWireOp,\n results: TxPlanOpResult[],\n): Promise<Row[]> {\n const args = new Args();\n const table = quoteIdent(op.table);\n let sql: string;\n\n switch (op.op) {\n case \"insert\": {\n const cols = Object.keys(op.values ?? {});\n const rendered = cols.map((c) => renderValue((op.values as Record<string, TxWireValue>)[c], c, args, results));\n sql = cols.length\n ? `INSERT INTO ${table} (${cols.map(quoteIdent).join(\", \")}) VALUES (${rendered.join(\", \")}) RETURNING *`\n : `INSERT INTO ${table} DEFAULT VALUES RETURNING *`;\n break;\n }\n case \"insertMany\": {\n const rows = (op.rows ?? []) as Record<string, TxWireValue>[];\n if (rows.length === 0 || !rows[0]) return [];\n // The column list comes from the FIRST row and every row is rendered\n // against it, so a row with a stray extra key cannot shift the columns of\n // the statement it shares.\n const cols = Object.keys(rows[0]);\n const tuples = rows.map(\n (r) => `(${cols.map((c) => renderValue(r[c], c, args, results)).join(\", \")})`,\n );\n sql = `INSERT INTO ${table} (${cols.map(quoteIdent).join(\", \")}) VALUES ${tuples.join(\", \")} RETURNING *`;\n break;\n }\n case \"update\": {\n const cols = Object.keys(op.set ?? {});\n if (cols.length === 0) throw new Error(`update ${op.table}: nothing to set`);\n const assignments = cols.map(\n (c) => `${quoteIdent(c)} = ${renderValue((op.set as Record<string, TxWireValue>)[c], c, args, results)}`,\n );\n sql = `UPDATE ${table} SET ${assignments.join(\", \")}${renderWhere(op.where, args, results)} RETURNING *`;\n break;\n }\n case \"delete\": {\n sql = `DELETE FROM ${table}${renderWhere(op.where, args, results)} RETURNING *`;\n break;\n }\n case \"select\": {\n const limit = op.limit !== undefined ? ` LIMIT ${Number(op.limit)}` : \"\";\n const lock = op.lock === \"update\" ? \" FOR UPDATE\" : \"\";\n sql = `SELECT * FROM ${table}${renderWhere(op.where, args, results)}${limit}${lock}`;\n break;\n }\n default:\n // Loudly, rather than rendering something for an op nobody wrote.\n throw new Error(`unknown operation \"${String((op as { op: string }).op)}\" in a transaction plan`);\n }\n\n return (await sp.unsafe(sql, args.values)) as Row[];\n}\n\n/**\n * Enforce the author's declared expectation.\n *\n * The Error the author passed never travels: the plan carries a SLOT index and\n * the SDK maps it back. So a failure here throws the shape `runTxPlan` знает —\n * `{error_code: \"tx_guard_failed\", slot}` — and the savepoint unwinds.\n */\nfunction assertGuard(op: TxWireOp, result: TxPlanOpResult): void {\n const guard = op.guard;\n if (!guard) return;\n const n = result.rows.length;\n const ok =\n guard.kind === \"one\"\n ? n === 1\n : guard.kind === \"none\"\n ? n === 0\n : guard.kind === \"atLeast\"\n ? n >= guard.n\n : n <= guard.n;\n if (ok) return;\n throw Object.assign(new Error(`transaction expectation failed: ${guard.kind} (${n} row(s))`), {\n error_code: \"tx_guard_failed\",\n slot: guard.slot,\n });\n}\n","// The decorator registry — the single plain-data store the method + parameter\n// decorators write into, and the deploy/dispatch pipeline reads back. No\n// `reflect-metadata`, no `emitDecoratorMetadata`: the registry is built from the\n// decorator arguments + the parameter INDEX that esbuild/tsc preserve for legacy\n// parameter decorators (verified — see the design spec §0/§4.1).\n//\n// A controller class carries its route metadata on a symbol-keyed static\n// property (`ROUTES`). `@Get`/`@Post`/… append a {@link RouteMeta} entry;\n// `@Body`/`@User`/… append a {@link ParamMeta} entry onto the route for the\n// method they decorate. Because parameter decorators run BEFORE the method\n// decorator for the same member (TS evaluates innermost-first, params before the\n// method), the route entry may not exist yet when a param decorator fires — so\n// param metadata is buffered per method name and merged when the method\n// decorator creates the route entry.\nimport type { AuthSpec, RateLimitConfig } from \"../endpoint.js\";\nimport type { UploadConfig } from \"./upload.js\";\nimport type { ZodTypeAny } from \"zod\";\n\n/** The HTTP verbs a route may declare, upper-cased (the runtime router +\n * OpenAPI lower-case on their own). */\nexport type HttpMethodUpper = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\" | \"QUERY\";\n\n/** Route-level options accepted by the method decorators (`@Get`/`@Post`/…). */\nexport interface RouteOptions {\n /** OVERRIDES the controller-level default auth for this one route. */\n auth?: AuthSpec;\n /** Per-route rate limit. */\n rateLimit?: RateLimitConfig;\n /** Direct-storage upload config — present ONLY on `@Upload` routes (the\n * `@Get`/`@Post`/… decorators never set it). Its presence is what MARKS a\n * route as an upload route through the whole pipeline (registry → flatten →\n * openapi → codegen). The bytes go client→storage directly; the method body\n * runs as the completion handler. See {@link UploadConfig} (decorators/upload.ts). */\n uploadConfig?: UploadConfig;\n}\n\n/** The kind of value a parameter decorator injects. Drives both dispatch\n * (which request slice to inject) and codegen (which OpenAPI parameter source a\n * schema-bearing kind maps to). */\nexport type ParamKind =\n | \"body\"\n | \"query\"\n | \"param\"\n | \"headers\"\n | \"user\"\n | \"optionalUser\"\n | \"client\"\n | \"requestId\"\n | \"traceId\"\n | \"req\"\n // `@UploadedObject()` — injects the uploaded object (completion input) on an\n // `@Upload` route. No schema (the shape is the fixed UploadedObject type).\n | \"uploadedObject\";\n\n/** One parameter decorator's recorded metadata. `index` is the parameter\n * position esbuild/tsc preserve; `schema` is present for the schema-bearing\n * kinds (`body`/`query`/`headers`); `name` is the path-param name for `param`. */\nexport interface ParamMeta {\n index: number;\n kind: ParamKind;\n /** Zod schema for `body`/`query`/`headers` (validation + codegen source). */\n schema?: ZodTypeAny;\n /** Path-param name for `@Param(\"id\")`. */\n name?: string;\n}\n\n/** One inferred throw site: the error CLASS name (e.g. \"TodoLocked\") and its\n * wire code (e.g. \"todo_locked\"). `status`, `hasData`, and the data JSON schema\n * are NOT carried here — they resolve from the error registry by `code` at\n * extract/openapi time (single source of truth). */\nexport interface ThrowDescriptor {\n name: string;\n code: string;\n}\n\n/** One route's recorded metadata: the verb + subpath + method name + options,\n * the ordered parameter metas, and the resolved return schema (injected by the\n * codegen step — see `returnSchema`). */\nexport interface RouteMeta {\n method: HttpMethodUpper;\n subpath: string;\n fnName: string;\n options: RouteOptions;\n params: ParamMeta[];\n /** Response schema for the route, if any. Derived from the method's RETURN\n * TYPE by codegen and written here via `recordReturn` (a generated top-level\n * IIFE injected per controller), not by an author-written decorator. */\n returnSchema?: ZodTypeAny;\n /** Error classes this route can throw, if inferred. Derived from the method\n * body + service call graph by the deploy stager's throw analysis and written\n * here via `recordThrows` (a generated top-level IIFE injected per controller,\n * the `recordReturn` twin), not by an author-written decorator. */\n throws?: ThrowDescriptor[];\n}\n\n/** Symbol the route metadata list is stored under on a controller class. Using\n * a symbol (not a string key) keeps it off the public structural surface and\n * avoids any chance of an authored property collision. */\nexport const ROUTES: unique symbol = Symbol.for(\"palbase.backend.routes\");\n\n/** Symbol the per-method buffered parameter metas are stored under while a class\n * is being decorated. Parameter decorators fire before the method decorator, so\n * they buffer here keyed by method name; the method decorator drains the buffer\n * into the route entry it creates. */\nconst PARAM_BUFFER: unique symbol = Symbol.for(\"palbase.backend.paramBuffer\");\n\n/** Symbol the per-method buffered return-type schemas are stored under while a\n * class's registry is being populated. The codegen-injected `recordReturn` call\n * can fire before OR after the method decorator; it buffers here keyed by method\n * name and `recordRoute` drains it into the route entry (and `recordReturn`\n * writes through if the route already exists). Buffering on BOTH sides means a\n * fully-formed route entry always carries its return schema — a raw-symbol\n * reader (the runtime) never has to re-merge. */\nconst RETURN_BUFFER: unique symbol = Symbol.for(\"palbase.backend.returnBuffer\");\n\n/** Symbol the per-method buffered throw descriptors are stored under while a\n * class's registry is being populated. The stager-injected `recordThrows` call\n * can fire before OR after the method decorator; it buffers here keyed by method\n * name and `recordRoute` drains it into the route entry (and `recordThrows`\n * writes through if the route already exists). Buffering on BOTH sides means a\n * fully-formed route entry always carries its throw descriptors — a raw-symbol\n * reader (the runtime) never has to re-merge. */\nconst THROWS_BUFFER: unique symbol = Symbol.for(\"palbase.backend.throwsBuffer\");\n\n/** A class constructor carrying the symbol-keyed registry slots. We type the\n * registry-bearing class as this so the decorators can read/write the slots\n * without `any` — a plain `Function` does not carry index signatures. */\ninterface RegistryCarrier {\n [ROUTES]?: RouteMeta[];\n [PARAM_BUFFER]?: Record<string, ParamMeta[]>;\n [RETURN_BUFFER]?: Record<string, ZodTypeAny>;\n [THROWS_BUFFER]?: Record<string, ThrowDescriptor[]>;\n}\n\n/** Coerce a decorated target (class constructor or its prototype) into the\n * registry carrier that owns the slots. Method/param decorators receive the\n * PROTOTYPE as their target; the class decorator receives the constructor. We\n * always anchor the registry on the CONSTRUCTOR so `getRoutes(ctor)` finds it. */\nfunction carrierOf(target: object): RegistryCarrier {\n // For instance-member decorators, `target` is the prototype; its `.constructor`\n // is the class. For a static member or the class decorator, `target` is the\n // constructor already. Resolve to the constructor either way.\n const ctor =\n typeof target === \"function\"\n ? (target as unknown as RegistryCarrier)\n : (((target as { constructor?: unknown }).constructor ??\n target) as unknown as RegistryCarrier);\n return ctor;\n}\n\n/** Get (creating if absent) the own route list for a class constructor. Own —\n * not inherited — so a subclass does not mutate its base's routes. */\nfunction ownRoutes(carrier: RegistryCarrier): RouteMeta[] {\n if (!Object.prototype.hasOwnProperty.call(carrier, ROUTES)) {\n carrier[ROUTES] = [];\n }\n return carrier[ROUTES] as RouteMeta[];\n}\n\n/** Get (creating if absent) the own per-method param buffer for a class. */\nfunction ownParamBuffer(carrier: RegistryCarrier): Record<string, ParamMeta[]> {\n if (!Object.prototype.hasOwnProperty.call(carrier, PARAM_BUFFER)) {\n carrier[PARAM_BUFFER] = {};\n }\n return carrier[PARAM_BUFFER] as Record<string, ParamMeta[]>;\n}\n\n/** Record a route (called by the method decorators). Drains any parameter\n * metas already buffered for `fnName` into the new route entry, then sorts them\n * by parameter index so dispatch can inject positionally. */\nexport function recordRoute(\n target: object,\n fnName: string,\n method: HttpMethodUpper,\n subpath: string,\n options: RouteOptions,\n): void {\n const carrier = carrierOf(target);\n const routes = ownRoutes(carrier);\n const buffer = ownParamBuffer(carrier);\n const params = (buffer[fnName] ?? []).slice().sort((a, b) => a.index - b.index);\n const route: RouteMeta = { method, subpath, fnName, options, params };\n // Drain a buffered return schema (the recordReturn-ran-first ordering) so the\n // route entry is complete the moment it's created — a raw-symbol consumer\n // (the runtime extractor/worker) sees the return schema without re-merging.\n const returnBuffer = carrier[RETURN_BUFFER];\n if (returnBuffer && returnBuffer[fnName] !== undefined) {\n route.returnSchema = returnBuffer[fnName];\n }\n // Same drain for buffered throw descriptors (the recordThrows-ran-first\n // ordering) — the route entry is complete the moment it's created.\n const throwsBuffer = carrier[THROWS_BUFFER];\n if (throwsBuffer && throwsBuffer[fnName] !== undefined) {\n route.throws = throwsBuffer[fnName];\n }\n routes.push(route);\n}\n\n/** Record one parameter decorator (called by `@Body`/`@User`/…). Buffers per\n * method name; the method decorator merges the buffer into the route entry. If\n * the route already exists (method decorator ran first — TS does evaluate the\n * method decorator AFTER its parameter decorators, but we stay order-robust),\n * the meta is also appended directly so neither ordering loses it. */\nexport function recordParam(target: object, fnName: string, meta: ParamMeta): void {\n const carrier = carrierOf(target);\n const buffer = ownParamBuffer(carrier);\n (buffer[fnName] ??= []).push(meta);\n\n // Order-robust: if the route already exists, merge in place + keep sorted.\n const routes = carrier[ROUTES];\n if (routes) {\n const route = routes.find((r) => r.fnName === fnName);\n if (route) {\n route.params.push(meta);\n route.params.sort((a, b) => a.index - b.index);\n }\n }\n}\n\n/** Attach a return schema to the route for `fnName` (called by the codegen\n * injection that reads the method's return type). If the route does not exist\n * yet, the schema is buffered (RETURN_BUFFER) and drained into the route by\n * `recordRoute` when the method decorator runs. */\nexport function recordReturn(target: object, fnName: string, schema: ZodTypeAny): void {\n const carrier = carrierOf(target);\n const routes = carrier[ROUTES];\n const route = routes?.find((r) => r.fnName === fnName);\n if (route) {\n route.returnSchema = schema;\n return;\n }\n if (!Object.prototype.hasOwnProperty.call(carrier, RETURN_BUFFER)) {\n carrier[RETURN_BUFFER] = {};\n }\n const returnBuffer = carrier[RETURN_BUFFER];\n if (returnBuffer) returnBuffer[fnName] = schema;\n}\n\n/** Attach the inferred throw descriptors to the route for `fnName` (called by\n * the stager-injected IIFE that carries the throw analysis result — the\n * `recordReturn` twin). If the route does not exist yet, the descriptors are\n * buffered (THROWS_BUFFER) and drained into the route by `recordRoute` when the\n * method decorator runs. */\nexport function recordThrows(target: object, fnName: string, throws: ThrowDescriptor[]): void {\n const carrier = carrierOf(target);\n const routes = carrier[ROUTES];\n const route = routes?.find((r) => r.fnName === fnName);\n if (route) {\n route.throws = throws;\n return;\n }\n if (!Object.prototype.hasOwnProperty.call(carrier, THROWS_BUFFER)) {\n carrier[THROWS_BUFFER] = {};\n }\n const throwsBuffer = carrier[THROWS_BUFFER];\n if (throwsBuffer) throwsBuffer[fnName] = throws;\n}\n\n/** Read the route metadata for a controller class (the deploy/dispatch entry\n * point). Applies any buffered return schemas + throw descriptors (for the\n * recordReturn/recordThrows-runs-before orderings) and returns a defensive copy\n * so callers cannot mutate the registry.\n */\nexport function getRoutes(ctor: object): RouteMeta[] {\n const carrier = carrierOf(ctor);\n const routes = carrier[ROUTES] ?? [];\n const returnBuffer = carrier[RETURN_BUFFER];\n if (returnBuffer) {\n for (const route of routes) {\n const buffered = returnBuffer[route.fnName];\n if (buffered && route.returnSchema === undefined) {\n route.returnSchema = buffered;\n }\n }\n }\n const throwsBuffer = carrier[THROWS_BUFFER];\n if (throwsBuffer) {\n for (const route of routes) {\n const buffered = throwsBuffer[route.fnName];\n if (buffered && route.throws === undefined) {\n route.throws = buffered;\n }\n }\n }\n return routes.map((r) => ({\n ...r,\n params: r.params.slice(),\n ...(r.throws !== undefined ? { throws: r.throws.slice() } : {}),\n }));\n}\n","/**\n * engine/router.ts — the route table, built from the SDK's own registry.\n *\n * No third-party router. The table is known at boot (the decorators wrote it),\n * so matching is a segment walk over a small array rather than a compiled\n * pattern engine. Both authoring forms for a path parameter are accepted:\n * `{id}` (what the decorators are written with) and `:id`.\n */\nimport { getRoutes } from \"../decorators/registry.js\";\nimport type { RouteMeta } from \"../decorators/registry.js\";\n\nconst CONTROLLER_META = Symbol.for(\"palbase.backend.controllerMeta\");\n\nexport interface RouteEntry {\n method: string;\n /** Path segments; a parameter segment is stored as `:name`. */\n segments: string[];\n meta: RouteMeta;\n /** The controller instance the method is invoked on. */\n instance: Record<string, (...args: unknown[]) => unknown>;\n /** `GET /todos/{id}` — stable, human-readable, used as the rate-limit key. */\n id: string;\n /** The controller's `auth` default, if it declared one. */\n controllerAuth: unknown;\n}\n\nfunction toSegments(path: string): string[] {\n return path\n .split(\"/\")\n .filter(Boolean)\n .map((s) => (s.startsWith(\"{\") && s.endsWith(\"}\") ? `:${s.slice(1, -1)}` : s));\n}\n\n/**\n * Build the table from controller classes.\n *\n * @throws when a class carries no routes — a controller that collected zero\n * endpoints is the silent failure this whole runtime is built to refuse, and\n * it must be loud at boot rather than a 404 in production.\n */\nexport function buildRouteTable(controllers: readonly unknown[]): RouteEntry[] {\n const table: RouteEntry[] = [];\n for (const Ctrl of controllers) {\n const ctor = Ctrl as { new (): Record<string, (...a: unknown[]) => unknown> } & Record<\n symbol,\n { basePath?: string; defaultAuth?: unknown } | undefined\n >;\n const meta = ctor[CONTROLLER_META];\n const basePath = meta?.basePath ?? \"\";\n const routes = getRoutes(Ctrl as never) as RouteMeta[];\n if (routes.length === 0) {\n const name = (Ctrl as { name?: string }).name ?? \"<anonymous>\";\n throw new Error(\n `controller ${name} collected zero routes. Either it declares no @Get/@Post/… , ` +\n `or its decorator metadata was erased at build time — check that the bundle was ` +\n `compiled with experimentalDecorators enabled.`,\n );\n }\n const instance = new ctor();\n for (const r of routes) {\n const full = `${basePath}${r.subpath ?? \"\"}` || \"/\";\n table.push({\n method: r.method,\n segments: toSegments(full),\n meta: r,\n instance,\n id: `${r.method} ${full}`,\n controllerAuth: meta?.defaultAuth,\n });\n }\n }\n return table;\n}\n\nexport interface RouteMatch {\n entry: RouteEntry;\n params: Record<string, string>;\n}\n\n/** First match wins; the table is small and declaration order is the tiebreak. */\nexport function matchRoute(\n table: readonly RouteEntry[],\n method: string,\n pathname: string,\n): RouteMatch | null {\n const parts = pathname.split(\"/\").filter(Boolean);\n for (const entry of table) {\n if (entry.method !== method || entry.segments.length !== parts.length) continue;\n const params: Record<string, string> = {};\n let ok = true;\n for (let i = 0; i < entry.segments.length; i++) {\n const seg = entry.segments[i];\n const got = parts[i];\n if (seg === undefined || got === undefined) { ok = false; break; }\n if (seg.charCodeAt(0) === 58 /* ':' */) {\n params[seg.slice(1)] = decodeURIComponent(got);\n } else if (seg !== got) {\n ok = false;\n break;\n }\n }\n if (ok) return { entry, params };\n }\n return null;\n}\n","/**\n * upload.ts — the engine's half of `@Upload`.\n *\n * THE SHAPE, because it is unusual and the reason matters:\n *\n * client ──[ multipart: file + request body ]──► storage\n * storage ──[ authorize: which bucket, which path? ]──► THIS process\n * storage ── writes the bytes, renders the variants\n * storage ──[ signed: uploadedObject + request body ]──► THIS process\n * THIS process ── the handler runs, returns its typed result\n * storage ──[ that result ]──► client\n *\n * The tenant's code NEVER sees the bytes. It sees the metadata and the request\n * body, and it answers — which is what a completion handler is for. A 1 GB\n * video would otherwise stream through this process to reach the same place.\n *\n * Two calls arrive here, both from storage and neither from a browser:\n *\n * - AUTHORIZE asks which bucket and path a route writes to. Storage cannot\n * know: the answer lives in `@Upload({bucket, pathTemplate})`, which is\n * TypeScript, in the deployed bundle. Asking the process that HAS the\n * routes is what stops the client from naming its own bucket.\n * - COMPLETION runs the handler.\n *\n * Both are signed. An unsigned completion would let anyone with the route path\n * invent an upload that never happened.\n */\n\nimport type { RouteEntry } from \"./router.js\";\n\n/** What authorize answers: where this route's bytes go, and what they may be. */\nexport interface UploadGrant {\n bucket: string;\n path: string;\n maxBytes: number | null;\n mimeTypes: string[] | null;\n}\n\n/** The completion input storage sends after the bytes have landed. */\nexport interface CompletionEnvelope {\n uploadedObject: {\n uploadId: string;\n path: string;\n bucket: string;\n size: number;\n contentType: string;\n checksum: string;\n width?: number;\n height?: number;\n thumbhash?: string;\n variants: Record<string, string>;\n };\n /** The request body the client sent alongside the file. */\n body: unknown;\n}\n\n/** The internal path storage calls to ask where a route's bytes go. */\nexport const AUTHORIZE_PATH = \"/__palbase/upload/authorize\";\n\n/** Header carrying the shared-secret signature on both internal calls. */\nexport const SIGNATURE_HEADER = \"x-palbase-upload-signature\";\n\n/**\n * renderPath fills a `pathTemplate` on the SERVER.\n *\n * The client never chooses where its bytes land. `{filename}` is the one token\n * that comes from the caller, and it is sanitised to a single path segment:\n * without that, `../../../etc/passwd` is a filename, and a template that looks\n * like a folder structure becomes a way to write anywhere in the bucket.\n */\nexport function renderPath(template: string, tokens: {\n userId?: string | null;\n uploadId: string;\n filename?: string;\n}): string {\n return template\n .replaceAll(\"{userId}\", sanitizeSegment(tokens.userId ?? \"anonymous\"))\n .replaceAll(\"{uploadId}\", sanitizeSegment(tokens.uploadId))\n .replaceAll(\"{filename}\", sanitizeSegment(tokens.filename ?? \"file\"));\n}\n\n/**\n * sanitizeSegment reduces a value to something safe inside one path segment.\n *\n * Slashes, dots and control characters go. Keeping dots would allow `..`;\n * keeping slashes would allow a client to climb out of the prefix the template\n * put it in, which is the whole point of having a template.\n */\nexport function sanitizeSegment(raw: string): string {\n const cleaned = raw\n .replace(/[\\x00-\\x1F\\x7F]/g, \"\")\n .replace(/[/\\\\]/g, \"-\")\n .replace(/\\.{2,}/g, \".\")\n .replace(/^\\.+/, \"\")\n .trim();\n return cleaned === \"\" ? \"file\" : cleaned.slice(0, 200);\n}\n\n/**\n * grantFor resolves a route's upload configuration into a concrete grant.\n *\n * Returns null when the route is not an upload route — which is a refusal, not\n * an oversight: storage asking about a route with no `@Upload` means somebody\n * is trying to write through an endpoint that never offered to accept a file.\n */\nexport function grantFor(\n entry: RouteEntry | undefined,\n ctx: { userId: string | null; uploadId: string; filename?: string },\n bucketLimits?: { maxBytes: number | null; mimeTypes: string[] | null },\n): UploadGrant | null {\n const cfg = entry?.meta?.options?.uploadConfig;\n if (!cfg) return null;\n return {\n bucket: cfg.bucket,\n path: renderPath(cfg.pathTemplate, {\n userId: ctx.userId,\n uploadId: ctx.uploadId,\n filename: ctx.filename,\n }),\n maxBytes: bucketLimits?.maxBytes ?? null,\n mimeTypes: bucketLimits?.mimeTypes ?? null,\n };\n}\n\n/**\n * CompletionLedger makes a completion run its handler EXACTLY ONCE per upload.\n *\n * The completion is a mutation — it writes the row that makes the uploaded\n * bytes mean something — and it is delivered over a network by a caller that\n * retries. A retried completion must not create a second post for one photo, so\n * the second call is answered with the FIRST call's response rather than being\n * refused: to storage, and therefore to the client waiting on it, a retry that\n * succeeds is indistinguishable from the original, which is the point.\n *\n * Bounded, and oldest-first: an upload id is interesting for as long as a retry\n * could still arrive, not forever. The cap is what keeps a long-lived process\n * from turning this into a leak — a ledger that remembered every upload would\n * be a slow way to run out of memory.\n */\nexport class CompletionLedger {\n private readonly seen = new Map<string, CompletedResponse>();\n\n constructor(private readonly capacity = 1024) {}\n\n recall(uploadId: string): CompletedResponse | undefined {\n return this.seen.get(uploadId);\n }\n\n remember(uploadId: string, response: CompletedResponse): void {\n // Delete-then-set so a repeat moves to the back: Map iterates in insertion\n // order, and the eviction below takes the front.\n this.seen.delete(uploadId);\n this.seen.set(uploadId, response);\n while (this.seen.size > this.capacity) {\n const oldest = this.seen.keys().next();\n if (oldest.done) break;\n this.seen.delete(oldest.value);\n }\n }\n\n get size(): number {\n return this.seen.size;\n }\n}\n\n/** A completion's answer, kept verbatim so a retry receives what the first call did. */\nexport interface CompletedResponse {\n status: number;\n body: string | null;\n contentType: string | null;\n}\n\n/**\n * verifySignature compares a presented signature against the expected one in\n * constant time.\n *\n * Constant time because a leaky comparison on a shared secret is recoverable\n * byte by byte, and this secret authorises running a tenant's handler with an\n * upload the caller describes.\n */\nexport function verifySignature(presented: string, expected: string): boolean {\n if (presented.length !== expected.length) return false;\n let diff = 0;\n for (let i = 0; i < presented.length; i++) {\n diff |= presented.charCodeAt(i) ^ expected.charCodeAt(i);\n }\n return diff === 0;\n}\n","/**\n * engine/index.ts — the engine: a backend that boots itself.\n *\n * `createApp` turns a set of `@Controller` classes into a `fetch(Request)`\n * handler. No V8 isolate, no capability hop: this process owns its database\n * pool, verifies its own tokens, applies its own rate limits, and calls the\n * modules directly.\n *\n * import { createApp, loadConfig } from \"@palbase/backend/engine\";\n *\n * const app = await createApp({\n * config: loadConfig(process.env),\n * controllers: [TodosController],\n * schema,\n * });\n * Bun.serve({ port: app.config.port, fetch: app.handle });\n *\n * The Web-standard `fetch` signature is the point: the same handler runs under\n * Bun, Deno and any host that speaks Request/Response, so \"works locally\" and\n * \"works in the cloud\" are the same code path rather than two.\n */\nimport { __runWithRuntime, __requestALS } from \"../runtime.js\";\nimport type { RuntimeServices } from \"../runtime.js\";\nimport { isHttpError } from \"../errors.js\";\nimport type { CacheClient } from \"../endpoint.js\";\n\nimport { loadConfig, BootRefused } from \"./config.js\";\nimport type { EngineConfig } from \"./config.js\";\nimport { AuthVerifier, effectiveAuth } from \"./auth.js\";\nimport type { VerifiedClaims } from \"./auth.js\";\nimport { RateLimiter } from \"./ratelimit.js\";\nimport { makeMemoryCache } from \"./cache.js\";\nimport { createRequestDatabase, setSchema } from \"./db.js\";\nimport type { SqlDriver } from \"./db.js\";\nimport { buildRouteTable, matchRoute } from \"./router.js\";\nimport {\n AUTHORIZE_PATH,\n SIGNATURE_HEADER,\n grantFor,\n verifySignature,\n CompletionLedger,\n type CompletionEnvelope,\n} from \"./upload.js\";\nimport type { RouteEntry } from \"./router.js\";\n\nexport { loadConfig, BootRefused } from \"./config.js\";\nexport type { EngineConfig } from \"./config.js\";\nexport { AuthVerifier, effectiveAuth } from \"./auth.js\";\nexport { RateLimiter } from \"./ratelimit.js\";\nexport { makeMemoryCache } from \"./cache.js\";\nexport { createLazyTransaction, createOps, withTables, createRequestDatabase, quoteIdent } from \"./db.js\";\nexport type { SqlDriver, SqlTx, RequestDatabase } from \"./db.js\";\nexport { buildRouteTable, matchRoute } from \"./router.js\";\nexport type { RouteEntry } from \"./router.js\";\nexport { scrubSecrets, installEgressFence, hostAllowed } from \"./fence.js\";\nexport type { EgressPolicy, ScrubResult } from \"./fence.js\";\n\n/** The `__`-prefixed request-scope seam, as re-exported by a deployed bundle. */\nexport interface RuntimeHooks {\n __runWithRuntime: typeof __runWithRuntime;\n __requestALS: typeof __requestALS;\n}\n\n/** The module singletons the engine injects, minus the two it owns itself. */\nexport type ModuleClients = Partial<\n Pick<\n RuntimeServices,\n \"Documents\" | \"Storage\" | \"Notifications\" | \"Flags\" | \"Realtime\" | \"Purchases\" | \"Secrets\"\n >\n>;\n\nexport interface CreateAppOptions {\n config: EngineConfig;\n /** `@Controller` classes. A class that collected zero routes is fatal. */\n controllers: readonly unknown[];\n /** The project's `defineSchema()` result, for the typed `.tables` surface. */\n schema?: unknown;\n /** The SQL driver. Omitted ⇒ built from `Bun.sql` when running under Bun. */\n sql?: SqlDriver;\n /** Module clients. Omitted ⇒ each corresponding singleton throws when used. */\n modules?: ModuleClients;\n /** Cache. Omitted ⇒ this process's own memory. */\n cache?: CacheClient;\n /**\n * The request-scope hooks to run handlers inside.\n *\n * MUST come from the SAME `@palbase/backend` module instance the loaded\n * controllers were bundled against. A deployed bundle inlines its own copy of\n * the SDK and re-exports these two; the engine here has its own. Two copies\n * mean two AsyncLocalStorage instances, and the store this engine sets is not\n * the store the handler's `Database` proxy reads — every service would be\n * undefined at the first call, with nothing in the logs to say why. So the\n * host passes the BUNDLE's hooks and the seam closes.\n *\n * Omitted ⇒ this module's own, which is correct only when the controllers\n * were built against this same instance (tests, a single-package project).\n */\n runtimeHooks?: RuntimeHooks;\n logger?: Pick<Console, \"info\" | \"warn\" | \"error\" | \"debug\">;\n}\n\nexport interface App {\n handle: (req: Request) => Promise<Response>;\n routes: readonly RouteEntry[];\n config: EngineConfig;\n /**\n * Run work that has no request behind it — a scheduled job — inside the same\n * request scope a handler gets, with its own transaction.\n */\n runInServiceScope: <T>(fn: () => T | Promise<T>) => Promise<T>;\n /** Close the pool and release resources. */\n shutdown: () => Promise<void>;\n}\n\nconst JSON_HEADERS = { \"content-type\": \"application/json\" } as const;\n\nfunction envelope(\n error: string,\n description: string,\n status: number,\n requestId: string,\n extra?: Record<string, unknown>,\n): Response {\n return new Response(\n JSON.stringify({ error, error_description: description, status, request_id: requestId, ...extra }),\n { status, headers: JSON_HEADERS },\n );\n}\n\n/** A module that was never configured must say so by name on first use, not\n * fail with \"Cannot read properties of undefined\". */\n/**\n * A module singleton nobody injected.\n *\n * The message names TWO causes because there are two, and pointing at only one\n * sends an operator to check a setting that is already correct. Measured on\n * 2026-08-15: a handler reaching for `Purchases` was told to set\n * MODULE_BASE_URL — which was set. Purchases is simply not part of this\n * backend, and an error that hides that costs the reader the afternoon.\n */\nfunction unavailable(name: string): never {\n throw new Error(\n `${name} is unavailable. Either this backend was started without module clients ` +\n `(set MODULE_BASE_URL and the API keys so the engine can reach the module surface), ` +\n `or ${name} is not one of the modules this backend provides.`,\n );\n}\n\nfunction stubModule(name: string): unknown {\n return new Proxy(\n {},\n {\n get: () => unavailable(name),\n apply: () => unavailable(name),\n },\n );\n}\n\nasync function defaultSqlDriver(config: EngineConfig): Promise<SqlDriver> {\n const g = globalThis as { Bun?: { SQL: new (o: { url: string; max: number }) => SqlDriver } };\n if (!g.Bun?.SQL) {\n throw new BootRefused(\n [],\n \"boot refused: no SQL driver. Running outside Bun means the driver must be supplied — \" +\n \"pass `sql` to createApp().\",\n );\n }\n return new g.Bun.SQL({ url: config.databaseUrl, max: config.poolMax });\n}\n\n/**\n * Build the app. Fails fast: the database is reached here, at boot, rather than\n * on the first request that needs it.\n */\nexport async function createApp(opts: CreateAppOptions): Promise<App> {\n const { config, controllers } = opts;\n setSchema(opts.schema ?? {});\n\n const routes = buildRouteTable(controllers);\n if (routes.length === 0) {\n throw new BootRefused([], \"boot refused: zero endpoints collected — nothing would answer.\");\n }\n\n const sql = opts.sql ?? (await defaultSqlDriver(config));\n await sql.unsafe(\"select 1\");\n\n const auth = new AuthVerifier({ jwksUrl: config.authJwksUrl, issuer: config.authIssuer });\n const limiter = new RateLimiter();\n const cache = opts.cache ?? makeMemoryCache();\n const log = opts.logger ?? console;\n const modules = opts.modules ?? {};\n const runWithRuntime = opts.runtimeHooks?.__runWithRuntime ?? __runWithRuntime;\n const requestALS = opts.runtimeHooks?.__requestALS ?? __requestALS;\n\n // The secret storage signs its internal calls with. Absent means uploads are\n // not wired, and authorize REFUSES rather than answering with a grant anybody\n // could have asked for.\n const uploadSecret = config.uploadSecret ?? \"\";\n\n /**\n * Answer \"which bucket and path does this route write to?\".\n *\n * Storage cannot know: the answer is `@Upload({bucket, pathTemplate})`, which\n * lives in the deployed bundle. Asking the process that HAS the routes is\n * what keeps the client from naming its own bucket — the request carries the\n * route it wants to use, and this decides what that means.\n */\n // One ledger per app: a completion retried against this process must find\n // its own first answer, and a process restart legitimately forgets — the\n // window a retry lives in is far shorter than an uptime.\n const completions = new CompletionLedger();\n\n /**\n * The service bundle a scope binds, built around ONE request-scoped database.\n *\n * Extracted so the request path and the job path cannot drift: a second copy\n * of this object is a second definition of what a handler can reach, and the\n * one that goes stale is always the one nobody is looking at.\n */\n function buildServices(db: ReturnType<typeof createRequestDatabase>): RuntimeServices {\n return {\n Database: db.client,\n Cache: cache,\n Log: log,\n Documents: modules.Documents ?? stubModule(\"Documents\"),\n Storage: modules.Storage ?? stubModule(\"Storage\"),\n Notifications: modules.Notifications ?? stubModule(\"Notifications\"),\n Flags: modules.Flags ?? stubModule(\"Flags\"),\n Realtime: modules.Realtime ?? stubModule(\"Realtime\"),\n Purchases: modules.Purchases ?? stubModule(\"Purchases\"),\n // Named, never undefined. A backend started without a secrets client\n // that returned `undefined` here would fail inside the handler as\n // \"Cannot read properties of undefined\", which says nothing about what\n // to configure — the stub says the name and the variable.\n Secrets: modules.Secrets ?? stubModule(\"Secrets\"),\n } as unknown as RuntimeServices;\n }\n\n /**\n * Run `fn` as the system, with no request behind it.\n *\n * Scheduled jobs need exactly what a handler needs — Database, Log,\n * Notifications, resolved out of the request scope — but there is no request\n * to take an identity from. So the claims are EMPTY: a job is nobody, and\n * `Database` here satisfies no owner-scoped RLS policy. That is why a job\n * reaches for `Database.asService()`, and why this does not quietly hand it\n * service_role by default.\n *\n * The transaction settles the same way a request's does: commit on return,\n * rollback on throw. A job that fails halfway leaves nothing behind that the\n * next run has to reason about.\n */\n async function runInServiceScope<T>(fn: () => T | Promise<T>): Promise<T> {\n const db = createRequestDatabase(sql, {\n role: config.dbRole,\n serviceRole: config.dbServiceRole,\n claimsJson: \"{}\",\n });\n try {\n const out = await runWithRuntime(buildServices(db), fn as () => Promise<T>);\n await db.commit();\n return out;\n } catch (err) {\n await db.rollback(err);\n throw err;\n }\n }\n\n async function handleAuthorize(req: Request, requestId: string): Promise<Response> {\n if (uploadSecret === \"\" ||\n !verifySignature(req.headers.get(SIGNATURE_HEADER) ?? \"\", uploadSecret)) {\n return envelope(\"unauthorized\", \"This endpoint is not callable directly\", 401, requestId);\n }\n const body = (await req.json().catch(() => null)) as {\n method?: string;\n path?: string;\n userId?: string | null;\n uploadId?: string;\n filename?: string;\n } | null;\n if (!body?.path || !body.uploadId) {\n return envelope(\"bad_request\", \"authorize needs a path and an uploadId\", 400, requestId);\n }\n const target = matchRoute(routes, body.method ?? \"POST\", body.path);\n\n // THE AUTH DECISION HAPPENS HERE, BEFORE A SINGLE BYTE IS ACCEPTED.\n //\n // Storage asks this question precisely so it can refuse early: without it,\n // an anonymous caller could push a file at a route that requires a user,\n // have it written and its variants rendered, and only then be turned away\n // by the completion — the bytes were still accepted, and the work still\n // done, once per attempt.\n //\n // The credential is the caller's own, forwarded by storage, and it is\n // verified HERE rather than trusted: the userId that ends up in the path\n // template comes from these claims and from nothing else, so neither the\n // client nor storage can name a folder that belongs to somebody else.\n const spec = effectiveAuth(target?.entry.meta.options?.auth, target?.entry.controllerAuth);\n const callerClaims = await auth.verify(req.headers.get(\"authorization\"));\n if (spec.required && !callerClaims) {\n return envelope(\"unauthorized\", \"A valid access token is required\", 401, requestId);\n }\n if (callerClaims && spec.role && callerClaims.role !== spec.role) {\n return envelope(\"forbidden\", `This endpoint requires the \"${spec.role}\" role`, 403, requestId);\n }\n\n const grant = grantFor(target?.entry, {\n userId: typeof callerClaims?.sub === \"string\" ? callerClaims.sub : null,\n uploadId: body.uploadId,\n filename: body.filename,\n });\n if (!grant) {\n // A route with no @Upload never offered to accept a file. Refusing by\n // NAME rather than 404 so an operator reading storage's log learns which\n // route was asked for.\n return envelope(\"not_an_upload_route\",\n `${body.method ?? \"POST\"} ${body.path} does not declare @Upload`, 400, requestId);\n }\n return new Response(JSON.stringify(grant), { status: 200, headers: JSON_HEADERS });\n }\n\n async function handle(req: Request): Promise<Response> {\n const requestId = `req_${crypto.randomUUID()}`;\n const url = new URL(req.url);\n\n // ── storage's two internal calls, before ordinary routing ───────────────\n //\n // They are not the tenant's routes and must not be reachable as one: an\n // app that declared `POST /__palbase/upload/authorize` would otherwise\n // shadow the mechanism that decides where uploads land.\n if (url.pathname === AUTHORIZE_PATH) {\n return handleAuthorize(req, requestId);\n }\n\n const hit = matchRoute(routes, req.method, url.pathname);\n if (!hit) return envelope(\"not_found\", \"No route matches this method and path\", 404, requestId);\n const { meta } = hit.entry;\n\n // ── auth ────────────────────────────────────────────────────────────────\n const spec = effectiveAuth(meta.options?.auth, hit.entry.controllerAuth);\n const claims: VerifiedClaims | null = await auth.verify(req.headers.get(\"authorization\"));\n if (spec.required && !claims) {\n return envelope(\"unauthorized\", \"A valid access token is required\", 401, requestId);\n }\n const userId = typeof claims?.sub === \"string\" ? claims.sub : undefined;\n if (claims && spec.role && claims.role !== spec.role) {\n return envelope(\"forbidden\", `This endpoint requires the \"${spec.role}\" role`, 403, requestId);\n }\n if (claims && spec.verifiedEmail && claims.email_verified !== true) {\n return envelope(\"email_not_verified\", \"A verified email address is required\", 403, requestId);\n }\n\n // ── rate limit ──────────────────────────────────────────────────────────\n const retryAfter = limiter.check(\n meta.options?.rateLimit,\n RateLimiter.key(hit.entry.id, userId, req.headers),\n Date.now(),\n );\n if (retryAfter !== null) {\n return new Response(\n JSON.stringify({\n error: \"too_many_requests\",\n error_description: \"Rate limit exceeded for this endpoint\",\n status: 429,\n request_id: requestId,\n }),\n { status: 429, headers: { ...JSON_HEADERS, \"retry-after\": String(retryAfter) } },\n );\n }\n\n // ── arguments ───────────────────────────────────────────────────────────\n // Set when this request IS a completion, so its answer can be remembered.\n let completionUploadId: string | null = null;\n\n const args: unknown[] = [];\n let parsedBody: unknown;\n let bodyRead = false;\n for (const p of meta.params ?? []) {\n switch (p.kind) {\n case \"body\": {\n if (!bodyRead) {\n parsedBody = await req.json().catch(() => ({}));\n bodyRead = true;\n }\n const r = p.schema!.safeParse(parsedBody);\n if (!r.success) {\n return envelope(\"bad_request\", \"Request body failed validation\", 400, requestId, {\n fields: r.error.issues.map((i) => ({ field: i.path.join(\".\"), message: i.message })),\n });\n }\n args[p.index] = r.data;\n break;\n }\n case \"query\": {\n const r = p.schema!.safeParse(Object.fromEntries(url.searchParams));\n if (!r.success) {\n return envelope(\"bad_request\", \"Query parameters failed validation\", 400, requestId, {\n fields: r.error.issues.map((i) => ({ field: i.path.join(\".\"), message: i.message })),\n });\n }\n args[p.index] = r.data;\n break;\n }\n case \"param\":\n args[p.index] = hit.params[p.name!];\n break;\n case \"headers\":\n args[p.index] = Object.fromEntries(req.headers);\n break;\n case \"user\":\n case \"optionalUser\":\n args[p.index] = claims\n ? {\n id: userId,\n email: claims.email,\n role: claims.role,\n emailVerified: claims.email_verified === true,\n metadata: (claims.metadata as Record<string, unknown>) ?? {},\n }\n : null;\n break;\n case \"uploadedObject\": {\n // An @Upload route runs as a COMPLETION handler: the bytes went to\n // storage, and what arrives here is what storage recorded about them.\n // The call must be signed, or anyone who knows the route path could\n // invent an upload that never happened and make the handler write a\n // row for it.\n if (uploadSecret === \"\" ||\n !verifySignature(req.headers.get(SIGNATURE_HEADER) ?? \"\", uploadSecret)) {\n return envelope(\"unauthorized\",\n \"This endpoint accepts uploads through storage, not directly\", 401, requestId);\n }\n if (!bodyRead) {\n parsedBody = await req.json().catch(() => ({}));\n bodyRead = true;\n }\n const envelopeIn = parsedBody as CompletionEnvelope | null;\n if (!envelopeIn?.uploadedObject) {\n return envelope(\"bad_request\", \"the completion call carried no uploaded object\", 400, requestId);\n }\n // A RETRY MUST NOT RUN THE HANDLER AGAIN.\n //\n // Storage retries a completion it did not hear back from, and the\n // handler is a mutation: run twice, one uploaded photo becomes two\n // posts. The first answer is replayed instead, which is what makes\n // the retry invisible to the client waiting on the other end.\n const uploadId = envelopeIn.uploadedObject.uploadId;\n if (typeof uploadId === \"string\" && uploadId !== \"\") {\n const already = completions.recall(uploadId);\n if (already) {\n return new Response(already.body, {\n status: already.status,\n headers: already.contentType ? { \"content-type\": already.contentType } : undefined,\n });\n }\n completionUploadId = uploadId;\n }\n args[p.index] = envelopeIn.uploadedObject;\n // The author's @Body sees THEIR payload, not the envelope around it.\n parsedBody = envelopeIn.body ?? {};\n break;\n }\n case \"requestId\":\n args[p.index] = requestId;\n break;\n case \"traceId\":\n args[p.index] = requestId;\n break;\n case \"req\":\n args[p.index] = req;\n break;\n default:\n args[p.index] = undefined;\n }\n }\n\n // ── dispatch, inside the request's transaction(s) ───────────────────────\n //\n // One for the caller's identity, and — only if the handler asks for it —\n // one more for `Database.asService()`. Both settle here, together.\n const db = createRequestDatabase(sql, {\n role: config.dbRole,\n serviceRole: config.dbServiceRole,\n claimsJson: JSON.stringify(claims ?? {}),\n });\n try {\n const services = buildServices(db);\n\n const result = await runWithRuntime(services, () => {\n // The ALS box carries the caller's identity beside the services; Flags'\n // auto-bind reads it, and so does anything else that needs a\n // server-owned user id rather than one the caller supplied.\n const box = requestALS.getStore();\n if (box) {\n box.userId = userId ?? null;\n box.requestId = requestId;\n box.idempotencyKey = req.headers.get(\"idempotency-key\");\n }\n const method = hit.entry.instance[meta.fnName];\n if (typeof method !== \"function\") {\n throw new Error(\n `route ${hit.entry.id} names method ${meta.fnName}, which the controller does not define`,\n );\n }\n return method.apply(hit.entry.instance, args);\n });\n await db.commit();\n\n if (meta.returnSchema) {\n const v = meta.returnSchema.safeParse(result);\n if (!v.success) {\n log.error(`[engine] ${hit.entry.id} returned a value its declared type rejects`, v.error.issues);\n return envelope(\n \"output_invalid\",\n \"The handler returned a value its declared return type rejects\",\n 500,\n requestId,\n );\n }\n }\n if (result === undefined || result === null) {\n if (completionUploadId) {\n completions.remember(completionUploadId, { status: 204, body: null, contentType: null });\n }\n return new Response(null, { status: 204 });\n }\n const payload = JSON.stringify(result);\n if (completionUploadId) {\n completions.remember(completionUploadId, {\n status: 200,\n body: payload,\n contentType: JSON_HEADERS[\"content-type\"] ?? \"application/json\",\n });\n }\n return new Response(payload, { status: 200, headers: JSON_HEADERS });\n } catch (err) {\n // The handler threw after writing: nothing it wrote may survive.\n await db.rollback(err);\n // Branded, not `instanceof`: the tenant's bundle carries its own copy of\n // this SDK, so class identity does not survive the hop from the handler\n // to this catch. See HTTP_ERROR_BRAND.\n if (isHttpError(err)) {\n return envelope(\n err.error,\n err.errorDescription,\n err.status,\n requestId,\n err.data !== undefined ? { data: err.data } : undefined,\n );\n }\n log.error(`[engine] unhandled error in ${hit.entry.id}`, err);\n return envelope(\"internal_error\", \"The request could not be completed\", 500, requestId);\n }\n }\n\n return {\n handle,\n routes,\n config,\n runInServiceScope,\n async shutdown() {\n const closable = sql as { close?: () => Promise<void> | void; end?: () => Promise<void> | void };\n await closable.close?.();\n await closable.end?.();\n },\n };\n}\n","// `@Controller(basePath, options?)` — the class decorator that marks a class as\n// a Palbase backend controller. It stamps a non-enumerable `__palbase`\n// discriminant + the resolved controller metadata onto the class so the\n// deploy/dispatch pipeline (and `isController`/`resolveController`) can detect\n// and read it without `reflect-metadata`.\nimport type { AuthSpec } from \"../endpoint.js\";\nimport { getRoutes } from \"./registry.js\";\n\n/** The controller metadata stamped onto a `@Controller`-decorated class. The\n * default export of a `controllers/*.controller.ts` file resolves to this via\n * {@link resolveController}. */\nexport interface ControllerMeta {\n /** Discriminant the runtime + tooling read. */\n readonly __palbase: \"controller\";\n /** The base path every route in this controller mounts under (e.g. \"/todos\"). */\n basePath: string;\n /** Controller-level default auth, applied to routes that don't set their own\n * (`@Get(\"/x\", { auth })` overrides this). `undefined` ⇒ secure-by-default. */\n defaultAuth?: AuthSpec;\n}\n\n/** Options accepted by `@Controller`. */\nexport interface ControllerOptions {\n /** Default auth for ALL routes in this controller (route-level overrides). */\n auth?: AuthSpec;\n}\n\n/** Symbol the controller metadata is stamped under. Symbol-keyed (not a string\n * property) so it never collides with an authored member and stays off the\n * structural surface. */\nexport const CONTROLLER_META: unique symbol = Symbol.for(\"palbase.backend.controllerMeta\");\n\n/**\n * Every class `@Controller` has decorated, in decoration order.\n *\n * This is what lets a controller file need no export at all: importing the file\n * runs the decorator, the decorator records the class here, and the runtime\n * reads the list. Without it the only handle on a class is its export name, so\n * every controller had to be exported AND named in a generated entry — the\n * ceremony NestJS still charges (`export class` PLUS\n * `@Module({controllers:[…]})`).\n *\n * Keyed on a well-known Symbol against globalThis rather than held in a module\n * variable, because a deployed bundle inlines its own copy of this package: two\n * copies would keep two lists, and the runtime would read the empty one. The\n * same hazard `runtimeHooks` exists for, closed the same way — one shared slot.\n */\nconst REGISTRY: unique symbol = Symbol.for(\"palbase.backend.allControllers\") as never;\n\nfunction registry(): unknown[] {\n const g = globalThis as unknown as Record<symbol, unknown[] | undefined>;\n const existing = g[REGISTRY];\n if (existing) return existing;\n const fresh: unknown[] = [];\n g[REGISTRY] = fresh;\n return fresh;\n}\n\n/**\n * The controller classes this process has loaded, in decoration order.\n *\n * Decoration order is import order, which the bundler fixes by sorting the\n * files it emits imports for — so two builds of one tree produce the same\n * route table, and route precedence is not a function of module-resolution\n * accidents.\n */\nexport function getRegisteredControllers(): readonly unknown[] {\n return registry().slice();\n}\n\n/** Empty the registry. For tests, which load controllers repeatedly. */\nexport function __resetRegisteredControllers(): void {\n registry().length = 0;\n}\n\n/** A class carrying the stamped controller metadata + discriminant. */\ninterface ControllerCarrier {\n __palbase?: \"controller\";\n [CONTROLLER_META]?: ControllerMeta;\n}\n\n/** The one path segment the platform owns. The isolate matches\n * `^/webhooks/([^/]+)$` on the raw request path BEFORE controller dispatch, so\n * anything a controller resolves to under it answers `404 webhook_not_found`\n * and never runs. */\nconst RESERVED_FIRST_SEGMENT = \"webhooks\";\n\n/**\n * Throw if `path` resolves under the reserved segment. Segments are compared the\n * way the isolate compares them — `split(\"/\").filter(Boolean)` — NOT by string\n * prefix, because empty segments collapse there: `@Controller(\"/\")` +\n * `@Post(\"/webhooks/x\")` composes to `//webhooks/x`, which the isolate serves as\n * `/webhooks/x`. A prefix check reads that as safe; the segment check does not.\n * `/webhooksy` stays allowed for the same reason — it is a different segment.\n *\n * Every verb is refused, not just the POST the isolate currently intercepts: the\n * reservation is of the URL namespace, so a `@Get(\"/webhooks/x\")` that happens\n * to work today would be silently shadowed the moment the isolate's method gate\n * widens. Refusing at build is recoverable; discovering it as a 404 is not.\n */\nfunction assertNotReserved(path: string, subject: string): void {\n const [first] = path.split(\"/\").filter(Boolean);\n if (first === RESERVED_FIRST_SEGMENT) {\n throw new Error(\n `${subject} resolves under the reserved /${RESERVED_FIRST_SEGMENT} path — ` +\n \"inbound webhooks are served there and would shadow this route\",\n );\n }\n}\n\n/**\n * Mark a class as a Palbase backend controller. `basePath` is the mount path\n * for every route the class declares; `options.auth` sets the controller-level\n * default auth (a route's own `auth` overrides it; absent ⇒ secure-by-default).\n *\n * @example\n * \\@Controller(\"/todos\", { auth: false })\n * export class TodosController {\n * \\@Get(\"\") list(\\@QueryParams(ListTodosQuery) q: ListTodosQuery): TodoSchema[] { … }\n * }\n */\nexport function Controller(basePath: string, options: ControllerOptions = {}) {\n return function <T extends abstract new (...args: never[]) => object>(ctor: T): T {\n // /webhooks/* belongs to the platform: the isolate matches the inbound\n // webhook route before controller dispatch, so a controller mounted here\n // would never receive a request. Silent shadowing is the failure mode this\n // whole change exists to remove, so refuse it at build.\n //\n // The COMPOSED path is what gets shadowed, not the base path. `@Controller(\"\")`\n // and `@Controller(\"/\")` both pass a base-path-only check while a\n // `@Post(\"/webhooks/stripe\")` inside them resolves to exactly the path the\n // isolate intercepts. Method decorators run BEFORE the class decorator (TS\n // evaluates members first), so every route this class declares is already in\n // the registry here — which is why the composed check can live at this one\n // seam instead of on the dispatch read path. The `@Controller(\"\") +\n // @Post(\"/webhooks/stripe\")` test is the lock on that ordering: if it ever\n // stopped holding, that test goes red.\n assertNotReserved(basePath, `@Controller(\"${basePath}\")`);\n for (const route of getRoutes(ctor)) {\n assertNotReserved(\n `${basePath}${route.subpath}`,\n `@${route.method}(\"${route.subpath}\") in @Controller(\"${basePath}\")`,\n );\n }\n\n const carrier = ctor as unknown as ControllerCarrier;\n const meta: ControllerMeta = {\n __palbase: \"controller\",\n basePath,\n ...(options.auth !== undefined ? { defaultAuth: options.auth } : {}),\n };\n // Non-enumerable so it doesn't leak onto instances / structural checks.\n Object.defineProperty(carrier, CONTROLLER_META, {\n value: meta,\n enumerable: false,\n configurable: true,\n writable: false,\n });\n // The bare `__palbase` discriminant is the cheap detection marker the\n // runtime/extractor checks; keep it readable but non-enumerable.\n Object.defineProperty(carrier, \"__palbase\", {\n value: \"controller\",\n enumerable: false,\n configurable: true,\n writable: false,\n });\n // Record it, so importing the file is enough and exporting is optional.\n // Guarded against a double-decoration re-entering the same class twice.\n const all = registry();\n if (!all.includes(ctor)) all.push(ctor);\n return ctor;\n };\n}\n\n/** True when `value` is a `@Controller`-decorated class (cheap discriminant\n * check). Accepts the class constructor (the default export of a controller\n * file). */\nexport function isController(value: unknown): boolean {\n if (typeof value !== \"function\" && (typeof value !== \"object\" || value === null)) {\n return false;\n }\n const carrier = value as ControllerCarrier;\n return carrier.__palbase === \"controller\" && carrier[CONTROLLER_META] !== undefined;\n}\n\n/** Read the resolved controller metadata off a `@Controller`-decorated class.\n * Throws if the class was not decorated — callers should gate with\n * {@link isController} first (the loader does). */\nexport function resolveController(ctor: unknown): ControllerMeta {\n if (typeof ctor !== \"function\" && (typeof ctor !== \"object\" || ctor === null)) {\n throw new TypeError(\"resolveController: value is not a class\");\n }\n const meta = (ctor as ControllerCarrier)[CONTROLLER_META];\n if (!meta) {\n throw new TypeError(\n \"resolveController: class is not a @Controller — every controller file must `export default` a @Controller-decorated class\",\n );\n }\n return meta;\n}\n"],"mappings":"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","names":["resolveTx"]}
|
|
1
|
+
{"version":3,"sources":["../../src/bin/palbase-backend.ts","../../src/runtime.ts","../../src/db/tx-plan.ts","../../src/errors.ts","../../src/engine/config.ts","../../src/engine/auth.ts","../../src/engine/ratelimit.ts","../../src/engine/cache.ts","../../src/engine/db.ts","../../src/decorators/registry.ts","../../src/engine/router.ts","../../src/engine/upload.ts","../../src/engine/index.ts","../../src/decorators/controller.ts"],"sourcesContent":["#!/usr/bin/env bun\n/**\n * palbase-backend — run this project's backend.\n *\n * npm run dev → palbase-backend dev (reloads on change)\n * npm start → palbase-backend serve\n *\n * There is no scaffolding step and no server file to write. The project IS the\n * backend: every `controllers/*.controller.ts` is imported, which is what\n * registers it, and the engine is built around whatever registered.\n *\n * It is the same engine the deployed runtime builds — not a development\n * stand-in. A dev server that is a different program from the production one is\n * a source of \"works locally\" reports, and this one has no second implementation\n * to disagree with.\n */\nimport { readdir, stat } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport { createApp, loadConfig, BootRefused } from \"../engine/index.js\";\nimport { getRegisteredControllers } from \"../decorators/controller.js\";\n\nconst USAGE = `palbase-backend — run this project's backend\n\n palbase-backend serve start the backend\n palbase-backend dev start it and reload on change\n palbase-backend routes print the route table and exit\n\nConfiguration comes from the environment (a .env beside package.json is read):\n\n DATABASE_URL required — the stack's Postgres\n AUTH_JWKS_URL required — where your stack publishes its signing keys\n MODULE_BASE_URL where Documents/Storage/Notifications/Flags/Realtime live\n PALBASE_ANON_KEY publishable key, sent on module calls\n PALBASE_SERVICE_ROLE_KEY secret key, for privileged module calls\n PORT default 3000\n`;\n\nfunction die(message: string): never {\n console.error(message);\n process.exit(1);\n}\n\n/** Read a `.env` beside the project, without adding a dependency for it. */\nasync function loadDotEnv(root: string): Promise<void> {\n const file = Bun.file(join(root, \".env\"));\n if (!(await file.exists())) return;\n for (const raw of (await file.text()).split(\"\\n\")) {\n const line = raw.trim();\n if (!line || line.startsWith(\"#\")) continue;\n const eq = line.indexOf(\"=\");\n if (eq < 1) continue;\n const key = line.slice(0, eq).trim();\n // The environment wins: an exported value is the operator being explicit,\n // and a file quietly overriding it is how a \"why is it still pointing at\n // the old database\" hour begins.\n if (process.env[key] !== undefined) continue;\n let value = line.slice(eq + 1).trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n process.env[key] = value;\n }\n}\n\n/** Every `*.controller.ts` under `controllers/`, sorted, recursively. */\nasync function findControllers(root: string): Promise<string[]> {\n const dir = join(root, \"controllers\");\n try {\n if (!(await stat(dir)).isDirectory()) return [];\n } catch {\n return [];\n }\n const out: string[] = [];\n const walk = async (d: string): Promise<void> => {\n for (const entry of await readdir(d, { withFileTypes: true })) {\n const full = join(d, entry.name);\n if (entry.isDirectory()) await walk(full);\n else if (/\\.controller\\.(ts|js|mts|mjs)$/.test(entry.name)) out.push(full);\n }\n };\n await walk(dir);\n // Sorted so route precedence is the same on every machine.\n return out.sort();\n}\n\nasync function importSchema(root: string): Promise<unknown> {\n for (const candidate of [\"db/schema.ts\", \"db/schema.js\"]) {\n const path = join(root, candidate);\n try {\n await stat(path);\n return (await import(pathToFileURL(path).href)).default;\n } catch {\n // Not every project declares a schema; the typed `.tables` surface is\n // simply absent then.\n }\n }\n return undefined;\n}\n\nasync function main(): Promise<void> {\n const command = process.argv[2] ?? \"serve\";\n if (command === \"--help\" || command === \"-h\" || command === \"help\") {\n console.log(USAGE);\n return;\n }\n if (![\"serve\", \"dev\", \"routes\"].includes(command)) {\n die(`palbase-backend: unknown command \"${command}\".\\n\\n${USAGE}`);\n }\n if (typeof Bun === \"undefined\") {\n die(\n \"palbase-backend needs Bun: the engine serves `fetch` natively and opens its own\\n\" +\n \"Postgres pool through Bun.sql. Install it from https://bun.sh, then re-run.\",\n );\n }\n\n // `dev` is `serve` under Bun's watcher. Re-exec rather than reimplement:\n // one code path serves, and the reload is the runtime's job, not ours.\n if (command === \"dev\" && !process.env.PALBASE_WATCHING) {\n const self = Bun.fileURLToPath(import.meta.url);\n const child = Bun.spawn([\"bun\", \"--watch\", self, \"serve\"], {\n stdio: [\"inherit\", \"inherit\", \"inherit\"],\n env: { ...process.env, PALBASE_WATCHING: \"1\" },\n });\n process.exit(await child.exited);\n }\n\n const root = resolve(process.env.PALBASE_PROJECT_DIR ?? process.cwd());\n await loadDotEnv(root);\n\n const files = await findControllers(root);\n if (files.length === 0) {\n die(\n `palbase-backend: no controllers found under ${join(root, \"controllers\")}.\\n` +\n `A backend is its controllers — add one and run again:\\n\\n` +\n ` // controllers/hello.controller.ts\\n` +\n ` import { Controller, Get } from \"@palbase/backend\";\\n` +\n ` @Controller(\"/hello\")\\n` +\n ` class HelloController {\\n` +\n ` @Get(\"\") hi(): Promise<{ ok: boolean }> { return Promise.resolve({ ok: true }); }\\n` +\n ` }\\n`,\n );\n }\n\n // Importing IS the registration — the decorator records each class as it runs.\n for (const file of files) await import(pathToFileURL(file).href);\n const controllers = getRegisteredControllers();\n if (controllers.length === 0) {\n die(\n `palbase-backend: ${files.length} controller file(s) loaded but none registered.\\n` +\n `Every one of them is missing its @Controller decorator, or the files were\\n` +\n `compiled with decorators stripped. Nothing would answer, so this is fatal.`,\n );\n }\n\n let config;\n try {\n config = loadConfig(process.env as Record<string, string | undefined>);\n } catch (e) {\n if (e instanceof BootRefused) {\n die(\n `${e.message}\\n\\n` +\n `Put them in a .env beside package.json, or export them. A local stack\\n` +\n `(docker compose up) publishes both.`,\n );\n }\n throw e;\n }\n\n const app = await createApp({ config, controllers, schema: await importSchema(root) });\n\n if (command === \"routes\") {\n for (const route of app.routes) console.log(route.id);\n await app.shutdown();\n return;\n }\n\n Bun.serve({ port: config.port, idleTimeout: 60, fetch: app.handle });\n console.log(`palbase-backend listening on http://localhost:${config.port}`);\n console.log(` ${app.routes.length} endpoint(s) from ${files.length} controller file(s)`);\n for (const route of app.routes) console.log(` ${route.id}`);\n\n for (const signal of [\"SIGTERM\", \"SIGINT\"] as const) {\n process.on(signal, () => {\n void app.shutdown().finally(() => process.exit(0));\n });\n }\n}\n\n// Not a top-level await: this file is also emitted in a CommonJS flavour, where\n// one is a build error. The rejection handler is the point either way — an\n// unhandled one exits 0 on some runtimes, which would report a dead backend as\n// a successful start.\nmain().catch((e: unknown) => {\n console.error(e instanceof Error ? e.message : e);\n process.exit(1);\n});\n","/**\n * runtime.ts — request-scoped service singletons.\n *\n * The backend SDK no longer threads a `ctx` god-object through every handler.\n * Instead, controller methods import PascalCase service singletons directly:\n *\n * import { Controller, Post, Body, Database } from \"@palbase/backend\";\n *\n * \\@Controller(\"/todos\")\n * export default class TodosController {\n * \\@Post(\"\") create(\\@Body(CreateTodoBody) body: CreateTodoBody): unknown {\n * return Database.insert(\"todos\", { title: body.title });\n * }\n * }\n *\n * The singletons are thin Proxies. Every property access forwards to the live\n * client for the CURRENT request scope, resolved through {@link __getRuntime}.\n *\n * # Request-scope resolution (persistent app-server)\n *\n * The runtime is a long-running Node process that serves many concurrent\n * requests on one event loop (NOT a fresh subprocess per request). A single\n * module-global slot would let one in-flight request's services bleed into\n * another's. So the services are carried in an {@link AsyncLocalStorage} store\n * ({@link __requestALS}) that the runtime sets per request with\n * {@link __runWithRuntime}; every async continuation of that request reads its\n * own store. `__getRuntime` reads the ALS store first; the module-global slot\n * (set by {@link __setRuntime}) is only a fallback for callers that run OUTSIDE\n * an ALS scope (dev-server, unit tests, the legacy single-shot path). Because\n * each `br-<ref>` pod is single-tenant, there is no cross-tenant leakage; the\n * ALS store is what prevents cross-REQUEST leakage within the shared process.\n *\n * The seam that makes `import { Database } from \"@palbase/backend\"` resolve to\n * the runtime-injected client: `@palbase/backend` is marked esbuild-EXTERNAL\n * when the tenant bundle is built, and the package is installed globally in the\n * pod (NODE_PATH=/usr/local/lib/node_modules). So worker.js's\n * `require('@palbase/backend')` and the bundle's `import` resolve to ONE shared\n * module instance — the ALS store and `__setRuntime` slot on that instance are\n * visible to the singletons the bundle imported.\n */\n\nimport type { Buckets, BucketTypes } from \"./db/env.js\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type {\n DBClient,\n DBOps,\n CacheClient,\n Logger,\n PalbaseDocsClient,\n SecretsService,\n} from \"./endpoint.js\";\nimport type {\n PalbaseStorageClient,\n PalbaseBucketClient,\n PalbaseNotificationsClient,\n PalbaseFlagsClient,\n PalbaseFlagsServiceClient,\n PalbaseFlagContext,\n PalbaseFlagVariant,\n PalbaseFlag,\n PalbaseFlagValue,\n PalbaseSetOverrideResult,\n PalbaseRealtimeClient,\n} from \"./clients.js\";\nimport type { PalbaseResult } from \"./endpoint.js\";\nimport type {\n EnvTypedDatabase,\n EnvServiceDatabase,\n EnvTables,\n TxPlan,\n TxTables,\n} from \"./db/typed-db.js\";\nimport type { Materialized } from \"./db/tx-plan.js\";\nimport { TxPlanBuilder, runTxPlan } from \"./db/tx-plan.js\";\nimport type { PurchasesService } from \"./purchases/service.js\";\n\n/** The set of live clients the runtime injects per request scope.\n *\n * Realtime is BROADCAST-ONLY here (a stateless handler can push an event but\n * cannot hold a subscription socket — `subscribe()` lives on the client SDK).\n *\n * EXCLUDED on purpose: Functions, Links, Analytics, Auth. They are not\n * exposed as backend handler singletons (auth lives on the client SDK; the rest\n * are out of scope for backend endpoints). */\nexport interface RuntimeServices {\n Database: DBClient;\n Secrets: SecretsService;\n Documents: PalbaseDocsClient;\n Storage: PalbaseStorageClient;\n Cache: CacheClient;\n Log: Logger;\n Notifications: PalbaseNotificationsClient;\n Flags: PalbaseFlagsClient;\n Realtime: PalbaseRealtimeClient;\n Purchases: PurchasesService;\n}\n\n/**\n * The per-request ALS box.\n *\n * `runtime` is the service bundle. `userId` is the request's authenticated user\n * id, written by the runtime immediately after it assembles the request object\n * (worker.js: `requestALS.getStore().userId = pbReq.user?.id || null`) and\n * `null` on an anonymous request. It was already being written there for the\n * Flags client's auto-bind; declaring it here makes the existing contract typed\n * instead of implicit, which is what lets `currentSubjectId()` read a\n * server-owned identity rather than trusting anything the caller sent.\n */\nexport interface RequestStore {\n runtime: RuntimeServices;\n userId?: string | null;\n /** This request's id (`req_…`), written by the runtime. Used as the spend\n * idempotency scope when the caller supplied no `Idempotency-Key`. */\n requestId?: string;\n /** The caller's `Idempotency-Key` header, or `null` when absent. What makes a\n * client's retry replay its first result instead of charging twice. */\n idempotencyKey?: string | null;\n}\n\n/**\n * Per-request store. The persistent runtime runs each request inside\n * {@link __runWithRuntime}, so every async continuation of that request reads\n * its OWN `runtime` (and any other request-scoped fields the runtime adds).\n *\n * Exported with a `__` prefix so the runtime (worker.js) shares the SAME ALS\n * instance across the one module instance — two ALS instances would silently\n * not see each other's stores. NOT part of the public author-facing API.\n */\nexport const __requestALS = new AsyncLocalStorage<RequestStore>();\n\n/** Process-global fallback slot. Used only OUTSIDE an ALS scope (dev-server,\n * unit tests, legacy single-shot worker). Inside the persistent server every\n * request runs in {@link __requestALS}, which takes precedence. */\nlet runtime: RuntimeServices | null = null;\n\n/** Install the live clients in the process-global fallback slot.\n *\n * Persistent-server requests should use {@link __runWithRuntime} instead; this\n * remains for dev-server / tests / the legacy single-shot path that run without\n * an ALS scope. NOT part of the public author-facing API. */\nexport function __setRuntime(services: RuntimeServices): void {\n runtime = services;\n}\n\n/** Run `fn` with `services` bound as the request-scoped runtime.\n *\n * The persistent worker calls this once per request so concurrent requests\n * never share a services slot. NOT part of the public author-facing API. */\nexport function __runWithRuntime<T>(services: RuntimeServices, fn: () => T): T {\n return __requestALS.run({ runtime: services }, fn);\n}\n\n/** Read the live clients, throwing if accessed outside a request scope.\n *\n * Resolves the ALS store first (persistent server, per-request), then the\n * process-global fallback (dev-server / tests). NOT part of the public\n * author-facing API — used by the runtime and the singleton Proxies. */\nexport function __getRuntime(): RuntimeServices {\n const scoped = __requestALS.getStore();\n if (scoped) return scoped.runtime;\n if (runtime === null) {\n throw new Error(\n \"Palbase services accessed outside a request scope. The Database/Documents/… \" +\n \"singletons are only available inside an endpoint handler (or after the \" +\n \"runtime has called __runWithRuntime / __setRuntime).\",\n );\n }\n return runtime;\n}\n\n/**\n * Build a Proxy singleton that forwards every property access to the live\n * client named `key` on the current runtime.\n *\n * The single `as RuntimeServices[K]` is the only contained cast in the surface:\n * `Reflect.get` on a typed object returns `unknown` for a `string | symbol`\n * key, but `prop` is constrained to keys of the client interface at the call\n * sites (the exported singletons are typed below), so the forward is sound.\n */\nfunction makeServiceProxy<K extends keyof RuntimeServices>(key: K): RuntimeServices[K] {\n const handler: ProxyHandler<RuntimeServices[K]> = {\n get(_target, prop, receiver) {\n const client = __getRuntime()[key];\n const value = Reflect.get(client as object, prop, receiver) as unknown;\n // Bind methods to their owning client so `this` stays correct when the\n // author destructures or calls `Database.query(...)`.\n return typeof value === \"function\" ? value.bind(client) : value;\n },\n };\n // The Proxy target is irrelevant (all access goes through `get`); the cast\n // names the surface type the singleton presents to authors.\n return new Proxy({} as RuntimeServices[K], handler);\n}\n\n/**\n * Build the `.tables` accessor for the top-level `Database`. Each\n * `tables.<name>` access returns a small object that forwards the five CRUD ops\n * to the underlying client using `name` as the string table identifier. The\n * shapes are typed against the generated `palbase-env.d.ts` (`EnvTables`); at\n * runtime they are plain string-keyed calls, so no schema value is needed here.\n *\n * Returns `EnvTables` — TS cannot infer the mapped type through the Proxy, so\n * a single structural narrowing names the surface (the proxy returns a\n * correctly-shaped accessor for whatever string member is read).\n */\nfunction makeTablesAccessor(ops: () => DBOps): EnvTables {\n const tablesProxy = new Proxy(\n {},\n {\n get(_t, prop: string | symbol) {\n if (typeof prop !== \"string\") return undefined;\n const name = prop;\n return {\n insert: (data: Record<string, unknown>) => ops().insert(name, data),\n update: (id: string, data: Record<string, unknown>) => ops().update(name, id, data),\n delete: (id: string) => ops().delete(name, id),\n findById: (id: string) => ops().findById(name, id),\n findMany: (query?: Record<string, unknown>) => ops().findMany(name, query),\n search: (params?: Record<string, unknown>) => ops().search(name, params),\n };\n },\n },\n );\n return tablesProxy as EnvTables;\n}\n\n/** The raw string-keyed `DBClient` for the current request scope. */\nconst rawDatabase: DBClient = makeServiceProxy(\"Database\");\n\n/**\n * Wrap a raw `DBClient` into the typed `{ ...ops, tables, transaction }`\n * surface. The five string ops forward straight through; `tables` is the\n * env-typed accessor; `transaction` yields typed tables. Reused for both the\n * default (RLS-enforced) `Database` and the `asService()` sibling — each is\n * fed its own raw client (the default proxy vs `rawDatabase.asService()`).\n *\n * The `satisfies` pins the op surface so a missing/renamed op is a compile\n * error; the assembled object carries `tables`/`transaction` alongside.\n */\nfunction makeTypedSurface(raw: Omit<DBClient, \"asService\">): EnvServiceDatabase {\n const ops = {\n query: (sql: string, params?: unknown[]) => raw.query(sql, params),\n insert: (table: string, data: Record<string, unknown>) => raw.insert(table, data),\n update: (table: string, id: string, data: Record<string, unknown>) =>\n raw.update(table, id, data),\n delete: (table: string, id: string) => raw.delete(table, id),\n findById: (table: string, id: string) => raw.findById(table, id),\n findMany: (table: string, query?: Record<string, unknown>) => raw.findMany(table, query),\n search: (table: string, params?: Record<string, unknown>) => raw.search(table, params),\n } satisfies DBOps;\n return Object.assign(ops, {\n tables: makeTablesAccessor(() => raw),\n transaction<T>(\n fn: (tx: TxPlan) => T extends Promise<unknown> ? never : T,\n ): Promise<Materialized<T>> {\n // A FRESH builder per call: it holds this transaction's ops and its error\n // slot table, and the runtime serves concurrent requests on one event loop.\n // A shared builder would splice one request's writes into another's plan.\n const builder = new TxPlanBuilder();\n return runTxPlan(raw, makeTxTablesAccessor(builder), builder, fn) as Promise<\n Materialized<T>\n >;\n },\n });\n}\n\n/**\n * The transaction twin of {@link makeTablesAccessor}: `tables.<name>` yields the\n * table's PLAN operations, recorded into `builder` instead of sent one by one.\n *\n * Same Proxy shape and same reason for the single narrowing — TS cannot infer a\n * mapped type through a Proxy, so the cast names what the trap returns.\n */\nfunction makeTxTablesAccessor(builder: TxPlanBuilder): TxTables {\n const tablesProxy = new Proxy(\n {},\n {\n get(_t, prop: string | symbol) {\n if (typeof prop !== \"string\") return undefined;\n return builder.table(prop);\n },\n },\n );\n return tablesProxy as TxTables;\n}\n\n/**\n * The project's own Postgres (pgx, schema `env_<envId>`).\n *\n * Typed by default: `Database.tables.<name>.insert({...})` is typed against\n * the project's generated `palbase-env.d.ts` with NO import and NO generic.\n * The raw string ops (`query`/`insert`/`update`/`delete`/`findById`/`findMany`)\n * are also available for dynamic table names and read-only SQL.\n *\n * RLS is enforced by default (the runtime runs each op as `authenticated` with\n * the verified user's claims). To bypass RLS, call `Database.asService()` —\n * explicit and greppable — which runs as the `service_role` (BYPASSRLS).\n *\n * @example\n * import { Database } from \"@palbase/backend\";\n *\n * const todo = await Database.tables.todos.insert({ title: req.input.title });\n * todo.id; // string ✓\n * const rows = await Database.query(\"SELECT id FROM todos WHERE done = $1\", [false]);\n * const all = await Database.asService().tables.todos.findMany({}); // RLS bypass\n */\nexport const Database: EnvTypedDatabase = Object.assign(makeTypedSurface(rawDatabase), {\n /**\n * Lazily resolve the runtime's service-role sibling on each call. We do NOT\n * cache it: `rawDatabase.asService()` reads the CURRENT request scope through\n * the runtime proxy, and the per-request runtime injects a service client\n * bound to that request's identity headers — caching would leak one request's\n * sibling into another concurrent request.\n */\n asService(): EnvServiceDatabase {\n return makeTypedSurface(rawDatabase.asService());\n },\n});\n\n/** Firestore-like document client (PalDocs). */\nexport const Documents: PalbaseDocsClient = makeServiceProxy(\"Documents\");\n\n/**\n * `buckets.<name>` — the storage twin of `Database.tables.<name>`, and the same\n * mechanism: `config/storage.ts` generates a `Buckets` augmentation into\n * `palbase-env.d.ts`, so a bucket name is a property with no import and no\n * generic, and a typo is a compile error.\n *\n * The intermediate `.buckets` is there for the reason `.tables` is: bucket\n * names must not share a namespace with the client's own methods, or the day\n * somebody declares a bucket called `bucket` the surface breaks.\n */\nexport type EnvBuckets = {\n [K in keyof Buckets]: TypedBucketClient<Buckets[K] extends BucketTypes ? Buckets[K] : BucketTypes>;\n};\n\n/** One bucket, with its declared variant names in the type. */\nexport interface TypedBucketClient<B extends BucketTypes> extends Omit<PalbaseBucketClient, \"getPublicUrl\"> {\n /** The public URL for the object, or for one of THIS bucket's declared\n * renditions. A name the bucket does not declare is a compile error. */\n getPublicUrl(path: string, options?: { variant?: B[\"variants\"] }): string;\n}\n\nfunction makeBucketsAccessor(storage: () => PalbaseStorageClient): EnvBuckets {\n return new Proxy(\n {},\n {\n get(_t, prop: string | symbol) {\n if (typeof prop !== \"string\") return undefined;\n return storage().bucket(prop);\n },\n },\n ) as EnvBuckets;\n}\n\nconst rawStorage: PalbaseStorageClient = makeServiceProxy(\"Storage\");\n\n/**\n * Object storage: buckets, objects, renditions and signed URLs.\n *\n * `Storage.buckets.posts.upload(...)` is the typed path. `Storage.bucket(name)`\n * remains for a name computed at runtime — rare, and it gives up the typing,\n * which is the honest trade rather than a second blessed way to do it.\n */\nexport const Storage: PalbaseStorageClient & { buckets: EnvBuckets } = Object.assign(\n {\n // FORWARDED explicitly, not assigned onto the service proxy.\n //\n // `Object.assign(rawStorage, {buckets})` writes onto the proxy's TARGET, and\n // the proxy's only trap is `get`, which forwards every read to the module\n // client — so the property landed somewhere nothing reads and\n // `Storage.buckets.docs` was `undefined` in a deployed handler. It\n // typechecked, every test passed, and the live call answered\n // \"TypeError: undefined is not an object\". `Database` never had the bug\n // because it builds a plain surface the same way this now does.\n bucket: (name: string) => rawStorage.bucket(name),\n },\n { buckets: makeBucketsAccessor(() => rawStorage) },\n);\n\n/** JSON-typed cache (get/set/incr/getOrSet). */\nexport const Cache: CacheClient = makeServiceProxy(\"Cache\");\n\n\n/**\n * This tenant's secrets — API keys, provider credentials, signing material the\n * BACKEND owns.\n *\n * `await Secrets.get(\"STRIPE_KEY\")` in a handler. There is no `.env` to read\n * and no file to mount: a secret is written through the vault's authenticated\n * API (or the CLI/MCP that calls it), and this is how the deployed code reads\n * it back. A name this tenant has not set answers null — as does every name\n * the STACK holds, because no route returns a platform secret's value at all.\n */\nexport const Secrets: SecretsService = makeServiceProxy(\"Secrets\");\n\n/** Structured logger. */\nexport const Log: Logger = makeServiceProxy(\"Log\");\n\n/** Push / email / SMS / in-app notifications. */\nexport const Notifications: PalbaseNotificationsClient = makeServiceProxy(\"Notifications\");\n\n/**\n * Palstore purchases (entitlements + quota/credit spend).\n *\n * Reached by handlers through the `@RequireEntitlement` / `@Spend` decorators\n * rather than called directly in the common case; exposed as a singleton for\n * the cases the decorators deliberately do not cover (a dynamic spend count,\n * which must run BEFORE the billable side-effect).\n */\nexport const Purchases: PurchasesService = makeServiceProxy(\"Purchases\");\n\n/**\n * The raw runtime Flags client for the current request scope. Carries the\n * default-surface reads + `setOverride` AND the runtime's `asService()` sibling\n * (the br-pod's `buildFlagsClient` returns both). The default `Flags` singleton\n * below forwards reads + `setOverride` through here; `Flags.asService()`\n * forwards to this client's own `asService()`.\n */\nconst rawFlags: PalbaseFlagsClient = makeServiceProxy(\"Flags\");\n\n/**\n * Feature flags.\n *\n * Mirrors the `Database` / `Database.asService()` model. The default surface is\n * RLS-equivalent for flags: reads resolve against the CURRENT request user and\n * `Flags.setOverride(key, value)` writes an override for that same signed-in\n * user (no userId argument, no admin power). Cross-user admin writes\n * (`setOverrideForUser`, …) live behind `Flags.asService()` — explicit and\n * greppable, just like `Database.asService()`.\n *\n * @example\n * import { Flags } from \"@palbase/backend\";\n *\n * if (await Flags.isEnabled(\"new_checkout\")) { ... } // current user\n * await Flags.setOverride(\"new_checkout\", true); // current user\n * await Flags.asService().setOverrideForUser(\"u_9\", \"x\", true); // cross-user\n */\nexport const Flags: PalbaseFlagsClient = Object.assign(\n {\n isEnabled(\n flagName: string,\n context?: PalbaseFlagContext,\n ): Promise<PalbaseResult<boolean>> {\n return rawFlags.isEnabled(flagName, context);\n },\n getVariant(\n flagName: string,\n context?: PalbaseFlagContext,\n ): Promise<PalbaseResult<PalbaseFlagVariant>> {\n return rawFlags.getVariant(flagName, context);\n },\n getAll(context?: PalbaseFlagContext): Promise<PalbaseResult<PalbaseFlag[]>> {\n return rawFlags.getAll(context);\n },\n /**\n * Resolve a flag's value, with an optional fallback.\n *\n * FORWARDED as of 2026-08-15. This surface is written out by hand, method\n * by method, and `get` was missing from it — so the client implemented it,\n * thirty assertions covered it, and `Flags.get(\"x\")` was `undefined` in a\n * deployed handler. Exactly the shape of the `Storage.buckets` defect found\n * the same day: a hand-maintained forwarding list is a list somebody has to\n * remember to update.\n */\n get(\n flagName: string,\n defaultOrContext?: PalbaseFlagValue | PalbaseFlagContext,\n maybeContext?: PalbaseFlagContext,\n ): Promise<PalbaseResult<PalbaseFlagValue>> {\n return rawFlags.get(flagName, defaultOrContext, maybeContext);\n },\n setOverride(\n key: string,\n value: PalbaseFlagValue,\n ): Promise<PalbaseResult<PalbaseSetOverrideResult>> {\n return rawFlags.setOverride(key, value);\n },\n },\n {\n /**\n * Lazily resolve the runtime's cross-user sibling on each call. We do NOT\n * cache it: `rawFlags.asService()` reads the CURRENT request scope through\n * the runtime proxy, so caching would leak one request's sibling into\n * another concurrent request. Mirrors `Database.asService()`.\n */\n asService(): PalbaseFlagsServiceClient {\n return rawFlags.asService();\n },\n },\n);\n\n/**\n * The Realtime broadcast singleton for the current request scope. Backend-side\n * Realtime is BROADCAST-ONLY (a stateless handler can push but not subscribe —\n * `subscribe()` lives on the client SDK's `pb.realtime`). Fire-and-forget:\n * `broadcast` resolves once accepted (or with an `error`), never blocking the\n * handler on subscribers.\n *\n * @example\n * import { Realtime } from \"@palbase/backend\";\n *\n * await Realtime.broadcast(\"room:42\", \"message\", { text, from: user.id });\n */\nexport const Realtime: PalbaseRealtimeClient = makeServiceProxy(\"Realtime\");\n","/**\n * tx-plan.ts — `Database.transaction()` as a PLAN, not a pinned session.\n *\n * A transaction used to be a conversation: BEGIN, then one network round trip\n * per operation, then COMMIT. Each of those round trips cost ~4 ms and, because\n * the pooler runs in transaction mode, an open transaction pinned a Postgres\n * backend for the whole conversation. A 121-operation statement upload pinned\n * one backend for ~490 ms.\n *\n * So the callback no longer TALKS to the database. It DESCRIBES what should\n * happen; the description is serialised and sent once; the broker runs the whole\n * thing inside one transaction and answers once. Committing on return and\n * rolling back on throw is unchanged — that is the only property tenant code\n * actually asked for.\n *\n * The consequences, stated plainly, because they are the whole design:\n *\n * - The callback is SYNCHRONOUS. There is nothing to await: no statement has\n * run yet when it returns. `async` on the callback and `await` inside it are\n * both compile errors (see {@link TxPlan} and {@link NotAwaitable}).\n * - `insert()` does not hand back a row, it hands back {@link TxRows}. Reading\n * a field requires `.expectOne(err)` first, which makes \"what if the row\n * isn't there\" a question you cannot route around: it is the argument.\n * - A field read from a row is a {@link Ref} — a PROMISE OF A VALUE THE SERVER\n * WILL PRODUCE, not the value. It can be written into a later operation and\n * it can be returned from the callback (it is substituted for the real value\n * before `transaction()` resolves). It cannot be branched on. See the\n * \"Truthiness\" note below — this is the sharp edge of the whole design.\n * - Control flow that needs a real value must move OUT of the callback: read\n * before the transaction, or express the condition as a guard\n * (`updateWhere({ id, accepted_at: null }, …).expectOne(new Conflict(…))`)\n * which the server evaluates and which rolls the whole plan back.\n *\n * # Truthiness — the hole this file CANNOT close\n *\n * JavaScript does not let a Proxy trap truthiness. `if (ref)` takes the true\n * branch, always, for every Ref, and no `get` handler ever runs. `tsc` is silent\n * because a Ref is a perfectly good object. So:\n *\n * const pot = tx.tables.pots.select({ id }, { limit: 1 }).expectOne(e);\n * if (!pot.balance) { … } // ← ALWAYS false. Silently wrong data.\n *\n * What this file does close: coercion (`Symbol.toPrimitive`/`valueOf`/\n * `toString`), awaiting (`then` is a callable member with a non-thenable\n * signature, which is a *compile* error), serialisation (`toJSON`), and nesting\n * a Ref inside a literal value where the server would store it as data. What it\n * cannot close is a bare truthiness test. The real defence is the build-time\n * static analysis (`tx_analysis.js`, phase P4); until that ships, this hole is\n * open and this comment is the only warning.\n *\n * # Wire contract\n *\n * The JSON this file emits is consumed by\n * `modules/backend/internal/management/tx_program.go`. That decoder rejects\n * unknown fields at every level, so an op carries EXACTLY the fields its kind\n * takes. Everything here that looks like a needless restriction is one of the\n * server's rules made visible early:\n *\n * - `$ref` only points BACKWARDS, and only at an op statically known to yield\n * at most one row (insert, or a `one`/`atMost 1` guard, or `select limit 1`).\n * `.expectOne()` is what this file uses to satisfy that, always.\n * - `$expr` is a closed set: `inc`/`dec` (update only — they read the column's\n * current value) and `now()`.\n * - `update`/`delete` require a `where`; `insert` refuses one.\n * - `insertMany` rows must all set the same columns.\n * - ≤1000 ops, ≤5000 rows per insertMany, ≤8 MiB of JSON.\n *\n * Column keys are emitted SORTED, so the same callback always produces byte-\n * identical JSON. That is what lets the Go decoder be locked to golden files\n * this SDK emits (`testdata/tx_plan_golden/`).\n */\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\n/**\n * A plan handle was used as if it were a value: awaited, coerced to a string or\n * number, serialised, or nested inside another value.\n *\n * Thrown while the callback is still BUILDING the plan, so nothing has been sent\n * and nothing has been written.\n */\nexport class TxRefError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TxRefError\";\n }\n}\n\n/**\n * The plan the callback described cannot be sent: it breaks a rule the server\n * would reject, and rejecting it here names the line that wrote it instead of\n * returning a 400 about an op index.\n */\nexport class TxPlanError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TxPlanError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Wire types — mirror tx_program.go's decoder exactly.\n// ---------------------------------------------------------------------------\n\n/** A backwards reference to an earlier op's single-row result. */\nexport interface TxWireRef {\n $ref: { op: number; field: string };\n}\n\n/** A call from the server's closed function set. */\nexport interface TxWireExpr {\n $expr: { fn: \"inc\" | \"dec\"; by: number } | { fn: \"now\" };\n}\n\n/** One value in a `values`/`set`/`where` map: a literal, a `$ref` or a `$expr`. */\nexport type TxWireValue = TxWireRef | TxWireExpr | unknown;\n\n/** The tenant's declared expectation about an op's row count. `slot` indexes the\n * client-side error table — the error OBJECT never travels. */\nexport interface TxWireGuard {\n kind: \"one\" | \"none\" | \"atLeast\" | \"atMost\";\n n: number;\n slot: number;\n}\n\n/** One operation in the wire plan. Fields are omitted, never null: the decoder\n * rejects a field that does not belong to the op's kind. */\nexport interface TxWireOp {\n op: \"insert\" | \"insertMany\" | \"update\" | \"delete\" | \"select\";\n table: string;\n values?: Record<string, TxWireValue>;\n rows?: Record<string, TxWireValue>[];\n set?: Record<string, TxWireValue>;\n where?: Record<string, TxWireValue>;\n limit?: number;\n lock?: \"update\";\n guard?: TxWireGuard;\n}\n\n/** The plan the engine executes on the request's own transaction. */\nexport interface TxPlanBody {\n ops: TxWireOp[];\n}\n\n/** One op's outcome, positionally matched to the plan's ops. */\nexport interface TxPlanOpResult {\n rows: Record<string, unknown>[];\n rows_affected: number;\n}\n\n/** One result per op, in plan order. */\nexport interface TxPlanResponse {\n results: TxPlanOpResult[];\n}\n\n/**\n * The fields the runtime must copy from the broker's error envelope onto the\n * rejection it throws out of {@link DBClient.txPlan}.\n *\n * `slot` is the whole point: on a guard failure the server answers with the\n * INDEX of the expectation that did not hold, never with an error message of its\n * own, and this SDK maps that index back to the `Error` the callback handed to\n * `.expectOne(…)`. Without `slot` a guard failure degrades to a generic 409.\n */\nexport interface TxPlanRejection {\n status?: number;\n /** `tx_plan_invalid` | `tx_guard_failed` | `tx_ref_unresolved` | a pg class. */\n error_code?: string;\n /** Present only for `tx_guard_failed`: the client-side error table index. */\n slot?: number;\n /** Present on a database error: which op failed. */\n op?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Handle types\n// ---------------------------------------------------------------------------\n\ndeclare const refBrand: unique symbol;\ndeclare const rowBrand: unique symbol;\ndeclare const rowsBrand: unique symbol;\n\n/**\n * Makes a handle a compile error to `await`.\n *\n * `then` is declared as a CALLABLE member whose signature is not `PromiseLike`,\n * which is precisely the shape TypeScript rejects: `await handle` is TS1320 and\n * `async () => handle` is TS1058. A non-callable `then` would not do it — the\n * compiler simply ignores those.\n */\nexport interface NotAwaitable {\n /** Not a promise. Nothing here has run yet; there is nothing to await. */\n then(doNotAwaitAPlanHandle: \"a transaction plan is built synchronously\"): never;\n}\n\n/**\n * A value the SERVER will produce, standing in for a column of a row this plan\n * writes or reads.\n *\n * Legal uses: write it into a later operation's `values`/`set`/`where`, or\n * return it from the callback (it is replaced by the real value before\n * `transaction()` resolves).\n *\n * Illegal, and caught: `await`, `String(ref)`, `` `${ref}` ``, `ref + 1`,\n * `JSON.stringify(ref)`, burying it inside a jsonb object.\n *\n * Illegal, and NOT caught: `if (ref)`. See the truthiness note at the top.\n */\nexport interface Ref<T> extends NotAwaitable {\n readonly [refBrand]: T;\n}\n\n/** The brand carried by a single-row handle, and the seam `Materialized` reads\n * to turn `return st` into the whole row. */\nexport interface TxRowHandle<Row> extends NotAwaitable {\n readonly [rowBrand]: Row;\n}\n\n/**\n * A row this plan is known to produce exactly one of. Every property is a\n * {@link Ref}; returning the handle itself yields the whole row.\n *\n * Only `.expectOne(err)` produces one — which is the design: a row you can read\n * fields from is a row whose absence you have already answered for.\n */\nexport type TxRow<Row> = { readonly [K in keyof Row]: Ref<Row[K]> } & TxRowHandle<Row>;\n\n/**\n * The result of one operation, before any expectation is declared about it.\n *\n * Deliberately not a row and not a list: an operation's row count is not known\n * until the server runs it, so the only thing that can be said about it here is\n * an EXPECTATION. Declaring one is also the only way to get a readable row.\n *\n * At most one expectation per operation — the wire carries one guard per op, and\n * a second call throws rather than silently dropping the first.\n */\nexport interface TxRows<Row> extends NotAwaitable {\n readonly [rowsBrand]: Row;\n /**\n * Require exactly one row, and read it. On any other count the server rolls\n * the whole transaction back and this `error` is thrown to the caller.\n *\n * This is the only way to reach a row's fields, and the only shape a `$ref`\n * may point at.\n */\n expectOne(error: Error): TxRow<Row>;\n /** Require zero rows (e.g. \"this membership must not already exist\"). */\n expectNone(error: Error): void;\n /** Require at least `n` rows. */\n expectAtLeast(n: number, error: Error): void;\n /** Require at most `n` rows. */\n expectAtMost(n: number, error: Error): void;\n}\n\n/** `now()` — the server's clock, usable wherever a value is. */\nexport interface TxNow extends NotAwaitable {\n readonly $expr: { fn: \"now\" };\n}\n\n/** `inc(n)` / `dec(n)` — read the column's CURRENT value and write it back\n * changed. Only meaningful in an update's `set`, which is where the types allow\n * it and where the server allows it. */\nexport interface TxColumnExpr extends NotAwaitable {\n readonly $expr: { fn: \"inc\" | \"dec\"; by: number };\n}\n\n/**\n * Resolve a callback's return type against what actually comes back: every\n * {@link Ref} becomes its value, every {@link TxRow} becomes its row, and\n * anything else keeps its shape.\n *\n * A {@link TxRows} resolves to an explanatory string type rather than a row\n * list: it has no single answer to give, and saying so in the type is louder\n * than a runtime throw.\n */\nexport type Materialized<T> = T extends Ref<infer U>\n ? U\n : T extends TxRowHandle<infer R>\n ? R\n : T extends TxRows<unknown>\n ? \"a TxRows cannot leave the transaction callback — read a row with .expectOne(err) first\"\n : T extends Date\n ? T\n : T extends object\n ? { [K in keyof T]: Materialized<T[K]> }\n : T;\n\n// ---------------------------------------------------------------------------\n// Author-facing value types\n// ---------------------------------------------------------------------------\n\n/** A value written by an INSERT: a literal, an earlier row's field, or `now()`.\n * `inc`/`dec` are absent on purpose — they read a current value, and an inserted\n * row has none. */\nexport type TxInsertValue<V> = V | Ref<V> | TxNow;\n\n/** A value written by an UPDATE's `set`: everything an insert takes, plus the\n * read-modify-write expressions. */\nexport type TxSetValue<V> = V | Ref<V> | TxNow | TxColumnExpr;\n\n/** An insert payload: the table's insert shape, with refs and `now()` allowed. */\nexport type TxInsertShape<Insert> = { [K in keyof Insert]: TxInsertValue<Insert[K]> };\n\n/** An update's `set`: any subset of the insert shape, with expressions allowed. */\nexport type TxSetShape<Insert> = { [K in keyof Insert]?: TxSetValue<Insert[K]> };\n\n/**\n * A filter. Every entry is an equality test and they are AND-ed; a `null`\n * becomes `IS NULL`, which is what makes `{ accepted_at: null }` a usable\n * \"not yet accepted\" guard rather than a clause that matches nothing.\n */\nexport type TxWhere<Row> = { [K in keyof Row]?: Row[K] | Ref<Row[K]> };\n\n/** Options for a plan `select`. */\nexport interface TxSelectOptions {\n /** Cap the rows read. */\n limit?: number;\n /** Take a real `FOR UPDATE` row lock for the rest of the transaction. */\n lock?: \"update\";\n}\n\n/** One table, as the plan sees it. */\nexport interface TxTable<Row, Insert> {\n /** Insert one row. Returns a handle — call `.expectOne(err)` to read fields. */\n insert(values: TxInsertShape<Insert>): TxRows<Row>;\n /**\n * Insert many rows in ONE statement. Every row must set the same columns\n * (a row that omits one would silently take the column's default).\n *\n * An empty list writes nothing and sends nothing.\n */\n insertMany(rows: readonly TxInsertShape<Insert>[]): TxRows<Row>;\n /**\n * Update every row matching `where`. The filter comes first because it is the\n * dangerous half: an update whose `where` you got wrong rewrites rows you\n * never looked at. The server refuses an update with no `where` at all.\n */\n updateWhere(where: TxWhere<Row>, set: TxSetShape<Insert>): TxRows<Row>;\n /** Delete every row matching `where`. The server refuses an unfiltered delete. */\n deleteWhere(where: TxWhere<Row>): TxRows<Row>;\n /** Read rows, optionally locking them for the rest of the transaction. */\n select(where?: TxWhere<Row>, options?: TxSelectOptions): TxRows<Row>;\n}\n\n/**\n * The handle a transaction callback receives.\n *\n * It carries tables and nothing else: no `query`, no `findById`, no `asService`.\n * A read whose value the plan does not write belongs OUTSIDE the transaction,\n * where it costs one round trip and can be branched on like an ordinary value.\n */\nexport interface TxPlanHandle<TTables> {\n tables: TTables;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — expressions\n// ---------------------------------------------------------------------------\n\n/** Internal marker read by the serialiser. */\nconst EXPR = Symbol.for(\"palbase.tx.expr\");\nconst REF = Symbol.for(\"palbase.tx.ref\");\nconst ROW = Symbol.for(\"palbase.tx.row\");\nconst ROWS = Symbol.for(\"palbase.tx.rows\");\n\ninterface RefDescriptor {\n op: number;\n field: string;\n}\n\n/** Property reads that must not silently produce a value on a plan handle.\n * `then` is the one that matters for correctness (it makes `await` a compile\n * error AND stops a handle from being adopted by a promise); the rest turn a\n * silent wrong answer — `\"[object Object]\"`, `NaN`, `{}` — into a thrown one. */\nconst TRAPPED_PROPS: readonly (string | symbol)[] = [\n \"then\",\n \"valueOf\",\n \"toString\",\n \"toJSON\",\n Symbol.toPrimitive,\n];\n\nfunction trap(prop: string | symbol, what: string, hint: string): never {\n const name = typeof prop === \"symbol\" ? prop.description ?? String(prop) : prop;\n throw new TxRefError(\n `${what} was used as a value (via \\`${name}\\`). Nothing in a transaction ` +\n `callback has run yet, so there is no value to read. ${hint}`,\n );\n}\n\n/** The server's `now()`. */\nexport function now(): TxNow {\n return makeExpr({ fn: \"now\" }) as TxNow;\n}\n\n/** Add `by` to the column's current value. Only valid in an update's `set`. */\nexport function inc(by: number): TxColumnExpr {\n assertFiniteNumber(by, \"inc\");\n return makeExpr({ fn: \"inc\", by }) as TxColumnExpr;\n}\n\n/** Subtract `by` from the column's current value. Only valid in an update's `set`. */\nexport function dec(by: number): TxColumnExpr {\n assertFiniteNumber(by, \"dec\");\n return makeExpr({ fn: \"dec\", by }) as TxColumnExpr;\n}\n\nfunction assertFiniteNumber(by: number, fn: string): void {\n if (typeof by !== \"number\" || !Number.isFinite(by)) {\n // JSON has no NaN/Infinity: they would serialise to `null` and the server\n // would reject the plan with an unhelpful decode error.\n throw new TxPlanError(`${fn}() needs a finite number, got ${String(by)}`);\n }\n}\n\nfunction makeExpr(expr: TxWireExpr[\"$expr\"]): unknown {\n return new Proxy(\n { [EXPR]: expr } as Record<string | symbol, unknown>,\n {\n get(target, prop) {\n if (prop === EXPR) return target[EXPR];\n if (TRAPPED_PROPS.includes(prop)) {\n trap(prop, \"A plan expression\", \"Write it into an operation instead.\");\n }\n return undefined;\n },\n },\n );\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — refs and row handles\n// ---------------------------------------------------------------------------\n\nfunction makeRef(op: number, field: string): unknown {\n const target: Record<string | symbol, unknown> = { [REF]: { op, field } satisfies RefDescriptor };\n return new Proxy(target, {\n get(t, prop) {\n if (prop === REF) return t[REF];\n if (TRAPPED_PROPS.includes(prop)) {\n trap(\n prop,\n `\\`${field}\\` of a row this transaction has not written yet`,\n \"Pass it to another operation in the same plan, or return it from the \" +\n \"callback and read it after `transaction()` resolves.\",\n );\n }\n return undefined;\n },\n });\n}\n\nfunction makeRowHandle(op: number): unknown {\n const target: Record<string | symbol, unknown> = { [ROW]: op };\n return new Proxy(target, {\n get(t, prop) {\n if (prop === ROW) return t[ROW];\n if (TRAPPED_PROPS.includes(prop)) {\n trap(\n prop,\n \"A row this transaction has not written yet\",\n \"Read one of its columns to reference it, or return the row from the \" +\n \"callback and read it after `transaction()` resolves.\",\n );\n }\n if (typeof prop === \"symbol\") return undefined;\n return makeRef(op, prop);\n },\n });\n}\n\nfunction refDescriptor(v: unknown): RefDescriptor | null {\n if (typeof v !== \"object\" || v === null) return null;\n const d = (v as Record<symbol, unknown>)[REF];\n return isRefDescriptor(d) ? d : null;\n}\n\nfunction isRefDescriptor(d: unknown): d is RefDescriptor {\n return (\n typeof d === \"object\" &&\n d !== null &&\n typeof (d as RefDescriptor).op === \"number\" &&\n typeof (d as RefDescriptor).field === \"string\"\n );\n}\n\nfunction rowOpIndex(v: unknown): number | null {\n if (typeof v !== \"object\" || v === null) return null;\n const op = (v as Record<symbol, unknown>)[ROW];\n return typeof op === \"number\" ? op : null;\n}\n\nfunction exprOf(v: unknown): TxWireExpr[\"$expr\"] | null {\n if (typeof v !== \"object\" || v === null) return null;\n const e = (v as Record<symbol, unknown>)[EXPR];\n return typeof e === \"object\" && e !== null ? (e as TxWireExpr[\"$expr\"]) : null;\n}\n\nfunction isRowsHandle(v: unknown): boolean {\n return typeof v === \"object\" && v !== null && (v as Record<symbol, unknown>)[ROWS] !== undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — value encoding\n// ---------------------------------------------------------------------------\n\n/**\n * Encode one value of a `values`/`set`/`where` map.\n *\n * The nesting check is not defensive tidiness. The server treats `$ref` as a\n * tagged value only at the TOP of a column's value; a ref buried inside a jsonb\n * payload is just data, and would be stored as the literal object\n * `{\"$ref\":{...}}` — a write that succeeds, commits, and is wrong. So a nested\n * handle is a hard error here, where the line that wrote it is still on the\n * stack.\n */\nfunction encodeValue(value: unknown, column: string, allowColumnExpr: boolean): TxWireValue {\n const ref = refDescriptor(value);\n if (ref) return { $ref: { op: ref.op, field: ref.field } } satisfies TxWireRef;\n\n const expr = exprOf(value);\n if (expr) {\n if (expr.fn !== \"now\" && !allowColumnExpr) {\n throw new TxPlanError(\n `\\`${column}\\`: ${expr.fn}() reads the column's current value, so it is ` +\n `only valid in updateWhere(where, set).`,\n );\n }\n return { $expr: expr } satisfies TxWireExpr;\n }\n\n if (rowOpIndex(value) !== null) {\n throw new TxPlanError(\n `\\`${column}\\`: a row handle is not a value. Read the column you meant ` +\n `(e.g. \\`row.id\\`).`,\n );\n }\n if (isRowsHandle(value)) {\n throw new TxPlanError(\n `\\`${column}\\`: an operation result is not a value. Declare an expectation ` +\n `first (\\`.expectOne(err)\\`) and read a column from the row.`,\n );\n }\n\n assertNoNestedHandles(value, column);\n return value;\n}\n\nfunction assertNoNestedHandles(value: unknown, column: string): void {\n if (typeof value !== \"object\" || value === null) return;\n if (value instanceof Date) return;\n if (refDescriptor(value) || exprOf(value) || rowOpIndex(value) !== null || isRowsHandle(value)) {\n throw new TxPlanError(\n `\\`${column}\\`: a plan handle is nested inside a value. The server would ` +\n `store it as literal JSON, not resolve it. Put the reference directly in ` +\n `the column.`,\n );\n }\n if (Array.isArray(value)) {\n for (const item of value) assertNoNestedHandles(item, column);\n return;\n }\n for (const item of Object.values(value as Record<string, unknown>)) {\n assertNoNestedHandles(item, column);\n }\n}\n\n/**\n * Encode a column map, dropping `undefined` and emitting keys SORTED.\n *\n * Sorting is what makes the same callback produce byte-identical JSON every\n * time, which is what lets the Go decoder be locked to goldens this SDK emits.\n * Dropping `undefined` mirrors what `JSON.stringify` would do anyway, but does\n * it where the resulting column list is still checkable.\n */\nfunction encodeMap(\n map: Record<string, unknown>,\n allowColumnExpr: boolean,\n): Record<string, TxWireValue> {\n const out: Record<string, TxWireValue> = {};\n for (const key of Object.keys(map).sort()) {\n const value = map[key];\n if (value === undefined) continue;\n out[key] = encodeValue(value, key, allowColumnExpr);\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — the builder\n// ---------------------------------------------------------------------------\n\n/** How many rows an op can produce, as far as the CLIENT can tell before it\n * runs. Only the empty `insertMany` is knowable, and knowing it is what lets a\n * doomed expectation fail on the line that declared it. */\nconst SKIPPED_OP = -1;\n\nclass TxRowsImpl<Row> implements TxRows<Row> {\n // Present so `isRowsHandle` recognises the object; never read for its value.\n readonly [ROWS] = true;\n // Phantom: the type brand that stops a bare object passing as a TxRows. Never\n // present at run time, which is what `declare` says.\n declare readonly [rowsBrand]: Row;\n private guarded = false;\n\n constructor(\n private readonly builder: TxPlanBuilder,\n private readonly opIndex: number,\n private readonly what: string,\n ) {}\n\n // The type-level `await` guard made real: TS rejects `await rows` at compile\n // time, and reaching this means someone called `.then(...)` by hand.\n then(): never {\n throw new TxRefError(\n `${this.what} cannot be awaited: a transaction callback builds a plan, it ` +\n `does not run statements. Remove the \\`await\\`.`,\n );\n }\n\n expectOne(error: Error): TxRow<Row> {\n this.declareGuard(\"one\", 1, error);\n if (this.opIndex === SKIPPED_OP) throw error;\n return makeRowHandle(this.opIndex) as TxRow<Row>;\n }\n\n expectNone(error: Error): void {\n this.declareGuard(\"none\", 0, error);\n }\n\n expectAtLeast(n: number, error: Error): void {\n assertGuardCount(n, \"expectAtLeast\");\n this.declareGuard(\"atLeast\", n, error);\n if (this.opIndex === SKIPPED_OP && n > 0) throw error;\n }\n\n expectAtMost(n: number, error: Error): void {\n assertGuardCount(n, \"expectAtMost\");\n this.declareGuard(\"atMost\", n, error);\n }\n\n private declareGuard(kind: TxWireGuard[\"kind\"], n: number, error: Error): void {\n if (!(error instanceof Error)) {\n // The error object is the ONLY thing that describes this failure to the\n // caller — the server sends back an index, never a message.\n throw new TxPlanError(\n `${this.what}: an expectation needs the Error to throw when it does not ` +\n `hold (e.g. \\`.expect…(new Conflict(\"already accepted\"))\\`).`,\n );\n }\n if (this.guarded) {\n throw new TxPlanError(\n `${this.what} already has an expectation. One operation carries one ` +\n `expectation; declare the second one on its own operation.`,\n );\n }\n this.guarded = true;\n if (this.opIndex === SKIPPED_OP) return;\n this.builder.attachGuard(this.opIndex, kind, n, error);\n }\n}\n\nfunction assertGuardCount(n: number, fn: string): void {\n if (!Number.isInteger(n) || n < 0) {\n throw new TxPlanError(`${fn}(n) needs a non-negative integer, got ${String(n)}`);\n }\n}\n\n/** Bounds mirrored from tx_program.go so an over-sized plan is named here rather\n * than rejected as an opaque 400 after it has crossed the network. */\nconst MAX_OPS = 1000;\nconst MAX_ROWS = 5000;\n\n/**\n * Accumulates ops and the client-side error table while the callback runs.\n *\n * Exported for the runtime and for tests that need the serialised plan without\n * a server; author code never sees it.\n */\nexport class TxPlanBuilder {\n private readonly ops: TxWireOp[] = [];\n /** Errors handed to expectations, indexed by the `slot` the server echoes. */\n private readonly slots: Error[] = [];\n\n /** The table surface handed to the callback. Untyped here; the public\n * `transaction()` signatures put the schema types on top. */\n table(name: string): TxTable<Record<string, unknown>, Record<string, unknown>> {\n return {\n insert: (values) => {\n const encoded = encodeMap(values as Record<string, unknown>, false);\n if (Object.keys(encoded).length === 0) {\n throw new TxPlanError(`${name}.insert() needs at least one column`);\n }\n return this.push({ op: \"insert\", table: name, values: encoded }, `${name}.insert()`);\n },\n\n insertMany: (rows) => {\n if (rows.length === 0) {\n // Nothing to write. Emitting an op would be a guaranteed 400 (the\n // server requires rows), and refusing outright would punish the\n // ordinary \"filtered every candidate out\" case.\n return new TxRowsImpl(this, SKIPPED_OP, `${name}.insertMany()`);\n }\n if (rows.length > MAX_ROWS) {\n throw new TxPlanError(\n `${name}.insertMany() has ${rows.length} rows; the limit is ${MAX_ROWS}. ` +\n `Split the write across requests.`,\n );\n }\n const encoded = rows.map((row) => encodeMap(row as Record<string, unknown>, false));\n assertUniformRows(encoded, name);\n return this.push({ op: \"insertMany\", table: name, rows: encoded }, `${name}.insertMany()`);\n },\n\n updateWhere: (where, set) => {\n const encodedWhere = encodeMap(where as Record<string, unknown>, false);\n const encodedSet = encodeMap(set as Record<string, unknown>, true);\n if (Object.keys(encodedWhere).length === 0) {\n throw new TxPlanError(\n `${name}.updateWhere() needs a filter. An update with no filter ` +\n `rewrites the whole table.`,\n );\n }\n if (Object.keys(encodedSet).length === 0) {\n throw new TxPlanError(`${name}.updateWhere() needs at least one column to set`);\n }\n return this.push(\n { op: \"update\", table: name, set: encodedSet, where: encodedWhere },\n `${name}.updateWhere()`,\n );\n },\n\n deleteWhere: (where) => {\n const encodedWhere = encodeMap(where as Record<string, unknown>, false);\n if (Object.keys(encodedWhere).length === 0) {\n throw new TxPlanError(\n `${name}.deleteWhere() needs a filter. A delete with no filter empties ` +\n `the table.`,\n );\n }\n return this.push(\n { op: \"delete\", table: name, where: encodedWhere },\n `${name}.deleteWhere()`,\n );\n },\n\n select: (where, options) => {\n const op: TxWireOp = { op: \"select\", table: name };\n const encodedWhere = encodeMap((where ?? {}) as Record<string, unknown>, false);\n if (Object.keys(encodedWhere).length > 0) op.where = encodedWhere;\n if (options?.limit !== undefined) {\n if (!Number.isInteger(options.limit) || options.limit < 0) {\n throw new TxPlanError(\n `${name}.select(): limit needs a non-negative integer, got ${String(options.limit)}`,\n );\n }\n op.limit = options.limit;\n }\n if (options?.lock !== undefined) op.lock = options.lock;\n return this.push(op, `${name}.select()`);\n },\n };\n }\n\n private push(op: TxWireOp, what: string): TxRows<Record<string, unknown>> {\n if (this.ops.length >= MAX_OPS) {\n throw new TxPlanError(\n `this transaction has ${MAX_OPS} operations, which is the limit. Use ` +\n `insertMany() for bulk writes, or split the work across requests.`,\n );\n }\n const index = this.ops.length;\n this.ops.push(op);\n return new TxRowsImpl(this, index, what);\n }\n\n /** Attach an expectation to an op and record its error in the slot table. */\n attachGuard(opIndex: number, kind: TxWireGuard[\"kind\"], n: number, error: Error): void {\n const op = this.ops[opIndex];\n // Unreachable: the index came from `push`. A loud failure beats a silently\n // unguarded write if that ever stops being true.\n if (!op) throw new TxPlanError(`internal: expectation on unknown operation ${opIndex}`);\n const slot = this.slots.length;\n this.slots.push(error);\n op.guard = { kind, n, slot };\n }\n\n /** The serialisable plan. Empty when the callback described no writes. */\n body(): TxPlanBody {\n return { ops: this.ops };\n }\n\n /** The error the server's `slot` selects, or `null` when it names one this\n * plan never declared (a server/client disagreement, not a tenant error). */\n errorForSlot(slot: number): Error | null {\n return this.slots[slot] ?? null;\n }\n}\n\nfunction assertUniformRows(rows: Record<string, TxWireValue>[], table: string): void {\n const first = rows[0];\n if (!first) return;\n const want = Object.keys(first);\n const wantKey = want.join(\",\");\n for (let i = 1; i < rows.length; i++) {\n const got = Object.keys(rows[i] as Record<string, TxWireValue>);\n if (got.join(\",\") !== wantKey) {\n // One statement, one column list. A ragged row would take the DB default\n // for the column it omitted — a write that succeeds and is wrong.\n throw new TxPlanError(\n `${table}.insertMany(): every row must set the same columns. Row 0 sets ` +\n `[${want.join(\", \")}] but row ${i} sets [${got.join(\", \")}]. ` +\n `(A property set to \\`undefined\\` counts as absent — use \\`null\\`.)`,\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — materialisation\n// ---------------------------------------------------------------------------\n\n/**\n * Replace every handle in the callback's return value with what the server\n * actually produced.\n *\n * Walks arrays and PLAIN objects only. Class instances (a Date, a Zod schema, a\n * domain object) are returned untouched — recursing into them would rebuild them\n * as bare objects, and nothing inside one can be a handle that this SDK created.\n */\nexport function materializeResult(value: unknown, results: TxPlanOpResult[]): unknown {\n const ref = refDescriptor(value);\n if (ref) {\n const row = rowOf(results, ref.op, `\\`${ref.field}\\``);\n if (!(ref.field in row)) {\n throw new TxPlanError(\n `the transaction's operation ${ref.op} returned no column \\`${ref.field}\\`.`,\n );\n }\n return row[ref.field];\n }\n\n const rowOp = rowOpIndex(value);\n if (rowOp !== null) return rowOf(results, rowOp, \"a row\");\n\n if (isRowsHandle(value)) {\n throw new TxPlanError(\n \"an operation result cannot be returned from a transaction callback: its \" +\n \"row count is not known until the plan runs. Declare an expectation \" +\n \"(`.expectOne(err)`) and return the row, or a column of it.\",\n );\n }\n\n if (Array.isArray(value)) return value.map((item) => materializeResult(item, results));\n\n if (isPlainObject(value)) {\n const out: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) out[key] = materializeResult(item, results);\n return out;\n }\n\n return value;\n}\n\nfunction rowOf(results: TxPlanOpResult[], opIndex: number, what: string): Record<string, unknown> {\n const result = results[opIndex];\n if (!result) {\n throw new TxPlanError(\n `the transaction returned no result for operation ${opIndex}, so ${what} ` +\n `cannot be read.`,\n );\n }\n const row = result.rows[0];\n if (!row) {\n // Unreachable through the public API: a handle only exists behind an\n // `expectOne`, and the server rolls back rather than answering 200 with a\n // guard unmet. Loud, because the alternative is `undefined` in tenant data.\n throw new TxPlanError(\n `the transaction's operation ${opIndex} returned no row, so ${what} cannot ` +\n `be read.`,\n );\n }\n return row;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — the driver\n// ---------------------------------------------------------------------------\n\n/** What {@link runTxPlan} needs from the runtime: one call, one transaction. */\nexport interface TxPlanTransport {\n txPlan(plan: TxPlanBody): Promise<TxPlanResponse>;\n}\n\n/**\n * Build the plan, send it, and resolve the callback's return value.\n *\n * A callback that throws never reaches the network: there is nothing to roll\n * back because nothing was sent. A callback that describes no writes also skips\n * the round trip entirely.\n *\n * The RETURN type is `unknown` here on purpose. `Materialized<T>` is a compile-\n * time rewrite of the callback's return type, and it belongs on the public\n * `transaction()` signatures where `T` is inferred from the author's callback;\n * threading it through this driver as well would mean inferring `T` twice, from\n * two different positions, and reconciling them. The public wrappers narrow\n * once, at the seam where the value types were erased anyway.\n */\nexport async function runTxPlan<TTables>(\n transport: TxPlanTransport,\n tables: TTables,\n builder: TxPlanBuilder,\n fn: (tx: TxPlanHandle<TTables>) => unknown,\n): Promise<unknown> {\n const returned = fn({ tables });\n const body = builder.body();\n if (body.ops.length === 0) {\n return materializeResult(returned, []);\n }\n\n let response: TxPlanResponse;\n try {\n response = await transport.txPlan(body);\n } catch (err) {\n throw translateRejection(err, builder);\n }\n return materializeResult(returned, response.results);\n}\n\n/**\n * Turn the broker's rejection back into the tenant's own error.\n *\n * The server never sees the `Error` an expectation was given — only its slot\n * index — so this is the only place the intended error can be produced. A\n * rejection this SDK does not recognise passes through untouched: inventing an\n * error for it would hide the real failure.\n */\nfunction translateRejection(err: unknown, builder: TxPlanBuilder): unknown {\n if (typeof err !== \"object\" || err === null) return err;\n const rejection = err as TxPlanRejection;\n if (rejection.error_code !== \"tx_guard_failed\" || typeof rejection.slot !== \"number\") {\n return err;\n }\n return builder.errorForSlot(rejection.slot) ?? err;\n}\n","/** HTTP error with structured error response format.\n *\n * The base class for the throwable error classes (`PalError`, `Conflict`,\n * `NotFound`, …). Construct one directly with `throw new HttpError(404,\n * \"todo_not_found\", \"No such todo\")`, or throw a named subclass\n * (`throw new NotFound(\"todo not found\")`). The runtime catches any `HttpError`\n * and emits the standard envelope; on the wire (and to iOS) it surfaces as\n * `BackendError.server(code, status, message, requestId)`.\n *\n * The optional `data` field carries a structured payload alongside the\n * standard envelope — for errors that need to ship extra context\n * (e.g. `new Conflict(\"locked\", \"title_locked\", { retryAfter: 30 })`). It rides\n * through to the iOS typed enum's associated value.\n */\n/**\n * The brand that identifies an HttpError ACROSS SDK instances.\n *\n * A process legitimately holds more than one copy of this SDK — the runtime\n * loads the engine from its own node_modules while the tenant's bundle carries\n * an inlined copy, which is why the controller registry and the error registry\n * are both anchored on `Symbol.for`. The one place that did not follow the\n * pattern was the engine's catch: `err instanceof HttpError` compares CLASS\n * IDENTITY, so a `throw new NotFound()` from the bundle's copy did not match\n * the engine's copy and every typed error in every deployed backend degraded to\n * `500 internal_error`. Measured through the edge on a real deploy: a route\n * throwing `NotFound` answered 500 while the runtime's own log printed the\n * error object with `status: 404` right beside it.\n *\n * `Symbol.for` puts this in the cross-realm registry, so every copy of the SDK\n * agrees on it by VALUE rather than by identity.\n */\nexport const HTTP_ERROR_BRAND: unique symbol = Symbol.for(\"palbase.backend.httpError\");\n\n/**\n * Whether a thrown value is an HttpError from ANY copy of this SDK.\n *\n * The shape is checked as well as the brand: the brand says \"this claims to be\n * one of ours\", the fields say the envelope can actually be built from it, and\n * a half-formed object must fall through to the 500 path rather than produce a\n * malformed response.\n */\nexport function isHttpError(err: unknown): err is HttpError {\n if (typeof err !== \"object\" || err === null) return false;\n const e = err as Record<PropertyKey, unknown>;\n return (\n e[HTTP_ERROR_BRAND] === true &&\n typeof e.status === \"number\" &&\n typeof e.error === \"string\" &&\n typeof e.errorDescription === \"string\"\n );\n}\n\nexport class HttpError extends Error {\n public readonly status: number;\n public readonly error: string;\n public readonly errorDescription: string;\n public readonly data?: unknown;\n /** See {@link HTTP_ERROR_BRAND} — how the engine recognises this across SDK copies. */\n public readonly [HTTP_ERROR_BRAND] = true;\n\n constructor(status: number, error: string, errorDescription: string, data?: unknown) {\n super(errorDescription);\n this.name = \"HttpError\";\n this.status = status;\n this.error = error;\n this.errorDescription = errorDescription;\n if (data !== undefined) {\n this.data = data;\n }\n }\n\n /**\n * Serialize to the standard Palbase error response format.\n * The `requestId` is injected by the runtime layer from the request context.\n * When called without arguments (e.g. JSON.stringify), request_id is omitted.\n * When `data` is set, it is appended as a strict-superset field.\n */\n toJSON(requestId?: string): {\n error: string;\n error_description: string;\n status: number;\n request_id?: string;\n data?: unknown;\n } {\n const result: {\n error: string;\n error_description: string;\n status: number;\n request_id?: string;\n data?: unknown;\n } = {\n error: this.error,\n error_description: this.errorDescription,\n status: this.status,\n };\n if (requestId) {\n result.request_id = requestId;\n }\n if (this.data !== undefined) {\n result.data = this.data;\n }\n return result;\n }\n}\n\n/**\n * Throw with a custom HTTP status + wire code. The general-purpose escape hatch\n * when none of the named classes (`Conflict`/`NotFound`/…) fits.\n *\n * @example\n * throw new PalError(418, \"teapot\", \"I'm a teapot\");\n */\nexport class PalError extends HttpError {\n constructor(status: number, code: string, description: string, data?: unknown) {\n super(status, code, description, data);\n this.name = \"PalError\";\n }\n}\n\n/** Base for the named status classes. Each subclass fixes its HTTP status; the\n * `code` defaults to the class's canonical wire code (overridable), and the\n * `message` defaults to a human-readable label (overridable). */\nabstract class NamedHttpError extends HttpError {\n protected constructor(\n status: number,\n defaultCode: string,\n name: string,\n message?: string,\n code?: string,\n data?: unknown,\n ) {\n super(status, code ?? defaultCode, message ?? defaultMessage(name), data);\n this.name = name;\n }\n}\n\n/** Derive a default human-readable message from a class name\n * (\"NotFound\" → \"Not found\", \"TooManyRequests\" → \"Too many requests\"). */\nfunction defaultMessage(name: string): string {\n const spaced = name.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\");\n return spaced.charAt(0).toUpperCase() + spaced.slice(1).toLowerCase();\n}\n\n/**\n * 400 — the request was malformed or failed validation. Carries a fixed typed\n * payload: `new BadRequest({ fields: [{ field: \"email\", message: \"invalid\" }] })`.\n * The shape is declared once in the SDK so codegen surfaces `error.data.fields`\n * typed on the client.\n */\nexport class BadRequest extends NamedHttpError {\n public declare readonly data: BadRequestData;\n constructor(data: BadRequestData, message?: string) {\n super(400, \"bad_request\", \"BadRequest\", message, undefined, data);\n }\n}\n\n/** 401 — the caller is not authenticated. */\nexport class Unauthorized extends NamedHttpError {\n constructor(message?: string, code?: string, data?: unknown) {\n super(401, \"unauthorized\", \"Unauthorized\", message, code, data);\n }\n}\n\n/** 403 — the caller is authenticated but not allowed. */\nexport class Forbidden extends NamedHttpError {\n constructor(message?: string, code?: string, data?: unknown) {\n super(403, \"forbidden\", \"Forbidden\", message, code, data);\n }\n}\n\n/** 404 — the requested resource does not exist. */\nexport class NotFound extends NamedHttpError {\n constructor(message?: string, code?: string, data?: unknown) {\n super(404, \"not_found\", \"NotFound\", message, code, data);\n }\n}\n\n/** 409 — the request conflicts with the current state. */\nexport class Conflict extends NamedHttpError {\n constructor(message?: string, code?: string, data?: unknown) {\n super(409, \"conflict\", \"Conflict\", message, code, data);\n }\n}\n\n/** A single field-level validation failure carried by {@link BadRequest}. */\nexport interface FieldError {\n /** The offending field's name (dotted path for nested fields). */\n field: string;\n /** Human-readable reason the field failed. */\n message: string;\n}\n\n/** The fixed, typed payload {@link BadRequest} ships. */\nexport interface BadRequestData {\n /** The fields that failed validation. */\n fields: FieldError[];\n}\n\n/** The fixed, typed payload {@link TooManyRequests} ships. */\nexport interface TooManyRequestsData {\n /** Seconds the caller should wait before retrying. */\n retryAfter: number;\n}\n\n/**\n * 429 — the caller has exceeded the rate limit. Carries a fixed typed payload:\n * `new TooManyRequests({ retryAfter: 30 })`. The shape is declared once in the\n * SDK (error-registry pre-seed) so codegen surfaces `error.data.retryAfter`\n * typed on the client — no per-project definition needed.\n */\nexport class TooManyRequests extends NamedHttpError {\n public declare readonly data: TooManyRequestsData;\n constructor(data: TooManyRequestsData, message?: string) {\n super(429, \"too_many_requests\", \"TooManyRequests\", message, undefined, data);\n }\n}\n","/**\n * engine/config.ts — settings from the environment, and the gate that refuses\n * to boot without them.\n *\n * A mandatory module that is not configured must stop the process, by name.\n * The failure this prevents is the expensive one: a stack that boots, passes\n * its probes, and answers 500 on first contact — where the missing value is\n * discovered by a customer rather than by the operator who could fix it.\n *\n * Database and Auth are mandatory. That is a product decision (2026-08-14), not\n * a technical necessity: a backend whose data layer or whose notion of \"who is\n * calling\" is undefined has nothing safe to do with a request.\n */\n\n/** Everything the engine needs to serve. Built once, at boot, never re-read. */\nexport interface EngineConfig {\n /** Postgres connection string. MANDATORY. */\n databaseUrl: string;\n /** Where this stack publishes its token signing keys. MANDATORY. */\n authJwksUrl: string;\n /** When set, a token whose `iss` differs is rejected. */\n authIssuer?: string;\n /** Base URL of the module surface (`/v1/*`, `/auth/*`). Empty ⇒ module\n * singletons throw a named error on first use rather than silently no-op. */\n moduleBaseUrl: string;\n /**\n * The address CLIENTS reach this stack at — `https://<ref>.palbase.studio` in\n * the cloud, whatever domain the certificate is for when self-hosted.\n *\n * NOT `moduleBaseUrl`, and the distinction is the whole point: that one is\n * this process's internal route to palsvc (`http://127.0.0.1:8080`), which\n * resolves nowhere outside the pod. A public object URL has to survive\n * leaving the response body, so it cannot be built from the internal one.\n *\n * Only the operator knows this value, so only the operator sets it\n * (`PALBASE_PUBLIC_ORIGIN`). Empty ⇒ `Storage…getPublicUrl()` throws a named\n * error, the same way an unconfigured module does.\n */\n publicOrigin: string;\n /** Shared secret storage signs its internal upload calls with. Empty means\n * uploads are not wired, and those calls are refused. */\n uploadSecret: string;\n /** Publishable key, sent as `apikey` on module calls. */\n anonKey: string;\n /** Secret key. Used for privileged module calls. */\n serviceRoleKey: string;\n /** HMAC the realtime broadcast token is signed with. Empty ⇒ broadcast\n * returns a clear `realtime_unconfigured` error instead of failing silently. */\n realtimeSecret: string;\n port: number;\n /** The Postgres role each request is bound to. RLS policies are written\n * against it, so changing it changes who the database thinks is asking. */\n dbRole: string;\n /**\n * The Postgres role `Database.asService()` is bound to. It is the one that\n * carries BYPASSRLS, which is the whole of what \"as service\" means — a name\n * pointing at a role without it does not fail, it returns fewer rows.\n *\n * Configurable for the same reason `dbRole` is, and beside it on purpose: a\n * stack that renames one of the pair must rename both, or the request and its\n * service sibling stop being two identities of the same installation.\n */\n dbServiceRole: string;\n poolMax: number;\n}\n\n/** Thrown when a mandatory module is unconfigured. Carries the missing names. */\nexport class BootRefused extends Error {\n readonly missing: readonly string[];\n constructor(missing: readonly string[], message: string) {\n super(message);\n this.name = \"BootRefused\";\n this.missing = missing;\n }\n}\n\nconst MANDATORY: ReadonlyArray<{ key: string; what: string }> = [\n { key: \"DATABASE_URL\", what: \"the stack's Postgres (Database module)\" },\n { key: \"AUTH_JWKS_URL\", what: \"where this stack publishes its token signing keys (Auth module)\" },\n];\n\n/**\n * Read the engine's settings, or refuse.\n *\n * @throws {BootRefused} naming every missing mandatory value at once — one\n * restart per missing variable is a bad way to learn what a stack needs.\n */\nexport function loadConfig(env: Record<string, string | undefined>): EngineConfig {\n const missing = MANDATORY.filter((m) => !env[m.key]?.trim()).map((m) => m.key);\n if (missing.length > 0) {\n const detail = MANDATORY.filter((m) => missing.includes(m.key))\n .map((m) => ` ${m.key.padEnd(16)}${m.what}`)\n .join(\"\\n\");\n throw new BootRefused(\n missing,\n `boot refused: mandatory module not configured — missing ${missing.join(\", \")}.\\n${detail}`,\n );\n }\n\n const port = Number(env.PORT ?? 3000);\n if (!Number.isInteger(port) || port < 0 || port > 65535) {\n throw new BootRefused([], `boot refused: PORT is not a valid port number (got ${env.PORT}).`);\n }\n const poolMax = Number(env.DB_POOL_MAX ?? 10);\n if (!Number.isInteger(poolMax) || poolMax < 1) {\n throw new BootRefused([], `boot refused: DB_POOL_MAX must be a positive integer (got ${env.DB_POOL_MAX}).`);\n }\n\n return {\n databaseUrl: env.DATABASE_URL!.trim(),\n authJwksUrl: env.AUTH_JWKS_URL!.trim(),\n authIssuer: env.AUTH_ISSUER?.trim() || undefined,\n moduleBaseUrl: (env.MODULE_BASE_URL ?? \"\").replace(/\\/+$/, \"\"),\n publicOrigin: (env.PALBASE_PUBLIC_ORIGIN ?? \"\").trim().replace(/\\/+$/, \"\"),\n // The secret storage signs its two internal calls with (authorize, and the\n // completion that runs an @Upload handler). Empty means uploads are not\n // wired, and both calls REFUSE — an unsigned completion would let anyone\n // who knows a route path invent an upload that never happened.\n uploadSecret: env.PALBASE_UPLOAD_SECRET ?? \"\",\n anonKey: env.PALBASE_ANON_KEY ?? \"\",\n serviceRoleKey: env.PALBASE_SERVICE_ROLE_KEY ?? \"\",\n realtimeSecret: env.REALTIME_INGESTION_SECRET ?? \"\",\n port,\n dbRole: env.DB_ROLE ?? \"backend_authenticated\",\n // Verified against the stack that provisions them, not from memory: the six\n // roles and their attributes are declared in v2/internal/migrate/provision.go\n // (`roleBackendServiceRole = \"backend_service_role\"`, NOLOGIN BYPASSRLS),\n // and the live database agrees (pg_roles.rolbypassrls = true).\n dbServiceRole: env.DB_SERVICE_ROLE ?? \"backend_service_role\",\n poolMax,\n };\n}\n","/**\n * engine/auth.ts — verifying the stack's own access tokens.\n *\n * The engine does this itself rather than trusting a header stamped upstream.\n * In the isolate architecture a gateway verified the token and the runtime read\n * the result; a backend that boots on its own has no such upstream, so the\n * verification lives here — against the keys the stack publishes.\n *\n * Deliberately narrow: ES256 over P-256, which is what palauth mints. An\n * unrecognised `alg` is refused rather than accommodated, because the classic\n * JWT break is a verifier that is helpful about algorithms.\n */\n\n/** A JSON Web Key, narrowed to the EC keys this verifier accepts. */\ninterface EcJwk {\n kid: string;\n kty: string;\n crv: string;\n x: string;\n y: string;\n}\n\n/** The claims the engine reads. Everything else rides along untyped. */\nexport interface VerifiedClaims extends Record<string, unknown> {\n sub?: string;\n role?: string;\n email?: string;\n email_verified?: boolean;\n exp?: number;\n iss?: string;\n}\n\nfunction b64urlToBytes(s: string): Uint8Array<ArrayBuffer> {\n const pad = s.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const full = pad.padEnd(Math.ceil(pad.length / 4) * 4, \"=\");\n const bin = atob(full);\n // Backed by a plain ArrayBuffer so the result satisfies BufferSource — a\n // Uint8Array over ArrayBufferLike could be shared memory, which the WebCrypto\n // signatures reject.\n const out = new Uint8Array(new ArrayBuffer(bin.length));\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nexport interface AuthVerifierOptions {\n jwksUrl: string;\n issuer?: string;\n /** Injectable for tests; defaults to global fetch. */\n fetchImpl?: typeof fetch;\n /** How long a fetched keyset is trusted before it is fetched again. A key\n * rotation must become visible without a restart, and an unknown `kid` must\n * not be able to force a fetch per request (that is a free DoS lever). */\n keysetTtlMs?: number;\n}\n\nexport class AuthVerifier {\n private keys = new Map<string, CryptoKey>();\n private fetchedAt = 0;\n private inflight: Promise<void> | null = null;\n private readonly jwksUrl: string;\n private readonly issuer?: string;\n private readonly fetchImpl: typeof fetch;\n private readonly ttl: number;\n\n constructor(opts: AuthVerifierOptions) {\n this.jwksUrl = opts.jwksUrl;\n this.issuer = opts.issuer;\n this.fetchImpl = opts.fetchImpl ?? ((...a: Parameters<typeof fetch>) => fetch(...a));\n this.ttl = opts.keysetTtlMs ?? 5 * 60_000;\n }\n\n /** Fetch the keyset at most once per TTL, and at most once concurrently. */\n private async refresh(): Promise<void> {\n if (this.inflight) return this.inflight;\n this.inflight = (async () => {\n try {\n const res = await this.fetchImpl(this.jwksUrl);\n if (!res.ok) return;\n const body = (await res.json()) as { keys?: EcJwk[] };\n const next = new Map<string, CryptoKey>();\n for (const jwk of body.keys ?? []) {\n if (jwk.kty !== \"EC\" || jwk.crv !== \"P-256\") continue;\n try {\n next.set(\n jwk.kid,\n await crypto.subtle.importKey(\n \"jwk\",\n { kty: \"EC\", crv: jwk.crv, x: jwk.x, y: jwk.y, ext: true },\n { name: \"ECDSA\", namedCurve: \"P-256\" },\n true,\n [\"verify\"],\n ),\n );\n } catch {\n // A single malformed key must not blind the verifier to the rest.\n }\n }\n if (next.size > 0) {\n this.keys = next;\n this.fetchedAt = Date.now();\n }\n } finally {\n this.inflight = null;\n }\n })();\n return this.inflight;\n }\n\n private async key(kid: string): Promise<CryptoKey | null> {\n const stale = Date.now() - this.fetchedAt > this.ttl;\n if (!this.keys.has(kid) || stale) await this.refresh();\n return this.keys.get(kid) ?? null;\n }\n\n /**\n * Verify an `Authorization` header value.\n *\n * @returns the verified claims, or `null` for absent / malformed / expired /\n * wrong-issuer / bad-signature. One `null` for every failure on purpose:\n * the caller answers 401 either way, and a detailed reason is an oracle.\n */\n async verify(authorization: string | null | undefined): Promise<VerifiedClaims | null> {\n if (!authorization || !authorization.startsWith(\"Bearer \")) return null;\n const parts = authorization.slice(7).trim().split(\".\");\n if (parts.length !== 3) return null;\n const h = parts[0];\n const p = parts[1];\n const sig = parts[2];\n if (h === undefined || p === undefined || sig === undefined) return null;\n\n let header: { alg?: string; kid?: string };\n let claims: VerifiedClaims;\n try {\n header = JSON.parse(new TextDecoder().decode(b64urlToBytes(h)));\n claims = JSON.parse(new TextDecoder().decode(b64urlToBytes(p)));\n } catch {\n return null;\n }\n // `none`, `HS256`-with-the-public-key, and friends all die here.\n if (header.alg !== \"ES256\" || !header.kid) return null;\n\n const key = await this.key(header.kid);\n if (!key) return null;\n\n let ok = false;\n try {\n ok = await crypto.subtle.verify(\n { name: \"ECDSA\", hash: \"SHA-256\" },\n key,\n b64urlToBytes(sig),\n new TextEncoder().encode(`${h}.${p}`),\n );\n } catch {\n return null;\n }\n if (!ok) return null;\n if (typeof claims.exp === \"number\" && claims.exp * 1000 <= Date.now()) return null;\n if (this.issuer && claims.iss !== this.issuer) return null;\n return claims;\n }\n}\n\n/** What a route demands, after the route's own spec and the controller's\n * default have been reconciled. */\nexport interface EffectiveAuth {\n required: boolean;\n role?: string;\n verifiedEmail: boolean;\n}\n\n/**\n * Reconcile route-level and controller-level auth.\n *\n * The route's own spec wins when it says anything at all; otherwise the\n * controller's default applies; when NEITHER speaks, the answer is `required`.\n * That last clause is the whole point — a route that forgot to declare must be\n * closed, not open. (Measured: an engine that only read the route level served\n * a controller marked `auth: false` as 401, and would have served the reverse\n * mistake as an open endpoint.)\n */\nexport function effectiveAuth(routeAuth: unknown, controllerAuth: unknown): EffectiveAuth {\n const spec = routeAuth !== undefined ? routeAuth : controllerAuth;\n if (spec === false) return { required: false, verifiedEmail: false };\n if (spec === true || spec === undefined || spec === null) return { required: true, verifiedEmail: false };\n if (typeof spec !== \"object\") return { required: true, verifiedEmail: false };\n\n const o = spec as { required?: unknown; role?: unknown; verifiedEmail?: unknown };\n const role = typeof o.role === \"string\" && o.role.trim() !== \"\" ? o.role.trim() : undefined;\n return {\n required: o.required !== false,\n role,\n verifiedEmail: o.verifiedEmail === true,\n };\n}\n","/**\n * engine/ratelimit.ts — the customer's own per-route limit, enforced here.\n *\n * This is the PRODUCT feature (`@Get(\"/x\", { rateLimit: { max, window } })`),\n * not a quota the platform imposes. It runs in this process, on this pod,\n * because the route table lives here: the edge proxies by path and has never\n * seen a route's options, so teaching it would mean shipping the table twice\n * and keeping the copies in step.\n *\n * Fixed window, in memory. A single-tenant backend is the whole stack rather\n * than a shard of it, so \"in process\" is not an approximation. A restart\n * forgets the window, which for an endpoint guard fails in the right\n * direction: it forgives, it never invents a refusal.\n */\n\nexport interface RateLimitRule {\n max: number;\n /** Seconds. */\n window: number;\n}\n\ninterface Bucket {\n count: number;\n resetAt: number;\n}\n\nexport class RateLimiter {\n private buckets = new Map<string, Bucket>();\n /** Bound on distinct keys held, so an attacker cycling identities cannot\n * grow this map without limit. On overflow the oldest windows are dropped —\n * forgiving, consistent with the restart behaviour above. */\n constructor(private readonly maxKeys = 100_000) {}\n\n /**\n * Identify the caller: the signed-in user when the route resolved one,\n * otherwise the address the edge forwarded. Callers the edge did not\n * identify share one bucket — deliberately conservative, since the\n * alternative is a limit anyone resets by omitting a header.\n */\n static key(routeId: string, userId: string | undefined, headers: Headers): string {\n if (userId) return `${routeId}\\x00u:${userId}`;\n const fwd = headers.get(\"x-forwarded-for\");\n const addr = (fwd ? (fwd.split(\",\")[0] ?? \"\") : (headers.get(\"x-real-ip\") ?? \"\")).trim();\n return `${routeId}\\x00a:${addr || \"anonymous\"}`;\n }\n\n /**\n * @returns `null` when the request may proceed, or the number of seconds to\n * wait (never 0 — a caller told to wait 0 comes straight back to the same\n * refusal).\n */\n check(rule: RateLimitRule | undefined, key: string, now: number): number | null {\n if (!rule || !(rule.max > 0) || !(rule.window > 0)) return null;\n\n const bucket = this.buckets.get(key);\n if (!bucket || now >= bucket.resetAt) {\n if (this.buckets.size >= this.maxKeys) this.evict(now);\n this.buckets.set(key, { count: 1, resetAt: now + rule.window * 1000 });\n return null;\n }\n if (bucket.count < rule.max) {\n bucket.count++;\n return null;\n }\n return Math.max(1, Math.ceil((bucket.resetAt - now) / 1000));\n }\n\n /** Drop expired windows; if none are expired, drop the earliest-resetting\n * quarter so the map cannot wedge at the ceiling. */\n private evict(now: number): void {\n let dropped = 0;\n for (const [k, b] of this.buckets) {\n if (now >= b.resetAt) {\n this.buckets.delete(k);\n dropped++;\n }\n }\n if (dropped > 0) return;\n const byReset = [...this.buckets.entries()].sort((a, b) => a[1].resetAt - b[1].resetAt);\n for (let i = 0; i < Math.ceil(byReset.length / 4); i++) {\n const victim = byReset[i];\n if (victim) this.buckets.delete(victim[0]);\n }\n }\n\n /** Test seam. */\n get size(): number {\n return this.buckets.size;\n }\n}\n","/**\n * engine/cache.ts — the cache, in this process's own memory.\n *\n * A stack that serves one tenant has nobody to share a cache with; palsvc drew\n * exactly this conclusion for itself when it dropped Redis, and a backend that\n * reaches over a network for a hash map is paying a round trip for nothing.\n *\n * JSON-typed, matching `CacheClient`: values round-trip as whatever was stored.\n */\nimport type { CacheClient } from \"../endpoint.js\";\n\ninterface Entry {\n value: unknown;\n /** Epoch ms, or 0 for \"no expiry\". */\n expiresAt: number;\n}\n\nexport interface MemoryCacheOptions {\n /** Bound on entries held. On overflow the soonest-to-expire are dropped. */\n maxEntries?: number;\n /** Injectable clock, for tests. */\n now?: () => number;\n}\n\n/**\n * Build an in-process cache.\n *\n * `getOrSet` is single-flight: concurrent misses on one key share one fill, so\n * a cold key under load does not become N identical expensive calls.\n */\nexport function makeMemoryCache(opts: MemoryCacheOptions = {}): CacheClient {\n const maxEntries = opts.maxEntries ?? 50_000;\n const now = opts.now ?? (() => Date.now());\n const store = new Map<string, Entry>();\n const inflight = new Map<string, Promise<unknown>>();\n\n const live = (key: string): Entry | undefined => {\n const e = store.get(key);\n if (!e) return undefined;\n if (e.expiresAt !== 0 && e.expiresAt <= now()) {\n store.delete(key);\n return undefined;\n }\n return e;\n };\n\n const evict = () => {\n const t = now();\n let dropped = 0;\n for (const [k, e] of store) {\n if (e.expiresAt !== 0 && e.expiresAt <= t) {\n store.delete(k);\n dropped++;\n }\n }\n if (dropped > 0) return;\n // Nothing expired: drop the soonest-to-expire quarter (entries with no\n // expiry sort last, so an unbounded writer sheds its own oldest first).\n const order = [...store.entries()].sort(\n (a, b) => (a[1].expiresAt || Infinity) - (b[1].expiresAt || Infinity),\n );\n for (let i = 0; i < Math.ceil(order.length / 4); i++) {\n const victim = order[i];\n if (victim) store.delete(victim[0]);\n }\n };\n\n const set = async (key: string, value: unknown, ttl?: number): Promise<void> => {\n if (store.size >= maxEntries && !store.has(key)) evict();\n store.set(key, { value, expiresAt: ttl && ttl > 0 ? now() + ttl * 1000 : 0 });\n };\n\n return {\n async get<T = unknown>(key: string): Promise<T | null> {\n const e = live(key);\n return e ? (e.value as T) : null;\n },\n set,\n async del(key: string): Promise<void> {\n store.delete(key);\n },\n async incr(key: string): Promise<number> {\n const e = live(key);\n const next = (typeof e?.value === \"number\" ? e.value : 0) + 1;\n store.set(key, { value: next, expiresAt: e?.expiresAt ?? 0 });\n return next;\n },\n async getOrSet<T>(key: string, ttl: number, fn: () => Promise<T> | T): Promise<T> {\n const hit = live(key);\n if (hit) return hit.value as T;\n\n const running = inflight.get(key);\n if (running) return running as Promise<T>;\n\n const fill = (async () => {\n try {\n const value = await fn();\n await set(key, value, ttl);\n return value;\n } finally {\n inflight.delete(key);\n }\n })();\n inflight.set(key, fill);\n return fill as Promise<T>;\n },\n };\n}\n","/**\n * engine/db.ts — a real pooled connection, and the identity every request is\n * bound to inside it.\n *\n * # Why one transaction per request\n *\n * In the isolate architecture every `Database.*` call was its own HTTP hop to a\n * capability surface, so two writes in one handler could not be atomic — a\n * handler that wrote and then threw left the first write behind. Here the whole\n * request runs inside one transaction: it commits when the handler returns and\n * rolls back when it throws. Atomicity stops being something the author has to\n * ask for.\n *\n * # Why it opens lazily\n *\n * A handler that touches no table must cost no round trip. Opening eagerly cost\n * four (BEGIN + bind + … + COMMIT) on endpoints that never query — measured at\n * 1,243 rps against 31,579 for the same endpoint once the open became lazy.\n *\n * # How the caller's identity reaches RLS\n *\n * One statement, not three:\n *\n * select set_config('role',$1,true),\n * set_config('search_path','public',true),\n * set_config('request.jwt.claims',$2,true)\n *\n * `set_config(..., is_local => true)` is transaction-scoped exactly like\n * `SET LOCAL`, but takes BOUND PARAMETERS, which `SET LOCAL` cannot. So the\n * role and the caller's claims travel as parameters — user identity is never\n * spliced into SQL text — and `auth.uid()` resolves inside RLS policies, which\n * means the row filter is enforced by Postgres rather than by our code.\n */\nimport type { DBClient, DBOps } from \"../endpoint.js\";\nimport type {\n TxPlanBody,\n TxPlanOpResult,\n TxPlanResponse,\n TxWireExpr,\n TxWireOp,\n TxWireRef,\n TxWireValue,\n} from \"../db/tx-plan.js\";\n\n/** The slice of a SQL driver the engine uses. `Bun.sql` satisfies it. */\nexport interface SqlDriver {\n /** Run a parameterised statement. */\n unsafe(sql: string, params?: unknown[]): Promise<unknown>;\n /** Open a transaction; the driver commits when `cb` resolves and rolls back\n * when it rejects. */\n begin<T>(cb: (tx: SqlTx) => Promise<T>): Promise<T>;\n}\n\nexport interface SqlTx {\n unsafe(sql: string, params?: unknown[]): Promise<unknown>;\n savepoint<T>(cb: (sp: SqlTx) => Promise<T>): Promise<T>;\n}\n\ntype Row = Record<string, unknown>;\n\n/** Quote an identifier. Table and column names reach here from the schema and\n * from handler arguments; neither is allowed to become syntax. */\nexport function quoteIdent(name: string): string {\n return `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\nconst BIND_SQL =\n \"select set_config('role',$1,true), set_config('search_path','public',true), set_config('request.jwt.claims',$2,true)\";\n\n/**\n * A transaction that does not exist until somebody reads or writes.\n *\n * `begin(cb)` is callback-scoped, so to hold one open across a whole request\n * the callback parks on a promise this object controls: `commit()` resolves it\n * (the driver commits), `rollback()` rejects it (the driver rolls back). A\n * request that never touches the database never enters the callback at all.\n */\nexport function createLazyTransaction(\n sql: SqlDriver,\n role: string,\n claimsJson: string,\n options: { lockTimeout?: string } = {},\n) {\n const { lockTimeout } = options;\n // `lock_timeout` travels as a BOUND parameter like the other two, so a value\n // from configuration can never become SQL text.\n const bindSql = lockTimeout ? `${BIND_SQL}, set_config('lock_timeout',$3,true)` : BIND_SQL;\n const bindParams = lockTimeout ? [role, claimsJson, lockTimeout] : [role, claimsJson];\n\n let opening: Promise<SqlTx> | null = null;\n let release: (() => void) | null = null;\n let fail: ((e: unknown) => void) | null = null;\n let settled: Promise<unknown> | null = null;\n\n const ensure = (): Promise<SqlTx> => {\n if (opening) return opening;\n opening = new Promise<SqlTx>((resolveTx, rejectTx) => {\n const parked = new Promise<void>((res, rej) => {\n release = res;\n fail = rej;\n });\n settled = sql\n .begin(async (tx) => {\n await tx.unsafe(bindSql, bindParams);\n resolveTx(tx);\n await parked;\n })\n .catch((e: unknown) => {\n // Both paths matter: a caller awaiting `ensure()` must see the\n // failure, and `commit()` must not hang waiting for a dead driver.\n rejectTx(e);\n throw e;\n });\n });\n return opening;\n };\n\n return {\n ensure,\n get opened(): boolean {\n return opening !== null;\n },\n async commit(): Promise<void> {\n if (!opening) return;\n release!();\n await settled;\n },\n async rollback(reason: unknown): Promise<void> {\n if (!opening) return;\n fail!(reason);\n // The rejection is the mechanism, not an error to report twice.\n await settled?.catch(() => undefined);\n },\n };\n}\n\nexport type LazyTransaction = ReturnType<typeof createLazyTransaction>;\n\n/** Either a live driver transaction or the lazy holder above. */\ntype TxLike = SqlTx | LazyTransaction;\n\nconst resolveTx = async (tx: TxLike): Promise<SqlTx> =>\n typeof (tx as LazyTransaction).ensure === \"function\"\n ? await (tx as LazyTransaction).ensure()\n : (tx as SqlTx);\n\n/**\n * What a row LOOKS like to the code that reads it.\n *\n * The driver hands back a `Date` for every timestamp column, while the typed\n * surface this SDK generates for the same table says `string` — and so does the\n * response schema derived from a handler's return type, and so does the JSON on\n * the wire. So a handler that returned a row straight from `Database.tables.x`\n * failed its OWN declared type: measured on 2026-08-16, `POST /todos` answered\n * 500 `output_invalid` with \"expected string, received date\" for `created_at`,\n * from code that had done nothing wrong.\n *\n * ISO-8601, because that is what the schema, the generated client and every\n * JSON reader already agree on.\n */\nfunction asWireValue(value: unknown): unknown {\n if (value instanceof Date) return value.toISOString();\n if (Array.isArray(value)) return value.map(asWireValue);\n return value;\n}\n\n/** Every row a caller receives passes through here. */\nfunction asWireRow<T>(row: T): T {\n if (row === null || typeof row !== \"object\") return row;\n const out: Row = {};\n for (const [key, value] of Object.entries(row as Row)) out[key] = asWireValue(value);\n return out as T;\n}\n\nfunction asWireRows(rows: Row[]): Row[] {\n return rows.map((row) => asWireRow(row));\n}\n\n/** pgvector text literal: '[v1,v2,...]' — the driver would otherwise bind a\n * Postgres ARRAY, which vector's input function refuses. (FR-008) */\nfunction toVectorLiteral(v: number[]): string {\n return `[${v.join(\",\")}]`;\n}\n\n/**\n * The vector-typed column names of one table, read from the installed schema.\n *\n * Ops receive the PHYSICAL table name (`withTables` maps key → `def.name`), so\n * the lookup matches `def.name ?? key`. A column arrives either as a\n * ColumnBuilder (with `_def`) or as the plain def — the same double reading\n * schema-json does, for the same reason: both shapes exist in the wild.\n */\nfunction vectorColumnsOf(schema: typeof currentSchema, table: string): Set<string> {\n const out = new Set<string>();\n for (const [key, def] of Object.entries(schema.tables ?? {})) {\n if ((def.name ?? key) !== table) continue;\n for (const [col, c] of Object.entries(def.columns ?? {})) {\n const d = (c !== null && typeof c === \"object\" && \"_def\" in c\n ? (c as { _def: unknown })._def\n : c) as { type?: unknown } | null;\n if (d !== null && typeof d === \"object\" && d.type === \"vector\") out.add(col);\n }\n }\n return out;\n}\n\n/** The driver hands a vector back as its text literal; JSON.parse restores the\n * number[] the typed surface declares — the literal is valid JSON (C-9). A null\n * (row without an embedding yet) passes through untouched. */\nfunction reviveVectors<T>(row: T, vectorCols: Set<string>): T {\n if (row === null || typeof row !== \"object\" || vectorCols.size === 0) return row;\n const out = row as Row;\n for (const col of vectorCols) {\n const v = out[col];\n if (typeof v === \"string\") out[col] = JSON.parse(v);\n }\n return row;\n}\n\n/** `asWireRow`, made table-aware: what the table's schema calls a vector comes\n * back as number[]. Rows from tables the schema does not know pass unchanged. */\nfunction asTableRow<T>(table: string, row: T): T {\n return reviveVectors(asWireRow(row), vectorColumnsOf(currentSchema, table));\n}\n\nfunction asTableRows(table: string, rows: Row[]): Row[] {\n const vectorCols = vectorColumnsOf(currentSchema, table);\n return rows.map((row) => reviveVectors(asWireRow(row), vectorCols));\n}\n\n/** Bind parameters for one write: a value headed for a vector column becomes\n * the pgvector text literal; everything else binds as-is. (FR-008) */\nfunction asBindParams(table: string, cols: string[], data: Row): unknown[] {\n const vectorCols = vectorColumnsOf(currentSchema, table);\n return cols.map((c) => {\n const v = data[c];\n return Array.isArray(v) && vectorCols.has(c) ? toVectorLiteral(v) : v;\n });\n}\n\n// ---------------------------------------------------------------------------\n// search (T017, FR-013..016) — tek-SQL hibrit RRF.\n// ---------------------------------------------------------------------------\n\n/** Metrik → operatör. Tek kelimeden türetilir; opclass/operatör asla yüzeye\n * çıkmaz, uyumsuzluk yapısal olarak imkânsız (D-5, prod arıza #2). */\n// ≤ bu kadar satır eşleşiyorsa vektör kolu EXACT taranır (10K×1536d ≈ 10-20ms;\n// HNSW'nin seçici filtrede recall çöküşüne karşı — ölçüm: engine/db.ts NFR-005 yorumu).\nconst SELECTIVITY_EXACT_THRESHOLD = 10000;\n\nconst METRIC_OPERATOR: Record<string, string> = {\n cosine: \"<=>\",\n euclidean: \"<->\",\n inner_product: \"<#>\",\n};\n\ninterface SearchLeg {\n column: string;\n metric: string;\n /** Auto-embed beyanı (authoring EmbeddingModelRef — runtime şeması defineSchema çıktısıdır). */\n embed?: { model: string; apiKeyName: string; baseURL?: string; dimensions?: number };\n}\n\ninterface SearchConfig {\n pk: string;\n cols: string[];\n colSet: Set<string>;\n ftsCols: string[];\n legs: SearchLeg[];\n}\n\n/** Tablonun arama konfigürasyonu, runtime'ın kurduğu şemadan (setSchema — C-9).\n * `search` bloğu yoksa vector kolonlarının VARLIĞI yeter (D-3/FR-013): her\n * vector kolonu cosine metrikli bir leg olur. Tablo şemada yoksa null. */\nfunction searchConfigFor(table: string): SearchConfig | null {\n const t = currentSchema.tables?.[table];\n if (!t) return null;\n const columns = t.columns ?? {};\n const defOf = (c: unknown): { type?: string } =>\n c !== null && typeof c === \"object\" && \"_def\" in (c as Record<string, unknown>)\n ? ((c as { _def: { type?: string } })._def)\n : ((c ?? {}) as { type?: string });\n const cols = Object.keys(columns);\n const vectorCols = cols.filter((c) => defOf((columns as Record<string, unknown>)[c]).type === \"vector\");\n // PK adı ŞEMADAN (review I3): Go tarafı tek-kolon PK'nın adını bilinçli\n // serbest bırakır (FR-020 \"adı serbesttir\") — SQL'e 'id' gömmek, pk'sı\n // başka adla declare edilmiş searchable tabloyu runtime 500'üne çevirirdi.\n const defOfFull = (c: unknown): { type?: string; primaryKey?: boolean } =>\n c !== null && typeof c === \"object\" && \"_def\" in (c as Record<string, unknown>)\n ? ((c as { _def: { type?: string; primaryKey?: boolean } })._def)\n : ((c ?? {}) as { type?: string; primaryKey?: boolean });\n const pkCols = cols.filter((c) => defOfFull((columns as Record<string, unknown>)[c]).primaryKey === true);\n const pk = pkCols.length === 1 ? pkCols[0]! : cols.includes(\"id\") ? \"id\" : null;\n if (pk === null) {\n throw new Error(\n `search(${table}): tek-kolon primary key bulunamadı — arama sıralaması ve satır birleşimi PK ister (FR-020)`,\n );\n }\n const search = (t as { search?: { text?: string[]; vector?: unknown } }).search;\n const ftsCols = search?.text ?? [];\n const rawLegs = search?.vector === undefined ? [] : Array.isArray(search.vector) ? search.vector : [search.vector];\n let legs: SearchLeg[];\n if (rawLegs.length > 0) {\n legs = rawLegs.map((leg) => {\n const l = leg as { column?: string; metric?: string };\n const column = l.column ?? (vectorCols.length === 1 ? vectorCols[0]! : undefined);\n if (column === undefined) {\n throw new Error(`search(${table}): birden çok vector kolonu var — beyanda 'column' zorunlu (FR-010)`);\n }\n const model = (l as { model?: { model: string; apiKeyName?: string; baseURL?: string; dimensions?: number } }).model;\n return {\n column,\n metric: l.metric ?? \"cosine\",\n ...(model !== undefined\n ? { embed: { model: model.model, apiKeyName: model.apiKeyName ?? \"OPENAI_API_KEY\",\n ...(model.baseURL !== undefined ? { baseURL: model.baseURL } : {}),\n ...(model.dimensions !== undefined ? { dimensions: model.dimensions } : {}) } }\n : {}),\n };\n });\n } else {\n legs = vectorCols.map((column) => ({ column, metric: \"cosine\" }));\n }\n if (ftsCols.length === 0 && legs.length === 0) return null;\n return { pk, cols, colSet: new Set(cols), ftsCols, legs };\n}\n\n/** using → hedef leg. using yok + tek leg → o; using yok + çok leg → adlandırılmış\n * hata (model geçişinde seçim bilinçli olmalı); using yanlış → adlandırılmış hata. */\nfunction pickLeg(table: string, legs: SearchLeg[], using: string | undefined): SearchLeg | null {\n if (legs.length === 0) return null;\n if (using !== undefined) {\n const hit = legs.find((l) => l.column === using);\n if (!hit) {\n throw new Error(\n `search(${table}): using \"${using}\" bir vektör kolunu adlamıyor — mevcut: ${legs.map((l) => l.column).join(\", \")}`,\n );\n }\n return hit;\n }\n if (legs.length === 1) return legs[0]!;\n throw new Error(`search(${table}): birden çok vektör kolu var — 'using' ile seçin (FR-013) — salt metin arıyorsan mode:\\\"text\\\" kullan`);\n}\n\nconst WHERE_OPS: Record<string, string> = { gt: \">\", gte: \">=\", lt: \"<\", lte: \"<=\", neq: \"<>\" };\n\n/** where → SQL (FR-016): eşitlik + gt/gte/lt/lte/neq/in, AND'li. Kolon adı\n * şemadan doğrulanır — bilinmeyen ad SQL'e ulaşmadan, adıyla reddedilir. */\nfunction compileWhere(\n table: string,\n colSet: Set<string>,\n where: Record<string, unknown>,\n add: (v: unknown) => string,\n): string {\n const parts: string[] = [];\n for (const [col, cond] of Object.entries(where)) {\n if (!colSet.has(col)) {\n throw new Error(`search(${table}): where kolonu \"${col}\" tabloda yok (FR-016)`);\n }\n const q = `t.${quoteIdent(col)}`;\n if (cond !== null && typeof cond === \"object\" && !Array.isArray(cond)) {\n for (const [op, v] of Object.entries(cond as Record<string, unknown>)) {\n if (op === \"in\") {\n if (!Array.isArray(v)) throw new Error(`search(${table}): where.${col}.in bir dizi olmalı`);\n if (v.length === 0) {\n // Boş in-listesi \"hiçbir satır\" demektir — sessiz tam-tarama yerine\n // anlamı SQL'e açıkça yaz (review I5).\n parts.push(\"false\");\n continue;\n }\n // Placeholder genişletmesi: her eleman AYRI parametre. `= ANY($n)`\n // dizi bind'i sürücüde Postgres array literal'ine çevrilmiyor ve\n // canlıda `malformed array literal: \"ops,general\"` 500'ü veriyordu\n // (verify 19-3b, 2026-08-28). IN listesi tip-agnostik ve sürücüden\n // bağımsız; boş liste yukarıda açık `false`.\n parts.push(`${q} IN (${v.map((x) => add(x)).join(\", \")})`);\n } else if (op in WHERE_OPS) {\n parts.push(`${q} ${WHERE_OPS[op]} ${add(v)}`);\n } else {\n throw new Error(`search(${table}): where.${col} bilinmeyen operatör \"${op}\" (gt/gte/lt/lte/neq/in)`);\n }\n }\n } else {\n parts.push(`${q} = ${add(cond)}`);\n }\n }\n return parts.length === 0 ? \"\" : ` AND ${parts.join(\" AND \")}`;\n}\n\n/** vector extension'ının yaşadığı şema (C-10): canlı stack'te public, taze\n * stack'te extensions — operatör bununla nitelenir, search_path'e GÜVENİLMEZ\n * (M-1 ölçümü; veri düzlemi search_path=public kurar, handler.go:101). */\nlet cachedVectorSchema: string | null = null;\n/** GUC + (soğukken) extension-şema çözümü TEK statement'ta (review I4). */\nasync function vectorSchemaWithGuc(runner: { unsafe(sql: string, params?: unknown[]): Promise<unknown> }): Promise<string> {\n if (cachedVectorSchema !== null) {\n // NFR-005 kapanışı, ÖLÇÜMLE (40K×384, %1 filtre, exact referans):\n // relaxed (vars. 20K tavan) → recall@20 0.62\n // relaxed + max_scan_tuples=200K → 0.64 (tavan tek başına YETMEZ:\n // iterative scan LIMIT dolunca durur, bulduğu ilk N \"en yakın N\" değil)\n // relaxed + 200K + ef_search=200 → 0.95 (asıl düğme aday genişliği)\n // ef_search=200 normal sorguya ms-mertebesi maliyet ekler; karşılığı\n // seçici filtrede doğru sonuç. strict_order ölçümde ek kazanç vermedi.\n await runner.unsafe(\n \"select set_config('hnsw.iterative_scan','relaxed_order',true), set_config('hnsw.max_scan_tuples','200000',true), set_config('hnsw.ef_search','200',true)\",\n );\n return cachedVectorSchema;\n }\n const rows = (await runner.unsafe(\n \"select set_config('hnsw.iterative_scan','relaxed_order',true), set_config('hnsw.max_scan_tuples','200000',true), set_config('hnsw.ef_search','200',true), \" +\n \"(select n.nspname from pg_extension e join pg_namespace n on n.oid = e.extnamespace where e.extname = 'vector') as nspname\",\n )) as { nspname?: string }[];\n const name = rows?.[0]?.nspname;\n if (typeof name !== \"string\" || name === \"\") {\n throw new Error(\"pgvector extension kurulu değil — vector araması çalışamaz (extensions beyanı deploy'dan geçti mi?)\");\n }\n cachedVectorSchema = name;\n return name;\n}\n\n/** Test edilebilirlik: setSchema gibi, cache'i sıfırlar. */\nexport function resetVectorSchemaCache(): void {\n cachedVectorSchema = null;\n}\n\n// ---------------------------------------------------------------------------\n// Sorgu-anı embed (T024, FR-025) — CLAIM-N1: POST /v1/embeddings.\n// ---------------------------------------------------------------------------\n\ntype SecretReader = (name: string) => Promise<string | null>;\nlet secretReader: SecretReader | null = null;\n/** Runtime boot'ta bağlanır (setSchema ile AYNI kanal deseni): vault'tan\n * secret okuma. Engine anahtarın yalnız ADINI bilir, değeri buradan akar. */\nexport function setSecretReader(fn: SecretReader | null): void {\n secretReader = fn;\n}\n\ntype EmbedFetch = (url: string, init?: RequestInit) => Promise<Response>;\nlet embedFetch: EmbedFetch = (url, init) => fetch(url, init);\n/** Test dikişi: sağlayıcı çağrısının fetch'i. Üretimde global fetch. */\nexport function setEmbedFetch(fn: EmbedFetch | null): void {\n embedFetch = fn ?? ((url, init) => fetch(url, init));\n}\n\n/** Sorgu metnini beyan edilen modelle vektörler (CLAIM-N1). Tek deneme, 10s\n * timeout — retry worker'ın işidir, sorgu yolunun değil. Hata apiKeyName'i\n * ADLANDIRIR; anahtar yoksa sağlayıcı hiç aranmaz. */\nasync function embedQuery(\n embed: NonNullable<SearchLeg[\"embed\"]>,\n text: string,\n): Promise<number[]> {\n if (secretReader === null) {\n throw new Error(`query embed: secret reader bağlanmamış — ${embed.apiKeyName} okunamıyor`);\n }\n const key = await secretReader(embed.apiKeyName);\n if (key === null || key === \"\") {\n throw new Error(`query embed: vault'ta ${embed.apiKeyName} yok (FR-021/FR-025)`);\n }\n const url = (embed.baseURL ?? \"https://api.openai.com/v1\").replace(/\\/$/, \"\") + \"/embeddings\";\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), 10_000);\n try {\n const res = await embedFetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Authorization: `Bearer ${key}` },\n body: JSON.stringify({\n model: embed.model,\n input: [text],\n ...(embed.dimensions !== undefined ? { dimensions: embed.dimensions } : {}),\n }),\n signal: controller.signal,\n });\n if (!res.ok) {\n throw new Error(`query embed: sağlayıcı ${res.status} döndü (${embed.apiKeyName} ile) — anahtar/model doğru mu?`);\n }\n const data = (await res.json()) as { data?: { embedding?: number[] }[] };\n const vec = data.data?.[0]?.embedding;\n if (!Array.isArray(vec)) {\n throw new Error(\"query embed: sağlayıcı yanıtında data[0].embedding yok (CLAIM-N1 şekli)\");\n }\n return vec;\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** The six string-keyed operations, plus an interactive `transaction`. */\nexport function createOps(tx: TxLike) {\n const at = () => resolveTx(tx);\n\n const ops = {\n async query(sql: string, params: unknown[] = []): Promise<Row[]> {\n return asWireRows((await (await at()).unsafe(sql, params)) as Row[]);\n },\n\n async insert(table: string, data: Row): Promise<Row> {\n const cols = Object.keys(data);\n if (cols.length === 0) throw new Error(`insert into ${table}: no columns given`);\n const placeholders = cols.map((_, i) => `$${i + 1}`).join(\", \");\n const sql =\n `INSERT INTO ${quoteIdent(table)} (${cols.map(quoteIdent).join(\", \")}) ` +\n `VALUES (${placeholders}) RETURNING *`;\n const rows = (await (await at()).unsafe(sql, asBindParams(table, cols, data))) as Row[];\n const inserted = rows[0];\n if (!inserted) {\n // RETURNING * with no row back means the write was filtered away — an\n // RLS WITH CHECK that rejected it, most often. Silence here would hand\n // the author `undefined` and a 500 three lines later.\n throw new Error(\n `insert into ${table} returned no row — the write was rejected (an RLS policy, most likely).`,\n );\n }\n return asTableRow(table, inserted);\n },\n\n async update(table: string, id: string, data: Row): Promise<Row | null> {\n const cols = Object.keys(data);\n if (cols.length === 0) return ops.findById(table, id);\n const assignments = cols.map((c, i) => `${quoteIdent(c)} = $${i + 1}`).join(\", \");\n const sql = `UPDATE ${quoteIdent(table)} SET ${assignments} WHERE id = $${cols.length + 1} RETURNING *`;\n const rows = (await (await at()).unsafe(sql, [...asBindParams(table, cols, data), id])) as Row[];\n return rows[0] ? asTableRow(table, rows[0]) : null;\n },\n\n async delete(table: string, id: string): Promise<void> {\n await (await at()).unsafe(`DELETE FROM ${quoteIdent(table)} WHERE id = $1`, [id]);\n },\n\n async findById(table: string, id: string): Promise<Row | null> {\n const rows = (await (await at()).unsafe(\n `SELECT * FROM ${quoteIdent(table)} WHERE id = $1`,\n [id],\n )) as Row[];\n return rows[0] ? asTableRow(table, rows[0]) : null;\n },\n\n async findMany(table: string, query: Row = {}): Promise<Row[]> {\n const cols = Object.keys(query);\n const where = cols.length\n ? ` WHERE ${cols.map((c, i) => `${quoteIdent(c)} = $${i + 1}`).join(\" AND \")}`\n : \"\";\n return asTableRows(table, (await (await at()).unsafe(\n `SELECT * FROM ${quoteIdent(table)}${where}`,\n cols.map((c) => query[c]),\n )) as Row[]);\n },\n\n /**\n * Tek-SQL hibrit arama (FR-014): iki kol CTE + FULL OUTER JOIN + RRF\n * (1/(50+rank), CLAIM-N4). Operatör şema-nitelikli (C-10, M-1); GUC\n * hnsw.iterative_scan=relaxed_order aynı tx'te set_config ile (CLAIM-N3 —\n * RLS/filtre altında LIMIT-altı dönüş açığını kapatır). Sorgu-anı embed\n * T024'te gelir; o zamana dek vector kolu yalnız params.vector ile koşar.\n */\n async search(\n table: string,\n params: {\n query?: string;\n vector?: number[];\n where?: Record<string, unknown>;\n limit?: number;\n using?: string;\n mode?: \"hybrid\" | \"text\" | \"vector\";\n } = {},\n ): Promise<Row[]> {\n const cfg = searchConfigFor(table);\n if (!cfg) {\n throw new Error(`search(${table}): tablo aranabilir değil — ne vector kolonu ne search beyanı var (FR-013)`);\n }\n const rawLimit = params.limit ?? 20;\n if (typeof rawLimit !== \"number\" || !Number.isFinite(rawLimit)) {\n throw new Error(`search(${table}): limit sonlu bir sayı olmalı, ${String(rawLimit)} verildi (FR-013)`);\n }\n const limit = Math.min(Math.max(1, Math.trunc(rawLimit)), 100);\n const pool = Math.max(limit * 3, 30);\n const wantText =\n params.mode !== \"vector\" && cfg.ftsCols.length > 0 && typeof params.query === \"string\" && params.query !== \"\";\n // Vektör kolu ancak GERÇEKTEN istenecekse çözülür (FR-015, review C1):\n // çok kollu tabloda salt-text arama 'using' zorunluluğuna TAKILMAZ.\n const anyEmbed = cfg.legs.some((l) => l.embed !== undefined);\n const vectorAsked =\n params.mode !== \"text\" &&\n (Array.isArray(params.vector) || params.using !== undefined || params.mode === \"vector\" ||\n (anyEmbed && typeof params.query === \"string\" && params.query !== \"\"));\n const leg = vectorAsked ? pickLeg(table, cfg.legs, params.using) : null;\n let qv: number[] | null = Array.isArray(params.vector) ? params.vector : null;\n if (qv === null && leg?.embed !== undefined && typeof params.query === \"string\" && params.query !== \"\") {\n // FR-025: beyan edilen modelle TEK sağlayıcı çağrısı. Başarısızlıkta\n // FR-015 düşüşü: text kolu koşulabiliyorsa arama ONUNLA döner; yoksa\n // adlandırılmış hata (sessiz boş dönüş asla).\n try {\n qv = await embedQuery(leg.embed, params.query);\n } catch (e) {\n if (!wantText) throw e;\n qv = null;\n }\n }\n const wantVector = leg !== null && qv !== null;\n if (!wantText && !wantVector) {\n throw new Error(\n `search(${table}): koşulabilir kol yok — metin için 'query' (FTS beyanı gerekir), semantik için 'vector' verin (FR-015)`,\n );\n }\n const bind: unknown[] = [];\n const add = (v: unknown): string => {\n bind.push(v);\n return `$${bind.length}`;\n };\n const whereSql = compileWhere(table, cfg.colSet, params.where ?? {}, add);\n const live = await at();\n const K = 50;\n let semSql = \"\";\n let kwSql = \"\";\n if (wantVector && leg) {\n // GUC yalnız hnsw taramasını etkiler — salt-text arama onu hiç koşmaz\n // (review I4). Soğuk yolda extension-şema lookup'ı AYNI statement'a\n // biner: sıcak yol +1, soğuk yol +1 (eskiden +2) round-trip; kalan tek\n // ekstra tur NFR-002'de karar kaydıyla kabul edildi.\n const sch = await vectorSchemaWithGuc(live);\n const op = METRIC_OPERATOR[leg.metric] ?? METRIC_OPERATOR.cosine;\n // SEÇİCİ FİLTREDE EXACT YOL (NFR-005 kapanışı, ölçümle): HNSW iterative\n // scan %1 seçicilikte 100K ölçeğinde hedefe ULAŞAMIYOR — GUC gridi\n // (relaxed/strict × max_scan_tuples 200K × ef_search 200..1000) en iyi\n // 0.38 recall verdi. Filtreli küme küçükse doğru cevap index'i HİÇ\n // kullanmamak: ≤10K satırda exact mesafe taraması ms'ler sürer ve\n // recall=1.0. Seçicilik bir probe ile ölçülür (RLS aynı tx'te — sayım\n // tenant'ın görebildiği satırlarla); index'i devre dışı bırakmak için\n // sıralama ifadesine + 0.0 eklenir (planner ifade-eşleşmesini kaybeder;\n // EXPLAIN'le doğrulandı — GUC'suz, tx yan etkisiz).\n let exactOrder = \"\";\n if (whereSql !== \"\") {\n const probeRows = (await live.unsafe(\n `SELECT count(*)::int AS n FROM (SELECT 1 FROM ${quoteIdent(table)} t WHERE t.${quoteIdent(leg.column)} IS NOT NULL${whereSql} LIMIT ${SELECTIVITY_EXACT_THRESHOLD + 1}) s`,\n bind.slice(),\n )) as { n?: number }[];\n const n = probeRows?.[0]?.n;\n if (typeof n === \"number\" && n <= SELECTIVITY_EXACT_THRESHOLD) {\n exactOrder = \" + 0.0\";\n }\n }\n const vp = add(toVectorLiteral(qv!));\n semSql =\n `SELECT t.${quoteIdent(cfg.pk)} AS id, ROW_NUMBER() OVER (ORDER BY (t.${quoteIdent(leg.column)} OPERATOR(${quoteIdent(sch)}.${op}) ${vp}::${quoteIdent(sch)}.vector)${exactOrder}) AS r ` +\n `FROM ${quoteIdent(table)} t WHERE t.${quoteIdent(leg.column)} IS NOT NULL${whereSql} ORDER BY r LIMIT ${pool}`;\n }\n if (wantText) {\n const qp = add(params.query);\n kwSql =\n `SELECT t.${quoteIdent(cfg.pk)} AS id, ROW_NUMBER() OVER (ORDER BY ts_rank_cd(t.palbase_fts, websearch_to_tsquery('simple', ${qp})) DESC) AS r ` +\n `FROM ${quoteIdent(table)} t WHERE t.palbase_fts @@ websearch_to_tsquery('simple', ${qp})${whereSql} ORDER BY r LIMIT ${pool}`;\n }\n const colList = cfg.cols.map((c) => `t.${quoteIdent(c)}`).join(\", \");\n let sql: string;\n if (semSql !== \"\" && kwSql !== \"\") {\n sql =\n `WITH sem AS (${semSql}), kw AS (${kwSql}), fused AS (` +\n `SELECT COALESCE(sem.id, kw.id) AS id, ` +\n `(COALESCE(1.0/(${K} + sem.r), 0) + COALESCE(1.0/(${K} + kw.r), 0))::float8 AS _score ` +\n `FROM sem FULL OUTER JOIN kw ON sem.id = kw.id) ` +\n `SELECT ${colList}, fused._score AS _score FROM fused ` +\n `JOIN ${quoteIdent(table)} t ON t.${quoteIdent(cfg.pk)} = fused.id ` +\n `ORDER BY fused._score DESC, t.${quoteIdent(cfg.pk)} LIMIT ${limit}`;\n } else {\n const single = semSql !== \"\" ? `sem AS (${semSql})` : `kw AS (${kwSql})`;\n const alias = semSql !== \"\" ? \"sem\" : \"kw\";\n sql =\n `WITH ${single} ` +\n `SELECT ${colList}, (1.0/(${K} + ${alias}.r))::float8 AS _score FROM ${alias} ` +\n `JOIN ${quoteIdent(table)} t ON t.${quoteIdent(cfg.pk)} = ${alias}.id ` +\n `ORDER BY _score DESC, t.${quoteIdent(cfg.pk)} LIMIT ${limit}`;\n }\n const rows = (await live.unsafe(sql, bind)) as Row[];\n return asTableRows(table, rows);\n },\n\n /** A real SAVEPOINT inside the request's transaction. */\n async transaction<T>(cb: (t: unknown) => Promise<T>): Promise<T> {\n const live = await at();\n return live.savepoint(async (sp) => cb(withTables(createOps(sp), currentSchema)));\n },\n\n /**\n * Execute a whole transaction plan — what `Database.transaction(fn)` builds.\n *\n * WHY IT RUNS HERE. The platform used to carry a complete implementation\n * of this at `/internal-api/db/tx`, for tenant code that ran in an isolate\n * with no connection of its own. Running the plan there means running it on\n * a DIFFERENT connection: a transaction would not see the uncommitted\n * writes of the request that started it, and the two would hold separate\n * RLS bindings of the same identity. In this stack the tenant's code and\n * the connection share a process, so the plan runs on the request's own\n * transaction inside one SAVEPOINT — and that surface was removed on\n * 2026-08-15, once this was the last thing that could have called it.\n *\n * Until 2026-08-15 it ran NOWHERE: `runTxPlan` called `transport.txPlan` and\n * nothing here implemented it, so a live handler answered\n * \"transport.txPlan is not a function\" while every test that covered\n * transactions passed against a mock that did implement it.\n */\n async txPlan(plan: TxPlanBody): Promise<TxPlanResponse> {\n const live = await at();\n // ONE savepoint for the whole plan: a failed expectation must undo the\n // transaction the author wrote, and nothing outside it.\n return live.savepoint(async (sp) => {\n const results: TxPlanOpResult[] = [];\n for (const op of plan.ops) {\n const rows = asTableRows(op.table, await runPlanOp(sp, op, results)) as typeof results[number][\"rows\"];\n const result: TxPlanOpResult = { rows, rows_affected: rows.length };\n results.push(result);\n assertGuard(op, result);\n }\n return { results };\n });\n },\n } satisfies DBOps & Record<string, unknown>;\n\n return ops;\n}\n\n/** The schema whose table names the typed `.tables` surface is built from —\n * and, per table, whose columns the vector transform reads. */\nlet currentSchema: {\n tables?: Record<string, { name?: string; columns?: Record<string, unknown> }>;\n} = {};\n\n/** Install the project's `defineSchema()` result. Called once at boot. */\nexport function setSchema(schema: unknown): void {\n // Yeni şema kurulumu yeni bir bağlanma demektir: vector extension'ının\n // şeması da yeniden çözülür (review I3 — iki DB'li süreçte bayat cache,\n // public↔extensions ikiliğini sessizce yanlış tarafa kilitlerdi).\n cachedVectorSchema = null;\n const s = schema as { default?: unknown } | undefined;\n currentSchema = ((s && \"default\" in s ? s.default : s) ?? {}) as typeof currentSchema;\n}\n\n/**\n * Merge the typed `.tables` accessor onto a raw op surface.\n *\n * Mirrors what the pod runtime does, including the recursive application to the\n * transaction callback: without it `tx.tables.rooms.insert(...)` throws\n * \"Cannot read properties of undefined\".\n */\nexport function withTables<T extends ReturnType<typeof createOps>>(\n ops: T,\n schema: { tables?: Record<string, { name?: string }> } = currentSchema,\n): T & { tables: Record<string, unknown> } {\n const tables: Record<string, unknown> = {};\n for (const key of Object.keys(schema.tables ?? {})) {\n const name = schema.tables?.[key]?.name ?? key;\n tables[key] = {\n insert: (data: Row) => ops.insert(name, data),\n update: (id: string, data: Row) => ops.update(name, id, data),\n delete: (id: string) => ops.delete(name, id),\n findById: (id: string) => ops.findById(name, id),\n findMany: (query?: Row) => ops.findMany(name, query ?? {}),\n };\n }\n const base: Record<string, unknown> = Object.create(null);\n return Object.assign(base, ops, { tables });\n}\n\n// ── the two identities one request may speak with ──────────────────────────\n\n/**\n * How long a statement on the SERVICE transaction may wait for a row lock.\n *\n * The bound exists because `asService()` runs in a SECOND transaction on a\n * SECOND connection (see {@link createRequestDatabase} for why it must). A\n * handler that writes a row through `Database.*` and then touches the same row\n * through `Database.asService()` is waiting on a lock held by a transaction\n * that cannot commit until the handler returns — a wait that can never end.\n * Unbounded, that hangs the request AND holds two pool connections for as long\n * as the process lives; a few of those and the runtime stops answering at all.\n *\n * 5s, from the two numbers around it: a healthy contended write resolves in\n * milliseconds, and the edge cuts a tenant request at 60s\n * (v2/deploy/envoy/routes.yaml, the catch-all route).\n * So the failure arrives as a legible error at the caller instead of a 504 with\n * both connections still held.\n */\nconst SERVICE_LOCK_TIMEOUT = \"5s\";\n\n/** Postgres raises 55P03 (lock_not_available) when `lock_timeout` fires. */\nfunction isLockTimeout(e: unknown): boolean {\n const code = (e as { code?: unknown } | null)?.code;\n const message = String((e as { message?: unknown } | null)?.message ?? \"\");\n return code === \"55P03\" || /lock timeout/i.test(message);\n}\n\n/**\n * Wrap a driver so a lock timeout says what actually happened.\n *\n * \"canceling statement due to lock timeout\" is true and useless: the author's\n * two surfaces are two transactions, which is the one thing the message cannot\n * tell them. Applied recursively through `savepoint`, so `transaction()` and\n * `txPlan` inside the service surface answer the same way.\n */\nfunction diagnosingDriver(sql: SqlDriver): SqlDriver {\n const explain = (e: unknown): unknown =>\n isLockTimeout(e)\n ? new Error(\n \"Database.asService() waited too long for a row lock. It runs in its OWN transaction, so a \" +\n \"row this request already wrote through Database.* is locked against it until the request \" +\n \"commits — a wait that cannot end. Do that row's work on one surface or the other. \" +\n `(${String((e as { message?: unknown } | null)?.message ?? e)})`,\n )\n : e;\n\n const wrapTx = (tx: SqlTx): SqlTx => ({\n async unsafe(text: string, params?: unknown[]) {\n try {\n return await tx.unsafe(text, params);\n } catch (e) {\n throw explain(e);\n }\n },\n savepoint<T>(cb: (sp: SqlTx) => Promise<T>) {\n return tx.savepoint((sp) => cb(wrapTx(sp)));\n },\n });\n\n return {\n unsafe: (text: string, params?: unknown[]) => sql.unsafe(text, params),\n begin: <T>(cb: (tx: SqlTx) => Promise<T>) => sql.begin((tx) => cb(wrapTx(tx))),\n };\n}\n\n/** The two transactions a request may hold, and the single `Database` over them. */\nexport interface RequestDatabase {\n /** What the engine injects as the request's `Database` singleton. */\n readonly client: DBClient;\n /** Commit whatever was opened. Called once, after the handler returns. */\n commit(): Promise<void>;\n /** Roll back whatever was opened. Called once, when the handler throws. */\n rollback(reason: unknown): Promise<void>;\n}\n\n/**\n * The `Database` one request sees: RLS-enforced by default, with the\n * service-role sibling behind `asService()`.\n *\n * # Why the sibling cannot ride the request's own transaction\n *\n * The role reaches Postgres ONCE, in the BEGIN's bind statement, and it is\n * transaction-scoped. So a sibling built on the same transaction runs as\n * `backend_authenticated` no matter what it is called — RLS still filters every\n * row and `asService()` silently means nothing. That is the failure mode worth\n * naming: it does not throw, it does not log, it simply returns the caller's own\n * rows where the author asked for everyone's, and a handler that trusts it\n * (`if (existing) throw new Conflict()`) makes the wrong decision on data it was\n * never shown.\n *\n * The obvious repair — re-issue `set_config('role', …)` around each service op\n * — is worse than the bug. Two statements are not one: `Promise.all([\n * Database.query(…), Database.asService().query(…) ])` interleaves them on the\n * single connection, and the user's query can execute between the service's\n * set-role and its own statement. That is RLS silently OFF on the DEFAULT path,\n * which is precisely the direction a security seam must never fail.\n *\n * So the service surface gets its own transaction, on its own connection, bound\n * to the service role at BEGIN. The identity separation is physical: no\n * statement of either surface can change what the other runs as.\n *\n * # What that costs, stated plainly\n *\n * - **One extra connection per request that uses it**, and only then: the second\n * transaction is lazy exactly like the first, so `asService()` called and\n * never used opens nothing.\n * - **Called twice, it is the same surface** — one transaction per REQUEST, not\n * per call — so a handler cannot leak connections by reaching for it in a\n * loop.\n * - **The two are not atomic with each other.** Both settle with the request\n * (commit when the handler returns, roll back when it throws), but they settle\n * as two transactions: if the second COMMIT fails, the first has already\n * landed. The request's own work commits first, so the failure that survives\n * is never \"the audit row exists and the thing it audits does not\".\n * - **They can wait on each other's locks.** Bounded in the service direction by\n * {@link SERVICE_LOCK_TIMEOUT}; in the other direction — a `Database.*` write\n * to a row `asService()` has already written — the wait is the request's own,\n * and the answer is not to write one row from both surfaces.\n *\n * # Claims travel unchanged\n *\n * The service transaction carries the SAME `request.jwt.claims` as the user's.\n * `asService()` changes what the caller may TOUCH, not who they are, so\n * `auth.uid()` still resolves inside a trigger or a column default. It is also\n * the fail-closed direction: a service role provisioned WITHOUT `BYPASSRLS`\n * (measured live on 2026-08-13, created by hand during a diagnosis) is not named\n * by any policy, so it reads zero rows instead of quietly reading everyone's.\n */\nexport function createRequestDatabase(\n sql: SqlDriver,\n identity: { role: string; serviceRole: string; claimsJson: string },\n): RequestDatabase {\n const tx = createLazyTransaction(sql, identity.role, identity.claimsJson);\n\n // Opened on FIRST use and shared by every later `asService()` call.\n let serviceTx: LazyTransaction | null = null;\n let serviceClient: Omit<DBClient, \"asService\"> | null = null;\n\n const asService = (): Omit<DBClient, \"asService\"> => {\n if (serviceClient === null) {\n serviceTx = createLazyTransaction(\n diagnosingDriver(sql),\n identity.serviceRole,\n identity.claimsJson,\n { lockTimeout: SERVICE_LOCK_TIMEOUT },\n );\n // No `asService` on it: the type says `Omit<DBClient, \"asService\">` and so\n // does the object, so a second bypass is neither typeable nor callable.\n serviceClient = withTables(createOps(serviceTx));\n }\n return serviceClient;\n };\n\n return {\n client: Object.assign(withTables(createOps(tx)), { asService }),\n async commit(): Promise<void> {\n // The request's declared work first; see \"not atomic with each other\".\n await tx.commit();\n await serviceTx?.commit();\n },\n async rollback(reason: unknown): Promise<void> {\n await tx.rollback(reason);\n await serviceTx?.rollback(reason);\n },\n };\n}\n\n\n// ── the transaction plan executor ──────────────────────────────────────────\n//\n// The plan is a closed little language: five op kinds, equality-only filters,\n// and three value forms (a literal, a `$ref` to an earlier op's row, an\n// `$expr`). It is built by `TxPlanBuilder` in this same package, so the\n// executor's job is to run it faithfully rather than to defend against it —\n// with one exception that still matters: identifiers reach SQL as text, so\n// every table and column name goes through `quoteIdent`, exactly as the six\n// single-statement ops above do.\n\n/** Collects bound parameters so a value is never spliced into SQL text. */\nclass Args {\n readonly values: unknown[] = [];\n bind(value: unknown): string {\n this.values.push(value);\n return `$${this.values.length}`;\n }\n}\n\nfunction isRef(v: unknown): v is TxWireRef {\n return typeof v === \"object\" && v !== null && \"$ref\" in v;\n}\nfunction isExpr(v: unknown): v is TxWireExpr {\n return typeof v === \"object\" && v !== null && \"$expr\" in v;\n}\n\n/**\n * Render one value into SQL, binding whatever is data.\n *\n * `column` is only used by `inc`/`dec`, which read the column they write.\n */\nfunction renderValue(\n value: TxWireValue,\n column: string,\n args: Args,\n results: TxPlanOpResult[],\n vectorCols?: Set<string>,\n): string {\n if (isRef(value)) {\n const source = results[value.$ref.op];\n const row = source?.rows[0];\n if (!row || !(value.$ref.field in row)) {\n throw Object.assign(new Error(`op ${value.$ref.op} has no column \"${value.$ref.field}\" to reference`), {\n error_code: \"tx_ref_unresolved\",\n });\n }\n return bindMaybeVector(args, column, vectorCols, row[value.$ref.field]);\n }\n if (isExpr(value)) {\n const fn = value.$expr;\n if (fn.fn === \"now\") return \"now()\";\n const operator = fn.fn === \"inc\" ? \"+\" : \"-\";\n // The column is an identifier; the operand is BOUND. This is the one place\n // the tenant's digits could otherwise have reached SQL text.\n return `${quoteIdent(column)} ${operator} ${bindMaybeVector(args, column, vectorCols, fn.by)}`;\n }\n return bindMaybeVector(args, column, vectorCols, value);\n}\n\n/**\n * Render a WHERE clause.\n *\n * A null is compared with IS NULL, never `= NULL`: the latter is never true, so\n * a filter written that way silently matches nothing.\n */\nfunction renderWhere(\n where: Record<string, TxWireValue> | undefined,\n args: Args,\n results: TxPlanOpResult[],\n): string {\n const cols = Object.keys(where ?? {});\n if (cols.length === 0) return \"\";\n const terms = cols.map((c) => {\n const v = (where as Record<string, TxWireValue>)[c];\n if (v === null) return `${quoteIdent(c)} IS NULL`;\n return `${quoteIdent(c)} = ${renderValue(v, c, args, results)}`;\n });\n return ` WHERE ${terms.join(\" AND \")}`;\n}\n\n/** tx-plan bind'i (FR-008, review C2): vektör kolonuna giden number[] literal'e\n * çevrilir — düz op'lardaki asBindParams'ın plan-yolu ikizi. */\nfunction bindMaybeVector(\n args: { bind(v: unknown): string },\n column: string | undefined,\n vectorCols: Set<string> | undefined,\n value: unknown,\n): string {\n if (column !== undefined && vectorCols?.has(column) && Array.isArray(value)) {\n return args.bind(toVectorLiteral(value as number[]));\n }\n return args.bind(value);\n}\n\nasync function runPlanOp(\n sp: SqlTx,\n op: TxWireOp,\n results: TxPlanOpResult[],\n): Promise<Row[]> {\n const opVectorCols = vectorColumnsOf(currentSchema, op.table);\n const args = new Args();\n const table = quoteIdent(op.table);\n let sql: string;\n\n switch (op.op) {\n case \"insert\": {\n const cols = Object.keys(op.values ?? {});\n const rendered = cols.map((c) => renderValue((op.values as Record<string, TxWireValue>)[c], c, args, results, opVectorCols));\n sql = cols.length\n ? `INSERT INTO ${table} (${cols.map(quoteIdent).join(\", \")}) VALUES (${rendered.join(\", \")}) RETURNING *`\n : `INSERT INTO ${table} DEFAULT VALUES RETURNING *`;\n break;\n }\n case \"insertMany\": {\n const rows = (op.rows ?? []) as Record<string, TxWireValue>[];\n if (rows.length === 0 || !rows[0]) return [];\n // The column list comes from the FIRST row and every row is rendered\n // against it, so a row with a stray extra key cannot shift the columns of\n // the statement it shares.\n const cols = Object.keys(rows[0]);\n const tuples = rows.map(\n (r) => `(${cols.map((c) => renderValue(r[c], c, args, results, opVectorCols)).join(\", \")})`,\n );\n sql = `INSERT INTO ${table} (${cols.map(quoteIdent).join(\", \")}) VALUES ${tuples.join(\", \")} RETURNING *`;\n break;\n }\n case \"update\": {\n const cols = Object.keys(op.set ?? {});\n if (cols.length === 0) throw new Error(`update ${op.table}: nothing to set`);\n const assignments = cols.map(\n (c) => `${quoteIdent(c)} = ${renderValue((op.set as Record<string, TxWireValue>)[c], c, args, results, opVectorCols)}`,\n );\n sql = `UPDATE ${table} SET ${assignments.join(\", \")}${renderWhere(op.where, args, results)} RETURNING *`;\n break;\n }\n case \"delete\": {\n sql = `DELETE FROM ${table}${renderWhere(op.where, args, results)} RETURNING *`;\n break;\n }\n case \"select\": {\n const limit = op.limit !== undefined ? ` LIMIT ${Number(op.limit)}` : \"\";\n const lock = op.lock === \"update\" ? \" FOR UPDATE\" : \"\";\n sql = `SELECT * FROM ${table}${renderWhere(op.where, args, results)}${limit}${lock}`;\n break;\n }\n default:\n // Loudly, rather than rendering something for an op nobody wrote.\n throw new Error(`unknown operation \"${String((op as { op: string }).op)}\" in a transaction plan`);\n }\n\n return (await sp.unsafe(sql, args.values)) as Row[];\n}\n\n/**\n * Enforce the author's declared expectation.\n *\n * The Error the author passed never travels: the plan carries a SLOT index and\n * the SDK maps it back. So a failure here throws the shape `runTxPlan` знает —\n * `{error_code: \"tx_guard_failed\", slot}` — and the savepoint unwinds.\n */\nfunction assertGuard(op: TxWireOp, result: TxPlanOpResult): void {\n const guard = op.guard;\n if (!guard) return;\n const n = result.rows.length;\n const ok =\n guard.kind === \"one\"\n ? n === 1\n : guard.kind === \"none\"\n ? n === 0\n : guard.kind === \"atLeast\"\n ? n >= guard.n\n : n <= guard.n;\n if (ok) return;\n throw Object.assign(new Error(`transaction expectation failed: ${guard.kind} (${n} row(s))`), {\n error_code: \"tx_guard_failed\",\n slot: guard.slot,\n });\n}\n","// The decorator registry — the single plain-data store the method + parameter\n// decorators write into, and the deploy/dispatch pipeline reads back. No\n// `reflect-metadata`, no `emitDecoratorMetadata`: the registry is built from the\n// decorator arguments + the parameter INDEX that esbuild/tsc preserve for legacy\n// parameter decorators (verified — see the design spec §0/§4.1).\n//\n// A controller class carries its route metadata on a symbol-keyed static\n// property (`ROUTES`). `@Get`/`@Post`/… append a {@link RouteMeta} entry;\n// `@Body`/`@User`/… append a {@link ParamMeta} entry onto the route for the\n// method they decorate. Because parameter decorators run BEFORE the method\n// decorator for the same member (TS evaluates innermost-first, params before the\n// method), the route entry may not exist yet when a param decorator fires — so\n// param metadata is buffered per method name and merged when the method\n// decorator creates the route entry.\nimport type { AuthSpec, RateLimitConfig } from \"../endpoint.js\";\nimport type { UploadConfig } from \"./upload.js\";\nimport type { ZodTypeAny } from \"zod\";\n\n/** The HTTP verbs a route may declare, upper-cased (the runtime router +\n * OpenAPI lower-case on their own). */\nexport type HttpMethodUpper = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\" | \"QUERY\";\n\n/** Route-level options accepted by the method decorators (`@Get`/`@Post`/…). */\nexport interface RouteOptions {\n /** OVERRIDES the controller-level default auth for this one route. */\n auth?: AuthSpec;\n /** Per-route rate limit. */\n rateLimit?: RateLimitConfig;\n /** Direct-storage upload config — present ONLY on `@Upload` routes (the\n * `@Get`/`@Post`/… decorators never set it). Its presence is what MARKS a\n * route as an upload route through the whole pipeline (registry → flatten →\n * openapi → codegen). The bytes go client→storage directly; the method body\n * runs as the completion handler. See {@link UploadConfig} (decorators/upload.ts). */\n uploadConfig?: UploadConfig;\n}\n\n/** The kind of value a parameter decorator injects. Drives both dispatch\n * (which request slice to inject) and codegen (which OpenAPI parameter source a\n * schema-bearing kind maps to). */\nexport type ParamKind =\n | \"body\"\n | \"query\"\n | \"param\"\n | \"headers\"\n | \"user\"\n | \"optionalUser\"\n | \"client\"\n | \"requestId\"\n | \"traceId\"\n | \"req\"\n // `@UploadedObject()` — injects the uploaded object (completion input) on an\n // `@Upload` route. No schema (the shape is the fixed UploadedObject type).\n | \"uploadedObject\";\n\n/** One parameter decorator's recorded metadata. `index` is the parameter\n * position esbuild/tsc preserve; `schema` is present for the schema-bearing\n * kinds (`body`/`query`/`headers`); `name` is the path-param name for `param`. */\nexport interface ParamMeta {\n index: number;\n kind: ParamKind;\n /** Zod schema for `body`/`query`/`headers` (validation + codegen source). */\n schema?: ZodTypeAny;\n /** Path-param name for `@Param(\"id\")`. */\n name?: string;\n}\n\n/** One inferred throw site: the error CLASS name (e.g. \"TodoLocked\") and its\n * wire code (e.g. \"todo_locked\"). `status`, `hasData`, and the data JSON schema\n * are NOT carried here — they resolve from the error registry by `code` at\n * extract/openapi time (single source of truth). */\nexport interface ThrowDescriptor {\n name: string;\n code: string;\n}\n\n/** One route's recorded metadata: the verb + subpath + method name + options,\n * the ordered parameter metas, and the resolved return schema (injected by the\n * codegen step — see `returnSchema`). */\nexport interface RouteMeta {\n method: HttpMethodUpper;\n subpath: string;\n fnName: string;\n options: RouteOptions;\n params: ParamMeta[];\n /** Response schema for the route, if any. Derived from the method's RETURN\n * TYPE by codegen and written here via `recordReturn` (a generated top-level\n * IIFE injected per controller), not by an author-written decorator. */\n returnSchema?: ZodTypeAny;\n /** Error classes this route can throw, if inferred. Derived from the method\n * body + service call graph by the deploy stager's throw analysis and written\n * here via `recordThrows` (a generated top-level IIFE injected per controller,\n * the `recordReturn` twin), not by an author-written decorator. */\n throws?: ThrowDescriptor[];\n}\n\n/** Symbol the route metadata list is stored under on a controller class. Using\n * a symbol (not a string key) keeps it off the public structural surface and\n * avoids any chance of an authored property collision. */\nexport const ROUTES: unique symbol = Symbol.for(\"palbase.backend.routes\");\n\n/** Symbol the per-method buffered parameter metas are stored under while a class\n * is being decorated. Parameter decorators fire before the method decorator, so\n * they buffer here keyed by method name; the method decorator drains the buffer\n * into the route entry it creates. */\nconst PARAM_BUFFER: unique symbol = Symbol.for(\"palbase.backend.paramBuffer\");\n\n/** Symbol the per-method buffered return-type schemas are stored under while a\n * class's registry is being populated. The codegen-injected `recordReturn` call\n * can fire before OR after the method decorator; it buffers here keyed by method\n * name and `recordRoute` drains it into the route entry (and `recordReturn`\n * writes through if the route already exists). Buffering on BOTH sides means a\n * fully-formed route entry always carries its return schema — a raw-symbol\n * reader (the runtime) never has to re-merge. */\nconst RETURN_BUFFER: unique symbol = Symbol.for(\"palbase.backend.returnBuffer\");\n\n/** Symbol the per-method buffered throw descriptors are stored under while a\n * class's registry is being populated. The stager-injected `recordThrows` call\n * can fire before OR after the method decorator; it buffers here keyed by method\n * name and `recordRoute` drains it into the route entry (and `recordThrows`\n * writes through if the route already exists). Buffering on BOTH sides means a\n * fully-formed route entry always carries its throw descriptors — a raw-symbol\n * reader (the runtime) never has to re-merge. */\nconst THROWS_BUFFER: unique symbol = Symbol.for(\"palbase.backend.throwsBuffer\");\n\n/** A class constructor carrying the symbol-keyed registry slots. We type the\n * registry-bearing class as this so the decorators can read/write the slots\n * without `any` — a plain `Function` does not carry index signatures. */\ninterface RegistryCarrier {\n [ROUTES]?: RouteMeta[];\n [PARAM_BUFFER]?: Record<string, ParamMeta[]>;\n [RETURN_BUFFER]?: Record<string, ZodTypeAny>;\n [THROWS_BUFFER]?: Record<string, ThrowDescriptor[]>;\n}\n\n/** Coerce a decorated target (class constructor or its prototype) into the\n * registry carrier that owns the slots. Method/param decorators receive the\n * PROTOTYPE as their target; the class decorator receives the constructor. We\n * always anchor the registry on the CONSTRUCTOR so `getRoutes(ctor)` finds it. */\nfunction carrierOf(target: object): RegistryCarrier {\n // For instance-member decorators, `target` is the prototype; its `.constructor`\n // is the class. For a static member or the class decorator, `target` is the\n // constructor already. Resolve to the constructor either way.\n const ctor =\n typeof target === \"function\"\n ? (target as unknown as RegistryCarrier)\n : (((target as { constructor?: unknown }).constructor ??\n target) as unknown as RegistryCarrier);\n return ctor;\n}\n\n/** Get (creating if absent) the own route list for a class constructor. Own —\n * not inherited — so a subclass does not mutate its base's routes. */\nfunction ownRoutes(carrier: RegistryCarrier): RouteMeta[] {\n if (!Object.prototype.hasOwnProperty.call(carrier, ROUTES)) {\n carrier[ROUTES] = [];\n }\n return carrier[ROUTES] as RouteMeta[];\n}\n\n/** Get (creating if absent) the own per-method param buffer for a class. */\nfunction ownParamBuffer(carrier: RegistryCarrier): Record<string, ParamMeta[]> {\n if (!Object.prototype.hasOwnProperty.call(carrier, PARAM_BUFFER)) {\n carrier[PARAM_BUFFER] = {};\n }\n return carrier[PARAM_BUFFER] as Record<string, ParamMeta[]>;\n}\n\n/** Record a route (called by the method decorators). Drains any parameter\n * metas already buffered for `fnName` into the new route entry, then sorts them\n * by parameter index so dispatch can inject positionally. */\nexport function recordRoute(\n target: object,\n fnName: string,\n method: HttpMethodUpper,\n subpath: string,\n options: RouteOptions,\n): void {\n const carrier = carrierOf(target);\n const routes = ownRoutes(carrier);\n const buffer = ownParamBuffer(carrier);\n const params = (buffer[fnName] ?? []).slice().sort((a, b) => a.index - b.index);\n const route: RouteMeta = { method, subpath, fnName, options, params };\n // Drain a buffered return schema (the recordReturn-ran-first ordering) so the\n // route entry is complete the moment it's created — a raw-symbol consumer\n // (the runtime extractor/worker) sees the return schema without re-merging.\n const returnBuffer = carrier[RETURN_BUFFER];\n if (returnBuffer && returnBuffer[fnName] !== undefined) {\n route.returnSchema = returnBuffer[fnName];\n }\n // Same drain for buffered throw descriptors (the recordThrows-ran-first\n // ordering) — the route entry is complete the moment it's created.\n const throwsBuffer = carrier[THROWS_BUFFER];\n if (throwsBuffer && throwsBuffer[fnName] !== undefined) {\n route.throws = throwsBuffer[fnName];\n }\n routes.push(route);\n}\n\n/** Record one parameter decorator (called by `@Body`/`@User`/…). Buffers per\n * method name; the method decorator merges the buffer into the route entry. If\n * the route already exists (method decorator ran first — TS does evaluate the\n * method decorator AFTER its parameter decorators, but we stay order-robust),\n * the meta is also appended directly so neither ordering loses it. */\nexport function recordParam(target: object, fnName: string, meta: ParamMeta): void {\n const carrier = carrierOf(target);\n const buffer = ownParamBuffer(carrier);\n (buffer[fnName] ??= []).push(meta);\n\n // Order-robust: if the route already exists, merge in place + keep sorted.\n const routes = carrier[ROUTES];\n if (routes) {\n const route = routes.find((r) => r.fnName === fnName);\n if (route) {\n route.params.push(meta);\n route.params.sort((a, b) => a.index - b.index);\n }\n }\n}\n\n/** Attach a return schema to the route for `fnName` (called by the codegen\n * injection that reads the method's return type). If the route does not exist\n * yet, the schema is buffered (RETURN_BUFFER) and drained into the route by\n * `recordRoute` when the method decorator runs. */\nexport function recordReturn(target: object, fnName: string, schema: ZodTypeAny): void {\n const carrier = carrierOf(target);\n const routes = carrier[ROUTES];\n const route = routes?.find((r) => r.fnName === fnName);\n if (route) {\n route.returnSchema = schema;\n return;\n }\n if (!Object.prototype.hasOwnProperty.call(carrier, RETURN_BUFFER)) {\n carrier[RETURN_BUFFER] = {};\n }\n const returnBuffer = carrier[RETURN_BUFFER];\n if (returnBuffer) returnBuffer[fnName] = schema;\n}\n\n/** Attach the inferred throw descriptors to the route for `fnName` (called by\n * the stager-injected IIFE that carries the throw analysis result — the\n * `recordReturn` twin). If the route does not exist yet, the descriptors are\n * buffered (THROWS_BUFFER) and drained into the route by `recordRoute` when the\n * method decorator runs. */\nexport function recordThrows(target: object, fnName: string, throws: ThrowDescriptor[]): void {\n const carrier = carrierOf(target);\n const routes = carrier[ROUTES];\n const route = routes?.find((r) => r.fnName === fnName);\n if (route) {\n route.throws = throws;\n return;\n }\n if (!Object.prototype.hasOwnProperty.call(carrier, THROWS_BUFFER)) {\n carrier[THROWS_BUFFER] = {};\n }\n const throwsBuffer = carrier[THROWS_BUFFER];\n if (throwsBuffer) throwsBuffer[fnName] = throws;\n}\n\n/** Read the route metadata for a controller class (the deploy/dispatch entry\n * point). Applies any buffered return schemas + throw descriptors (for the\n * recordReturn/recordThrows-runs-before orderings) and returns a defensive copy\n * so callers cannot mutate the registry.\n */\nexport function getRoutes(ctor: object): RouteMeta[] {\n const carrier = carrierOf(ctor);\n const routes = carrier[ROUTES] ?? [];\n const returnBuffer = carrier[RETURN_BUFFER];\n if (returnBuffer) {\n for (const route of routes) {\n const buffered = returnBuffer[route.fnName];\n if (buffered && route.returnSchema === undefined) {\n route.returnSchema = buffered;\n }\n }\n }\n const throwsBuffer = carrier[THROWS_BUFFER];\n if (throwsBuffer) {\n for (const route of routes) {\n const buffered = throwsBuffer[route.fnName];\n if (buffered && route.throws === undefined) {\n route.throws = buffered;\n }\n }\n }\n return routes.map((r) => ({\n ...r,\n params: r.params.slice(),\n ...(r.throws !== undefined ? { throws: r.throws.slice() } : {}),\n }));\n}\n","/**\n * engine/router.ts — the route table, built from the SDK's own registry.\n *\n * No third-party router. The table is known at boot (the decorators wrote it),\n * so matching is a segment walk over a small array rather than a compiled\n * pattern engine. Both authoring forms for a path parameter are accepted:\n * `{id}` (what the decorators are written with) and `:id`.\n */\nimport { getRoutes } from \"../decorators/registry.js\";\nimport type { RouteMeta } from \"../decorators/registry.js\";\n\nconst CONTROLLER_META = Symbol.for(\"palbase.backend.controllerMeta\");\n\nexport interface RouteEntry {\n method: string;\n /** Path segments; a parameter segment is stored as `:name`. */\n segments: string[];\n meta: RouteMeta;\n /** The controller instance the method is invoked on. */\n instance: Record<string, (...args: unknown[]) => unknown>;\n /** `GET /todos/{id}` — stable, human-readable, used as the rate-limit key. */\n id: string;\n /** The controller's `auth` default, if it declared one. */\n controllerAuth: unknown;\n}\n\nfunction toSegments(path: string): string[] {\n return path\n .split(\"/\")\n .filter(Boolean)\n .map((s) => (s.startsWith(\"{\") && s.endsWith(\"}\") ? `:${s.slice(1, -1)}` : s));\n}\n\n/**\n * Build the table from controller classes.\n *\n * @throws when a class carries no routes — a controller that collected zero\n * endpoints is the silent failure this whole runtime is built to refuse, and\n * it must be loud at boot rather than a 404 in production.\n */\nexport function buildRouteTable(controllers: readonly unknown[]): RouteEntry[] {\n const table: RouteEntry[] = [];\n for (const Ctrl of controllers) {\n const ctor = Ctrl as { new (): Record<string, (...a: unknown[]) => unknown> } & Record<\n symbol,\n { basePath?: string; defaultAuth?: unknown } | undefined\n >;\n const meta = ctor[CONTROLLER_META];\n const basePath = meta?.basePath ?? \"\";\n const routes = getRoutes(Ctrl as never) as RouteMeta[];\n if (routes.length === 0) {\n const name = (Ctrl as { name?: string }).name ?? \"<anonymous>\";\n throw new Error(\n `controller ${name} collected zero routes. Either it declares no @Get/@Post/… , ` +\n `or its decorator metadata was erased at build time — check that the bundle was ` +\n `compiled with experimentalDecorators enabled.`,\n );\n }\n const instance = new ctor();\n for (const r of routes) {\n const full = `${basePath}${r.subpath ?? \"\"}` || \"/\";\n table.push({\n method: r.method,\n segments: toSegments(full),\n meta: r,\n instance,\n id: `${r.method} ${full}`,\n controllerAuth: meta?.defaultAuth,\n });\n }\n }\n return table;\n}\n\nexport interface RouteMatch {\n entry: RouteEntry;\n params: Record<string, string>;\n}\n\n/** First match wins; the table is small and declaration order is the tiebreak. */\nexport function matchRoute(\n table: readonly RouteEntry[],\n method: string,\n pathname: string,\n): RouteMatch | null {\n const parts = pathname.split(\"/\").filter(Boolean);\n for (const entry of table) {\n if (entry.method !== method || entry.segments.length !== parts.length) continue;\n const params: Record<string, string> = {};\n let ok = true;\n for (let i = 0; i < entry.segments.length; i++) {\n const seg = entry.segments[i];\n const got = parts[i];\n if (seg === undefined || got === undefined) { ok = false; break; }\n if (seg.charCodeAt(0) === 58 /* ':' */) {\n params[seg.slice(1)] = decodeURIComponent(got);\n } else if (seg !== got) {\n ok = false;\n break;\n }\n }\n if (ok) return { entry, params };\n }\n return null;\n}\n","/**\n * upload.ts — the engine's half of `@Upload`.\n *\n * THE SHAPE, because it is unusual and the reason matters:\n *\n * client ──[ multipart: file + request body ]──► storage\n * storage ──[ authorize: which bucket, which path? ]──► THIS process\n * storage ── writes the bytes, renders the variants\n * storage ──[ signed: uploadedObject + request body ]──► THIS process\n * THIS process ── the handler runs, returns its typed result\n * storage ──[ that result ]──► client\n *\n * The tenant's code NEVER sees the bytes. It sees the metadata and the request\n * body, and it answers — which is what a completion handler is for. A 1 GB\n * video would otherwise stream through this process to reach the same place.\n *\n * Two calls arrive here, both from storage and neither from a browser:\n *\n * - AUTHORIZE asks which bucket and path a route writes to. Storage cannot\n * know: the answer lives in `@Upload({bucket, pathTemplate})`, which is\n * TypeScript, in the deployed bundle. Asking the process that HAS the\n * routes is what stops the client from naming its own bucket.\n * - COMPLETION runs the handler.\n *\n * Both are signed. An unsigned completion would let anyone with the route path\n * invent an upload that never happened.\n */\n\nimport type { RouteEntry } from \"./router.js\";\n\n/** What authorize answers: where this route's bytes go, and what they may be. */\nexport interface UploadGrant {\n bucket: string;\n path: string;\n maxBytes: number | null;\n mimeTypes: string[] | null;\n /**\n * Who is uploading, or null when nobody is signed in.\n *\n * Storage records this on the object row so deleting the user takes their\n * files with them. It is reported rather than DECIDED here — this process\n * already resolved the caller to render `{userId}` in a path template, and\n * storage has no identity of its own to derive one from. Authorization stays\n * exactly where it was (the route's own `auth` declaration); this is\n * attribution, which is a different question with the same answer already in\n * hand.\n *\n * null is the anonymous upload, and it stays null: a file uploaded by nobody\n * belongs to nobody, and attributing it to whoever signs in next on that\n * device would file one person's upload under another's name.\n */\n ownerUid: string | null;\n}\n\n/** The completion input storage sends after the bytes have landed. */\nexport interface CompletionEnvelope {\n uploadedObject: {\n uploadId: string;\n path: string;\n bucket: string;\n size: number;\n contentType: string;\n checksum: string;\n width?: number;\n height?: number;\n thumbhash?: string;\n variants: Record<string, string>;\n };\n /** The request body the client sent alongside the file. */\n body: unknown;\n}\n\n/** The internal path storage calls to ask where a route's bytes go. */\nexport const AUTHORIZE_PATH = \"/__palbase/upload/authorize\";\n\n/** Header carrying the shared-secret signature on both internal calls. */\nexport const SIGNATURE_HEADER = \"x-palbase-upload-signature\";\n\n/**\n * renderPath fills a `pathTemplate` on the SERVER.\n *\n * The client never chooses where its bytes land. `{filename}` is the one token\n * that comes from the caller, and it is sanitised to a single path segment:\n * without that, `../../../etc/passwd` is a filename, and a template that looks\n * like a folder structure becomes a way to write anywhere in the bucket.\n */\nexport function renderPath(template: string, tokens: {\n userId?: string | null;\n uploadId: string;\n filename?: string;\n}): string {\n return template\n .replaceAll(\"{userId}\", sanitizeSegment(tokens.userId ?? \"anonymous\"))\n .replaceAll(\"{uploadId}\", sanitizeSegment(tokens.uploadId))\n .replaceAll(\"{filename}\", sanitizeSegment(tokens.filename ?? \"file\"));\n}\n\n/**\n * sanitizeSegment reduces a value to something safe inside one path segment.\n *\n * Slashes, dots and control characters go. Keeping dots would allow `..`;\n * keeping slashes would allow a client to climb out of the prefix the template\n * put it in, which is the whole point of having a template.\n */\nexport function sanitizeSegment(raw: string): string {\n const cleaned = raw\n .replace(/[\\x00-\\x1F\\x7F]/g, \"\")\n .replace(/[/\\\\]/g, \"-\")\n .replace(/\\.{2,}/g, \".\")\n .replace(/^\\.+/, \"\")\n .trim();\n return cleaned === \"\" ? \"file\" : cleaned.slice(0, 200);\n}\n\n/**\n * grantFor resolves a route's upload configuration into a concrete grant.\n *\n * Returns null when the route is not an upload route — which is a refusal, not\n * an oversight: storage asking about a route with no `@Upload` means somebody\n * is trying to write through an endpoint that never offered to accept a file.\n */\nexport function grantFor(\n entry: RouteEntry | undefined,\n ctx: { userId: string | null; uploadId: string; filename?: string },\n bucketLimits?: { maxBytes: number | null; mimeTypes: string[] | null },\n): UploadGrant | null {\n const cfg = entry?.meta?.options?.uploadConfig;\n if (!cfg) return null;\n return {\n bucket: cfg.bucket,\n path: renderPath(cfg.pathTemplate, {\n userId: ctx.userId,\n uploadId: ctx.uploadId,\n filename: ctx.filename,\n }),\n maxBytes: bucketLimits?.maxBytes ?? null,\n mimeTypes: bucketLimits?.mimeTypes ?? null,\n ownerUid: ctx.userId ?? null,\n };\n}\n\n/**\n * CompletionLedger makes a completion run its handler EXACTLY ONCE per upload.\n *\n * The completion is a mutation — it writes the row that makes the uploaded\n * bytes mean something — and it is delivered over a network by a caller that\n * retries. A retried completion must not create a second post for one photo, so\n * the second call is answered with the FIRST call's response rather than being\n * refused: to storage, and therefore to the client waiting on it, a retry that\n * succeeds is indistinguishable from the original, which is the point.\n *\n * Bounded, and oldest-first: an upload id is interesting for as long as a retry\n * could still arrive, not forever. The cap is what keeps a long-lived process\n * from turning this into a leak — a ledger that remembered every upload would\n * be a slow way to run out of memory.\n */\nexport class CompletionLedger {\n private readonly seen = new Map<string, CompletedResponse>();\n\n constructor(private readonly capacity = 1024) {}\n\n recall(uploadId: string): CompletedResponse | undefined {\n return this.seen.get(uploadId);\n }\n\n remember(uploadId: string, response: CompletedResponse): void {\n // Delete-then-set so a repeat moves to the back: Map iterates in insertion\n // order, and the eviction below takes the front.\n this.seen.delete(uploadId);\n this.seen.set(uploadId, response);\n while (this.seen.size > this.capacity) {\n const oldest = this.seen.keys().next();\n if (oldest.done) break;\n this.seen.delete(oldest.value);\n }\n }\n\n get size(): number {\n return this.seen.size;\n }\n}\n\n/** A completion's answer, kept verbatim so a retry receives what the first call did. */\nexport interface CompletedResponse {\n status: number;\n body: string | null;\n contentType: string | null;\n}\n\n/**\n * verifySignature compares a presented signature against the expected one in\n * constant time.\n *\n * Constant time because a leaky comparison on a shared secret is recoverable\n * byte by byte, and this secret authorises running a tenant's handler with an\n * upload the caller describes.\n */\nexport function verifySignature(presented: string, expected: string): boolean {\n if (presented.length !== expected.length) return false;\n let diff = 0;\n for (let i = 0; i < presented.length; i++) {\n diff |= presented.charCodeAt(i) ^ expected.charCodeAt(i);\n }\n return diff === 0;\n}\n","/**\n * engine/index.ts — the engine: a backend that boots itself.\n *\n * `createApp` turns a set of `@Controller` classes into a `fetch(Request)`\n * handler. No V8 isolate, no capability hop: this process owns its database\n * pool, verifies its own tokens, applies its own rate limits, and calls the\n * modules directly.\n *\n * import { createApp, loadConfig } from \"@palbase/backend/engine\";\n *\n * const app = await createApp({\n * config: loadConfig(process.env),\n * controllers: [TodosController],\n * schema,\n * });\n * Bun.serve({ port: app.config.port, fetch: app.handle });\n *\n * The Web-standard `fetch` signature is the point: the same handler runs under\n * Bun, Deno and any host that speaks Request/Response, so \"works locally\" and\n * \"works in the cloud\" are the same code path rather than two.\n */\nimport type { ZodError, ZodTypeAny } from \"zod\";\n\nimport { __runWithRuntime, __requestALS } from \"../runtime.js\";\nimport type { RuntimeServices } from \"../runtime.js\";\nimport { isHttpError } from \"../errors.js\";\nimport type { CacheClient, ClientInfo } from \"../endpoint.js\";\n\nimport { loadConfig, BootRefused } from \"./config.js\";\nimport type { EngineConfig } from \"./config.js\";\nimport { AuthVerifier, effectiveAuth } from \"./auth.js\";\nimport type { VerifiedClaims } from \"./auth.js\";\nimport { RateLimiter } from \"./ratelimit.js\";\nimport { makeMemoryCache } from \"./cache.js\";\nimport { createRequestDatabase, setSchema, setSecretReader } from \"./db.js\";\nimport type { SqlDriver } from \"./db.js\";\nimport { buildRouteTable, matchRoute } from \"./router.js\";\nimport {\n AUTHORIZE_PATH,\n SIGNATURE_HEADER,\n grantFor,\n verifySignature,\n CompletionLedger,\n type CompletionEnvelope,\n} from \"./upload.js\";\nimport type { RouteEntry } from \"./router.js\";\n\nexport { loadConfig, BootRefused } from \"./config.js\";\nexport type { EngineConfig } from \"./config.js\";\nexport { AuthVerifier, effectiveAuth } from \"./auth.js\";\nexport { RateLimiter } from \"./ratelimit.js\";\nexport { makeMemoryCache } from \"./cache.js\";\nexport { createLazyTransaction, createOps, withTables, createRequestDatabase, quoteIdent } from \"./db.js\";\nexport type { SqlDriver, SqlTx, RequestDatabase } from \"./db.js\";\nexport { buildRouteTable, matchRoute } from \"./router.js\";\nexport type { RouteEntry } from \"./router.js\";\nexport { scrubSecrets, installEgressFence, hostAllowed } from \"./fence.js\";\nexport type { EgressPolicy, ScrubResult } from \"./fence.js\";\n\n/** The `__`-prefixed request-scope seam, as re-exported by a deployed bundle. */\nexport interface RuntimeHooks {\n __runWithRuntime: typeof __runWithRuntime;\n __requestALS: typeof __requestALS;\n}\n\n/** The module singletons the engine injects, minus the two it owns itself. */\nexport type ModuleClients = Partial<\n Pick<\n RuntimeServices,\n \"Documents\" | \"Storage\" | \"Notifications\" | \"Flags\" | \"Realtime\" | \"Purchases\" | \"Secrets\"\n >\n>;\n\nexport interface CreateAppOptions {\n /**\n * Vault'tan TEK secret okuma (FR-025): sorgu-anı embedding'in anahtarı\n * buradan akar. Verilmezse auto-embed'li search({query}) adlandırılmış\n * hatayla düşer — sessiz boş sonuç asla (FR-015).\n */\n secretReader?: (name: string) => Promise<string | null>;\n config: EngineConfig;\n /** `@Controller` classes. A class that collected zero routes is fatal. */\n controllers: readonly unknown[];\n /** The project's `defineSchema()` result, for the typed `.tables` surface. */\n schema?: unknown;\n /** The SQL driver. Omitted ⇒ built from `Bun.sql` when running under Bun. */\n sql?: SqlDriver;\n /** Module clients. Omitted ⇒ each corresponding singleton throws when used. */\n modules?: ModuleClients;\n /** Cache. Omitted ⇒ this process's own memory. */\n cache?: CacheClient;\n /**\n * The request-scope hooks to run handlers inside.\n *\n * MUST come from the SAME `@palbase/backend` module instance the loaded\n * controllers were bundled against. A deployed bundle inlines its own copy of\n * the SDK and re-exports these two; the engine here has its own. Two copies\n * mean two AsyncLocalStorage instances, and the store this engine sets is not\n * the store the handler's `Database` proxy reads — every service would be\n * undefined at the first call, with nothing in the logs to say why. So the\n * host passes the BUNDLE's hooks and the seam closes.\n *\n * Omitted ⇒ this module's own, which is correct only when the controllers\n * were built against this same instance (tests, a single-package project).\n */\n runtimeHooks?: RuntimeHooks;\n logger?: Pick<Console, \"info\" | \"warn\" | \"error\" | \"debug\">;\n}\n\nexport interface App {\n handle: (req: Request) => Promise<Response>;\n routes: readonly RouteEntry[];\n config: EngineConfig;\n /**\n * Run work that has no request behind it — a scheduled job — inside the same\n * request scope a handler gets, with its own transaction.\n */\n runInServiceScope: <T>(fn: () => T | Promise<T>) => Promise<T>;\n /** Close the pool and release resources. */\n shutdown: () => Promise<void>;\n}\n\nconst JSON_HEADERS = { \"content-type\": \"application/json\" } as const;\n\n/** Flatten a zod failure into the `{ field, message }[]` the SDK's own\n * `BadRequest` payload declares — one shape for the engine's automatic\n * refusals and for `throw new BadRequest({ fields })` alike. */\nfunction fieldErrors(err: ZodError): Array<{ field: string; message: string }> {\n return err.issues.map((i) => ({ field: i.path.join(\".\"), message: i.message }));\n}\n\n/** Re-key the header map onto the names an `@Headers` schema declares.\n *\n * HTTP HEADER NAMES ARE CASE-INSENSITIVE (RFC 9110 §5.1); a zod key is a\n * literal. `Headers` iteration lowercases, so `Object.fromEntries(req.headers)`\n * only ever carries `x-tenant` — while the deploy gate lowercases a declared\n * name only for its RESERVED check (`extract_meta.js` validateHeadersSchema),\n * so `z.object({ \"X-Tenant\": … })` ships. That is also the spelling every HTTP\n * document uses and the one the iOS/Android generators emit into the generated\n * call's signature, so the caller really does send it.\n *\n * Comparing case-sensitively would answer 400 on a header the caller DID send,\n * on every request, forever — the schema was inert before it was enforced, so\n * the refusal would arrive with the SDK upgrade and name a header the client\n * can see itself sending. The lowercase twin stays in the map (zod strips\n * unknown keys), so the parsed value carries exactly the declared spelling.\n */\nfunction headersFor(raw: Record<string, string>, schema: ZodTypeAny): Record<string, string> {\n const shape = (schema as { shape?: Record<string, unknown> }).shape;\n if (typeof shape !== \"object\" || shape === null) return raw;\n let aliased: Record<string, string> | null = null;\n for (const declared of Object.keys(shape)) {\n const lower = declared.toLowerCase();\n if (lower === declared) continue;\n const value = raw[lower];\n if (value === undefined) continue;\n aliased ??= { ...raw };\n aliased[declared] = value;\n }\n return aliased ?? raw;\n}\n\nfunction envelope(\n error: string,\n description: string,\n status: number,\n requestId: string,\n extra?: Record<string, unknown>,\n): Response {\n return new Response(\n JSON.stringify({ error, error_description: description, status, request_id: requestId, ...extra }),\n { status, headers: JSON_HEADERS },\n );\n}\n\n/** A module that was never configured must say so by name on first use, not\n * fail with \"Cannot read properties of undefined\". */\n/**\n * A module singleton nobody injected.\n *\n * The message names TWO causes because there are two, and pointing at only one\n * sends an operator to check a setting that is already correct. Measured on\n * 2026-08-15: a handler reaching for `Purchases` was told to set\n * MODULE_BASE_URL — which was set. Purchases is simply not part of this\n * backend, and an error that hides that costs the reader the afternoon.\n */\nfunction unavailable(name: string): never {\n throw new Error(\n `${name} is unavailable. Either this backend was started without module clients ` +\n `(set MODULE_BASE_URL and the API keys so the engine can reach the module surface), ` +\n `or ${name} is not one of the modules this backend provides.`,\n );\n}\n\nfunction stubModule(name: string): unknown {\n return new Proxy(\n {},\n {\n get: () => unavailable(name),\n apply: () => unavailable(name),\n },\n );\n}\n\nasync function defaultSqlDriver(config: EngineConfig): Promise<SqlDriver> {\n const g = globalThis as { Bun?: { SQL: new (o: { url: string; max: number }) => SqlDriver } };\n if (!g.Bun?.SQL) {\n throw new BootRefused(\n [],\n \"boot refused: no SQL driver. Running outside Bun means the driver must be supplied — \" +\n \"pass `sql` to createApp().\",\n );\n }\n return new g.Bun.SQL({ url: config.databaseUrl, max: config.poolMax });\n}\n\n/**\n * Build the app. Fails fast: the database is reached here, at boot, rather than\n * on the first request that needs it.\n */\nexport async function createApp(opts: CreateAppOptions): Promise<App> {\n const { config, controllers } = opts;\n setSchema(opts.schema ?? {});\n setSecretReader(opts.secretReader ?? null);\n\n const routes = buildRouteTable(controllers);\n if (routes.length === 0) {\n throw new BootRefused([], \"boot refused: zero endpoints collected — nothing would answer.\");\n }\n\n const sql = opts.sql ?? (await defaultSqlDriver(config));\n await sql.unsafe(\"select 1\");\n\n const auth = new AuthVerifier({ jwksUrl: config.authJwksUrl, issuer: config.authIssuer });\n const limiter = new RateLimiter();\n const cache = opts.cache ?? makeMemoryCache();\n const log = opts.logger ?? console;\n const modules = opts.modules ?? {};\n const runWithRuntime = opts.runtimeHooks?.__runWithRuntime ?? __runWithRuntime;\n const requestALS = opts.runtimeHooks?.__requestALS ?? __requestALS;\n\n // The secret storage signs its internal calls with. Absent means uploads are\n // not wired, and authorize REFUSES rather than answering with a grant anybody\n // could have asked for.\n const uploadSecret = config.uploadSecret ?? \"\";\n\n /**\n * Answer \"which bucket and path does this route write to?\".\n *\n * Storage cannot know: the answer is `@Upload({bucket, pathTemplate})`, which\n * lives in the deployed bundle. Asking the process that HAS the routes is\n * what keeps the client from naming its own bucket — the request carries the\n * route it wants to use, and this decides what that means.\n */\n // One ledger per app: a completion retried against this process must find\n // its own first answer, and a process restart legitimately forgets — the\n // window a retry lives in is far shorter than an uptime.\n const completions = new CompletionLedger();\n\n /**\n * The service bundle a scope binds, built around ONE request-scoped database.\n *\n * Extracted so the request path and the job path cannot drift: a second copy\n * of this object is a second definition of what a handler can reach, and the\n * one that goes stale is always the one nobody is looking at.\n */\n function buildServices(db: ReturnType<typeof createRequestDatabase>): RuntimeServices {\n return {\n Database: db.client,\n Cache: cache,\n Log: log,\n Documents: modules.Documents ?? stubModule(\"Documents\"),\n Storage: modules.Storage ?? stubModule(\"Storage\"),\n Notifications: modules.Notifications ?? stubModule(\"Notifications\"),\n Flags: modules.Flags ?? stubModule(\"Flags\"),\n Realtime: modules.Realtime ?? stubModule(\"Realtime\"),\n Purchases: modules.Purchases ?? stubModule(\"Purchases\"),\n // Named, never undefined. A backend started without a secrets client\n // that returned `undefined` here would fail inside the handler as\n // \"Cannot read properties of undefined\", which says nothing about what\n // to configure — the stub says the name and the variable.\n Secrets: modules.Secrets ?? stubModule(\"Secrets\"),\n } as unknown as RuntimeServices;\n }\n\n /**\n * Run `fn` as the system, with no request behind it.\n *\n * Scheduled jobs need exactly what a handler needs — Database, Log,\n * Notifications, resolved out of the request scope — but there is no request\n * to take an identity from. So the claims are EMPTY: a job is nobody, and\n * `Database` here satisfies no owner-scoped RLS policy. That is why a job\n * reaches for `Database.asService()`, and why this does not quietly hand it\n * service_role by default.\n *\n * The transaction settles the same way a request's does: commit on return,\n * rollback on throw. A job that fails halfway leaves nothing behind that the\n * next run has to reason about.\n */\n async function runInServiceScope<T>(fn: () => T | Promise<T>): Promise<T> {\n const db = createRequestDatabase(sql, {\n role: config.dbRole,\n serviceRole: config.dbServiceRole,\n claimsJson: \"{}\",\n });\n try {\n const out = await runWithRuntime(buildServices(db), fn as () => Promise<T>);\n await db.commit();\n return out;\n } catch (err) {\n await db.rollback(err);\n throw err;\n }\n }\n\n async function handleAuthorize(req: Request, requestId: string): Promise<Response> {\n if (uploadSecret === \"\" ||\n !verifySignature(req.headers.get(SIGNATURE_HEADER) ?? \"\", uploadSecret)) {\n return envelope(\"unauthorized\", \"This endpoint is not callable directly\", 401, requestId);\n }\n const body = (await req.json().catch(() => null)) as {\n method?: string;\n path?: string;\n userId?: string | null;\n uploadId?: string;\n filename?: string;\n } | null;\n if (!body?.path || !body.uploadId) {\n return envelope(\"bad_request\", \"authorize needs a path and an uploadId\", 400, requestId);\n }\n const target = matchRoute(routes, body.method ?? \"POST\", body.path);\n\n // THE AUTH DECISION HAPPENS HERE, BEFORE A SINGLE BYTE IS ACCEPTED.\n //\n // Storage asks this question precisely so it can refuse early: without it,\n // an anonymous caller could push a file at a route that requires a user,\n // have it written and its variants rendered, and only then be turned away\n // by the completion — the bytes were still accepted, and the work still\n // done, once per attempt.\n //\n // The credential is the caller's own, forwarded by storage, and it is\n // verified HERE rather than trusted: the userId that ends up in the path\n // template comes from these claims and from nothing else, so neither the\n // client nor storage can name a folder that belongs to somebody else.\n const spec = effectiveAuth(target?.entry.meta.options?.auth, target?.entry.controllerAuth);\n const callerClaims = await auth.verify(req.headers.get(\"authorization\"));\n if (spec.required && !callerClaims) {\n return envelope(\"unauthorized\", \"A valid access token is required\", 401, requestId);\n }\n if (callerClaims && spec.role && callerClaims.role !== spec.role) {\n return envelope(\"forbidden\", `This endpoint requires the \"${spec.role}\" role`, 403, requestId);\n }\n\n const grant = grantFor(target?.entry, {\n userId: typeof callerClaims?.sub === \"string\" ? callerClaims.sub : null,\n uploadId: body.uploadId,\n filename: body.filename,\n });\n if (!grant) {\n // A route with no @Upload never offered to accept a file. Refusing by\n // NAME rather than 404 so an operator reading storage's log learns which\n // route was asked for.\n return envelope(\"not_an_upload_route\",\n `${body.method ?? \"POST\"} ${body.path} does not declare @Upload`, 400, requestId);\n }\n return new Response(JSON.stringify(grant), { status: 200, headers: JSON_HEADERS });\n }\n\n async function handle(req: Request): Promise<Response> {\n const requestId = `req_${crypto.randomUUID()}`;\n const url = new URL(req.url);\n\n // ── storage's two internal calls, before ordinary routing ───────────────\n //\n // They are not the tenant's routes and must not be reachable as one: an\n // app that declared `POST /__palbase/upload/authorize` would otherwise\n // shadow the mechanism that decides where uploads land.\n if (url.pathname === AUTHORIZE_PATH) {\n return handleAuthorize(req, requestId);\n }\n\n const hit = matchRoute(routes, req.method, url.pathname);\n if (!hit) return envelope(\"not_found\", \"No route matches this method and path\", 404, requestId);\n const { meta } = hit.entry;\n\n // ── auth ────────────────────────────────────────────────────────────────\n const spec = effectiveAuth(meta.options?.auth, hit.entry.controllerAuth);\n const claims: VerifiedClaims | null = await auth.verify(req.headers.get(\"authorization\"));\n if (spec.required && !claims) {\n return envelope(\"unauthorized\", \"A valid access token is required\", 401, requestId);\n }\n const userId = typeof claims?.sub === \"string\" ? claims.sub : undefined;\n if (claims && spec.role && claims.role !== spec.role) {\n return envelope(\"forbidden\", `This endpoint requires the \"${spec.role}\" role`, 403, requestId);\n }\n if (claims && spec.verifiedEmail && claims.email_verified !== true) {\n return envelope(\"email_not_verified\", \"A verified email address is required\", 403, requestId);\n }\n\n // ── rate limit ──────────────────────────────────────────────────────────\n const retryAfter = limiter.check(\n meta.options?.rateLimit,\n RateLimiter.key(hit.entry.id, userId, req.headers),\n Date.now(),\n );\n if (retryAfter !== null) {\n // THE HINT GOES IN THE BODY TOO, under the name this SDK already\n // publishes for it. `error-registry.ts` declares\n // `too_many_requests: { retryAfter: number }`, so codegen types\n // `error.data.retryAfter` on every generated client and a thrown\n // `new TooManyRequests({ retryAfter })` already answers in that shape.\n // This limiter answered with the header ALONE, so the one 429 the engine\n // itself produces was the one shape no generated client could read — and\n // a browser behind a CORS gateway cannot see `Retry-After` at all unless\n // it is explicitly exposed. The header stays: it is the HTTP-correct\n // signal, and `@palbase/core`'s retry loop reads it.\n return new Response(\n JSON.stringify({\n error: \"too_many_requests\",\n error_description: \"Rate limit exceeded for this endpoint\",\n status: 429,\n request_id: requestId,\n data: { retryAfter },\n }),\n { status: 429, headers: { ...JSON_HEADERS, \"retry-after\": String(retryAfter) } },\n );\n }\n\n // ── arguments ───────────────────────────────────────────────────────────\n // Set when this request IS a completion, so its answer can be remembered.\n let completionUploadId: string | null = null;\n\n const args: unknown[] = [];\n let parsedBody: unknown;\n let bodyRead = false;\n for (const p of meta.params ?? []) {\n switch (p.kind) {\n case \"body\": {\n if (!bodyRead) {\n parsedBody = await req.json().catch(() => ({}));\n bodyRead = true;\n }\n const r = p.schema!.safeParse(parsedBody);\n if (!r.success) {\n return envelope(\"bad_request\", \"Request body failed validation\", 400, requestId, {\n data: { fields: fieldErrors(r.error) },\n });\n }\n args[p.index] = r.data;\n break;\n }\n case \"query\": {\n const r = p.schema!.safeParse(Object.fromEntries(url.searchParams));\n if (!r.success) {\n return envelope(\"bad_request\", \"Query parameters failed validation\", 400, requestId, {\n data: { fields: fieldErrors(r.error) },\n });\n }\n args[p.index] = r.data;\n break;\n }\n case \"param\":\n args[p.index] = hit.params[p.name!];\n break;\n case \"headers\": {\n // A DECLARED HEADER SCHEMA IS A CONTRACT, and three other systems\n // already treat it as one: the deploy gate REFUSES a build whose\n // schema names a reserved or non-string header\n // (cli/internal/backend/devjs/extract_meta.js), the OpenAPI document\n // lists it as an `in: header` parameter, and the iOS/Android\n // generators put it in the generated call's signature. The runtime\n // was the only one that read the schema and did nothing with it, so a\n // request with the header missing or malformed answered 200 and the\n // handler read `undefined` off a value whose type says `string`.\n //\n // Keys arrive LOWERCASE — `Headers` iteration lowercases them — so\n // the declared names are matched case-insensitively (`headersFor`)\n // and `x-tenant` and `X-Tenant` both work, as HTTP says they must.\n const raw = Object.fromEntries(req.headers);\n if (!p.schema) {\n args[p.index] = raw;\n break;\n }\n const r = p.schema.safeParse(headersFor(raw, p.schema));\n if (!r.success) {\n return envelope(\"bad_request\", \"Request headers failed validation\", 400, requestId, {\n data: { fields: fieldErrors(r.error) },\n });\n }\n // The PARSED value, matching @Body/@QueryParams: the parameter's type\n // is `z.infer<Schema>`, and injecting the whole header map made the\n // value wider than its own declared type. An author who wants every\n // header still writes `@Headers()` with no schema.\n args[p.index] = r.data;\n break;\n }\n case \"user\":\n case \"optionalUser\":\n args[p.index] = claims\n ? {\n id: userId,\n email: claims.email,\n role: claims.role,\n emailVerified: claims.email_verified === true,\n metadata: (claims.metadata as Record<string, unknown>) ?? {},\n }\n : null;\n break;\n case \"uploadedObject\": {\n // An @Upload route runs as a COMPLETION handler: the bytes went to\n // storage, and what arrives here is what storage recorded about them.\n // The call must be signed, or anyone who knows the route path could\n // invent an upload that never happened and make the handler write a\n // row for it.\n if (uploadSecret === \"\" ||\n !verifySignature(req.headers.get(SIGNATURE_HEADER) ?? \"\", uploadSecret)) {\n return envelope(\"unauthorized\",\n \"This endpoint accepts uploads through storage, not directly\", 401, requestId);\n }\n if (!bodyRead) {\n parsedBody = await req.json().catch(() => ({}));\n bodyRead = true;\n }\n const envelopeIn = parsedBody as CompletionEnvelope | null;\n if (!envelopeIn?.uploadedObject) {\n return envelope(\"bad_request\", \"the completion call carried no uploaded object\", 400, requestId);\n }\n // A RETRY MUST NOT RUN THE HANDLER AGAIN.\n //\n // Storage retries a completion it did not hear back from, and the\n // handler is a mutation: run twice, one uploaded photo becomes two\n // posts. The first answer is replayed instead, which is what makes\n // the retry invisible to the client waiting on the other end.\n const uploadId = envelopeIn.uploadedObject.uploadId;\n if (typeof uploadId === \"string\" && uploadId !== \"\") {\n const already = completions.recall(uploadId);\n if (already) {\n return new Response(already.body, {\n status: already.status,\n headers: already.contentType ? { \"content-type\": already.contentType } : undefined,\n });\n }\n completionUploadId = uploadId;\n }\n args[p.index] = envelopeIn.uploadedObject;\n // The author's @Body sees THEIR payload, not the envelope around it.\n parsedBody = envelopeIn.body ?? {};\n break;\n }\n case \"requestId\":\n args[p.index] = requestId;\n break;\n case \"traceId\":\n args[p.index] = requestId;\n break;\n case \"client\":\n // The data was always on the wire; nothing read it. Every shipped\n // client SDK stamps these four on every request (iOS\n // Palbe/Core/ClientInfo.swift, web core/src/http.ts), and the\n // platform already reads the same names in Go\n // (user-flags/internal/middleware/clientcontext.go). Header names are\n // canonical here, not invented: the deploy gate REFUSES an\n // `@Headers` schema that names an `x-palbase-*` key, which makes\n // `@Client()` the only sanctioned reader of them.\n //\n // `Headers.get()` answers `string | null`, which is exactly what\n // `ClientInfo` declares — a non-SDK caller (curl, server-to-server)\n // sends none of these and gets four nulls rather than a throw.\n args[p.index] = {\n sdkVersion: req.headers.get(\"x-palbase-sdk-version\"),\n appVersion: req.headers.get(\"x-palbase-client-version\"),\n platform: req.headers.get(\"x-platform\"),\n osVersion: req.headers.get(\"x-os-version\"),\n } satisfies ClientInfo;\n break;\n case \"req\":\n args[p.index] = req;\n break;\n default:\n args[p.index] = undefined;\n }\n }\n\n // ── dispatch, inside the request's transaction(s) ───────────────────────\n //\n // One for the caller's identity, and — only if the handler asks for it —\n // one more for `Database.asService()`. Both settle here, together.\n const db = createRequestDatabase(sql, {\n role: config.dbRole,\n serviceRole: config.dbServiceRole,\n claimsJson: JSON.stringify(claims ?? {}),\n });\n try {\n const services = buildServices(db);\n\n const result = await runWithRuntime(services, () => {\n // The ALS box carries the caller's identity beside the services; Flags'\n // auto-bind reads it, and so does anything else that needs a\n // server-owned user id rather than one the caller supplied.\n const box = requestALS.getStore();\n if (box) {\n box.userId = userId ?? null;\n box.requestId = requestId;\n box.idempotencyKey = req.headers.get(\"idempotency-key\");\n }\n const method = hit.entry.instance[meta.fnName];\n if (typeof method !== \"function\") {\n throw new Error(\n `route ${hit.entry.id} names method ${meta.fnName}, which the controller does not define`,\n );\n }\n return method.apply(hit.entry.instance, args);\n });\n await db.commit();\n\n if (meta.returnSchema) {\n const v = meta.returnSchema.safeParse(result);\n if (!v.success) {\n log.error(`[engine] ${hit.entry.id} returned a value its declared type rejects`, v.error.issues);\n return envelope(\n \"output_invalid\",\n \"The handler returned a value its declared return type rejects\",\n 500,\n requestId,\n );\n }\n }\n if (result === undefined || result === null) {\n if (completionUploadId) {\n completions.remember(completionUploadId, { status: 204, body: null, contentType: null });\n }\n return new Response(null, { status: 204 });\n }\n const payload = JSON.stringify(result);\n if (completionUploadId) {\n completions.remember(completionUploadId, {\n status: 200,\n body: payload,\n contentType: JSON_HEADERS[\"content-type\"] ?? \"application/json\",\n });\n }\n return new Response(payload, { status: 200, headers: JSON_HEADERS });\n } catch (err) {\n // The handler threw after writing: nothing it wrote may survive.\n await db.rollback(err);\n // Branded, not `instanceof`: the tenant's bundle carries its own copy of\n // this SDK, so class identity does not survive the hop from the handler\n // to this catch. See HTTP_ERROR_BRAND.\n if (isHttpError(err)) {\n return envelope(\n err.error,\n err.errorDescription,\n err.status,\n requestId,\n err.data !== undefined ? { data: err.data } : undefined,\n );\n }\n log.error(`[engine] unhandled error in ${hit.entry.id}`, err);\n return envelope(\"internal_error\", \"The request could not be completed\", 500, requestId);\n }\n }\n\n return {\n handle,\n routes,\n config,\n runInServiceScope,\n async shutdown() {\n const closable = sql as { close?: () => Promise<void> | void; end?: () => Promise<void> | void };\n await closable.close?.();\n await closable.end?.();\n },\n };\n}\n","// `@Controller(basePath, options?)` — the class decorator that marks a class as\n// a Palbase backend controller. It stamps a non-enumerable `__palbase`\n// discriminant + the resolved controller metadata onto the class so the\n// deploy/dispatch pipeline (and `isController`/`resolveController`) can detect\n// and read it without `reflect-metadata`.\nimport type { AuthSpec } from \"../endpoint.js\";\nimport { getRoutes } from \"./registry.js\";\n\n/** The controller metadata stamped onto a `@Controller`-decorated class. The\n * default export of a `controllers/*.controller.ts` file resolves to this via\n * {@link resolveController}. */\nexport interface ControllerMeta {\n /** Discriminant the runtime + tooling read. */\n readonly __palbase: \"controller\";\n /** The base path every route in this controller mounts under (e.g. \"/todos\"). */\n basePath: string;\n /** Controller-level default auth, applied to routes that don't set their own\n * (`@Get(\"/x\", { auth })` overrides this). `undefined` ⇒ secure-by-default. */\n defaultAuth?: AuthSpec;\n}\n\n/** Options accepted by `@Controller`. */\nexport interface ControllerOptions {\n /** Default auth for ALL routes in this controller (route-level overrides). */\n auth?: AuthSpec;\n}\n\n/** Symbol the controller metadata is stamped under. Symbol-keyed (not a string\n * property) so it never collides with an authored member and stays off the\n * structural surface. */\nexport const CONTROLLER_META: unique symbol = Symbol.for(\"palbase.backend.controllerMeta\");\n\n/**\n * Every class `@Controller` has decorated, in decoration order.\n *\n * This is what lets a controller file need no export at all: importing the file\n * runs the decorator, the decorator records the class here, and the runtime\n * reads the list. Without it the only handle on a class is its export name, so\n * every controller had to be exported AND named in a generated entry — the\n * ceremony NestJS still charges (`export class` PLUS\n * `@Module({controllers:[…]})`).\n *\n * Keyed on a well-known Symbol against globalThis rather than held in a module\n * variable, because a deployed bundle inlines its own copy of this package: two\n * copies would keep two lists, and the runtime would read the empty one. The\n * same hazard `runtimeHooks` exists for, closed the same way — one shared slot.\n */\nconst REGISTRY: unique symbol = Symbol.for(\"palbase.backend.allControllers\") as never;\n\nfunction registry(): unknown[] {\n const g = globalThis as unknown as Record<symbol, unknown[] | undefined>;\n const existing = g[REGISTRY];\n if (existing) return existing;\n const fresh: unknown[] = [];\n g[REGISTRY] = fresh;\n return fresh;\n}\n\n/**\n * The controller classes this process has loaded, in decoration order.\n *\n * Decoration order is import order, which the bundler fixes by sorting the\n * files it emits imports for — so two builds of one tree produce the same\n * route table, and route precedence is not a function of module-resolution\n * accidents.\n */\nexport function getRegisteredControllers(): readonly unknown[] {\n return registry().slice();\n}\n\n/** Empty the registry. For tests, which load controllers repeatedly. */\nexport function __resetRegisteredControllers(): void {\n registry().length = 0;\n}\n\n/** A class carrying the stamped controller metadata + discriminant. */\ninterface ControllerCarrier {\n __palbase?: \"controller\";\n [CONTROLLER_META]?: ControllerMeta;\n}\n\n/** The one path segment the platform owns. The isolate matches\n * `^/webhooks/([^/]+)$` on the raw request path BEFORE controller dispatch, so\n * anything a controller resolves to under it answers `404 webhook_not_found`\n * and never runs. */\nconst RESERVED_FIRST_SEGMENT = \"webhooks\";\n\n/**\n * Throw if `path` resolves under the reserved segment. Segments are compared the\n * way the isolate compares them — `split(\"/\").filter(Boolean)` — NOT by string\n * prefix, because empty segments collapse there: `@Controller(\"/\")` +\n * `@Post(\"/webhooks/x\")` composes to `//webhooks/x`, which the isolate serves as\n * `/webhooks/x`. A prefix check reads that as safe; the segment check does not.\n * `/webhooksy` stays allowed for the same reason — it is a different segment.\n *\n * Every verb is refused, not just the POST the isolate currently intercepts: the\n * reservation is of the URL namespace, so a `@Get(\"/webhooks/x\")` that happens\n * to work today would be silently shadowed the moment the isolate's method gate\n * widens. Refusing at build is recoverable; discovering it as a 404 is not.\n */\nfunction assertNotReserved(path: string, subject: string): void {\n const [first] = path.split(\"/\").filter(Boolean);\n if (first === RESERVED_FIRST_SEGMENT) {\n throw new Error(\n `${subject} resolves under the reserved /${RESERVED_FIRST_SEGMENT} path — ` +\n \"inbound webhooks are served there and would shadow this route\",\n );\n }\n}\n\n/**\n * Mark a class as a Palbase backend controller. `basePath` is the mount path\n * for every route the class declares; `options.auth` sets the controller-level\n * default auth (a route's own `auth` overrides it; absent ⇒ secure-by-default).\n *\n * @example\n * \\@Controller(\"/todos\", { auth: false })\n * export class TodosController {\n * \\@Get(\"\") list(\\@QueryParams(ListTodosQuery) q: ListTodosQuery): TodoSchema[] { … }\n * }\n */\nexport function Controller(basePath: string, options: ControllerOptions = {}) {\n return function <T extends abstract new (...args: never[]) => object>(ctor: T): T {\n // /webhooks/* belongs to the platform: the isolate matches the inbound\n // webhook route before controller dispatch, so a controller mounted here\n // would never receive a request. Silent shadowing is the failure mode this\n // whole change exists to remove, so refuse it at build.\n //\n // The COMPOSED path is what gets shadowed, not the base path. `@Controller(\"\")`\n // and `@Controller(\"/\")` both pass a base-path-only check while a\n // `@Post(\"/webhooks/stripe\")` inside them resolves to exactly the path the\n // isolate intercepts. Method decorators run BEFORE the class decorator (TS\n // evaluates members first), so every route this class declares is already in\n // the registry here — which is why the composed check can live at this one\n // seam instead of on the dispatch read path. The `@Controller(\"\") +\n // @Post(\"/webhooks/stripe\")` test is the lock on that ordering: if it ever\n // stopped holding, that test goes red.\n assertNotReserved(basePath, `@Controller(\"${basePath}\")`);\n for (const route of getRoutes(ctor)) {\n assertNotReserved(\n `${basePath}${route.subpath}`,\n `@${route.method}(\"${route.subpath}\") in @Controller(\"${basePath}\")`,\n );\n }\n\n const carrier = ctor as unknown as ControllerCarrier;\n const meta: ControllerMeta = {\n __palbase: \"controller\",\n basePath,\n ...(options.auth !== undefined ? { defaultAuth: options.auth } : {}),\n };\n // Non-enumerable so it doesn't leak onto instances / structural checks.\n Object.defineProperty(carrier, CONTROLLER_META, {\n value: meta,\n enumerable: false,\n configurable: true,\n writable: false,\n });\n // The bare `__palbase` discriminant is the cheap detection marker the\n // runtime/extractor checks; keep it readable but non-enumerable.\n Object.defineProperty(carrier, \"__palbase\", {\n value: \"controller\",\n enumerable: false,\n configurable: true,\n writable: false,\n });\n // Record it, so importing the file is enough and exporting is optional.\n // Guarded against a double-decoration re-entering the same class twice.\n const all = registry();\n if (!all.includes(ctor)) all.push(ctor);\n return ctor;\n };\n}\n\n/** True when `value` is a `@Controller`-decorated class (cheap discriminant\n * check). Accepts the class constructor (the default export of a controller\n * file). */\nexport function isController(value: unknown): boolean {\n if (typeof value !== \"function\" && (typeof value !== \"object\" || value === null)) {\n return false;\n }\n const carrier = value as ControllerCarrier;\n return carrier.__palbase === \"controller\" && carrier[CONTROLLER_META] !== undefined;\n}\n\n/** Read the resolved controller metadata off a `@Controller`-decorated class.\n * Throws if the class was not decorated — callers should gate with\n * {@link isController} first (the loader does). */\nexport function resolveController(ctor: unknown): ControllerMeta {\n if (typeof ctor !== \"function\" && (typeof ctor !== \"object\" || ctor === null)) {\n throw new TypeError(\"resolveController: value is not a class\");\n }\n const meta = (ctor as ControllerCarrier)[CONTROLLER_META];\n if (!meta) {\n throw new TypeError(\n \"resolveController: class is not a @Controller — every controller file must `export default` a @Controller-decorated class\",\n );\n }\n return meta;\n}\n"],"mappings":"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","names":["resolveTx"]}
|