@palbase/backend 22.0.1 → 23.0.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.
Files changed (73) hide show
  1. package/dist/bin/palbase-backend.cjs +764 -25
  2. package/dist/bin/palbase-backend.cjs.map +1 -1
  3. package/dist/bin/palbase-backend.js +4 -4
  4. package/dist/{chunk-POYAFBLF.js → chunk-FSGSB42K.js} +13 -6
  5. package/dist/chunk-FSGSB42K.js.map +1 -0
  6. package/dist/{chunk-SSGAMC26.js → chunk-HAF67F2H.js} +114 -5
  7. package/dist/chunk-HAF67F2H.js.map +1 -0
  8. package/dist/{chunk-QMVK4X3V.js → chunk-OMRTHM4X.js} +98 -98
  9. package/dist/chunk-OMRTHM4X.js.map +1 -0
  10. package/dist/{chunk-QYOHMVUW.js → chunk-REZU6UKT.js} +755 -24
  11. package/dist/chunk-REZU6UKT.js.map +1 -0
  12. package/dist/{chunk-YL4C5NRY.js → chunk-Y5HXVUMP.js} +2 -2
  13. package/dist/{chunk-N32VDWKH.js → chunk-ZC6Q2BRD.js} +4 -59
  14. package/dist/chunk-ZC6Q2BRD.js.map +1 -0
  15. package/dist/db/env.cjs.map +1 -1
  16. package/dist/db/env.d.cts +3 -21
  17. package/dist/db/env.d.ts +3 -21
  18. package/dist/db/index.cjs +117 -6
  19. package/dist/db/index.cjs.map +1 -1
  20. package/dist/db/index.d.cts +3 -2
  21. package/dist/db/index.d.ts +3 -2
  22. package/dist/db/index.js +7 -3
  23. package/dist/{endpoint-B0LpZixz.d.cts → endpoint-BavvbW4P.d.ts} +116 -14
  24. package/dist/{endpoint-B0LpZixz.d.ts → endpoint-i8TTCohk.d.cts} +116 -14
  25. package/dist/engine/index.cjs +764 -25
  26. package/dist/engine/index.cjs.map +1 -1
  27. package/dist/engine/index.d.cts +6 -5
  28. package/dist/engine/index.d.ts +6 -5
  29. package/dist/engine/index.js +3 -3
  30. package/dist/{index-g-EzitI-.d.ts → index-B3jmmItD.d.ts} +203 -7
  31. package/dist/{index-BCNtlG1w.d.ts → index-B7YBEG5w.d.ts} +117 -93
  32. package/dist/{index-BGSCWlUa.d.cts → index-Bmvx1EvJ.d.cts} +203 -7
  33. package/dist/{index-B4W6d2VJ.d.cts → index-E7OscPJT.d.cts} +117 -93
  34. package/dist/index.cjs +509 -1085
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +203 -1133
  37. package/dist/index.d.ts +203 -1133
  38. package/dist/index.js +288 -900
  39. package/dist/index.js.map +1 -1
  40. package/dist/openapi/index.cjs +3 -57
  41. package/dist/openapi/index.cjs.map +1 -1
  42. package/dist/openapi/index.d.cts +3 -2
  43. package/dist/openapi/index.d.ts +3 -2
  44. package/dist/openapi/index.js +5 -22
  45. package/dist/openapi/index.js.map +1 -1
  46. package/dist/{registry-3BLYv4si.d.ts → registry-C3H2uPeZ.d.cts} +13 -169
  47. package/dist/{registry-Cw0YEYCg.d.cts → registry-DY3d9l1k.d.ts} +13 -169
  48. package/dist/{purchases/keys.cjs → stack.cjs} +4 -4
  49. package/dist/stack.cjs.map +1 -0
  50. package/dist/stack.d.cts +76 -0
  51. package/dist/stack.d.ts +76 -0
  52. package/dist/stack.js +1 -0
  53. package/docs/README.md +7 -6
  54. package/docs/endpoints.md +1 -1
  55. package/docs/errors.md +9 -0
  56. package/docs/llms-full.txt +17 -261
  57. package/docs/llms.txt +0 -2
  58. package/package.json +7 -7
  59. package/template/package.json +1 -1
  60. package/dist/chunk-N32VDWKH.js.map +0 -1
  61. package/dist/chunk-POYAFBLF.js.map +0 -1
  62. package/dist/chunk-QMVK4X3V.js.map +0 -1
  63. package/dist/chunk-QYOHMVUW.js.map +0 -1
  64. package/dist/chunk-SSGAMC26.js.map +0 -1
  65. package/dist/purchases/keys.cjs.map +0 -1
  66. package/dist/purchases/keys.d.cts +0 -42
  67. package/dist/purchases/keys.d.ts +0 -42
  68. package/dist/purchases/keys.js +0 -1
  69. package/docs/config.md +0 -147
  70. package/docs/resources.md +0 -97
  71. package/template/config/secrets.ts +0 -24
  72. /package/dist/{chunk-YL4C5NRY.js.map → chunk-Y5HXVUMP.js.map} +0 -0
  73. /package/dist/{purchases/keys.js.map → stack.js.map} +0 -0
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/purchases/errors.ts","../src/purchases/subject.ts","../src/purchases/decorators.ts","../src/clients/http.ts","../src/clients/documents.ts","../src/clients/flags.ts","../src/clients/notifications.ts","../src/clients/realtime.ts","../src/clients/storage.ts","../src/clients/index.ts","../src/purchases/keys-gen.ts","../src/db/schema-json.ts","../src/db/env-gen.ts","../src/config/storage.ts","../src/config/egress.ts","../src/config/notifications.ts","../src/config/test-users.ts","../src/config/flags.ts","../src/config/secrets.ts","../src/decorators/methods.ts","../src/decorators/webhook.ts","../src/decorators/hook.ts","../src/decorators/upload.ts","../src/decorators/params.ts","../src/middleware.ts","../src/job.ts","../src/decorators/job.ts","../src/resource.ts","../src/index.ts"],"sourcesContent":["/**\n * Map palstore's thrown errors onto palbase's wire envelope.\n *\n * This mapping is REQUIRED, not cosmetic: the runtime only serializes a throw\n * that carries `{ status: number, error: string }` (worker.js's HttpError\n * catch). A palstore error carries `{ status, code }` — no `error` — so an\n * unmapped `QuotaExceededError` would leave the handler as a 500 and the client\n * would see \"internal error\" for a perfectly ordinary exhausted quota.\n *\n * The detection is STRUCTURAL (`code` + `status`) rather than `instanceof`,\n * because `@palbase/backend` deliberately has no dependency on\n * `@palstore/purchases` — see purchases/service.ts for why.\n */\n\nimport { HttpError, PalError } from \"../errors.js\";\n\n/** The shape every `PalstoreError` subclass presents: a stable snake_case wire\n * code plus the HTTP status it stands for. */\ninterface PalstoreErrorLike {\n code: string;\n status: number;\n message: string;\n}\n\nfunction asPalstoreError(err: unknown): PalstoreErrorLike | null {\n if (!(err instanceof Error)) return null;\n const e = err as Error & { code?: unknown; status?: unknown };\n if (typeof e.code !== \"string\" || typeof e.status !== \"number\") return null;\n return { code: e.code, status: e.status, message: e.message };\n}\n\n/**\n * Translate a purchases failure into an `HttpError`, or return the error\n * untouched when it is not one.\n *\n * Anything unrecognised is rethrown VERBATIM — a transport failure, a bug, a\n * 500 from palstore — because turning an unknown fault into a tidy 403/429\n * would tell the client \"you lack access\" when the truth is \"we are broken\",\n * and would hide the outage from whoever is on call.\n */\nexport function toHttpError(err: unknown): unknown {\n // Already a palbase error (e.g. the 401 from subject resolution): leave it.\n if (err instanceof HttpError) return err;\n\n const p = asPalstoreError(err);\n if (!p) return err;\n\n switch (p.code) {\n case \"entitlement_required\": {\n const entitlement = (err as { entitlement?: unknown }).entitlement ?? null;\n return new PalError(403, \"entitlement_required\", p.message, { entitlement });\n }\n case \"quota_exceeded\":\n case \"credit_insufficient\": {\n // The LimitState/CreditState rides on `data` so a client can render the\n // real ceiling and reset time instead of guessing a retry delay. This is\n // why the 429 is NOT palbase's `TooManyRequests`: that class fixes its\n // payload to `{ retryAfter }`, which is rate-limiting's shape, not a\n // quota's — and squeezing a LimitState through it would drop `max`,\n // `used` and `remaining`, the three fields a paywall needs.\n const state = (err as { state?: unknown }).state;\n return new PalError(429, p.code, p.message, state);\n }\n default:\n return err;\n }\n}\n\n/** Run `fn`, translating any purchases failure on the way out. */\nexport async function mappingPurchaseErrors<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (err) {\n throw toHttpError(err);\n }\n}\n","/**\n * subject.ts — the ONLY place a purchases subject is resolved.\n *\n * The subject is derived from the SERVER-OWNED authenticated user on the\n * request context. It is never a decorator argument, never a body field, never\n * a header. A caller who could name their own subject could read someone\n * else's entitlements or spend someone else's quota, so the surface simply\n * offers no way to say it — `currentSubjectId()` takes no parameters.\n */\n\nimport { Purchases, __requestALS, type RequestStore } from \"../runtime.js\";\nimport { Unauthorized } from \"../errors.js\";\nimport type { StoreEnv } from \"./service.js\";\n\n/**\n * Per-request memo, keyed on the ALS box (one object per request, collected\n * with it). Both decorators on one route need the subject; resolving it twice\n * would double the round-trip to palstore for no gain. Kept here rather than as\n * a field on `RequestStore` so the core request type stays free of purchases\n * concerns.\n *\n * The PROMISE is memoized, not the resolved value, so two decorators that race\n * (or any concurrent caller) share one in-flight resolution instead of firing\n * two and keeping the loser.\n */\nconst subjectByRequest = new WeakMap<RequestStore, Promise<string>>();\n\n/**\n * The store environment subjects resolve against. Sandbox purchases are\n * isolated from production ones all the way down the palstore schema, so this\n * is a DEPLOYMENT fact, not a per-request one — a request cannot select it.\n * Defaults to production: a project that forgets to set it gets the strict\n * environment, never a sandbox subject that would accept test purchases.\n */\nfunction storeEnv(): StoreEnv {\n return process.env.PALSTORE_STORE_ENV === \"sandbox\" ? \"sandbox\" : \"production\";\n}\n\n/**\n * Resolve the palstore subject for the request in scope.\n *\n * Throws 401 when the request carries no authenticated user — and does so\n * BEFORE any call to palstore, so an anonymous request never mints a subject.\n */\nexport async function currentSubjectId(): Promise<string> {\n // Async, so every failure is a rejection — a Promise-returning function that\n // sometimes throws synchronously is a footgun for `.catch()`-only callers.\n // The body runs to the memo write before its first await, so two concurrent\n // callers still share one resolution.\n const store = __requestALS.getStore();\n if (!store) {\n throw new Error(\n \"Purchases decorators used outside a request scope. @RequireEntitlement/@Spend \" +\n \"resolve the subject from the request's authenticated user, so they only work \" +\n \"inside an endpoint handler.\",\n );\n }\n\n const memoized = subjectByRequest.get(store);\n if (memoized) return memoized;\n\n const userId = store.userId;\n if (!userId) {\n throw new Unauthorized(\n \"This endpoint requires an authenticated user: purchases entitlements and quota \" +\n \"are per-user, and the subject is resolved from the request's identity.\",\n );\n }\n\n const resolving = Purchases.resolveSubject({ userRef: userId, storeEnv: storeEnv() }).then(\n (r) => r.subjectId,\n );\n // ponytail: a failed resolution is NOT memoized — cache the promise, then drop\n // it on rejection so the next request-scoped caller retries instead of\n // inheriting a permanently poisoned subject for the life of the request.\n subjectByRequest.set(store, resolving);\n resolving.catch(() => subjectByRequest.delete(store));\n return resolving;\n}\n","/**\n * `@RequireEntitlement` and `@Spend` — access and metering at the decorator\n * level, so a controller method says what it costs instead of wiring it.\n *\n * TWO decorators, deliberately, because not every subscription is limit-based.\n * Most products just say \"pro users may call this\" and consume nothing; a\n * zero-count spend would express that badly and run the whole reserve/commit\n * machine for no reason.\n *\n * @RequireEntitlement('pro') pure gate → 403, consumes nothing\n * @Spend('bookCreate') consumption → 429 when exhausted\n *\n * ORDER IS FIXED, and not by where you wrote them. Both decorators record\n * metadata and share ONE installed wrapper that always runs the entitlement\n * gate before it reserves quota. Reserving for someone who is about to get a\n * 403 is wasted work and a race window, so the source order of the two\n * decorators cannot introduce it.\n */\n\nimport { Purchases, __requestALS } from \"../runtime.js\";\nimport { toHttpError } from \"./errors.js\";\nimport type { EntitlementKey, LimitKey } from \"./keys.js\";\nimport { entitlementFor, recordEntitlement, recordSpend, spendFor } from \"./registry.js\";\nimport { currentSubjectId } from \"./subject.js\";\n\n/** Marks a method whose purchases wrapper is already installed, so applying\n * both decorators wraps once rather than nesting two half-pipelines. */\nconst WRAPPED: unique symbol = Symbol.for(\"palbase.backend.purchases.wrapped\");\n\ntype Wrapped = ((...args: unknown[]) => unknown) & { [WRAPPED]?: true };\n\ntype MethodDecorator = (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n) => void;\n\n/**\n * The idempotency key for this request's spend.\n *\n * palstore requires one (§9 scopes idempotency by `(project_ref, subject_id,\n * operation, idempotency_key)`) and refuses a call without it rather than\n * running it non-idempotently. The caller's `Idempotency-Key` header is the\n * honest source — it is what makes a client's RETRY replay the first result\n * instead of charging twice. With no header we fall back to the request id,\n * which still satisfies the server and still makes the two decorators on one\n * request share a scope, but cannot deduplicate across a retry the client\n * never labelled.\n *\n * Suffixed with the limit key so two different `@Spend`s reached in one request\n * are separate operations rather than a self-collision.\n */\nfunction idempotencyKeyFor(key: LimitKey): string {\n const store = __requestALS.getStore();\n const base = store?.idempotencyKey || store?.requestId;\n if (!base) {\n throw new Error(\n \"@Spend needs a request-scoped idempotency key, and the runtime supplied neither an \" +\n \"Idempotency-Key header nor a request id. Spending without one would let a retried \" +\n \"request charge the user twice.\",\n );\n }\n return `${base}:${key}`;\n}\n\n/**\n * Install the single purchases wrapper on a method, if it is not there yet.\n *\n * The wrapper reads the registry at CALL time, so whichever decorator happens\n * to be applied first still yields the same fixed pipeline.\n */\nfunction ensureWrapper(target: object, fnName: string, descriptor: PropertyDescriptor): void {\n const original = descriptor.value as Wrapped | undefined;\n if (typeof original !== \"function\") {\n throw new Error(\n `@RequireEntitlement/@Spend can only decorate a method; \"${fnName}\" is not one.`,\n );\n }\n if (original[WRAPPED]) return;\n\n const wrapper = async function (this: unknown, ...args: unknown[]): Promise<unknown> {\n const ctor = (this as { constructor: object }).constructor;\n const entitlement = entitlementFor(ctor, fnName);\n const spend = spendFor(ctor, fnName);\n\n // One resolution per request, shared by both decorators (subject.ts memoizes).\n let subjectId: string;\n try {\n subjectId = await currentSubjectId();\n } catch (err) {\n throw toHttpError(err);\n }\n\n // GATE FIRST — always, regardless of decoration order.\n if (entitlement !== undefined) {\n try {\n await Purchases.require(subjectId, entitlement);\n } catch (err) {\n throw toHttpError(err);\n }\n }\n\n if (spend === undefined) {\n return original.apply(this, args);\n }\n\n // `withSpend` reserves, runs, then commits on success / cancels on throw,\n // always rethrowing the handler's own error. We track that error by\n // identity so the mapping below never reshapes a tenant's exception into a\n // purchases one on its way out.\n let handlerFailure: { err: unknown } | undefined;\n try {\n return await Purchases.withSpend(\n subjectId,\n spend.key,\n { count: spend.count, idempotencyKey: idempotencyKeyFor(spend.key) },\n async () => {\n try {\n return await original.apply(this, args);\n } catch (err) {\n handlerFailure = { err };\n throw err;\n }\n },\n );\n } catch (err) {\n if (handlerFailure !== undefined && handlerFailure.err === err) throw err;\n throw toHttpError(err);\n }\n } as Wrapped;\n\n wrapper[WRAPPED] = true;\n descriptor.value = wrapper;\n}\n\n/**\n * Require an active entitlement. Answers 403 `entitlement_required` when it is\n * absent and consumes nothing.\n *\n * The key is a member of the generated `EntitlementKey` union, so a typo is a\n * compile error rather than a gate that silently never matches.\n */\nexport function RequireEntitlement(key: EntitlementKey): MethodDecorator {\n return function (target, propertyKey, descriptor) {\n const fnName = String(propertyKey);\n recordEntitlement(target, fnName, key);\n ensureWrapper(target, fnName, descriptor);\n };\n}\n\n/**\n * Consume one unit of a limit or credit for the request's subject.\n *\n * Reserves before the handler runs and commits only if it returns; a throw\n * cancels the hold, so a user is never charged for work that did not complete.\n * Answers 429 `quota_exceeded` (carrying the `LimitState`) when exhausted.\n *\n * The count is fixed at 1. A DYNAMIC amount is deliberately not expressible\n * here: it has to be decided inside the handler and spent BEFORE the billable\n * side-effect, which is an explicit `Purchases.withSpend(...)` call, not a\n * decorator.\n */\nexport function Spend(key: LimitKey): MethodDecorator {\n return function (target, propertyKey, descriptor) {\n const fnName = String(propertyKey);\n recordSpend(target, fnName, { key, count: 1 });\n ensureWrapper(target, fnName, descriptor);\n };\n}\n","/**\n * http.ts — the transport every module client speaks over.\n *\n * WHY IT IS HERE. This code, and the five clients built on it, spent their life\n * in `v2/runtime/internal/runtime/module-clients.js`: 1,768 lines of untyped\n * CommonJS that entered the SDK through an `@ts-expect-error` and left through\n * `unknown` casts. The interfaces those clients implement were always in this\n * package — only the implementations were outside it, where nothing checked one\n * against the other. Two defects came through that gap on 2026-08-15 (a type\n * that described a different server's columns; an accessor that was `undefined`\n * in a deployed handler), and both were green on each side alone.\n *\n * WHAT IT IS NOT. Nothing Bun-specific lives here. The transport is a `fetch`\n * the caller may supply, so this package stays runtime-agnostic and the process\n * that knows which runtime it is decides what to hand in.\n */\n\nimport type { PalbaseResult } from \"../endpoint.js\";\n\n/** Per-request options a module client may pass. */\nexport interface RequestOptions {\n /** JSON-serialised unless it is a string, a Uint8Array, a Blob or FormData. */\n body?: unknown;\n headers?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/**\n * What a module client is given. An INTERFACE rather than a class, because the\n * clients depend on this shape and not on the thing that implements it — which\n * is what lets a test drive a whole client without a server.\n */\nexport interface ModuleTransport {\n /** The platform's base URL, for the rare client that must build a URL. */\n readonly baseUrl: string;\n request<T = unknown>(\n method: string,\n path: string,\n options?: RequestOptions,\n ): Promise<PalbaseResult<T>>;\n}\n\nexport interface TransportConfig {\n baseUrl: string;\n apiKey: string;\n /**\n * The `fetch` to use. Omitted means the ambient one — resolved at CALL time,\n * never captured here: the egress fence replaces `globalThis.fetch` after the\n * clients are built, and a captured reference would keep calling the\n * un-fenced original.\n */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * A module call that failed.\n *\n * `code` is the platform's own error code (`forbidden`, `not_found`, …) so a\n * caller can branch on it without matching message text.\n */\nexport class PalbaseModuleError extends Error {\n readonly code: string;\n readonly status: number;\n readonly details: Record<string, unknown>;\n\n constructor(code: string, message: string, status: number, details: Record<string, unknown> = {}) {\n super(message);\n this.name = \"PalbaseModuleError\";\n this.code = code;\n this.status = status;\n this.details = details;\n }\n}\n\nexport function makeHttpClient(cfg: TransportConfig): ModuleTransport {\n async function request<T>(\n method: string,\n path: string,\n options: RequestOptions = {},\n ): Promise<PalbaseResult<T>> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...(options.headers ?? {}),\n };\n if (cfg.apiKey) headers[\"apikey\"] = cfg.apiKey;\n\n const init: RequestInit = { method, headers };\n if (options.body !== undefined) {\n if (typeof options.body === \"string\" || options.body instanceof Uint8Array) {\n init.body = options.body as RequestInit[\"body\"];\n } else if (typeof FormData !== \"undefined\" && options.body instanceof FormData) {\n // The platform writes Content-Type itself, WITH the multipart boundary.\n // Setting it here omits the boundary, and the server then parses zero\n // parts from a request that looks perfectly well formed.\n delete headers[\"Content-Type\"];\n init.body = options.body;\n } else if (typeof Blob !== \"undefined\" && options.body instanceof Blob) {\n delete headers[\"Content-Type\"];\n init.body = options.body;\n } else {\n init.body = JSON.stringify(options.body);\n }\n }\n if (options.signal) init.signal = options.signal;\n\n // Resolved HERE, per call. See TransportConfig.fetchImpl.\n const doFetch = cfg.fetchImpl ?? globalThis.fetch;\n\n let response: Response;\n try {\n response = await doFetch(`${cfg.baseUrl}${path}`, init);\n } catch (err) {\n // AN ENVELOPE, not an exception.\n //\n // This threw until 2026-08-15, and the throw made three separate claims\n // false at once:\n //\n // 1. The package's own rule — \"Response: { data, error }, no thrown API\n // errors\". Every client here is written to that contract.\n // 2. `Flags.get(key, default)`, whose documented behaviour is that the\n // default applies when the flag is absent AND when the service is\n // unreachable. It reads `resp.error !== null` to decide, and a throw\n // never reaches that branch: measured, `get(\"beta\", \"DEFAULT\")`\n // raised `connect ECONNREFUSED` instead of answering \"DEFAULT\". The\n // test that was supposed to cover it handed the client a hand-made\n // error envelope — a shape this code could not produce.\n // 3. Consistency with the Realtime client, which already envelopes a\n // network failure so a handler that wrote a row does not lose it\n // because pubsub was down.\n //\n // A caller destructuring { data, error } and checking `error` was being\n // defeated by an exception: the defensive code existed and did not help,\n // which is the worst kind of surprise to leave in a package.\n return {\n data: null,\n error: new PalbaseModuleError(\n \"network_error\",\n err instanceof Error ? err.message : \"Network request failed\",\n 0,\n ),\n status: 0,\n };\n }\n\n const contentType = response.headers.get(\"Content-Type\") ?? \"\";\n let parsed: unknown = null;\n if (method !== \"HEAD\" && contentType.includes(\"json\")) {\n parsed = await response.json().catch(() => null);\n } else if (method !== \"HEAD\" && contentType.startsWith(\"image/\")) {\n // QR codes and the like: hand back bytes the caller can write or forward.\n parsed = new Uint8Array(await response.arrayBuffer());\n } else if (method !== \"HEAD\" && response.body) {\n // A non-JSON error still says something; \"request failed\" says nothing.\n parsed = await response.text().catch(() => null);\n }\n\n if (!response.ok) {\n const body = (parsed && typeof parsed === \"object\" ? parsed : {}) as Record<string, unknown>;\n const code = typeof body.error === \"string\" && body.error ? body.error : \"unknown_error\";\n const message =\n (typeof body.error_description === \"string\" && body.error_description) ||\n response.statusText ||\n \"request failed\";\n return {\n data: null,\n error: new PalbaseModuleError(code, message, response.status, body),\n status: response.status,\n };\n }\n\n return { data: parsed as T, error: null, status: response.status };\n }\n\n return { baseUrl: cfg.baseUrl, request };\n}\n","/**\n * documents.ts — the Documents client, Firestore-shaped.\n *\n * Moved in from `v2/runtime/internal/runtime/module-clients.js:705-773` (plus\n * the `buildDocumentRef` / `buildCollectionRef` helpers above it) with its\n * behaviour intact: the same methods, the same paths, the same bodies. What\n * changed is that it now sits beside the interface it implements, so a drift\n * between the two is a compile error rather than a runtime surprise.\n */\n\nimport type {\n PalbaseCollectionRef,\n PalbaseDocsClient,\n PalbaseDocumentRef,\n PalbaseDocumentSnapshot,\n PalbaseQuerySnapshot,\n PalbaseResult,\n PalbaseWhereOperator,\n} from \"../endpoint.js\";\nimport { PalbaseModuleError, type ModuleTransport } from \"./http.js\";\n\n/**\n * A path segment the platform will accept.\n *\n * Validated HERE rather than at the server, because a rejected segment is a\n * programming mistake and the useful moment to hear about it is the call.\n */\nconst SEGMENT_RE = /^[A-Za-z0-9_-]+$/;\n\nfunction validateSegment(segment: string, label: string): void {\n if (!SEGMENT_RE.test(segment)) {\n throw new Error(`Invalid ${label}: \"${segment}\". Must match ${SEGMENT_RE.source}`);\n }\n}\n\ninterface WhereClause {\n field: string;\n op: PalbaseWhereOperator;\n value: unknown;\n}\ninterface OrderClause {\n field: string;\n direction: \"asc\" | \"desc\";\n}\ninterface ChainState {\n where: WhereClause[];\n orderBy: OrderClause[];\n limit?: number;\n}\n\ninterface RawDocument {\n id?: string;\n exists?: boolean;\n data?: Record<string, unknown>;\n}\n\nfunction buildDocumentRef<T extends Record<string, unknown>>(\n http: ModuleTransport,\n path: string,\n): PalbaseDocumentRef<T> {\n return {\n path,\n async set(data: T) {\n return http.request<void>(\"PUT\", `/v1/docs/${path}`, { body: data });\n },\n async get(): Promise<PalbaseResult<PalbaseDocumentSnapshot<T>>> {\n const response = await http.request<RawDocument>(\"GET\", `/v1/docs/${path}`);\n if (response.error) return { data: null, error: response.error, status: response.status };\n const raw = response.data ?? {};\n const exists = raw.exists !== undefined ? raw.exists : Boolean(raw.data || raw.id);\n const segments = path.split(\"/\");\n const id = raw.id || segments[segments.length - 1] || \"\";\n return {\n data: { id, exists, data: () => raw.data as T | undefined, ref: { path } },\n error: null,\n status: response.status,\n };\n },\n async update(data: Partial<T>) {\n return http.request<void>(\"PATCH\", `/v1/docs/${path}`, { body: data });\n },\n async delete() {\n return http.request<void>(\"DELETE\", `/v1/docs/${path}`);\n },\n collection<C extends Record<string, unknown>>(name: string): PalbaseCollectionRef<C> {\n validateSegment(name, \"subcollection name\");\n return buildCollectionRef<C>(http, `${path}/${name}`);\n },\n };\n}\n\nfunction buildCollectionRef<T extends Record<string, unknown>>(\n http: ModuleTransport,\n path: string,\n state: ChainState = { where: [], orderBy: [] },\n): PalbaseCollectionRef<T> {\n function snapshot(doc: { id: string; data: Record<string, unknown> }): PalbaseDocumentSnapshot<T> {\n return {\n id: doc.id,\n exists: true,\n data: () => doc.data as T,\n ref: { path: `${path}/${doc.id}` },\n };\n }\n\n function querySnapshot(docs: PalbaseDocumentSnapshot<T>[]): PalbaseQuerySnapshot<T> {\n return {\n docs,\n empty: docs.length === 0,\n size: docs.length,\n docChanges: () => docs.map((doc) => ({ type: \"added\" as const, doc })),\n };\n }\n\n return {\n path,\n\n doc(id: string) {\n validateSegment(id, \"document ID\");\n return buildDocumentRef<T>(http, `${path}/${id}`);\n },\n\n async add(data: T) {\n const resp = await http.request<{ id: string }>(\"POST\", `/v1/docs/${path}`, { body: data });\n if (resp.error || !resp.data) {\n return { data: null, error: resp.error, status: resp.status };\n }\n return {\n data: buildDocumentRef<T>(http, `${path}/${resp.data.id}`),\n error: null,\n status: resp.status,\n };\n },\n\n // Each narrowing returns a NEW ref. A builder that mutated in place would\n // leak one caller's filter into a query another caller had already held.\n where(field: string, op: PalbaseWhereOperator, value: unknown) {\n return buildCollectionRef<T>(http, path, {\n ...state,\n where: [...state.where, { field, op, value }],\n });\n },\n orderBy(field: string, direction: \"asc\" | \"desc\" = \"asc\") {\n return buildCollectionRef<T>(http, path, {\n ...state,\n orderBy: [...state.orderBy, { field, direction }],\n });\n },\n limit(n: number) {\n return buildCollectionRef<T>(http, path, { ...state, limit: n });\n },\n\n async get(): Promise<PalbaseResult<PalbaseQuerySnapshot<T>>> {\n const narrowed =\n state.where.length > 0 || state.orderBy.length > 0 || state.limit !== undefined;\n\n const resp = narrowed\n ? await http.request<{ documents?: { id: string; data: Record<string, unknown> }[] }>(\n \"POST\",\n `/v1/docs/${path}/query`,\n { body: queryBody(state) },\n )\n : await http.request<{ documents?: { id: string; data: Record<string, unknown> }[] }>(\n \"GET\",\n `/v1/docs/${path}`,\n );\n\n if (resp.error) return { data: null, error: resp.error, status: resp.status };\n const docs = (resp.data?.documents ?? []).map(snapshot);\n return { data: querySnapshot(docs), error: null, status: resp.status };\n },\n };\n}\n\nfunction queryBody(state: ChainState): Record<string, unknown> {\n const body: Record<string, unknown> = {};\n if (state.where.length > 0) {\n body.where = state.where.map((w) => ({ field: w.field, op: w.op, value: w.value }));\n }\n if (state.orderBy.length > 0) {\n body.orderBy = state.orderBy.map((o) => ({ field: o.field, direction: o.direction }));\n }\n if (state.limit !== undefined) body.limit = state.limit;\n return body;\n}\n\n/** The largest batch the platform accepts in one call. */\nconst MAX_BATCH = 500;\n\nexport function buildDocumentsClient(http: ModuleTransport): PalbaseDocsClient {\n return {\n /**\n * `Documents.doc(\"users/alice\")` — segments are collection/documentId PAIRS,\n * so an odd count addresses a COLLECTION and is refused. Accepting it would\n * write a document whose id happens to be a collection's name.\n */\n doc<T extends Record<string, unknown>>(path: string): PalbaseDocumentRef<T> {\n const segments = String(path)\n .split(\"/\")\n .filter((s) => s.length > 0);\n if (segments.length === 0 || segments.length % 2 !== 0) {\n throw new Error(\n `Invalid document path: \"${path}\". Expected collection/documentId pairs, got ${segments.length} segment(s).`,\n );\n }\n segments.forEach((s, i) => validateSegment(s, i % 2 === 0 ? \"collection name\" : \"document ID\"));\n return buildDocumentRef<T>(http, segments.join(\"/\"));\n },\n\n collection<T extends Record<string, unknown>>(name: string): PalbaseCollectionRef<T> {\n validateSegment(name, \"collection name\");\n return buildCollectionRef<T>(http, name);\n },\n\n async batch(operations) {\n // Refused HERE, without a request: the server would refuse it too, and\n // spending a round trip to be told so is the caller's time.\n if (operations.length > MAX_BATCH) {\n return {\n data: null,\n error: new PalbaseModuleError(\n \"batch_too_large\",\n `Batch size ${operations.length} exceeds maximum of ${MAX_BATCH}`,\n 400,\n ),\n status: 400,\n };\n }\n if (operations.length === 0) return { data: null, error: null, status: 200 };\n\n return http.request<void>(\"POST\", \"/v1/docs/batch\", {\n body: operations.map((op) => ({ op: op.op, path: op.ref.path, data: op.data })),\n });\n },\n };\n}\n","/**\n * flags.ts — feature flags, resolved for the request's own user.\n *\n * Moved in from `v2/runtime/internal/runtime/module-clients.js:941-1164`.\n *\n * THE ONE RULE WORTH STATING: the user a flag resolves for comes from the\n * SDK's own request scope, never from anything the caller passed on the wire.\n * A handler can pass an explicit context (including an explicit `null` for a\n * deliberate anonymous read) and that wins — but the default is the person the\n * request is being served for, which is what makes `Flags.get(\"x\")` mean the\n * obvious thing inside a handler.\n *\n * Writes mirror the Database model: `setOverride` writes for the CURRENT user\n * and needs no admin power; cross-user writes live behind `asService()` so they\n * are explicit and greppable.\n */\n\nimport type {\n PalbaseBatchOverrideOperation,\n PalbaseFlagContext,\n PalbaseFlagValue,\n PalbaseFlagsClient,\n PalbaseFlagsServiceClient,\n} from \"../clients.js\";\nimport type { PalbaseResult } from \"../endpoint.js\";\nimport type { ModuleTransport } from \"./http.js\";\n\nconst FLAG_NAME_RE = /^[A-Za-z0-9_.-]+$/;\n\nexport interface FlagsConfig {\n /** The request's user, read from the SDK's ALS box — never from the caller. */\n getCurrentUserId: () => string | null;\n}\n\nfunction assertFlagName(flagName: string): void {\n if (!FLAG_NAME_RE.test(flagName)) {\n throw new Error(`Invalid flag name: \"${flagName}\". Flag names must match ${FLAG_NAME_RE.source}`);\n }\n}\n\n/** A truthy flag value, in the platform's own terms. */\nfunction flagEnabled(value: unknown): boolean {\n if (typeof value === \"boolean\") return value;\n return value != null && value !== 0 && value !== \"\";\n}\n\nfunction flagVariant(value: unknown): { name: string } | null {\n return typeof value === \"string\" ? { name: value } : null;\n}\n\n/**\n * A context object carries `userId`/`properties`; anything else passed in that\n * position is a DEFAULT VALUE. This is what tells `Flags.get(key, ctx)` apart\n * from `Flags.get(key, someObjectDefault)`.\n */\nfunction isContextObject(v: unknown): v is PalbaseFlagContext {\n return (\n v !== null && typeof v === \"object\" && !Array.isArray(v) && (\"userId\" in v || \"properties\" in v)\n );\n}\n\ninterface MergedSnapshot {\n values?: Record<string, PalbaseFlagValue>;\n}\n\nexport function buildFlagsClient(http: ModuleTransport, cfg: FlagsConfig): PalbaseFlagsClient {\n /**\n * The effective user for a call. An explicit `userId` in the context wins —\n * INCLUDING an explicit `null`, which is a deliberate anonymous read.\n */\n function resolveUserId(context?: PalbaseFlagContext): string | null | undefined {\n if (context && \"userId\" in context) return context.userId ?? null;\n return cfg.getCurrentUserId() || undefined;\n }\n\n function mergedPath(context?: PalbaseFlagContext): string {\n const uid = resolveUserId(context);\n return uid ? `/v1/user-flags/users/${encodeURIComponent(uid)}` : \"/v1/user-flags\";\n }\n\n function fetchMerged(context?: PalbaseFlagContext) {\n return http.request<MergedSnapshot>(\"GET\", mergedPath(context));\n }\n\n const service: PalbaseFlagsServiceClient = {\n async setOverrideForUser(userId, key, value) {\n return http.request(\n \"PUT\",\n `/v1/user-flags/users/${encodeURIComponent(userId)}/${encodeURIComponent(key)}`,\n { body: { value } },\n );\n },\n async setOverridesForUser(userId, values) {\n return http.request(\"PUT\", `/v1/user-flags/users/${encodeURIComponent(userId)}`, {\n body: { values },\n });\n },\n async clearOverrideForUser(userId, key) {\n return http.request(\n \"DELETE\",\n `/v1/user-flags/users/${encodeURIComponent(userId)}/${encodeURIComponent(key)}`,\n );\n },\n async clearAllOverridesForUser(userId) {\n return http.request(\"DELETE\", `/v1/user-flags/users/${encodeURIComponent(userId)}`);\n },\n async batchSetOverrides(operations: ReadonlyArray<PalbaseBatchOverrideOperation>) {\n // The argument is camelCase, the wire is snake_case. Mapped here so a\n // stray `userId` never reaches the server — and an explicit `user_id`, if\n // a caller already wrote one, is preserved.\n const ops = (operations ?? []).map((op) => {\n const raw = op as unknown as { userId?: string; user_id?: string; values: unknown };\n return { user_id: raw.userId ?? raw.user_id, values: raw.values };\n });\n return http.request(\"POST\", \"/v1/user-flags/batch\", { body: { operations: ops } });\n },\n };\n\n return {\n async isEnabled(flagName: string, context?: PalbaseFlagContext) {\n assertFlagName(flagName);\n const res = await fetchMerged(context);\n if (res.error || res.data == null) return { data: null, error: res.error, status: res.status };\n return { data: flagEnabled(res.data.values?.[flagName]), error: null, status: res.status };\n },\n\n async getVariant(flagName: string, context?: PalbaseFlagContext) {\n assertFlagName(flagName);\n const res = await fetchMerged(context);\n // A missing or non-string value is a NULL variant on a successful read;\n // errors and empty bodies pass through as null too, which is why this is\n // written out rather than mapped.\n if (res.error || res.data == null) return { data: null, error: res.error, status: res.status };\n return { data: flagVariant(res.data.values?.[flagName]), error: null, status: res.status };\n },\n\n /**\n * `get(key)` · `get(key, default)` · `get(key, default, ctx)` · `get(key, ctx)`.\n *\n * The default is substituted when the flag is ABSENT or when the flags\n * service is unreachable — a product that hides a feature because a lookup\n * timed out is behaving correctly; one that crashes is not.\n */\n async get(\n flagName: string,\n defaultOrContext?: PalbaseFlagValue | PalbaseFlagContext,\n maybeContext?: PalbaseFlagContext,\n ): Promise<PalbaseResult<PalbaseFlagValue>> {\n assertFlagName(flagName);\n\n let defaultValue: PalbaseFlagValue | undefined;\n let context: PalbaseFlagContext | undefined;\n let hasDefault = false;\n if (maybeContext !== undefined) {\n defaultValue = defaultOrContext as PalbaseFlagValue;\n hasDefault = true;\n context = maybeContext;\n } else if (isContextObject(defaultOrContext)) {\n context = defaultOrContext;\n } else if (defaultOrContext !== undefined) {\n defaultValue = defaultOrContext as PalbaseFlagValue;\n hasDefault = true;\n }\n\n const resp = await fetchMerged(context);\n if (resp.error !== null) {\n if (hasDefault) return { data: defaultValue ?? null, error: null, status: resp.status };\n return { data: null, error: resp.error, status: resp.status };\n }\n const values = resp.data?.values ?? {};\n const value = values[flagName];\n // An absent key on a SUCCESSFUL read is not an error.\n if (value === undefined) {\n return { data: hasDefault ? (defaultValue ?? null) : null, error: null, status: resp.status };\n }\n return { data: value, error: null, status: resp.status };\n },\n\n async getAll(context?: PalbaseFlagContext) {\n const res = await fetchMerged(context);\n if (res.error || res.data == null) return { data: null, error: res.error, status: res.status };\n const values = res.data.values ?? {};\n return {\n data: Object.keys(values).map((name) => {\n const value = values[name];\n const flag: { name: string; enabled: boolean; variant?: { name: string } } = {\n name,\n enabled: flagEnabled(value),\n };\n if (typeof value === \"string\") flag.variant = { name: value };\n return flag;\n }),\n error: null,\n status: res.status,\n };\n },\n\n /**\n * Override a flag for the CURRENT request user.\n *\n * On an anonymous request this does not silently no-op and does not write\n * for nobody: it refuses and names the call that does cross-user writes.\n */\n async setOverride(key: string, value: PalbaseFlagValue) {\n const uid = cfg.getCurrentUserId();\n if (!uid) {\n return {\n data: null,\n error: {\n message:\n \"setOverride requires a signed-in user; use Flags.asService().setOverrideForUser(userId, key, value) for cross-user writes\",\n },\n status: 400,\n };\n }\n return http.request(\n \"PUT\",\n `/v1/user-flags/users/${encodeURIComponent(uid)}/${encodeURIComponent(key)}`,\n { body: { value } },\n );\n },\n\n asService() {\n return service;\n },\n };\n}\n","/**\n * notifications.ts — push, email, SMS, verifications, inbox, preferences and\n * the two template surfaces.\n *\n * Moved in from `v2/runtime/internal/runtime/module-clients.js:1180-1379`.\n *\n * The theme of this file is a NAME GAP: the SDK speaks camelCase and palnotify\n * speaks snake_case, and every place they meet is a place a field can be\n * dropped in silence. One of them cost a live afternoon — `email.send({ html })`\n * was forwarded verbatim, palnotify reads `html_body`, and the answer was a 400\n * about a field the caller had supplied. The mappings below are that lesson,\n * and they are now checked against the declared parameter types instead of\n * being hand-carried across a package boundary.\n */\n\nimport type {\n PalbaseEmailClient,\n PalbaseEmailTemplate,\n PalbaseEmailTemplatesClient,\n PalbaseInboxClient,\n PalbaseNotificationsClient,\n PalbasePreferencesClient,\n PalbasePushClient,\n PalbaseSMSTemplate,\n PalbaseSMSTemplatesClient,\n PalbaseSmsClient,\n PalbaseVerificationsClient,\n} from \"../clients.js\";\nimport type { PalbaseResult } from \"../endpoint.js\";\nimport type { ModuleTransport } from \"./http.js\";\n\n/** Re-map the data of a SUCCESSFUL envelope; errors pass through untouched. */\nfunction mapEnvelope<In, Out>(res: PalbaseResult<In>, map: (data: In) => Out): PalbaseResult<Out> {\n if (res.error !== null || res.data === null || res.data === undefined) {\n return { data: null, error: res.error, status: res.status };\n }\n return { data: map(res.data), error: null, status: res.status };\n}\n\ntype Wire = Record<string, unknown>;\n\nfunction toEmailTemplate(wire: Wire): PalbaseEmailTemplate {\n const view: PalbaseEmailTemplate = {\n id: wire.id as string,\n slug: wire.slug as string,\n locale: wire.locale as string,\n subject: wire.subject as string,\n htmlBody: wire.html_body as string,\n variables: (wire.variables as string[]) ?? [],\n isDefault: wire.is_default as boolean,\n createdAt: wire.created_at as string,\n updatedAt: wire.updated_at as string,\n };\n if (wire.text_body !== undefined) view.textBody = wire.text_body as string;\n return view;\n}\n\nfunction toSmsTemplate(wire: Wire): PalbaseSMSTemplate {\n return {\n id: wire.id as string,\n slug: wire.slug as string,\n locale: wire.locale as string,\n body: wire.body as string,\n variables: (wire.variables as string[]) ?? [],\n isDefault: wire.is_default as boolean,\n createdAt: wire.created_at as string,\n updatedAt: wire.updated_at as string,\n };\n}\n\nexport function buildNotificationsClient(http: ModuleTransport): PalbaseNotificationsClient {\n const push: PalbasePushClient = {\n async send(params) {\n return http.request(\"POST\", \"/v1/notifications/push\", { body: params });\n },\n };\n\n const email: PalbaseEmailClient = {\n async send(params) {\n // `html`/`text` are what the SDK declares; palnotify reads\n // `html_body`/`text_body`. Forwarding them verbatim answered 400 about a\n // field the caller HAD supplied — live on todoapp, 2026-07-30.\n const { templateSlug, html, text, ...rest } = params;\n const body: Record<string, unknown> = { ...rest };\n if (templateSlug !== undefined) body.template_slug = templateSlug;\n if (html !== undefined) body.html_body = html;\n if (text !== undefined) body.text_body = text;\n return http.request(\"POST\", \"/v1/notifications/email\", { body });\n },\n };\n\n const sms: PalbaseSmsClient = {\n async send(params) {\n const { templateSlug, ...rest } = params;\n const body = templateSlug !== undefined ? { ...rest, template_slug: templateSlug } : rest;\n return http.request(\"POST\", \"/v1/notifications/sms\", { body });\n },\n };\n\n // Phone verification (OTP). Separate from sms.send on purpose: there is no\n // body here — the provider generates the code and the message text itself.\n const verifications: PalbaseVerificationsClient = {\n async start(params) {\n return http.request(\"POST\", \"/v1/notifications/verifications\", { body: params });\n },\n async check(params) {\n return http.request(\"POST\", \"/v1/notifications/verifications/check\", { body: params });\n },\n };\n\n const inbox: PalbaseInboxClient = {\n async send(params) {\n return http.request(\"POST\", \"/v1/notifications/inbox\", { body: params });\n },\n async list(options?: {\n cursor?: string;\n limit?: number;\n is_read?: boolean;\n category?: string;\n include_archived?: boolean;\n }) {\n const opts = options ?? {};\n const params = new URLSearchParams();\n if (opts.cursor) params.set(\"cursor\", opts.cursor);\n if (opts.limit !== undefined) params.set(\"limit\", String(opts.limit));\n if (opts.is_read !== undefined) params.set(\"is_read\", opts.is_read ? \"true\" : \"false\");\n if (opts.category) params.set(\"category\", opts.category);\n if (opts.include_archived) params.set(\"include_archived\", \"true\");\n const query = params.toString();\n return http.request(\"GET\", `/v1/notifications/inbox${query ? `?${query}` : \"\"}`);\n },\n async unreadCount() {\n return http.request(\"GET\", \"/v1/notifications/inbox/unread-count\");\n },\n async markRead(id: string) {\n return http.request(\"PATCH\", `/v1/notifications/inbox/${encodeURIComponent(id)}/read`);\n },\n async markAllRead() {\n return http.request(\"POST\", \"/v1/notifications/inbox/read-all\");\n },\n async archive(id: string) {\n return http.request(\"DELETE\", `/v1/notifications/inbox/${encodeURIComponent(id)}`);\n },\n };\n\n const preferences: PalbasePreferencesClient = {\n async get() {\n return http.request(\"GET\", \"/v1/notifications/preferences\");\n },\n async update(params) {\n return http.request(\"PUT\", \"/v1/notifications/preferences\", { body: params });\n },\n };\n\n const emailTemplates: PalbaseEmailTemplatesClient = {\n async list() {\n const resp = await http.request<Wire[]>(\"GET\", \"/v1/notifications/templates\");\n return mapEnvelope(resp, (rows) => (rows ?? []).map(toEmailTemplate));\n },\n async get(id: string) {\n const resp = await http.request<Wire>(\n \"GET\",\n `/v1/notifications/templates/${encodeURIComponent(id)}`,\n );\n return mapEnvelope(resp, toEmailTemplate);\n },\n async create(input: { slug: string; subject: string; htmlBody: string; textBody?: string; variables?: string[] }) {\n const body: Record<string, unknown> = {\n slug: input.slug,\n subject: input.subject,\n html_body: input.htmlBody,\n };\n if (input.textBody !== undefined) body.text_body = input.textBody;\n if (input.variables !== undefined) body.variables = input.variables;\n const resp = await http.request<Wire>(\"POST\", \"/v1/notifications/templates\", { body });\n return mapEnvelope(resp, toEmailTemplate);\n },\n async update(\n id: string,\n input: { subject?: string; htmlBody?: string; textBody?: string; variables?: string[] },\n ) {\n const body: Record<string, unknown> = {};\n if (input.subject !== undefined) body.subject = input.subject;\n if (input.htmlBody !== undefined) body.html_body = input.htmlBody;\n if (input.textBody !== undefined) body.text_body = input.textBody;\n if (input.variables !== undefined) body.variables = input.variables;\n const resp = await http.request<Wire>(\n \"PUT\",\n `/v1/notifications/templates/${encodeURIComponent(id)}`,\n { body },\n );\n return mapEnvelope(resp, toEmailTemplate);\n },\n async delete(id: string) {\n return http.request(\"DELETE\", `/v1/notifications/templates/${encodeURIComponent(id)}`);\n },\n };\n\n const smsTemplates: PalbaseSMSTemplatesClient = {\n async list() {\n const resp = await http.request<Wire[]>(\"GET\", \"/v1/notifications/sms-templates\");\n return mapEnvelope(resp, (rows) => (rows ?? []).map(toSmsTemplate));\n },\n async get(id: string) {\n const resp = await http.request<Wire>(\n \"GET\",\n `/v1/notifications/sms-templates/${encodeURIComponent(id)}`,\n );\n return mapEnvelope(resp, toSmsTemplate);\n },\n async create(input: { slug: string; body: string; variables?: string[] }) {\n const body: Record<string, unknown> = { slug: input.slug, body: input.body };\n if (input.variables !== undefined) body.variables = input.variables;\n const resp = await http.request<Wire>(\"POST\", \"/v1/notifications/sms-templates\", { body });\n return mapEnvelope(resp, toSmsTemplate);\n },\n async update(id: string, input: { body?: string; variables?: string[] }) {\n const body: Record<string, unknown> = {};\n if (input.body !== undefined) body.body = input.body;\n if (input.variables !== undefined) body.variables = input.variables;\n const resp = await http.request<Wire>(\n \"PUT\",\n `/v1/notifications/sms-templates/${encodeURIComponent(id)}`,\n { body },\n );\n return mapEnvelope(resp, toSmsTemplate);\n },\n async delete(id: string) {\n return http.request(\"DELETE\", `/v1/notifications/sms-templates/${encodeURIComponent(id)}`);\n },\n };\n\n return {\n push,\n email,\n sms,\n verifications,\n inbox,\n preferences,\n templates: { email: emailTemplates, sms: smsTemplates },\n async registerDevice(params) {\n return http.request(\"POST\", \"/v1/notifications/devices\", { body: params });\n },\n async unregisterDevice(deviceId: string) {\n return http.request(\"DELETE\", `/v1/notifications/devices/${encodeURIComponent(deviceId)}`);\n },\n };\n}\n","/**\n * realtime.ts — broadcast, and only broadcast.\n *\n * Moved in from `v2/runtime/internal/runtime/module-clients.js:811-883`.\n *\n * There is no `subscribe()` here, deliberately: a backend handler answers one\n * request and ends, so there is no honest place to hold a long-lived socket.\n * Subscription lives in the client SDKs; this side pushes.\n *\n * The V1 host/executor branch is GONE. It existed so an isolate could delegate\n * the secret-bearing token mint to a host that held the credential — and the\n * isolate was removed on 2026-08-14. A single-tenant process has nobody to hide\n * its own tenant's key from.\n */\n\nimport { createHmac } from \"node:crypto\";\n\nimport type { PalbaseRealtimeClient } from \"../clients.js\";\nimport { PalbaseModuleError } from \"./http.js\";\n\nexport interface RealtimeConfig {\n baseUrl: string;\n /**\n * The shared Realtime API secret. Empty means realtime is not provisioned for\n * this environment, and broadcast says so by name rather than failing oddly.\n */\n apiJwtSecret: string;\n /** Resolved at CALL time — see the note in http.ts. */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * A short-lived HS256 token Realtime's broadcast pipeline accepts.\n *\n * It needs a valid signature and a future `exp`, nothing more — this is a\n * service-to-service hop inside the stack, not a user session.\n */\nfunction mintToken(secret: string): string {\n const now = Math.floor(Date.now() / 1000);\n const header = Buffer.from(JSON.stringify({ alg: \"HS256\", typ: \"JWT\" })).toString(\"base64url\");\n const payload = Buffer.from(\n JSON.stringify({ iss: \"backend-runtime\", role: \"service_role\", iat: now, exp: now + 60 }),\n ).toString(\"base64url\");\n const sig = createHmac(\"sha256\", secret).update(`${header}.${payload}`).digest(\"base64url\");\n return `${header}.${payload}.${sig}`;\n}\n\nexport function buildRealtimeClient(cfg: RealtimeConfig): PalbaseRealtimeClient {\n const url = `${cfg.baseUrl}/realtime/api/broadcast`;\n\n return {\n async broadcast(channel: string, event: string, payload?: Record<string, unknown>) {\n // Cheap argument checks first, locally: a bad call gets an answer without\n // spending a round trip to be told the obvious.\n if (typeof channel !== \"string\" || channel.length === 0) {\n return {\n data: null,\n error: new PalbaseModuleError(\"invalid_argument\", \"channel must be a non-empty string\", 400),\n };\n }\n if (typeof event !== \"string\" || event.length === 0) {\n return {\n data: null,\n error: new PalbaseModuleError(\"invalid_argument\", \"event must be a non-empty string\", 400),\n };\n }\n if (!cfg.apiJwtSecret) {\n return {\n data: null,\n error: new PalbaseModuleError(\n \"realtime_unconfigured\",\n \"Realtime.broadcast is unavailable: realtime is not provisioned for this Environment \" +\n \"(PALBASE_REALTIME_API_JWT_SECRET unset).\",\n 503,\n ),\n };\n }\n\n let token: string;\n try {\n token = mintToken(cfg.apiJwtSecret);\n } catch (err) {\n return {\n data: null,\n error: new PalbaseModuleError(\n \"realtime_token_error\",\n err instanceof Error ? err.message : \"token mint failed\",\n 500,\n ),\n };\n }\n\n // The BARE sub-topic. Realtime prepends \"realtime:\" on delivery, and a\n // pre-prefixed topic double-prefixes and is silently dropped — proven live.\n const body = JSON.stringify({\n messages: [{ topic: channel, event, payload: payload ?? {}, private: false }],\n });\n\n const doFetch = cfg.fetchImpl ?? globalThis.fetch;\n let response: Response;\n try {\n response = await doFetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Authorization: `Bearer ${token}` },\n body,\n });\n } catch (err) {\n // FIRE AND FORGET: a handler that wrote a row and then broadcast must\n // not lose the row because the pubsub layer was unreachable. This is the\n // one client that answers with an envelope on a network failure rather\n // than throwing, and it is why.\n return {\n data: null,\n error: new PalbaseModuleError(\n \"network_error\",\n err instanceof Error ? err.message : \"broadcast request failed\",\n 0,\n ),\n };\n }\n\n if (response.status === 202 || response.status === 200) {\n return { data: undefined, error: null };\n }\n\n const detail = await response.text().catch(() => \"\");\n return {\n data: null,\n error: new PalbaseModuleError(\n \"realtime_broadcast_failed\",\n `broadcast returned ${response.status}: ${detail.slice(0, 200)}`,\n response.status,\n ),\n };\n },\n };\n}\n","/**\n * storage.ts — the Storage client.\n *\n * Moved in from `v2/runtime/internal/runtime/module-clients.js:474-589`. That\n * code addressed the native Supabase Storage wire under `/storage/v1` until\n * 2026-08-15, when it was repointed at this stack's own module — measured\n * against the live stack, where the old path answers 404 and the new one 200.\n * It arrives here so the SHAPE it returns and the type that declares that shape\n * are checked against each other: they were not, and the type spent a major\n * version describing another server's columns.\n */\n\nimport type {\n PalbaseBucketClient,\n PalbaseFileObject,\n PalbaseListOptions,\n PalbaseSignedUrlResponse,\n PalbaseStorageClient,\n PalbaseUploadOptions,\n} from \"../clients.js\";\nimport type { PalbaseResult } from \"../endpoint.js\";\nimport type { ModuleTransport } from \"./http.js\";\n\n/** What the platform accepts as a bucket name (schema: `^[a-z][a-z0-9-]{1,62}$`). */\nconst BUCKET_NAME_RE = /^[a-zA-Z0-9_-]+$/;\n/** What the platform accepts as an object path. */\nconst STORAGE_PATH_RE = /^[a-zA-Z0-9_./-]+$/;\nconst STORAGE_TRAVERSAL_RE = /(?:^|\\/)\\.\\.(?:\\/|$)/;\n\n/**\n * Refused HERE, before any request.\n *\n * A traversing path is a programming mistake, and the useful moment to hear\n * about it is the call that made it — not a 400 three layers away.\n */\nfunction validateStoragePath(p: string): void {\n if (!STORAGE_PATH_RE.test(p) || STORAGE_TRAVERSAL_RE.test(p)) {\n throw new Error(\n `Invalid file path: \"${p}\". Paths must not contain traversal sequences and must match ${STORAGE_PATH_RE.source}`,\n );\n }\n}\n\n/**\n * The wire's own shape, mapped onto what this package declares.\n *\n * v2's storage answers in camelCase with the variants and the thumbhash already\n * in it, so this maps rather than translates. The snake_case unwrapping that\n * used to live here (`metadata.mimetype`, `bucket_id`, `created_at`) belonged to\n * a different server, and reading those names off this wire produced an object\n * whose size was 0 and whose content type was \"\".\n */\nfunction toFileObject(bucket: string, row: Record<string, unknown>): PalbaseFileObject {\n return {\n name: (row.path as string) ?? \"\",\n path: (row.path as string) ?? \"\",\n bucket: (row.bucket as string) ?? bucket,\n size: typeof row.size === \"number\" ? row.size : 0,\n contentType: (row.contentType as string) ?? \"\",\n checksum: (row.checksum as string) ?? \"\",\n width: row.width as number | undefined,\n height: row.height as number | undefined,\n thumbhash: row.thumbhash as string | undefined,\n variants: (row.variants as Record<string, string>) ?? {},\n };\n}\n\n/** Re-map the data of a SUCCESSFUL envelope; pass errors through untouched. */\nfunction mapResponse<In, Out>(\n res: PalbaseResult<In>,\n map: (data: In) => Out,\n): PalbaseResult<Out> {\n if (res.error || res.data === null || res.data === undefined) {\n return { data: null, error: res.error, status: res.status };\n }\n return { data: map(res.data), error: null, status: res.status };\n}\n\nfunction buildBucketClient(\n http: ModuleTransport,\n bucketName: string,\n publicOrigin: string,\n): PalbaseBucketClient {\n const objectPath = (path: string) => `/v1/storage/object/${bucketName}/${path}`;\n\n return {\n async upload(path, file, options?: PalbaseUploadOptions) {\n validateStoragePath(path);\n const headers: Record<string, string> = {\n \"Content-Type\": options?.contentType ?? \"application/octet-stream\",\n };\n if (options?.upsert) headers[\"x-upsert\"] = \"true\";\n // The BYTES, as the body. Storage sniffs the content and decides for\n // itself what this is; the declared type is a hint it may overrule,\n // because a name and a header are both things a caller can be wrong about.\n const body = file instanceof ArrayBuffer ? new Uint8Array(file) : file;\n const res = await http.request<Record<string, unknown>>(\"PUT\", objectPath(path), {\n body,\n headers,\n });\n return mapResponse(res, (r) => toFileObject(bucketName, r ?? {}));\n },\n\n async download(path) {\n validateStoragePath(path);\n // The AUTHENTICATED read: the project already holds a credential this\n // stack verified, so it does not have to mint a signature to open its own\n // object — and this route serves private buckets, which the public one\n // refuses on purpose.\n return http.request<Blob>(\"GET\", objectPath(path), { headers: { Accept: \"*/*\" } });\n },\n\n getPublicUrl(path, options) {\n validateStoragePath(path);\n const variant = options?.variant ? `?variant=${encodeURIComponent(options.variant)}` : \"\";\n // ABSOLUTE — and the origin is a value the stack is TOLD, not the\n // transport's baseUrl.\n //\n // Those are two different addresses and conflating them is how this broke\n // once already: the transport points at palsvc over the loopback\n // (`http://127.0.0.1:8080`), and a URL built from it resolves nowhere\n // outside the pod. So this used to return the path alone.\n //\n // The path alone is not a smaller answer, it is a wrong one. A public URL\n // LEAVES the response body — into an <img>, an email, another app on\n // another host — and none of those have a base to resolve it against.\n // Measured live 24.08.2026: an iOS client handed the returned\n // `/v1/files/post-images/…` straight to URLSession and got\n // NSURLErrorUnsupportedURL (-1002). The upload had worked; only the URL\n // was unusable.\n //\n // `PALBASE_PUBLIC_ORIGIN` is set by whoever publishes the stack, because\n // only they know it: in the cloud the operator writes\n // `https://<ref>.<domain>`, and a self-hosted stack carries whatever\n // domain its certificate is for.\n if (!publicOrigin) {\n // NAMED, not silent — the same doctrine as the other unconfigured\n // modules in engine/config.ts (\"throw a named error on first use rather\n // than silently no-op\"). A returned path would pass every test here and\n // fail in the one place nobody is watching.\n throw new Error(\n `Storage.bucket(\"${bucketName}\").getPublicUrl() needs this stack's public origin, ` +\n \"and it was not configured. Set PALBASE_PUBLIC_ORIGIN to the address clients reach \" +\n \"this stack at (e.g. https://myproject.palbase.studio).\",\n );\n }\n return `${publicOrigin}/v1/files/${bucketName}/${path}${variant}`;\n },\n\n async createSignedUrl(path, options): Promise<PalbaseResult<PalbaseSignedUrlResponse>> {\n validateStoragePath(path);\n // A DURATION — `{ expiresIn: \"1h\" }`. A bare number is ambiguous between\n // seconds and minutes at every call site that reads it, and the ambiguity\n // is only discovered when a link outlives the object it opened.\n return http.request<PalbaseSignedUrlResponse>(\"POST\", `/v1/storage/sign/${bucketName}/${path}`, {\n body: { expiresIn: options.expiresIn },\n });\n },\n\n async list(prefix?: string, options?: PalbaseListOptions) {\n if (prefix) validateStoragePath(prefix);\n const params = new URLSearchParams();\n if (prefix) params.set(\"prefix\", prefix);\n if (options?.limit !== undefined) params.set(\"limit\", String(options.limit));\n const query = params.toString();\n const res = await http.request<{ objects?: Record<string, unknown>[] }>(\n \"GET\",\n `/v1/storage/bucket/${bucketName}${query ? `?${query}` : \"\"}`,\n );\n // `{objects: [...]}`, not a bare array: the envelope leaves room for the\n // paging this will grow, and unwrapping it here keeps that off callers.\n return mapResponse(res, (body) => (body?.objects ?? []).map((row) => toFileObject(bucketName, row)));\n },\n\n async remove(paths) {\n for (const p of paths) validateStoragePath(p);\n // One request per object: the module deletes an object WITH its variants,\n // and a batch endpoint reporting partial success would need a result shape\n // nobody would read. The first refusal ends it — continuing would report a\n // partial delete as a whole one.\n const removed: PalbaseFileObject[] = [];\n for (const p of paths) {\n const res = await http.request<void>(\"DELETE\", objectPath(p));\n if (res.error) return { data: null, error: res.error, status: res.status };\n removed.push(toFileObject(bucketName, { path: p }));\n }\n return { data: removed, error: null, status: 200 };\n },\n\n async move(from, to) {\n validateStoragePath(from);\n validateStoragePath(to);\n return http.request<void>(\"POST\", `/v1/storage/move/${bucketName}`, { body: { from, to } });\n },\n\n async copy(from, to) {\n validateStoragePath(from);\n validateStoragePath(to);\n return http.request<void>(\"POST\", `/v1/storage/copy/${bucketName}`, { body: { from, to } });\n },\n };\n}\n\n/**\n * @param publicOrigin the address CLIENTS reach this stack at — never the\n * transport's base, which is this process's internal route to palsvc. Empty\n * means it was not configured, and `getPublicUrl` refuses by name.\n */\nexport function buildStorageClient(\n http: ModuleTransport,\n publicOrigin: string,\n): PalbaseStorageClient {\n return {\n bucket(name: string) {\n if (!BUCKET_NAME_RE.test(name)) {\n throw new Error(`Invalid bucket name: \"${name}\". Bucket names must match ${BUCKET_NAME_RE.source}`);\n }\n // Sondaki eğik çizgi BURADA kırpılır: `${origin}/v1/files/...` iki\n // eğik çizgiyle biten bir yol üretirdi ve bazı sunucular onu ayrı bir\n // nesne sayar.\n return buildBucketClient(http, name, publicOrigin.replace(/\\/+$/, \"\"));\n },\n };\n}\n","/**\n * clients/index.ts — the composition root for the module clients.\n *\n * This is what the process calls once at boot. It builds the five clients the\n * engine injects and nothing else.\n *\n * WHAT IS NOT BUILT HERE, and why each one is absent rather than forgotten:\n *\n * - `auth`, `functions`, `analytics`, `links` — the SDK exports no singleton\n * for any of them (`runtime.ts` exports ten, and these four are not among\n * them), so no handler could reach them. They were constructed on every\n * boot and thrown away.\n * - `Purchases` — its client talks to palstore, and v2 contains no palstore\n * at all. The surface was unbacked before it was untyped. Dropped from v2\n * by the user's decision on 2026-08-15; the SDK's `src/purchases/` tree is\n * untouched and that decision is deferred, not silently taken.\n * - The V1 host/executor transport — the isolate it existed for was removed\n * on 2026-08-14. A single-tenant process has nobody to hide its own\n * tenant's credentials from.\n */\n\nimport type { ModuleClients } from \"../engine/index.js\";\nimport { buildDocumentsClient } from \"./documents.js\";\nimport { buildFlagsClient } from \"./flags.js\";\nimport { makeHttpClient } from \"./http.js\";\nimport { buildNotificationsClient } from \"./notifications.js\";\nimport { buildRealtimeClient } from \"./realtime.js\";\nimport { buildStorageClient } from \"./storage.js\";\n\nexport interface ModuleClientsConfig {\n /** Where the platform answers. Empty means \"not configured\" — see below. */\n baseUrl: string;\n /** The publishable key. Used only when no service-role key is supplied. */\n apiKey: string;\n /**\n * The service-role key, which is what a backend actually holds. Preferred\n * over `apiKey`: this process IS the project's server.\n */\n serviceRoleKey: string;\n /** The shared Realtime secret. Empty means realtime is not provisioned. */\n realtimeApiJwtSecret: string;\n /**\n * The address CLIENTS reach this stack at. Used ONLY to build public object\n * URLs; every request this bundle makes still goes over `baseUrl`.\n */\n publicOrigin: string;\n /** The request's user, read from the SDK's own scope — never from a caller. */\n getCurrentUserId: () => string | null;\n /** Injected in tests; resolved at call time in production. */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * Build the module clients.\n *\n * Returns an EMPTY bundle when there is no base URL, deliberately: the engine\n * then injects its named stubs, so a handler that reaches for `Storage` gets an\n * error saying which module is unconfigured rather than a crash reading a\n * property of undefined. Booting is not blocked — a project that never touches\n * a module runs fine without one.\n */\nexport function buildModuleClients(cfg: ModuleClientsConfig): ModuleClients {\n const baseUrl = (cfg.baseUrl || \"\").replace(/\\/+$/, \"\");\n if (!baseUrl) return {};\n\n // The service-role key when present: this process is the project's own\n // server, and the publishable key would refuse half of what it needs.\n const apiKey = cfg.serviceRoleKey || cfg.apiKey || \"\";\n const http = makeHttpClient({ baseUrl, apiKey, fetchImpl: cfg.fetchImpl });\n\n return {\n Documents: buildDocumentsClient(http),\n Storage: buildStorageClient(http, cfg.publicOrigin),\n Notifications: buildNotificationsClient(http),\n Flags: buildFlagsClient(http, { getCurrentUserId: cfg.getCurrentUserId }),\n Realtime: buildRealtimeClient({\n baseUrl,\n apiJwtSecret: cfg.realtimeApiJwtSecret,\n fetchImpl: cfg.fetchImpl,\n }),\n };\n}\n","/**\n * keys-gen.ts — generate the `palbase-purchases.d.ts` text from a catalog\n * manifest.\n *\n * The twin of `db/env-gen.ts`: the CLI / deploy pipeline calls\n * {@link makePurchasesDts} with the project's catalog revision and writes the\n * result to `palbase-purchases.d.ts` at the project root. That file augments\n * the `@palbase/backend/purchases` `Entitlements` / `Limits` interfaces, so\n * `@RequireEntitlement(...)` and `@Spend(...)` accept the project's real keys\n * and nothing else.\n *\n * Same catalog, two languages: this is the TypeScript half of what swiftgen\n * already emits for iOS. Neither side is hand-maintained, so the two cannot\n * drift from each other or from the manifest the server validated.\n *\n * The emitted file ends in `export {};` — same as `makeEnvDts`. Without it the\n * `.d.ts` is a global script, and `declare module \"…\"` there DECLARES an\n * ambient module (shadowing the real one, so every key silently becomes\n * invalid) instead of AUGMENTING it.\n */\n\n/** A catalog entry that may be tombstoned. */\ninterface Removable {\n removed?: boolean;\n}\n\n/**\n * The slice of `pur_catalogs.manifest` this generator reads. Deliberately\n * partial and permissive: the server already validated the manifest (its models\n * are `extra=\"forbid\"`), so re-checking here would be a second, weaker copy of\n * that authority.\n */\nexport interface PurchasesManifest {\n limits?: Record<string, Removable>;\n credits?: Record<string, Removable>;\n entitlements?: Record<string, Removable>;\n}\n\n/** Live keys, sorted, with tombstones dropped.\n *\n * `removed: true` is the catalog's tombstone: the key still exists so historical\n * receipts resolve, but it must NOT be offered to new code. Emitting it would\n * let a handler compile against a limit the project has retired. */\nfunction liveKeys(entries: Record<string, Removable> | undefined): string[] {\n return Object.entries(entries ?? {})\n .filter(([, def]) => def?.removed !== true)\n .map(([key]) => key)\n .sort();\n}\n\n/** A bare identifier stays bare; anything else is quoted. */\nfunction memberName(key: string): string {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : JSON.stringify(key);\n}\n\nfunction members(keys: string[]): string {\n if (keys.length === 0) return \"\";\n return `\\n${keys.map((k) => ` ${memberName(k)}: true;`).join(\"\\n\")}\\n `;\n}\n\n/**\n * Render the project's `palbase-purchases.d.ts`.\n *\n * `Limits` carries BOTH limits and credits: `@Spend` consumes either, and the\n * server answers both with a 429 (`quota_exceeded` / `credit_insufficient`), so\n * splitting them into two unions would make the author pick the right decorator\n * for a distinction the spend path does not make.\n */\nexport function makePurchasesDts(manifest: PurchasesManifest): string {\n const entitlements = liveKeys(manifest.entitlements);\n const limits = liveKeys({ ...manifest.limits, ...manifest.credits });\n\n return `// palbase-purchases.d.ts — GENERATED by @palbase/backend. Do not edit.\n// Source: the project's palstore catalog revision.\n\ndeclare module \"@palbase/backend/purchases\" {\n interface Entitlements {${members(entitlements)}}\n\n interface Limits {${members(limits)}}\n}\n\nexport {};\n`;\n}\n","// The wire shape of a declared schema — what the deploy reads.\n//\n// `defineSchema(...)` produces a value full of builders and phantom types, which\n// is the right shape for authoring and the wrong shape for anything outside this\n// process. The deploy is Go: it introspects the live database, diffs it against\n// the declaration, and applies the difference. So the declaration has to leave\n// TypeScript as data, and this file is where that happens.\n//\n// It lives in the SDK because the SDK owns the DSL. The alternative — a script\n// beside the deploy that reaches into `._def` — is a second reading of a private\n// shape, and it drifts the moment a column gains a property: the DSL keeps\n// working, the emitter silently omits it, and the database is missing something\n// nobody can see in the source.\n//\n// The field names below are a CONTRACT with Go's `schema.SchemaJSON`. Renaming\n// one here without renaming it there produces a declaration that parses to\n// something emptier than it was — the failure mode being a column, a policy, or\n// a whole table that quietly never gets created.\nimport type { ColumnBuilder, ColumnDef } from \"./columns.js\";\nimport type { PolicyDef } from \"./policy.js\";\nimport type { SchemaDef, TableDef } from \"./schema.js\";\n\n/** One column, flattened. Mirrors Go's `schema.ColumnJSON`. */\nexport interface ColumnJSON {\n type: string;\n nullable: boolean;\n primaryKey: boolean;\n defaultValue?: unknown;\n defaultRandom?: boolean;\n defaultNow?: boolean;\n renamedFrom?: string;\n references?: { table: string; column: string };\n onDeleteAction?: string;\n enumName?: string;\n enumValues?: string[];\n unique?: boolean;\n}\n\n/** One RLS policy. Mirrors Go's `schema.PolicyJSON`. */\nexport interface PolicyJSON {\n name: string;\n command: string;\n roles: string[];\n using: string | null;\n withCheck: string | null;\n permissive: boolean;\n}\n\n/** One table. Mirrors Go's `schema.TableJSON`. */\nexport interface TableJSON {\n name: string;\n columns: Record<string, ColumnJSON>;\n rls: boolean;\n policies: PolicyJSON[];\n primaryKey?: string[];\n uniqueConstraints?: { name: string; columns: string[] }[];\n rawConstraints?: { name: string; up: string; down: string | null }[];\n checks?: { name: string; expr: string }[];\n indexes?: { name: string; columns: string[] }[];\n}\n\n/** A whole declaration. Mirrors Go's `schema.SchemaJSON`. */\nexport interface SchemaJSON {\n tables: Record<string, TableJSON>;\n extensions: string[];\n}\n\n/** The definition behind a column, whichever side of the builder it arrives on. */\nfunction defOf(column: ColumnBuilder | ColumnDef): ColumnDef {\n return \"_def\" in column ? column._def : column;\n}\n\nfunction columnToJSON(column: ColumnBuilder | ColumnDef): ColumnJSON {\n const def = defOf(column);\n const out: ColumnJSON = {\n type: def.type,\n nullable: def.nullable,\n primaryKey: def.primaryKey,\n };\n // Every optional field is omitted rather than emitted as undefined: Go\n // distinguishes \"absent\" from \"present and empty\" on several of these, and a\n // `defaultValue: null` is a real default that says NULL.\n if (def.defaultValue !== undefined) out.defaultValue = def.defaultValue;\n if (def.defaultRandom === true) out.defaultRandom = true;\n if (def.defaultNow === true) out.defaultNow = true;\n if (def.renamedFrom !== undefined) out.renamedFrom = def.renamedFrom;\n if (def.references !== undefined) {\n out.references = { table: def.references.table, column: def.references.column };\n }\n if (def.onDeleteAction !== undefined) out.onDeleteAction = def.onDeleteAction;\n if (def.enumName !== undefined) out.enumName = def.enumName;\n if (def.enumValues !== undefined) out.enumValues = [...def.enumValues];\n if (def.unique === true) out.unique = true;\n return out;\n}\n\nfunction policyToJSON(policy: PolicyDef): PolicyJSON {\n return {\n name: policy.name,\n command: policy.command ?? \"all\",\n roles: policy.roles ? [...policy.roles] : [],\n // null rather than omitted: a policy with no USING clause is a different\n // thing from one whose clause the emitter forgot, and Go reads the\n // difference.\n using: policy.using ?? null,\n withCheck: policy.withCheck ?? null,\n permissive: policy.permissive !== false,\n };\n}\n\nfunction tableToJSON(table: TableDef): TableJSON {\n const columns: Record<string, ColumnJSON> = {};\n for (const [name, column] of Object.entries(table.columns)) {\n columns[name] = columnToJSON(column);\n }\n\n const out: TableJSON = {\n name: table.name,\n columns,\n // Read, not re-derived. `defineSchema` already resolves the fail-closed\n // default (RLS on unless the author wrote `rls: false`, and forced on by any\n // policy), and a second copy of a SECURITY default is exactly the thing that\n // drifts — the direction it drifted last time was \"expose everything\", and\n // the live proof was one user reading another's rows.\n rls: table.rls,\n policies: (table.policies ?? []).map(policyToJSON),\n };\n\n if (table.primaryKey !== undefined && table.primaryKey.length > 0) {\n out.primaryKey = [...table.primaryKey];\n }\n if (table.unique !== undefined && table.unique.length > 0) {\n out.uniqueConstraints = table.unique.map((u) => ({ name: u.name, columns: [...u.columns] }));\n }\n if (table.raw !== undefined && table.raw.length > 0) {\n out.rawConstraints = table.raw.map((r) => ({\n name: r.name,\n up: r.up,\n down: r.down ?? null,\n }));\n }\n if (table.checks !== undefined && table.checks.length > 0) {\n out.checks = table.checks.map((c) => ({ name: c.name, expr: c.expr }));\n }\n if (table.indexes !== undefined && table.indexes.length > 0) {\n out.indexes = table.indexes.map((i) => ({ name: i.name, columns: [...i.columns] }));\n }\n return out;\n}\n\n/**\n * Serialize a `defineSchema(...)` result into the JSON the deploy applies.\n *\n * Keyed by the SQL table name rather than by the author's object key, because\n * that is the name the live database answers to — and the diff on the other side\n * compares against what it introspected.\n */\nexport function toSchemaJSON(schema: SchemaDef): SchemaJSON {\n const tables: Record<string, TableJSON> = {};\n for (const table of Object.values(schema.tables)) {\n const json = tableToJSON(table);\n tables[json.name] = json;\n }\n return { tables, extensions: [...new Set(schema.extensions ?? [])] };\n}\n","/**\n * env-gen.ts — generate the `palbase-env.d.ts` text from a `defineSchema()`\n * result.\n *\n * The CLI (`palbase build`) and the deploy pipeline call\n * {@link makeEnvDts} with the project's schema and write the returned string to\n * `palbase-env.d.ts` at the project root. That file AUGMENTS the\n * `@palbase/backend/env` `Tables` interface (controlled global augmentation,\n * C5) so `Database.tables.<name>` is typed with no import and no generic.\n *\n * The output is FLAT: each table gets a `{ row: {...}; insert: {...} }` entry\n * with plain TypeScript object types. The phantom `ColumnBuilder<...>` type\n * NEVER appears in the generated `.d.ts` — that type only lives at authoring\n * time inside `db/schema.ts`.\n */\n\nimport type { ColumnDef } from \"./columns.js\";\nimport type { SchemaDef, TableDef } from \"./schema.js\";\n\n/** The TypeScript value type for a column, ignoring nullability (added by the\n * caller). Mirrors the `ColValue` mapped type in columns.ts exactly. */\nfunction baseTsType(def: ColumnDef): string {\n switch (def.type) {\n case \"uuid\":\n case \"text\":\n case \"timestamp\":\n return \"string\";\n case \"integer\":\n return \"number\";\n // Both are exact-precision in Postgres and lossy as a JSON number, so the\n // database proxy serializes them as strings — measured: 9007199254740993\n // used to arrive as ...992 and 41.00821234567890123 as 41.0082123456789.\n // numeric had no case at all and fell through to `unknown`, which typed\n // every numeric column out of existence.\n case \"bigint\":\n case \"numeric\":\n return \"string\";\n case \"boolean\":\n return \"boolean\";\n case \"jsonb\":\n return \"unknown\";\n case \"enum\": {\n const values = def.enumValues ?? [];\n if (values.length === 0) return \"string\";\n return values.map((v) => JSON.stringify(v)).join(\" | \");\n }\n default:\n return \"unknown\";\n }\n}\n\n/** The full row type for a column: base type, `| null` when nullable. */\nfunction rowType(def: ColumnDef): string {\n const base = baseTsType(def);\n return def.nullable ? `${base} | null` : base;\n}\n\n/** True when a column may be omitted on INSERT — nullable OR has any default.\n * Mirrors `ColIsOptionalOnInsert` in columns.ts. */\nfunction optionalOnInsert(def: ColumnDef): boolean {\n return (\n def.nullable === true ||\n def.defaultRandom === true ||\n def.defaultNow === true ||\n def.defaultValue !== undefined\n );\n}\n\n/** The table a foreign key must target for its column to be the OWNER column —\n * what `.referencesAuthUser(...)` writes into `ColumnDef.references.table`. */\nconst AUTH_USERS_TABLE = \"auth.users\";\n\n/**\n * The table's owner column: the one that foreign-keys `auth.users`, i.e. the\n * column a row is \"owned by\". Declared in `db/schema.ts` via\n * `.referencesAuthUser(...)` — we read the declaration rather than parsing the\n * RLS policy body, because the FK IS the ownership statement.\n *\n * When several columns reference `auth.users` (e.g. `user_id` and `created_by`)\n * the FIRST in declaration order wins — deterministic, and the remaining ones\n * stay ordinary writable columns.\n */\nfunction ownerColumnOf(table: TableDef): string | null {\n for (const [col, builder] of Object.entries(table.columns)) {\n if (builder._def.references?.table === AUTH_USERS_TABLE) return col;\n }\n return null;\n}\n\n/** One FK edge: `child.column` points at the parent table this edge hangs off. */\ntype ChildEdge = { child: string; column: string };\n\n/**\n * Collect the raw parent → children FK edges across the schema.\n *\n * Only edges between tables IN this schema participate — a reference to\n * `auth.users` / `auth.installations` (or any table the project doesn't\n * declare) has no parent bucket and is skipped. Self-FKs are skipped outright.\n *\n * A child that references the same parent through TWO columns is recorded once,\n * on the first column in declaration order: `children` maps a child table to a\n * single FK column, and the second FK stays an ordinary writable column.\n */\nfunction buildChildEdges(schema: SchemaDef): Map<string, ChildEdge[]> {\n const edges = new Map<string, ChildEdge[]>();\n for (const name of Object.keys(schema.tables)) edges.set(name, []);\n\n for (const childName of Object.keys(schema.tables)) {\n const table = schema.tables[childName];\n if (table === undefined) continue;\n for (const [col, builder] of Object.entries(table.columns)) {\n const ref = builder._def.references;\n if (ref === undefined) continue;\n if (ref.table === childName) continue; // self-FK\n const bucket = edges.get(ref.table);\n if (bucket === undefined) continue; // targets a table outside this schema\n if (bucket.some((e) => e.child === childName)) continue; // already linked\n bucket.push({ child: childName, column: col });\n }\n }\n return edges;\n}\n\n/**\n * Drop cycle back-edges from the FK graph.\n *\n * `children` feeds a RECURSIVE type in the seed/fixture DSL\n * (`SeedRow<T>` expands each child's own `children`). A cycle — `lists → todos`\n * plus `todos → lists` through a second FK — would make that type infinite\n * (\"Type instantiation is excessively deep\"). So we walk the graph depth-first\n * in declaration order and drop any edge pointing back at a table currently on\n * the DFS stack. Cross-edges into an already-FINISHED subtree are KEPT: they\n * re-expand a finite subtree, which terminates.\n *\n * Declaration order makes the choice of which edge to drop deterministic (the\n * generated .d.ts is golden-tested).\n */\nfunction pruneCycles(raw: Map<string, ChildEdge[]>): Map<string, ChildEdge[]> {\n const pruned = new Map<string, ChildEdge[]>();\n for (const table of raw.keys()) pruned.set(table, []);\n const state = new Map<string, \"visiting\" | \"done\">();\n\n function visit(table: string): void {\n state.set(table, \"visiting\");\n for (const edge of raw.get(table) ?? []) {\n if (state.get(edge.child) === \"visiting\") continue; // back-edge → drop\n pruned.get(table)?.push(edge);\n if (state.get(edge.child) === undefined) visit(edge.child);\n }\n state.set(table, \"done\");\n }\n\n for (const table of raw.keys()) {\n if (state.get(table) === undefined) visit(table);\n }\n return pruned;\n}\n\n/** Emit the `row` / `insert` / `owner` / `children` blocks for one table at the\n * given base indentation. */\nfunction tableBlock(table: TableDef, children: ChildEdge[], indent: string): string {\n const cols = Object.entries(table.columns);\n const rowLines = cols.map(([col, builder]) => {\n return `${indent} ${col}: ${rowType(builder._def)};`;\n });\n const insertLines = cols.map(([col, builder]) => {\n const def = builder._def;\n const opt = optionalOnInsert(def) ? \"?\" : \"\";\n return `${indent} ${col}${opt}: ${rowType(def)};`;\n });\n const owner = ownerColumnOf(table);\n const childEntries = children\n .map((e) => `${JSON.stringify(e.child)}: ${JSON.stringify(e.column)}`)\n .join(\"; \");\n return [\n `${indent}${table.name}: {`,\n `${indent} row: {`,\n ...rowLines,\n `${indent} };`,\n `${indent} insert: {`,\n ...insertLines,\n `${indent} };`,\n `${indent} owner: ${owner === null ? \"null\" : JSON.stringify(owner)};`,\n `${indent} children: {${childEntries === \"\" ? \"\" : ` ${childEntries} `}};`,\n `${indent}};`,\n ].join(\"\\n\");\n}\n\n/**\n * Generate the full `palbase-env.d.ts` text for a schema.\n *\n * @example\n * import { makeEnvDts } from \"@palbase/backend\";\n * import schema from \"./db/schema.js\";\n * writeFileSync(\"palbase-env.d.ts\", makeEnvDts(schema));\n */\nexport function makeEnvDts(schema: SchemaDef): string {\n const tableNames = Object.keys(schema.tables);\n const children = pruneCycles(buildChildEdges(schema));\n const blocks = tableNames.map((name) =>\n tableBlock(schema.tables[name]!, children.get(name) ?? [], \" \"),\n );\n const body = blocks.length > 0 ? `\\n${blocks.join(\"\\n\")}\\n ` : \"\";\n return `// AUTO-GENERATED by @palbase/backend — DO NOT EDIT.\n// Regenerated from db/schema.ts by \\`palbase build\\` and by every deploy.\n// Augments the @palbase/backend/env \\`Tables\\` interface so \\`Database.tables.*\\`\n// is typed with no import and no generic.\n\ndeclare module \"@palbase/backend/env\" {\n interface Tables {${body}}\n}\n\nexport {};\n`;\n}\n","/**\n * storage.ts — the storage-buckets config-as-code DSL.\n *\n * `defineStorage({ buckets })` is the first MODULE config-as-code surface (the\n * sibling of `db/schema.ts`'s `defineSchema`). A `config/storage.ts` file\n * default-exports a `defineStorage(...)` result; on deploy the br-pod evaluates\n * it to JSON and reconciles the declared buckets against the tenant's live\n * buckets via the Storage admin API (create missing, update changed; never\n * auto-delete — dropping a bucket is destructive and warned only).\n *\n * Buckets are DECLARATIVE: name + access + size/mime limits. The FILES inside a\n * bucket are runtime state (uploaded via the SDK), never in git.\n *\n * @example\n * import { defineStorage, bucket } from \"@palbase/backend\";\n *\n * export default defineStorage({\n * buckets: {\n * avatars: bucket({\n * public: true,\n * fileSizeLimit: \"5MB\",\n * allowedMimeTypes: [\"image/png\", \"image/jpeg\", \"image/webp\"],\n * }),\n * invoices: bucket({\n * public: false,\n * fileSizeLimit: \"20MB\",\n * allowedMimeTypes: [\"application/pdf\"],\n * }),\n * },\n * });\n *\n * The returned value is the EXACT JSON shape the runtime's generic config\n * extractor (`config_extract.js`) emits and the Go apply step parses:\n * { __config: \"storage\", buckets: { avatars: { public, fileSizeLimit, allowedMimeTypes }, ... } }\n * `fileSizeLimit` is always normalized to a number of bytes (or null when\n * omitted, meaning \"no limit\"); the apply step maps it to the Storage API's\n * `file_size_limit` field. `allowedMimeTypes` is the allowlist or null (any).\n */\n\n/** The discriminant written under `__config` so the eval/apply can tell which\n * module config a `config/*.ts` file describes. Storage is `\"storage\"`. */\nexport const STORAGE_CONFIG_KIND = \"storage\" as const;\n\n/**\n * The author-facing options for a single bucket.\n *\n * - `public`: when true the bucket is served without a signed URL. Defaults to\n * `false` (private — signed URLs only).\n * - `fileSizeLimit`: the per-object upload cap. Accepts a human string\n * (`\"5MB\"`, `\"20MB\"`, `\"1GB\"`) or a bare number of BYTES. Omit for no limit.\n * - `allowedMimeTypes`: an allowlist of MIME types accepted on upload. Omit to\n * allow any type. Each entry must look like `type/subtype` (e.g. `image/png`,\n * `application/pdf`, or a wildcard `image/*`).\n */\nexport interface BucketOptions {\n public?: boolean;\n fileSizeLimit?: string | number;\n allowedMimeTypes?: string[];\n variants?: Record<string, ImageVariant>;\n}\n\n/**\n * One named rendition of an uploaded image — the same three knobs\n * `getPublicUrl(path, ...)` takes, given a name so the size lives with the\n * bucket instead of being retyped at every call site.\n *\n * At least one of `width` / `height` must be set (a variant that resizes\n * nothing and converts nothing is a typo, not a variant).\n */\nexport interface ImageVariant {\n width?: number;\n height?: number;\n /**\n * How the source is made to meet the box. Defaults to `\"contain\"`.\n *\n * - `cover` fills the box exactly and crops the overflow from the centre —\n * what a square avatar or a grid cell needs.\n * - `contain` fits the whole picture inside the box, cropping nothing. One\n * side may come out smaller than declared.\n * - `inside` is `contain` that never ENLARGES. Blowing a 100px image up to\n * 1000px produces a blurry picture that is bigger on the wire.\n */\n fit?: \"cover\" | \"contain\" | \"inside\";\n format?: \"webp\" | \"avif\" | \"jpeg\" | \"png\";\n /** Encoder quality, 1–100. Defaults to 85. JPEG only. */\n quality?: number;\n}\n\nconst VARIANT_FORMATS = [\"webp\", \"avif\", \"jpeg\", \"png\"] as const;\nconst VARIANT_FITS = [\"cover\", \"contain\", \"inside\"] as const;\n\n/**\n * Validate + normalize a bucket's `variants` map.\n *\n * Renditions are produced AT UPLOAD and stored as objects of their own. That is\n * the trade: the upload takes a little longer once, and every read afterwards\n * is a static file behind an immutable URL — no transform on the request path,\n * so no way to turn one public URL into a CPU amplifier by asking for a\n * thousand sizes.\n *\n * The consequence to know: adding a variant later applies to objects uploaded\n * AFTER the change. Existing objects keep the renditions they were uploaded\n * with until they are re-uploaded.\n */\nfunction normalizeVariants(\n input: Record<string, ImageVariant>,\n): Record<string, ImageVariant> {\n if (input === null || typeof input !== \"object\" || Array.isArray(input)) {\n throw new Error(\"bucket variants must be an object of { <name>: { width?, height?, format? } }\");\n }\n const out: Record<string, ImageVariant> = {};\n for (const [name, spec] of Object.entries(input)) {\n // The name becomes part of a URL/response key, so keep it boring.\n if (!/^[a-z0-9][a-z0-9_-]*$/i.test(name)) {\n throw new Error(\n `bucket variant name \"${name}\" must be alphanumeric with optional - or _ (e.g. \"thumb\", \"card_2x\")`,\n );\n }\n if (spec === null || typeof spec !== \"object\" || Array.isArray(spec)) {\n throw new Error(`bucket variant \"${name}\" must be an object like { width: 100, height: 100 }`);\n }\n for (const dim of [\"width\", \"height\"] as const) {\n const value = spec[dim];\n if (value === undefined) continue;\n if (typeof value !== \"number\" || !Number.isInteger(value) || value <= 0) {\n throw new Error(`bucket variant \"${name}\" ${dim} must be a positive integer, got ${String(value)}`);\n }\n }\n if (spec.width === undefined && spec.height === undefined) {\n throw new Error(`bucket variant \"${name}\" must set width and/or height`);\n }\n if (spec.format !== undefined && !VARIANT_FORMATS.includes(spec.format)) {\n throw new Error(\n `bucket variant \"${name}\" format must be one of ${VARIANT_FORMATS.join(\", \")}, got \"${String(spec.format)}\"`,\n );\n }\n if (spec.fit !== undefined && !VARIANT_FITS.includes(spec.fit)) {\n throw new Error(\n `bucket variant \"${name}\" fit must be one of ${VARIANT_FITS.join(\", \")}, got \"${String(spec.fit)}\"`,\n );\n }\n if (spec.quality !== undefined) {\n const q = spec.quality;\n if (typeof q !== \"number\" || !Number.isInteger(q) || q < 1 || q > 100) {\n throw new Error(`bucket variant \"${name}\" quality must be an integer 1–100, got ${String(q)}`);\n }\n }\n // `cover` without both sides has no box to fill: cropping to a width and\n // \"whatever height\" is `contain` wearing the wrong name, and the author\n // meant one or the other.\n if (spec.fit === \"cover\" && (spec.width === undefined || spec.height === undefined)) {\n throw new Error(`bucket variant \"${name}\" uses fit \"cover\", which needs BOTH width and height`);\n }\n out[name] = {\n ...(spec.width !== undefined ? { width: spec.width } : {}),\n ...(spec.height !== undefined ? { height: spec.height } : {}),\n ...(spec.fit !== undefined ? { fit: spec.fit } : {}),\n ...(spec.format !== undefined ? { format: spec.format } : {}),\n ...(spec.quality !== undefined ? { quality: spec.quality } : {}),\n };\n }\n return out;\n}\n\n/**\n * The compiled, serializable bucket definition — the EXACT shape emitted to\n * JSON and consumed by the Go apply step.\n *\n * - `public`: always present (defaulted to `false`).\n * - `fileSizeLimit`: bytes as a number, or `null` for \"no limit\".\n * - `allowedMimeTypes`: the MIME allowlist, or `null` for \"any type\".\n */\nexport interface BucketDef {\n public: boolean;\n fileSizeLimit: number | null;\n allowedMimeTypes: string[] | null;\n /** Named renditions, or `null` when none are declared. Rendered AT UPLOAD and\n * stored as objects of their own, behind immutable URLs. */\n variants: Record<string, ImageVariant> | null;\n}\n\n/** A storage config definition: the discriminant + a map of bucket name →\n * {@link BucketDef}. This is the value `defineStorage` returns and the runtime\n * config extractor serializes. */\nexport interface StorageConfig {\n __config: typeof STORAGE_CONFIG_KIND;\n buckets: Record<string, BucketDef>;\n}\n\n/** The author-facing input to `defineStorage`: a `buckets` map whose keys are\n * the bucket names and whose values are `bucket({...})` builders. */\nexport interface StorageInput {\n buckets: Record<string, BucketDef>;\n}\n\n// Powers of 1024 (binary, IEC). Storage's `file_size_limit` string parser\n// (the `bytes` npm lib, used by Supabase Storage) treats \"MB\"/\"GB\" as binary\n// multiples, so \"5MB\" = 5 * 1024 * 1024. We match that exactly so the limit a\n// user declares is the limit the bucket enforces.\nconst UNIT_BYTES: Record<string, number> = {\n b: 1,\n kb: 1024,\n mb: 1024 ** 2,\n gb: 1024 ** 3,\n tb: 1024 ** 4,\n};\n\n/**\n * Parse a `fileSizeLimit` into a number of bytes.\n *\n * - A bare number is taken as bytes verbatim (must be a non-negative integer).\n * - A string is `<number><unit>` (e.g. `\"5MB\"`, `\"1.5GB\"`, `\"500kb\"`); the unit\n * is case-insensitive and optional (a bare numeric string = bytes). Binary\n * units (1 MB = 1024 squared bytes) to match the Storage module's parser.\n *\n * Throws on a negative value, a non-finite number, or an unrecognized unit so a\n * bad limit fails at config-author time, not silently at deploy.\n */\nexport function parseFileSizeLimit(input: string | number): number {\n if (typeof input === \"number\") {\n if (!Number.isFinite(input) || input < 0 || !Number.isInteger(input)) {\n throw new Error(\n `bucket fileSizeLimit must be a non-negative integer number of bytes, got ${input}`,\n );\n }\n return input;\n }\n\n const trimmed = input.trim();\n // <number><optional-unit>, e.g. \"5MB\", \"1.5 gb\", \"1024\", \"500kb\".\n const match = /^(\\d+(?:\\.\\d+)?)\\s*([a-zA-Z]+)?$/.exec(trimmed);\n if (!match) {\n throw new Error(\n `bucket fileSizeLimit string must be \"<number><unit>\" like \"5MB\" or \"1GB\", got \"${input}\"`,\n );\n }\n const value = Number.parseFloat(match[1]!);\n const unit = (match[2] ?? \"b\").toLowerCase();\n const multiplier = UNIT_BYTES[unit];\n if (multiplier === undefined) {\n throw new Error(\n `bucket fileSizeLimit has an unknown unit \"${match[2]}\" — use B, KB, MB, GB, or TB (e.g. \"5MB\")`,\n );\n }\n const bytes = value * multiplier;\n if (!Number.isFinite(bytes) || bytes < 0) {\n throw new Error(`bucket fileSizeLimit resolved to an invalid byte count: ${bytes}`);\n }\n // Round to a whole byte — a fractional byte is meaningless to the Storage API.\n return Math.round(bytes);\n}\n\n// A loose MIME-type shape check: `type/subtype`, where each side is a token of\n// alphanumerics plus the usual punctuation, and the subtype may be a wildcard\n// `*`. This is intentionally permissive (not an IANA allowlist) but rejects the\n// obvious typos (\"image\", \"imagepng\", \" \").\nconst MIME_RE = /^[a-zA-Z0-9][a-zA-Z0-9!#$&^_.+-]*\\/(?:\\*|[a-zA-Z0-9][a-zA-Z0-9!#$&^_.+-]*)$/;\n\n/**\n * Define a single bucket. The bucket NAME is supplied by the key in\n * `defineStorage({ buckets: { <name>: bucket({...}) } })`, so `bucket()` takes\n * only the options.\n *\n * Validates eagerly (at config-author time):\n * - `fileSizeLimit` parses to a valid non-negative byte count.\n * - each `allowedMimeTypes` entry is a `type/subtype` MIME string.\n *\n * Returns a normalized {@link BucketDef}: `public` defaulted to `false`,\n * `fileSizeLimit` as bytes-or-null, `allowedMimeTypes` deduped-or-null.\n */\nexport function bucket(opts: BucketOptions = {}): BucketDef {\n const fileSizeLimit =\n opts.fileSizeLimit === undefined ? null : parseFileSizeLimit(opts.fileSizeLimit);\n\n let allowedMimeTypes: string[] | null = null;\n if (opts.allowedMimeTypes !== undefined) {\n if (!Array.isArray(opts.allowedMimeTypes)) {\n throw new Error(\"bucket allowedMimeTypes must be an array of MIME-type strings\");\n }\n for (const mime of opts.allowedMimeTypes) {\n if (typeof mime !== \"string\" || !MIME_RE.test(mime.trim())) {\n throw new Error(\n `bucket allowedMimeTypes entry \"${mime}\" is not a valid MIME type (expected \"type/subtype\", e.g. \"image/png\")`,\n );\n }\n }\n // Dedupe + trim. An empty array means \"explicitly no types\" — keep it as []\n // rather than null so the apply step can distinguish \"any\" (null) from a\n // caller that passed [].\n allowedMimeTypes = [...new Set(opts.allowedMimeTypes.map((m) => m.trim()))];\n }\n\n return {\n public: opts.public ?? false,\n fileSizeLimit,\n allowedMimeTypes,\n variants: opts.variants === undefined ? null : normalizeVariants(opts.variants),\n };\n}\n\n/**\n * Define the storage config for a project. The bucket NAME comes from each\n * object key (authors never repeat the name). Returns the discriminated\n * {@link StorageConfig} the runtime config extractor serializes and the Go\n * apply step reconciles.\n *\n * @example\n * export default defineStorage({\n * buckets: { avatars: bucket({ public: true, fileSizeLimit: \"5MB\" }) },\n * });\n */\nexport function defineStorage(input: StorageInput): StorageConfig {\n if (input === null || typeof input !== \"object\" || typeof input.buckets !== \"object\") {\n throw new Error(\"defineStorage expects { buckets: { <name>: bucket({...}) } }\");\n }\n const buckets: Record<string, BucketDef> = {};\n for (const name of Object.keys(input.buckets)) {\n if (name.length === 0) {\n throw new Error(\"bucket name must be a non-empty string\");\n }\n const def = input.buckets[name];\n if (def === undefined) continue;\n buckets[name] = def;\n }\n return { __config: STORAGE_CONFIG_KIND, buckets };\n}\n","/**\n * egress.ts — the tenant outbound-HTTP allowlist config-as-code DSL.\n *\n * `defineEgress({ hosts, timeoutMs })` declares the external hosts a backend may\n * fetch(), and how long a single call may take. config/egress.ts default-exports\n * it; the deploy evals it to JSON (SchemaExtractor.EvaluateConfigFile →\n * config_extract.js) and bakes both into the artifact manifest → the isolate\n * loader → Tenant.egressAllow / Tenant.egressTimeoutMs. The tenantFetch\n * capability rejects any host NOT on the list. NO config/egress.ts (or an empty\n * list) ⇒ the backend has NO outbound network — fail-closed.\n *\n * @example\n * // config/egress.ts\n * import { defineEgress } from \"@palbase/backend\";\n * export default defineEgress({\n * hosts: [\"api.openai.com\"],\n * timeoutMs: 90_000, // a slow LLM call; default 30_000\n * });\n *\n * Each host is a bare hostname (no scheme/port/path/wildcard). A leading dot,\n * `.example.com`, also covers subdomains (Squid dstdomain semantics). Egress is\n * https-only on :443; the deploy REJECTS a malformed / IP-literal / internal host\n * (fail-closed — a security allowlist is never best-effort).\n *\n * `timeoutMs` is a CEILING, not a grant: the call still ends when the INVOCATION\n * ends. A job may run up to its own `@Job({ timeout })` (max 300s), while a\n * request is additionally bounded by the gateway. Setting 300_000 on a route\n * whose request dies earlier buys nothing — size it to the caller.\n *\n * Response bodies are BUFFERED whole (5 MB cap) before your fetch() resolves, so\n * a streaming/SSE upstream gives you no partial output and no earlier\n * first-byte: the entire stream must complete inside `timeoutMs`.\n *\n * Emits: { __config: \"egress\", hosts: [...], timeoutMs?: number }\n */\n\n/** The discriminant written under `__config` so the deploy eval knows the kind. */\nexport const EGRESS_CONFIG_KIND = \"egress\" as const;\n\n/**\n * Bounds on `timeoutMs`, duplicated (deliberately) in the deploy's\n * ParseEgressConfig. This copy shapes the authoring error; that one is\n * authoritative and fail-closed. They must agree — a value this accepts and the\n * deploy rejects is a broken deploy the author cannot see coming.\n */\nexport const EGRESS_TIMEOUT_MIN_MS = 1_000;\nexport const EGRESS_TIMEOUT_MAX_MS = 300_000;\n/** Applied when `timeoutMs` is omitted. Also spelled in the isolate capability. */\nexport const EGRESS_TIMEOUT_DEFAULT_MS = 30_000;\n\n/** The author-facing input to defineEgress. */\nexport interface EgressInput {\n hosts: string[];\n /**\n * Per-call ceiling for an outbound fetch, in milliseconds.\n * 1_000..300_000; omitted ⇒ 30_000.\n */\n timeoutMs?: number;\n}\n\n/** The evaluated config/egress.ts default export (what the deploy reads). */\nexport interface EgressConfig {\n __config: typeof EGRESS_CONFIG_KIND;\n hosts: string[];\n timeoutMs?: number;\n}\n\n/**\n * Declare the backend's outbound-HTTP allowlist. Client-side this only shapes +\n * validates the list; the authoritative fail-closed validation runs at deploy.\n */\nexport function defineEgress(input: EgressInput): EgressConfig {\n if (input === null || typeof input !== \"object\" || !Array.isArray(input.hosts)) {\n throw new Error(\"defineEgress expects { hosts: string[] }\");\n }\n const hosts: string[] = [];\n for (const h of input.hosts) {\n if (typeof h !== \"string\" || h.trim().length === 0) {\n throw new Error(\"defineEgress: every host must be a non-empty string\");\n }\n hosts.push(h.trim().toLowerCase());\n }\n if (input.timeoutMs === undefined) {\n return { __config: EGRESS_CONFIG_KIND, hosts };\n }\n const timeoutMs = input.timeoutMs;\n if (typeof timeoutMs !== \"number\" || !Number.isInteger(timeoutMs)) {\n throw new Error(\"defineEgress: timeoutMs must be an integer number of milliseconds\");\n }\n if (timeoutMs < EGRESS_TIMEOUT_MIN_MS || timeoutMs > EGRESS_TIMEOUT_MAX_MS) {\n throw new Error(\n `defineEgress: timeoutMs must be between ${EGRESS_TIMEOUT_MIN_MS} and ${EGRESS_TIMEOUT_MAX_MS} (got ${timeoutMs})`,\n );\n }\n return { __config: EGRESS_CONFIG_KIND, hosts, timeoutMs };\n}\n","/**\n * notifications.ts — the notification-providers config-as-code DSL.\n *\n * `defineNotifications({ push, email, sms })` is the second MODULE config-as-code\n * surface (the sibling of `config/storage.ts`'s `defineStorage`). A\n * `config/notifications.ts` file default-exports a `defineNotifications(...)`\n * result; on deploy the br-pod evaluates it to JSON and reconciles the declared\n * providers against the tenant's live providers via the PalNotify admin API\n * (create missing; never auto-delete — dropping a provider is destructive and\n * warned only).\n *\n * SECRETS ARE NEVER IN THE FILE. Each provider's NON-SECRET fields (team id, key\n * id, bundle id, region, host, port, from address, account sid, …) are literals\n * in the config. Each provider's SECRET material (the APNs .p8 key, the FCM\n * service-account JSON, an api_key, an auth token, the SMTP/ACS password, …) is\n * NOT a field here — it is bound BY CONVENTION to a RESERVED encrypted env var\n * and resolved at deploy from control-pg. The env-key convention is:\n *\n * PB_NOTIFICATIONS_<PROVIDER>_<FIELD> (UPPER_SNAKE_CASE)\n *\n * e.g. `PB_NOTIFICATIONS_APNS_P8`, `PB_NOTIFICATIONS_FCM_SERVICE_ACCOUNT`,\n * `PB_NOTIFICATIONS_TWILIO_AUTH_TOKEN`. The `PB_` namespace is reserved (the CLI\n * refuses a hand-set `palbase secret set PB_*`); the CLI's `palbase notifications\n * add <provider>` derives the key and uploads the secret for you, so an author\n * never types either the secret or the env-key name into git.\n *\n * @example\n * import { defineNotifications } from \"@palbase/backend\";\n *\n * export default defineNotifications({\n * push: {\n * apns: { enabled: true, teamId: \"ABCDE12345\", keyId: \"KEY1234567\", bundleId: \"com.acme.app\" },\n * fcm: { enabled: true },\n * },\n * email: {\n * sendgrid: { enabled: true, fromDomain: \"mail.acme.com\" },\n * },\n * sms: {\n * twilio: { enabled: true, accountSid: \"ACxxxxxxxx\", messagingServiceSid: \"MGxxxxxxxx\" },\n * },\n * });\n *\n * The returned value is the EXACT JSON shape the runtime's generic config\n * extractor (`config_extract.js`) emits and the Go apply step parses:\n * { __config: \"notifications\", push: {...}, email: {...}, sms: {...} }\n * Only ENABLED providers carry their non-secret fields; a disabled (or absent)\n * provider serializes as `{ enabled: false }` so the apply step skips it.\n */\n\n/** The `__config` discriminant the eval/apply reads to confirm a config/*.ts is\n * a notifications config. Notifications is `\"notifications\"`. */\nexport const NOTIFICATIONS_CONFIG_KIND = \"notifications\" as const;\n\n/** The reserved env-var prefix that backs provider secrets. A `palbase secret\n * set` of a key under this prefix is REFUSED by the CLI (it is managed by\n * `palbase notifications add`). Both the CLI and the br-pod apply step derive a\n * provider's secret env key as `${RESERVED_SECRET_PREFIX}_<PROVIDER>_<FIELD>`. */\nexport const RESERVED_SECRET_PREFIX = \"PB_NOTIFICATIONS\" as const;\n\n// ────────────────────────────────────────────────────────────────────────────\n// Provider catalog — the SINGLE SOURCE of which providers exist + their fields.\n//\n// Ported from platform/studio/src/server/trpc/routers/notifications.ts (the\n// per-provider credential zod schemas). Here the fields are split into:\n// • nonSecret: literals that live in config/notifications.ts (this file).\n// • secret: the field name(s) bound to a reserved env var (NOT in config).\n// The Go apply step + the CLI both mirror this catalog, so adding a provider is\n// a three-line change kept in lockstep across the SDK / runtime / CLI.\n// ────────────────────────────────────────────────────────────────────────────\n\n/** One provider's catalog entry: which non-secret fields are required, which are\n * optional, and which secret field-name(s) bind to reserved env vars. */\nexport interface ProviderCatalogEntry {\n /** The channel this provider serves (`push` | `email` | `sms`). */\n readonly channel: \"push\" | \"email\" | \"sms\";\n /** Non-secret config fields the author MUST supply (validated eagerly). */\n readonly required: readonly string[];\n /** Non-secret config fields the author MAY supply. */\n readonly optional: readonly string[];\n /** Secret field name(s) — each backed by `PB_NOTIFICATIONS_<PROVIDER>_<FIELD>`\n * (FIELD is the UPPER_SNAKE of the name here). NOT a config field. */\n readonly secrets: readonly string[];\n}\n\n/**\n * The provider catalog: provider key → fields. The non-secret field names are\n * the camelCase keys an author writes in `config/notifications.ts`; the secret\n * names are the snake-ish tokens that become the reserved env-var suffix.\n *\n * apns: team_id / key_id / bundle_id (+ optional is_production); secret = p8.\n * fcm: no non-secret fields; secret = service_account (the full JSON).\n * sendgrid: from_domain; secret = api_key.\n * ses: region / from_domain / access_key_id; secret = secret_access_key.\n * smtp: host / port / from_email (+ optional username, use_starttls); secret = password.\n * acs: from_email (+ optional from_name); secret = connection_string.\n * twilio: account_sid + (from_number OR messaging_service_sid); secret = auth_token.\n */\nexport const PROVIDER_CATALOG = {\n apns: {\n channel: \"push\",\n required: [\"teamId\", \"keyId\", \"bundleId\"],\n optional: [\"isProduction\"],\n secrets: [\"p8\"],\n },\n fcm: {\n channel: \"push\",\n required: [],\n optional: [],\n secrets: [\"serviceAccount\"],\n },\n sendgrid: {\n channel: \"email\",\n required: [\"fromDomain\"],\n optional: [],\n secrets: [\"apiKey\"],\n },\n ses: {\n channel: \"email\",\n required: [\"region\", \"accessKeyId\", \"fromDomain\"],\n optional: [],\n secrets: [\"secretAccessKey\"],\n },\n smtp: {\n channel: \"email\",\n required: [\"host\", \"port\", \"fromEmail\"],\n optional: [\"username\", \"useStarttls\"],\n secrets: [\"password\"],\n },\n acs: {\n channel: \"email\",\n required: [\"fromEmail\"],\n optional: [\"fromName\"],\n secrets: [\"connectionString\"],\n },\n twilio: {\n channel: \"sms\",\n // account_sid required; one of from_number / messaging_service_sid required\n // (enforced by the refine in buildProvider, not by the flat `required` list).\n required: [\"accountSid\"],\n optional: [\"fromNumber\", \"messagingServiceSid\"],\n secrets: [\"authToken\"],\n },\n} as const satisfies Record<string, ProviderCatalogEntry>;\n\n/** A provider key (`\"apns\" | \"fcm\" | \"sendgrid\" | …`). */\nexport type ProviderName = keyof typeof PROVIDER_CATALOG;\n\n// ── author-facing per-provider option types (non-secret fields only) ─────────\n\n/** APNs (Apple Push) — non-secret fields. The `.p8` key is the reserved secret\n * `PB_NOTIFICATIONS_APNS_P8` (uploaded via `palbase notifications add apns`). */\nexport interface ApnsOptions {\n enabled?: boolean;\n teamId: string;\n keyId: string;\n bundleId: string;\n /** APNs production gateway vs sandbox. Defaults to true (production). */\n isProduction?: boolean;\n}\n\n/** FCM (Firebase Cloud Messaging) — no non-secret fields; the service-account\n * JSON is the reserved secret `PB_NOTIFICATIONS_FCM_SERVICE_ACCOUNT`. */\nexport interface FcmOptions {\n enabled?: boolean;\n}\n\n/** SendGrid email — non-secret `fromDomain`; api_key is the reserved secret. */\nexport interface SendgridOptions {\n enabled?: boolean;\n fromDomain: string;\n}\n\n/** Amazon SES email — secret_access_key is the reserved secret. */\nexport interface SesOptions {\n enabled?: boolean;\n region: string;\n accessKeyId: string;\n fromDomain: string;\n}\n\n/** SMTP email — password is the reserved secret. */\nexport interface SmtpOptions {\n enabled?: boolean;\n host: string;\n port: number;\n fromEmail: string;\n username?: string;\n useStarttls?: boolean;\n}\n\n/** Azure Communication Services email — connection_string is the reserved secret. */\nexport interface AcsOptions {\n enabled?: boolean;\n fromEmail: string;\n fromName?: string;\n}\n\n/** Twilio SMS — auth_token is the reserved secret. Exactly one of `fromNumber`\n * or `messagingServiceSid` must be supplied. */\nexport interface TwilioOptions {\n enabled?: boolean;\n accountSid: string;\n fromNumber?: string;\n messagingServiceSid?: string;\n}\n\n/** The union of every provider's author-facing options. `buildProvider` accepts\n * this so each provider's typed options pass without a cast. */\nexport type ProviderOptions =\n | ApnsOptions\n | FcmOptions\n | SendgridOptions\n | SesOptions\n | SmtpOptions\n | AcsOptions\n | TwilioOptions;\n\n// ── templates ───────────────────────────────────────────────────────────────\n//\n// Templates are the OTHER half of config-as-code notifications. A provider says\n// *how* mail leaves; a template says *what* it says. Before this existed the\n// only way to create one was a live API call or a click in Studio — so the thing\n// your code sends by slug lived outside your repo, outside review, and outside\n// the deploy that depends on it. `Notifications.email.send({ templateSlug })`\n// would 404 on a fresh environment until somebody remembered to re-create it by\n// hand.\n\n/** The default locale a template row lands on when the author names none. Must\n * match PalNotify's `model.DefaultLocale`. */\nexport const DEFAULT_TEMPLATE_LOCALE = \"en\" as const;\n\n/** One locale's email content. */\nexport interface EmailTemplateContent {\n /** Subject line. Handlebars placeholders (`{{name}}`) are rendered at send. */\n subject: string;\n /** HTML body. */\n html: string;\n /** Plain-text body. Omit and the server derives one from `html` at render. */\n text?: string;\n /**\n * Variables the sender MUST supply. Omit and they are DERIVED from the\n * `{{placeholders}}` in this locale's content — see {@link extractVariables}.\n * Supply explicitly to make a placeholder optional (leave it out of the list)\n * or to require something a conditional references.\n */\n variables?: readonly string[];\n}\n\n/** An email template: base content, plus optional per-locale overrides. */\nexport interface EmailTemplateOptions extends EmailTemplateContent {\n /** Locale of the base content. Defaults to `\"en\"`. */\n locale?: string;\n /** Additional locales, keyed by BCP47 short tag (`tr`, `de`, …). */\n locales?: Record<string, EmailTemplateContent>;\n}\n\n/** One locale's SMS content. */\nexport interface SmsTemplateContent {\n /** Message body. Handlebars placeholders are rendered at send. */\n body: string;\n /** Variables the sender must supply. Derived from `body` when omitted. */\n variables?: readonly string[];\n}\n\n/** An SMS template: base content, plus optional per-locale overrides. */\nexport interface SmsTemplateOptions extends SmsTemplateContent {\n /** Locale of the base content. Defaults to `\"en\"`. */\n locale?: string;\n /** Additional locales, keyed by BCP47 short tag. */\n locales?: Record<string, SmsTemplateContent>;\n}\n\n/** Author-facing templates block: slug → template. */\nexport interface TemplatesInput {\n email?: Record<string, EmailTemplateOptions>;\n sms?: Record<string, SmsTemplateOptions>;\n}\n\n/** A compiled email-template row — one (slug, locale) pair, in the snake_case\n * wire shape PalNotify's templates API takes. */\nexport interface EmailTemplateDef {\n slug: string;\n locale: string;\n subject: string;\n html_body: string;\n text_body?: string;\n variables: string[];\n}\n\n/** A compiled SMS-template row — one (slug, locale) pair. */\nexport interface SmsTemplateDef {\n slug: string;\n locale: string;\n body: string;\n variables: string[];\n}\n\n/** The compiled templates block: flat, per-channel row lists. Flat rows (rather\n * than a nested locale map) are what the apply step iterates — one row is one\n * upsert against the (slug, locale) unique key. */\nexport interface TemplatesConfig {\n email: EmailTemplateDef[];\n sms: SmsTemplateDef[];\n}\n\n/**\n * Pull the variable names out of Handlebars content.\n *\n * Only PLAIN mustaches count: `{{name}}` and `{{{name}}}`. Deliberately skipped:\n * - block/section/partial/comment tokens (`{{#if}}`, `{{/if}}`, `{{else}}`,\n * `{{> partial}}`, `{{! comment}}`) — structure, not data the sender passes;\n * - helper calls (`{{formatDate at}}`) — the first token is a helper name;\n * - `this` and `@index`-style frame references.\n *\n * A dotted path contributes its ROOT (`{{user.name}}` → `user`), because that is\n * what the sender actually has to hand over.\n *\n * The list is what the server ENFORCES as required at render time, so keeping it\n * to the unambiguous cases is the point: an over-eager derivation would turn an\n * optional conditional into a mandatory argument and 400 real sends.\n */\nexport function extractVariables(...sources: (string | undefined)[]): string[] {\n const found = new Set<string>();\n for (const src of sources) {\n if (!src) continue;\n for (const match of src.matchAll(/\\{\\{\\{?\\s*([^{}]+?)\\s*\\}?\\}\\}/g)) {\n const token = (match[1] ?? \"\").trim();\n if (token === \"\" || \"#/^!>&\".includes(token.charAt(0)) || token === \"else\") continue;\n if (/\\s/.test(token)) continue; // helper invocation\n const root = token.split(\".\")[0] ?? \"\";\n if (root === \"\" || root === \"this\" || root.startsWith(\"@\")) continue;\n found.add(root);\n }\n }\n return [...found].sort();\n}\n\n/** Compile one email template into its per-locale rows. */\nfunction buildEmailTemplate(slug: string, opts: EmailTemplateOptions): EmailTemplateDef[] {\n const row = (locale: string, c: EmailTemplateContent): EmailTemplateDef => {\n if (!c.subject) throw new Error(`notifications: email template \"${slug}\" (${locale}) needs a subject`);\n if (!c.html) throw new Error(`notifications: email template \"${slug}\" (${locale}) needs an html body`);\n const def: EmailTemplateDef = {\n slug,\n locale,\n subject: c.subject,\n html_body: c.html,\n variables: c.variables ? [...c.variables] : extractVariables(c.subject, c.html, c.text),\n };\n if (c.text !== undefined) def.text_body = c.text;\n return def;\n };\n\n const rows = [row(opts.locale ?? DEFAULT_TEMPLATE_LOCALE, opts)];\n for (const [locale, content] of Object.entries(opts.locales ?? {})) {\n rows.push(row(locale, content));\n }\n return rows;\n}\n\n/** Compile one SMS template into its per-locale rows. */\nfunction buildSmsTemplate(slug: string, opts: SmsTemplateOptions): SmsTemplateDef[] {\n const row = (locale: string, c: SmsTemplateContent): SmsTemplateDef => {\n if (!c.body) throw new Error(`notifications: sms template \"${slug}\" (${locale}) needs a body`);\n return {\n slug,\n locale,\n body: c.body,\n variables: c.variables ? [...c.variables] : extractVariables(c.body),\n };\n };\n\n const rows = [row(opts.locale ?? DEFAULT_TEMPLATE_LOCALE, opts)];\n for (const [locale, content] of Object.entries(opts.locales ?? {})) {\n rows.push(row(locale, content));\n }\n return rows;\n}\n\n/** Compile the whole templates block, rejecting a duplicated (slug, locale). */\nfunction buildTemplates(input: TemplatesInput): TemplatesConfig {\n const out: TemplatesConfig = { email: [], sms: [] };\n const seen = new Set<string>();\n const claim = (channel: string, slug: string, locale: string) => {\n const key = `${channel}/${slug}/${locale}`;\n if (seen.has(key)) {\n throw new Error(`notifications: ${channel} template \"${slug}\" declares locale \"${locale}\" twice`);\n }\n seen.add(key);\n };\n\n for (const [slug, opts] of Object.entries(input.email ?? {})) {\n for (const row of buildEmailTemplate(slug, opts)) {\n claim(\"email\", row.slug, row.locale);\n out.email.push(row);\n }\n }\n for (const [slug, opts] of Object.entries(input.sms ?? {})) {\n for (const row of buildSmsTemplate(slug, opts)) {\n claim(\"sms\", row.slug, row.locale);\n out.sms.push(row);\n }\n }\n return out;\n}\n\n/** The author-facing input to `defineNotifications`. Every provider + every\n * channel is optional — declare only what you use. */\nexport interface NotificationsInput {\n push?: {\n apns?: ApnsOptions;\n fcm?: FcmOptions;\n };\n email?: {\n sendgrid?: SendgridOptions;\n ses?: SesOptions;\n smtp?: SmtpOptions;\n acs?: AcsOptions;\n };\n sms?: {\n twilio?: TwilioOptions;\n };\n /** Email + SMS templates, keyed by slug. Applied on every deploy. */\n templates?: TemplatesInput;\n}\n\n// ── compiled (serializable) provider defs — the EXACT JSON the apply parses ──\n\n/** A compiled provider def. `enabled` is always present; the remaining keys are\n * the provider's non-secret fields (verbatim from the catalog). A disabled\n * provider is `{ enabled: false }` with no other fields. */\nexport type ProviderDef = { enabled: boolean } & Record<string, unknown>;\n\n/** The compiled notifications config — the discriminant + per-channel maps of\n * provider name → {@link ProviderDef}. This is what `defineNotifications`\n * returns and the runtime extractor serializes. */\nexport interface NotificationsConfig {\n __config: typeof NOTIFICATIONS_CONFIG_KIND;\n push: Record<string, ProviderDef>;\n email: Record<string, ProviderDef>;\n sms: Record<string, ProviderDef>;\n templates: TemplatesConfig;\n}\n\n// ── validation + compilation ────────────────────────────────────────────────\n\n/**\n * Compile + validate one provider's author options into a {@link ProviderDef}.\n *\n * - A provider with `enabled === false` (or omitted) compiles to `{ enabled:\n * false }` and its required fields are NOT enforced (you can declare a disabled\n * provider as a placeholder without filling it in).\n * - An ENABLED provider must supply every `required` non-secret field from the\n * catalog; a missing one throws at config-author time (not silently at deploy).\n * - Only the catalog's non-secret fields (required + optional) are copied into\n * the def — an unknown extra key is ignored (it would have no effect on the\n * live provider). Secrets are never read here.\n */\nexport function buildProvider(name: ProviderName, opts: ProviderOptions): ProviderDef {\n const entry = PROVIDER_CATALOG[name];\n // A fresh, index-signature-bearing copy so catalog-driven field reads are\n // typed without a cast (the author-facing option interfaces are closed).\n const src: Record<string, unknown> = { ...opts };\n const enabled = src.enabled === undefined ? false : Boolean(src.enabled);\n if (!enabled) {\n return { enabled: false };\n }\n\n const def: ProviderDef = { enabled: true };\n\n for (const field of entry.required) {\n const value = src[field];\n if (value === undefined || value === null || value === \"\") {\n throw new Error(\n `notifications: provider \"${name}\" is enabled but missing required field \"${field}\"`,\n );\n }\n def[field] = value;\n }\n for (const field of entry.optional) {\n if (src[field] !== undefined) {\n def[field] = src[field];\n }\n }\n\n // Twilio: exactly one of fromNumber / messagingServiceSid is required (mirrors\n // the studio router's refine + the module's ValidateTwilioConfig).\n if (name === \"twilio\") {\n const hasFrom = Boolean(def.fromNumber);\n const hasMsg = Boolean(def.messagingServiceSid);\n if (!hasFrom && !hasMsg) {\n throw new Error(\n 'notifications: provider \"twilio\" requires one of \"fromNumber\" or \"messagingServiceSid\"',\n );\n }\n }\n\n return def;\n}\n\n/**\n * Define the notification-provider config for a project. Returns the\n * discriminated {@link NotificationsConfig} the runtime config extractor\n * serializes and the Go apply step reconciles. Validates eagerly: an enabled\n * provider missing a required non-secret field throws here (config-author time),\n * not at deploy.\n *\n * @example\n * export default defineNotifications({\n * push: { apns: { enabled: true, teamId: \"T\", keyId: \"K\", bundleId: \"com.x\" } },\n * });\n */\nexport function defineNotifications(input: NotificationsInput): NotificationsConfig {\n if (input === null || typeof input !== \"object\") {\n throw new Error(\"defineNotifications expects { push?, email?, sms? }\");\n }\n\n const config: NotificationsConfig = {\n __config: NOTIFICATIONS_CONFIG_KIND,\n push: {},\n email: {},\n sms: {},\n templates: buildTemplates(input.templates ?? {}),\n };\n\n const push = input.push ?? {};\n if (push.apns !== undefined) config.push.apns = buildProvider(\"apns\", push.apns);\n if (push.fcm !== undefined) config.push.fcm = buildProvider(\"fcm\", push.fcm);\n\n const email = input.email ?? {};\n if (email.sendgrid !== undefined) config.email.sendgrid = buildProvider(\"sendgrid\", email.sendgrid);\n if (email.ses !== undefined) config.email.ses = buildProvider(\"ses\", email.ses);\n if (email.smtp !== undefined) config.email.smtp = buildProvider(\"smtp\", email.smtp);\n if (email.acs !== undefined) config.email.acs = buildProvider(\"acs\", email.acs);\n\n const sms = input.sms ?? {};\n if (sms.twilio !== undefined) config.sms.twilio = buildProvider(\"twilio\", sms.twilio);\n\n return config;\n}\n\n/**\n * Derive the RESERVED env-var key that backs a provider's secret field, e.g.\n * `reservedSecretKey(\"apns\", \"p8\")` → `\"PB_NOTIFICATIONS_APNS_P8\"`. The CLI uses\n * this to upload the secret and the br-pod apply step uses the same derivation\n * to resolve it — they never hand-type the key, so they cannot drift.\n */\nexport function reservedSecretKey(provider: ProviderName, secretField: string): string {\n return `${RESERVED_SECRET_PREFIX}_${camelToUpperSnake(provider)}_${camelToUpperSnake(secretField)}`;\n}\n\n/** camelCase → UPPER_SNAKE_CASE (`serviceAccount` → `SERVICE_ACCOUNT`). */\nfunction camelToUpperSnake(s: string): string {\n return s.replace(/([a-z0-9])([A-Z])/g, \"$1_$2\").toUpperCase();\n}\n","/**\n * test-users.ts — the test-user fixtures config-as-code DSL.\n *\n * `defineTestUsers({ users })` is a MODULE config-as-code surface (a sibling of\n * `config/storage.ts`'s `defineStorage` and `config/flags.ts`'s `defineFlags`).\n * A `config/test-users.ts` file default-exports a `defineTestUsers(...)` result;\n * on deploy the runtime evaluates it to JSON and hands it to Studio, which owns\n * the single apply engine (mint + seed). Studio, the CLI and the deploy all go\n * through that one engine — there is no second interpreter of this JSON.\n *\n * TWO SHAPES, ONE DSL:\n *\n * - `email` GIVEN → a FIXTURE. Deploy materializes it create-if-missing, so\n * the app can always be signed into with the same credentials. Deliberately\n * NOT applied to a production Environment (the password lives in git).\n * - `email` OMITTED → a TEMPLATE. Deploy creates nothing; Studio and the CLI\n * mint as many fresh instances from it as you want (random credentials).\n *\n * Every minted user is an `is_test` user: excluded from MAU/billing, carrying\n * `test: true` in its token, and refused by the Test Data write path if it ever\n * turns out not to be one.\n *\n * @example\n * import { defineTestUsers, testUser } from \"@palbase/backend\";\n *\n * export default defineTestUsers({\n * users: {\n * demo: testUser({\n * email: \"demo@test.local\",\n * password: \"demo-password-1234\",\n * seed: {\n * profiles: [{ display_name: \"Demo\", tier: \"pro\" }],\n * lists: [\n * { title: \"Groceries\", todos: [{ title: \"Milk\" }, { title: \"Eggs\", done: true }] },\n * ],\n * },\n * }),\n * heavy_user: testUser({ seed: { lists: [{ title: \"L\", todos: [{ title: \"t\" }] }] } }),\n * },\n * });\n *\n * The returned value is the EXACT JSON shape the runtime's generic config\n * extractor emits and the apply engine consumes:\n * { __config: \"test-users\", users: { <name>: { email, password, seed } } }\n * `email` / `password` are the string or `null`; `seed` is `{}` when omitted.\n */\n\nimport type { TableTypes, Tables } from \"../db/env.js\";\n\n/** The `__config` discriminant the eval/apply reads to confirm a config/*.ts is\n * a test-users config. */\nexport const TEST_USERS_CONFIG_KIND = \"test-users\" as const;\n\n// ── Types derived from db/schema.ts ──────────────────────────────────────────\n//\n// `palbase-env.d.ts` (generated by makeEnvDts on every `palbase build` and\n// on deploy) augments the `Tables` interface with, per table:\n// `row`, `insert`, `owner` (the auth.users FK column, or null) and `children`\n// (tables that FK this one, mapped to their FK column). Those last two are what\n// let the seed shape below be fully derived — the author never writes an owner\n// or a foreign key, because the apply engine fills both.\n\n/**\n * A table graph in the shape the env `Tables` interface carries. The\n * derivations below are parameterized over it (rather than reading the global\n * `Tables` directly) so they can be type-tested against a fixture graph without\n * augmenting the global interface — augmentation is program-wide and would leak\n * into every other type test.\n *\n * The `Record<keyof G, …>` constraint is deliberate: a plain\n * `Record<string, TableTypes>` would reject the `Tables` INTERFACE, which has\n * no index signature.\n */\nexport type TableGraph = Record<string, TableTypes>;\n\n/** The user-rooted tables of `G` — the ones a test user owns rows in directly. */\nexport type OwnedTablesOf<G extends Record<keyof G, TableTypes>> = {\n [T in keyof G]: G[T][\"owner\"] extends string ? T : never;\n}[keyof G];\n\n/**\n * One authored seed row for table `T` of graph `G`.\n *\n * Starts from the table's INSERT shape and removes the two columns the engine\n * owns: the owner column (set to the minted user) and `Via` — the FK column\n * this row hangs off its parent by, when the row is nested under one. What\n * remains is extended with the table's children, each an optional array of\n * their own seed rows.\n *\n * Recursion terminates because `makeEnvDts` drops self-FKs and cycle\n * back-edges when it emits `children`.\n *\n * Name collision note: if a table has a COLUMN whose name equals a CHILD\n * table's name, the intersection makes that key unusable (its type collapses).\n * That is a schema-naming problem the author sees at compile time; the apply\n * engine resolves the same ambiguity live in favour of the column, because it\n * introspects the real table.\n */\nexport type SeedRowFor<\n G extends Record<keyof G, TableTypes>,\n T extends keyof G,\n Via extends string = never,\n> = Omit<G[T][\"insert\"], (G[T][\"owner\"] & string) | Via> & {\n [C in keyof G[T][\"children\"]]?: Array<\n SeedRowFor<G, C & keyof G, G[T][\"children\"][C] & string>\n >;\n};\n\n/** The typed seed over graph `G`: top-level keys are user-rooted tables only;\n * everything else is reached by nesting under its parent. */\nexport type SeedFor<G extends Record<keyof G, TableTypes>> = {\n [T in OwnedTablesOf<G>]?: Array<SeedRowFor<G, T>>;\n};\n\n/** The serialized seed — what travels as JSON and what the engine receives. */\nexport type SeedJson = Record<string, Array<Record<string, unknown>>>;\n\n/**\n * The author-facing seed type. Falls back to the loose shape when `Tables` is\n * still empty (no `db/schema.ts`, or `palbase-env.d.ts` not generated yet) so\n * an unseeded project gets a usable DSL instead of an inscrutable `{}` error.\n */\nexport type Seed = [keyof Tables] extends [never] ? SeedJson : SeedFor<Tables>;\n\n// ── Author-facing options / compiled defs ────────────────────────────────────\n\n/**\n * The options for one declared test user.\n *\n * - `email` / `password`: supply BOTH to make this a fixture with stable\n * credentials (deploy materializes it, the app signs in with them), or\n * NEITHER to make it a template the server generates credentials for.\n * - `seed`: the user's data tree, derived from `db/schema.ts`. Top-level keys\n * are user-rooted tables; FK children nest inside their parent's rows.\n */\nexport interface TestUserOptions {\n email?: string;\n password?: string;\n /**\n * A verified phone for this fixture, E.164 (`+905551112233`). Requires\n * {@link TestUserOptions.otp}: nothing can receive an SMS at a fabricated\n * number, so a phone fixture without a knowable code is one no test could\n * ever sign in as.\n */\n phone?: string;\n /**\n * The fixed code this fixture's phone accepts. Honoured ONLY for the\n * `is_test` user it belongs to — the real rail is untouched, and no\n * verification is ever sent (or billed) for a fixture.\n */\n otp?: string;\n seed?: Seed;\n}\n\n/** The compiled, serializable test-user definition — the EXACT shape emitted to\n * JSON and consumed by the apply engine. */\nexport interface TestUserDef {\n /** Fixed login e-mail (fixture), or `null` when the server should generate one. */\n email: string | null;\n /** Fixed password (fixture), or `null` when the server should generate one. */\n password: string | null;\n /** Verified phone in E.164, or `null` for an e-mail-only fixture. */\n phone: string | null;\n /** The code that phone accepts, or `null` when there is no phone. */\n otp: string | null;\n /** The user's data tree; `{}` when nothing is seeded. */\n seed: SeedJson;\n}\n\n/** A test-users config: the discriminant + the declared users by name. */\nexport interface TestUsersConfig {\n __config: typeof TEST_USERS_CONFIG_KIND;\n users: Record<string, TestUserDef>;\n}\n\n/** The author-facing input to `defineTestUsers`. */\nexport interface TestUsersInput {\n users: Record<string, TestUserDef>;\n}\n\n// Template names ride into control-pg as the scenario name and into the CLI as\n// `--template <name>`; keep them to the same key vocabulary flags use.\nconst TEST_USER_NAME_RE = /^[a-zA-Z][a-zA-Z0-9_]*$/;\n\n// Deliberately permissive: the real address validation is palauth's. This only\n// catches the obvious typo at config-author time.\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\n// E.164: a leading + and 1..15 digits, first digit non-zero. Same shape palauth\n// validates with; this only catches the obvious authoring typo early.\nconst E164_RE = /^\\+[1-9]\\d{1,14}$/;\n\n// The fixed code is what a test types, so it must match what the UI accepts:\n// palauth mints 6-digit OTPs and the phone screens are 6-box.\nconst OTP_LENGTH = 6;\nconst OTP_RE = /^\\d{6}$/;\n\n/**\n * Minimum fixture password length.\n *\n * NOT palauth's 15-character single-factor floor: an `is_test` user is a\n * disposable harness identity excluded from MAU, and palauth applies neither\n * the length policy nor the HIBP check to the credentials it mints for one. We\n * still refuse an empty or one-character password so a typo can't produce a\n * fixture nobody can reason about.\n */\nconst MIN_PASSWORD_LENGTH = 8;\n\n/** True for a plain `{...}` object (not null, not an array). */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Structurally validate a seed and return its serializable form.\n *\n * Deliberately SHALLOW on meaning: we check that the seed is\n * `{ <table>: [ {...}, ... ] }` with non-empty arrays of plain objects, and\n * stop there. Whether a key inside a row is a COLUMN or a CHILD TABLE is\n * resolved by the apply engine against the LIVE schema — it introspects the\n * real table, so it is the only side that can tell them apart (and a jsonb\n * column may legitimately hold an array, which a deeper structural rule here\n * would misread as a nested child).\n */\nfunction normalizeSeed(seed: unknown, userName: string): SeedJson {\n if (seed === undefined) return {};\n if (!isPlainObject(seed)) {\n throw new Error(`testUser ${JSON.stringify(userName)}: seed must be { <table>: [ {...} ] }`);\n }\n const out: SeedJson = {};\n for (const [table, rows] of Object.entries(seed)) {\n if (!Array.isArray(rows)) {\n throw new Error(\n `testUser ${JSON.stringify(userName)}: seed.${table} must be an array of rows`,\n );\n }\n if (rows.length === 0) {\n throw new Error(\n `testUser ${JSON.stringify(userName)}: seed.${table} is empty — remove it or add a row`,\n );\n }\n for (const row of rows) {\n if (!isPlainObject(row)) {\n throw new Error(\n `testUser ${JSON.stringify(userName)}: every row in seed.${table} must be an object`,\n );\n }\n }\n out[table] = rows as Array<Record<string, unknown>>;\n }\n return out;\n}\n\n/**\n * Define a single test user. The NAME is supplied by the object key in\n * `defineTestUsers({ users: { <name>: testUser({...}) } })`, so `testUser()`\n * takes only the options.\n *\n * Validates eagerly (at config-author time):\n * - `email` and `password` are supplied together or not at all — half a\n * credential pair would silently degrade a fixture into a template.\n * - `email` looks like an address; `password` is at least\n * {@link MIN_PASSWORD_LENGTH} characters.\n * - `seed` is structurally `{ <table>: [ {...}, ... ] }` with non-empty arrays.\n *\n * The user NAME is validated by `defineTestUsers`, which is where it is known.\n */\nexport function testUser(opts: TestUserOptions = {}): TestUserDef {\n if (!isPlainObject(opts)) {\n throw new Error(\"testUser() expects { email?, password?, phone?, otp?, seed? }\");\n }\n const hasEmail = opts.email !== undefined;\n const hasPassword = opts.password !== undefined;\n if (hasEmail !== hasPassword) {\n throw new Error(\n \"testUser() needs email AND password together (a fixture with stable credentials) or neither (a template the server generates credentials for)\",\n );\n }\n\n let email: string | null = null;\n let password: string | null = null;\n if (hasEmail) {\n if (typeof opts.email !== \"string\" || !EMAIL_RE.test(opts.email)) {\n throw new Error(`testUser email ${JSON.stringify(opts.email)} is not a valid address`);\n }\n if (typeof opts.password !== \"string\" || opts.password.length < MIN_PASSWORD_LENGTH) {\n throw new Error(\n `testUser password must be at least ${MIN_PASSWORD_LENGTH} characters (got ${\n typeof opts.password === \"string\" ? opts.password.length : 0\n })`,\n );\n }\n email = opts.email;\n password = opts.password;\n }\n\n // A phone needs its code and vice versa. Refused here, at authoring time,\n // rather than at deploy: a phone fixture with no knowable code provisions\n // fine and then fails as a test hanging on an SMS that can never arrive.\n const hasPhone = opts.phone !== undefined;\n const hasOTP = opts.otp !== undefined;\n if (hasPhone !== hasOTP) {\n throw new Error(\n \"testUser() needs phone AND otp together — nothing can receive an SMS at a fabricated number, so a phone fixture without its fixed code can never be signed in as\",\n );\n }\n\n let phone: string | null = null;\n let otp: string | null = null;\n if (hasPhone) {\n if (typeof opts.phone !== \"string\" || !E164_RE.test(opts.phone)) {\n throw new Error(\n `testUser phone ${JSON.stringify(opts.phone)} must be E.164, e.g. \"+905551112233\"`,\n );\n }\n if (typeof opts.otp !== \"string\" || !OTP_RE.test(opts.otp)) {\n throw new Error(\n `testUser otp ${JSON.stringify(opts.otp)} must be ${OTP_LENGTH} digits`,\n );\n }\n phone = opts.phone;\n otp = opts.otp;\n }\n\n // The user name is not known here (it is the object key in defineTestUsers),\n // so seed errors are labelled with the e-mail when there is one.\n return { email, password, phone, otp, seed: normalizeSeed(opts.seed, email ?? \"<template>\") };\n}\n\n/**\n * Define a project's test users. The user NAME comes from each object key\n * (authors never repeat it). Returns the discriminated {@link TestUsersConfig}\n * the runtime config extractor serializes and the apply engine consumes.\n *\n * Validates eagerly:\n * - each name matches `^[a-zA-Z][a-zA-Z0-9_]*$` (the CLI's `--template <name>`\n * and control-pg's scenario name share this vocabulary).\n * - no two fixtures declare the SAME e-mail — they would race to\n * create-if-missing the one account and the second would silently adopt the\n * first one's data tree.\n *\n * @example\n * export default defineTestUsers({\n * users: { demo: testUser({ email: \"demo@test.local\", password: \"demo-password-1234\" }) },\n * });\n */\nexport function defineTestUsers(input: TestUsersInput): TestUsersConfig {\n if (!isPlainObject(input) || !isPlainObject(input.users)) {\n throw new Error(\"defineTestUsers expects { users: { <name>: testUser({...}) } }\");\n }\n const users: Record<string, TestUserDef> = {};\n const emails = new Map<string, string>();\n for (const name of Object.keys(input.users)) {\n if (!TEST_USER_NAME_RE.test(name)) {\n throw new Error(\n `test user name ${JSON.stringify(name)} is invalid — must start with a letter and contain only letters, digits, and underscores`,\n );\n }\n const def = input.users[name];\n if (def === undefined) continue;\n if (def.email !== null) {\n const lower = def.email.toLowerCase();\n const already = emails.get(lower);\n if (already !== undefined) {\n throw new Error(\n `test users ${JSON.stringify(already)} and ${JSON.stringify(name)} declare the same e-mail ${JSON.stringify(def.email)}`,\n );\n }\n emails.set(lower, name);\n }\n users[name] = def;\n }\n return { __config: TEST_USERS_CONFIG_KIND, users };\n}\n","/**\n * flags.ts — the feature-flag-definitions config-as-code DSL.\n *\n * `defineFlags({ flags })` is the third MODULE config-as-code surface (a sibling\n * of `config/storage.ts`'s `defineStorage` and `config/notifications.ts`'s\n * `defineNotifications`). A `config/flags.ts` file default-exports a\n * `defineFlags(...)` result; on deploy the br-pod evaluates it to JSON and\n * UPSERTS the declared flag DEFINITIONS into PalFlags (the user-flags module's\n * system-flags admin API) — create-or-update, idempotent. A live flag NOT in\n * config is NEVER auto-deleted (an orphan flag is harmless; upsert-only).\n *\n * Flags are DECLARATIVE: a flag is a typed project-wide DEFAULT (its key, type,\n * default value, an optional description, and — for string flags — an optional\n * list of allowed `variants`). The VALUE of a flag for a specific USER (a\n * per-user override / A-B assignment) is runtime state set via the SDK, NEVER in\n * git. `variants` here is part of the DEFINITION (the allowed values a string\n * flag may take), not a per-user assignment.\n *\n * NO SECRETS. Unlike notifications, a flag carries no credentials — this is the\n * simplest module config (pure declarative data).\n *\n * @example\n * import { defineFlags, flag } from \"@palbase/backend\";\n *\n * export default defineFlags({\n * flags: {\n * new_dashboard: flag({ type: \"boolean\", default: false, description: \"Roll out the new dashboard\" }),\n * max_uploads: flag({ type: \"number\", default: 10 }),\n * theme: flag({ type: \"string\", default: \"light\", variants: [\"light\", \"dark\", \"system\"] }),\n * limits: flag({ type: \"json\", default: { daily: 10, burst: 50 } }),\n * },\n * });\n *\n * The returned value is the EXACT JSON shape the runtime's generic config\n * extractor (`config_extract.js`) emits and the Go apply step parses:\n * { __config: \"flags\", flags: { <key>: { type, default, variants, description }, ... } }\n * `variants` is the allowed-values list for a string flag, or `null` (any\n * string). `description` is the doc string, or `null`. The apply step maps the\n * author-facing `type` to PalFlags' `value_type`: \"boolean\" → \"bool\" and\n * \"json\" → \"object\"; \"number\"/\"string\" pass through.\n */\n\n/** The `__config` discriminant the eval/apply reads to confirm a config/*.ts is\n * a flags config. Flags is `\"flags\"`. */\nexport const FLAGS_CONFIG_KIND = \"flags\" as const;\n\n/**\n * A flag's type. The author-facing vocabulary is `\"boolean\" | \"number\" |\n * \"string\" | \"json\"`; the apply step maps it to PalFlags' `value_type` enum —\n * `\"boolean\"` → `\"bool\"`, `\"json\"` → `\"object\"`, the other two pass through. The\n * SDK keeps the JS-natural names so the DSL reads cleanly.\n *\n * `\"json\"` is a structured (object) flag. It is named for what an author types —\n * a JSON object literal — and matches the `--type json` the CLI's per-user\n * override commands already use for this same server type.\n */\nexport type FlagType = \"boolean\" | \"number\" | \"string\" | \"json\";\n\n/** Any value expressible in JSON — what may appear INSIDE a `\"json\"` flag's default. */\nexport type FlagJsonValue = boolean | number | string | null | FlagJsonValue[] | { [key: string]: FlagJsonValue };\n\n/**\n * The default of a `\"json\"` flag: a JSON OBJECT. Not an array and not a scalar —\n * PalFlags' `object` value type accepts a JSON object at the top level only\n * (`validate.ValidateValueTypeMatch`), and it caps nesting depth at 3.\n */\nexport type FlagJsonObject = { [key: string]: FlagJsonValue };\n\n/** The runtime JSON value a flag's `default` may hold (matches {@link FlagType}). */\nexport type FlagValue = boolean | number | string | FlagJsonObject;\n\n/**\n * The author-facing options for a single flag — a UNION keyed on `type`, so\n * `default` is checked against the declared type at compile time and `variants`\n * is only accepted where it means something.\n *\n * - `type`: the flag's type — `\"boolean\" | \"number\" | \"string\" | \"json\"`.\n * - `default`: the project-wide default value. MUST match `type` (a `number`\n * default with `type: \"boolean\"` is a type error, and throws at runtime).\n * - `variants`: ONLY valid for `type: \"string\"` — the allowed values the string\n * flag may take (a DEFINITION, not a per-user assignment). When given, the\n * `default` MUST be one of the variants. Supplying `variants` on any other\n * type is a type error, and throws at runtime. (PalFlags rejects variants for\n * every non-string `value_type`, so accepting them here would only produce a\n * config the server refuses.)\n * - `description`: an optional human description of what the flag controls.\n */\nexport type FlagOptions =\n | {\n type: \"boolean\";\n default: boolean;\n variants?: never;\n conditions?: FlagCondition<boolean>[];\n description?: string;\n }\n | {\n type: \"number\";\n default: number;\n variants?: never;\n conditions?: FlagCondition<number>[];\n description?: string;\n }\n | {\n type: \"string\";\n default: string;\n variants?: string[];\n conditions?: FlagCondition<string>[];\n description?: string;\n }\n | {\n type: \"json\";\n default: FlagJsonObject;\n variants?: never;\n conditions?: FlagCondition<FlagJsonObject>[];\n description?: string;\n };\n\n/**\n * One targeting branch: the value this flag resolves to when `when` matches the\n * caller's client context. Branch ORDER is priority — the first match wins, and\n * a flag with no matching branch falls back to its `default`.\n *\n * `when` is a small expression over what the client declares about itself:\n *\n * ```\n * client.platform == 'ios' && client.app_version >= '2.0.0'\n * client.locale startsWith 'tr'\n * client.platform in ['ios', 'android']\n * ```\n *\n * Those are CLAIMS, not proof — the server treats them as attacker-controlled.\n * They select WHICH value a caller sees, never WHETHER they may see it, so a\n * condition must not be the thing standing between a user and something paid.\n */\n/**\n * The variables the server exposes. Mirrors `declaredVars` in\n * `modules/user-flags/internal/conditions/conditions.go`; the server rejects\n * anything it does not know, so the worst a stale copy here does is offer too\n * little.\n *\n * `client.*` is what the SDK reports about the caller. `percentile` and\n * `server.now` are DERIVED server-side and cannot be moved by a lying client,\n * which is what makes a rollout or a time window mean anything.\n */\ntype StringVar = \"client.platform\" | \"client.locale\";\ntype SemverVar = \"client.app_version\" | \"client.os_version\";\n\ntype EqualityOp = \"==\" | \"!=\";\n/** Ordering only where order exists — a platform string has none. */\ntype OrderedOp = EqualityOp | \"<\" | \"<=\" | \">\" | \">=\";\ntype TextOp = EqualityOp | \"startsWith\" | \"endsWith\" | \"contains\";\n\n/** A single-quoted literal. Quoting is the mistake people make most. */\ntype Quoted = `'${string}'`;\n\ntype Comparison =\n | `${StringVar} ${TextOp} ${Quoted}`\n | `${StringVar} in [${string}]`\n | `${SemverVar} ${OrderedOp} ${Quoted}`\n // Bare number: quoting it would make the server compare a string and the\n // rule would silently never match.\n | `percentile ${OrderedOp} ${number}`\n | `server.now ${OrderedOp} ${Quoted}`;\n\n/**\n * One expression: a comparison, optionally chained with `&&` / `||`, or a\n * parenthesised group.\n *\n * ONE level, and the limit is TypeScript's, not a preference. Unrolling a second\n * level produced `TS2590: union type too complex`, and the failure mode there is\n * the worst possible one: the checker gives up and the type silently degrades to\n * `string`, so NOTHING is checked while the code still compiles. Measured, not\n * assumed — the two-level version accepted `client.app_verison` without\n * complaint.\n *\n * So the FIRST term is fully checked and the rest of a chain is not. That is\n * where the mistakes are: a rule is usually one comparison, and a typo in the\n * first one is the common case. A typo after an `&&` still reaches the server,\n * which parses the real grammar and rejects it.\n *\n * A group's contents go unchecked for the same reason.\n */\nexport type FlagConditionExpression =\n | Comparison\n | `${Comparison} && ${string}`\n | `${Comparison} || ${string}`\n | `(${string})`;\n\nexport interface FlagCondition<V> {\n when: FlagConditionExpression;\n value: V;\n}\n\n/**\n * The COMPILED shape of a condition — the JSON actually emitted and parsed by\n * the Go apply step.\n *\n * `when` widens back to `string` here on purpose. The narrow type is an\n * authoring aid; once the expression has been trimmed and serialised it is just\n * text on the wire, and keeping the template-literal type would force a cast on\n * every string operation without checking anything the author had not already\n * been checked on.\n */\nexport interface CompiledFlagCondition<V> {\n when: string;\n value: V;\n}\n\n/**\n * The compiled, serializable flag definition — the EXACT shape emitted to JSON\n * and consumed by the Go apply step.\n *\n * - `type`: the author-facing type verbatim (`\"boolean\" | \"number\" | \"string\" |\n * \"json\"`) — the apply step maps it to PalFlags' `value_type`.\n * - `default`: the default value (matches `type`).\n * - `variants`: the allowed-values list for a string flag, or `null` (any).\n * - `description`: the doc string, or `null`.\n */\nexport interface FlagDef {\n type: FlagType;\n default: FlagValue;\n variants: string[] | null;\n /** Ordered targeting branches, or `null` when the flag is unconditional. */\n conditions: CompiledFlagCondition<FlagValue>[] | null;\n description: string | null;\n}\n\n/** A flags config definition: the discriminant + a map of flag key →\n * {@link FlagDef}. This is the value `defineFlags` returns and the runtime\n * config extractor serializes. */\nexport interface FlagsConfig {\n __config: typeof FLAGS_CONFIG_KIND;\n flags: Record<string, FlagDef>;\n}\n\n/** The author-facing input to `defineFlags`: a `flags` map whose keys are the\n * flag keys and whose values are `flag({...})` builders. */\nexport interface FlagsInput {\n flags: Record<string, FlagDef>;\n}\n\n// Flag keys mirror PalFlags' system-flag key rule (validate.keyNameRe): a\n// letter, then letters / digits / underscores. We validate eagerly so a key the\n// CLI/SDK accepts is a key PalFlags accepts (the apply step never has to reject).\nconst FLAG_KEY_RE = /^[a-zA-Z][a-zA-Z0-9_]*$/;\n\n/** Reports whether `value` matches the declared {@link FlagType}. */\nfunction valueMatchesType(type: FlagType, value: FlagValue): boolean {\n switch (type) {\n case \"boolean\":\n return typeof value === \"boolean\";\n case \"number\":\n // A finite number only — NaN / Infinity are not serializable as JSON.\n return typeof value === \"number\" && Number.isFinite(value);\n case \"string\":\n return typeof value === \"string\";\n case \"json\":\n // A plain JSON OBJECT — not null, not an array. PalFlags' `object` value\n // type decodes to map[string]any and rejects anything else, so an array or\n // a bare scalar default must fail here rather than at deploy time.\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n }\n}\n\n/**\n * Define a single flag. The flag KEY is supplied by the object key in\n * `defineFlags({ flags: { <key>: flag({...}) } })`, so `flag()` takes only the\n * options.\n *\n * Validates eagerly (at config-author time):\n * - `type` is one of `\"boolean\" | \"number\" | \"string\" | \"json\"`.\n * - `default` matches `type` (e.g. a `number` default with `type: \"boolean\"`\n * throws; a `\"json\"` default must be a plain object, not an array or scalar).\n * - `variants` is ONLY allowed for a string flag (variants on any other type\n * throws); each entry is a non-empty string; the `default` must be one of the\n * variants.\n *\n * Returns a normalized {@link FlagDef}: `variants` deduped-or-null,\n * `description` trimmed-or-null.\n */\nexport function flag(opts: FlagOptions): FlagDef {\n if (opts === null || typeof opts !== \"object\") {\n throw new Error(\"flag() expects { type, default, variants?, description? }\");\n }\n const { type } = opts;\n if (type !== \"boolean\" && type !== \"number\" && type !== \"string\" && type !== \"json\") {\n throw new Error(`flag type must be \"boolean\", \"number\", \"string\", or \"json\", got ${JSON.stringify(type)}`);\n }\n if (!valueMatchesType(type, opts.default)) {\n throw new Error(\n `flag default ${JSON.stringify(opts.default)} does not match type \"${type}\"`,\n );\n }\n\n let variants: string[] | null = null;\n if (opts.variants !== undefined) {\n if (opts.type !== \"string\") {\n throw new Error(`flag variants are only valid for type \"string\" (got type \"${type}\")`);\n }\n if (!Array.isArray(opts.variants)) {\n throw new Error(\"flag variants must be an array of strings\");\n }\n for (const v of opts.variants) {\n if (typeof v !== \"string\" || v.length === 0) {\n throw new Error(`flag variant ${JSON.stringify(v)} must be a non-empty string`);\n }\n }\n // Dedupe while preserving first-seen order. An empty array is meaningless\n // (no value would be allowed) — reject it rather than silently widening.\n variants = [...new Set(opts.variants)];\n if (variants.length === 0) {\n throw new Error(\"flag variants must be a non-empty list when supplied\");\n }\n // `opts` narrowed to the string member above, so `default` is a string.\n if (!variants.includes(opts.default)) {\n throw new Error(\n `flag default ${JSON.stringify(opts.default)} is not one of its variants [${variants\n .map((v) => JSON.stringify(v))\n .join(\", \")}]`,\n );\n }\n }\n\n let conditions: CompiledFlagCondition<FlagValue>[] | null = null;\n if (opts.conditions !== undefined) {\n if (!Array.isArray(opts.conditions)) {\n throw new Error(\"flag conditions must be an array of { when, value }\");\n }\n const compiled: CompiledFlagCondition<FlagValue>[] = [];\n for (const [i, branch] of opts.conditions.entries()) {\n if (branch === null || typeof branch !== \"object\") {\n throw new Error(`flag condition ${i} must be an object { when, value }`);\n }\n if (typeof branch.when !== \"string\" || branch.when.trim().length === 0) {\n throw new Error(`flag condition ${i} needs a non-empty \"when\" expression`);\n }\n // Every branch has to satisfy exactly what the default satisfies: a flag\n // must not be able to resolve, through any door, to a value it would have\n // rejected as its own default.\n if (!valueMatchesType(type, branch.value as FlagValue)) {\n throw new Error(\n `flag condition ${i} value ${JSON.stringify(branch.value)} does not match type \"${type}\"`,\n );\n }\n if (variants !== null && !variants.includes(branch.value as string)) {\n throw new Error(\n `flag condition ${i} value ${JSON.stringify(branch.value)} is not one of its variants [${variants\n .map((v) => JSON.stringify(v))\n .join(\", \")}]`,\n );\n }\n compiled.push({ when: branch.when.trim(), value: branch.value as FlagValue });\n }\n conditions = compiled.length > 0 ? compiled : null;\n }\n\n let description: string | null = null;\n if (opts.description !== undefined) {\n if (typeof opts.description !== \"string\") {\n throw new Error(\"flag description must be a string\");\n }\n const trimmed = opts.description.trim();\n description = trimmed.length > 0 ? trimmed : null;\n }\n\n return {\n type,\n default: opts.default,\n variants,\n conditions,\n description,\n };\n}\n\n/**\n * Define the feature-flag definitions for a project. The flag KEY comes from\n * each object key (authors never repeat the key). Returns the discriminated\n * {@link FlagsConfig} the runtime config extractor serializes and the Go apply\n * step UPSERTS into PalFlags.\n *\n * @example\n * export default defineFlags({\n * flags: { dark_mode: flag({ type: \"boolean\", default: false }) },\n * });\n */\nexport function defineFlags(input: FlagsInput): FlagsConfig {\n if (input === null || typeof input !== \"object\" || typeof input.flags !== \"object\") {\n throw new Error(\"defineFlags expects { flags: { <key>: flag({...}) } }\");\n }\n const flags: Record<string, FlagDef> = {};\n for (const key of Object.keys(input.flags)) {\n if (!FLAG_KEY_RE.test(key)) {\n throw new Error(\n `flag key ${JSON.stringify(key)} is invalid — must start with a letter and contain only letters, digits, and underscores`,\n );\n }\n const def = input.flags[key];\n if (def === undefined) continue;\n flags[key] = def;\n }\n return { __config: FLAGS_CONFIG_KIND, flags };\n}\n","/**\n * secrets.ts — the tenant SECRET REQUIREMENT config-as-code DSL.\n *\n * `defineSecrets({ secrets: [secret(\"NEO4J_PASSWORD\")] })` declares WHICH secrets\n * a backend needs to run. It declares the requirement, never the value: the value\n * lives only in the vault, and nothing in this file — or in the repo it is\n * committed to — ever holds one.\n *\n * The gap it closes: today a backend's dependence on a secret is written nowhere\n * except inside the code that reads it (`process.env.NEO4J_PASSWORD`). Deploy a\n * project into an environment where that secret was never set and the build\n * passes, the pod starts, and the failure surfaces as a 500 on the first request\n * that touches it — measured on todoapp, whose `/graph/*` routes returned 500 for\n * exactly this reason. With the requirement declared, it travels WITH the code:\n * `push` compares this list against the environment's vault and refuses the\n * deploy, naming the missing secret, before anything ships.\n *\n * @example\n * // config/secrets.ts\n * import { defineSecrets, secret } from \"@palbase/backend\";\n * export default defineSecrets({\n * secrets: [\n * secret(\"NEO4J_PASSWORD\", { description: \"graph store password\" }),\n * secret(\"SENTRY_DSN\", { required: false, description: \"crash reporting\" }),\n * ],\n * });\n *\n * `required` defaults to TRUE. A declaration exists to be checked, so the safe\n * default is the checked one; `required: false` says the code has a working path\n * when the secret is absent, and downgrades a missing secret to a warning.\n *\n * Emits: { __config: \"secrets\", secrets: [{ name, required, description }] }\n * sorted by name, so the same declaration always evaluates to the same bytes and\n * a config diff shows what an author changed rather than how they reordered it.\n */\n\n/** The discriminant written under `__config` so the deploy eval knows the kind. */\nexport const SECRETS_CONFIG_KIND = \"secrets\" as const;\n\n/** The author-facing options for a single `secret()`. */\nexport interface SecretOptions {\n /**\n * Whether the deploy must REFUSE when this secret is absent from the target\n * environment's vault. Omitted ⇒ `true`.\n */\n required?: boolean;\n /** What the secret is for — shown when the deploy reports it missing. */\n description?: string;\n}\n\n/**\n * The compiled, serializable secret declaration — the EXACT shape emitted to\n * JSON and consumed by the Go deploy step.\n *\n * - `name`: the environment-variable name the code reads, verbatim.\n * - `required`: always present (defaulted to `true`).\n * - `description`: the doc string, or `null`.\n */\nexport interface SecretDef {\n name: string;\n required: boolean;\n description: string | null;\n}\n\n/** A secrets config definition: the discriminant + the name-sorted declarations.\n * This is the value `defineSecrets` returns and the build's config extractor\n * serializes into `.palbase/config.json`. */\nexport interface SecretsConfig {\n __config: typeof SECRETS_CONFIG_KIND;\n secrets: SecretDef[];\n}\n\n/** The author-facing input to `defineSecrets`: a list of `secret(...)` builders. */\nexport interface SecretsInput {\n secrets: SecretDef[];\n}\n\n// A secret name is an ENVIRONMENT VARIABLE name, and the code that reads it\n// spells it exactly this way (`process.env.NEO4J_PASSWORD`). Restricting the\n// alphabet to SCREAMING_SNAKE_CASE keeps the declaration and the read identical\n// across every layer that carries it — shell, container env, vault key — none of\n// which agree on how to quote anything else.\nconst SECRET_NAME_RE = /^[A-Z][A-Z0-9_]*$/;\n\n/**\n * Declare a single required (or optional) secret. Unlike `flag()` / `bucket()`,\n * the NAME is an argument rather than an object key: a secret's name is not a\n * label an author chooses, it is the exact env-var identifier the code already\n * reads, so it belongs where it can be validated as one.\n *\n * Validates eagerly (at config-author time):\n * - `name` is `[A-Z][A-Z0-9_]*` — anything else throws.\n * - `required` is a boolean; `description` is a string.\n *\n * Returns a normalized {@link SecretDef}: `required` defaulted to `true`,\n * `description` trimmed-or-null.\n */\nexport function secret(name: string, opts: SecretOptions = {}): SecretDef {\n if (typeof name !== \"string\" || !SECRET_NAME_RE.test(name)) {\n throw new Error(\n `secret name ${JSON.stringify(name)} is invalid — must be an environment-variable name: an uppercase letter, then uppercase letters, digits, and underscores (e.g. \"NEO4J_PASSWORD\")`,\n );\n }\n if (opts === null || typeof opts !== \"object\") {\n throw new Error(`secret(\"${name}\") expects { required?, description? }`);\n }\n\n let required = true;\n if (opts.required !== undefined) {\n if (typeof opts.required !== \"boolean\") {\n throw new Error(`secret(\"${name}\") required must be a boolean`);\n }\n required = opts.required;\n }\n\n let description: string | null = null;\n if (opts.description !== undefined) {\n if (typeof opts.description !== \"string\") {\n throw new Error(`secret(\"${name}\") description must be a string`);\n }\n const trimmed = opts.description.trim();\n description = trimmed.length > 0 ? trimmed : null;\n }\n\n return { name, required, description };\n}\n\n/**\n * Define the secrets a backend needs. Returns the discriminated\n * {@link SecretsConfig} the build's config extractor serializes and the deploy\n * checks against the target environment's vault BEFORE shipping anything.\n *\n * A name declared twice throws: two declarations of one name disagree about\n * something (usually `required`), and silently keeping either one is how a\n * secret stops being checked without anybody editing the check.\n */\nexport function defineSecrets(input: SecretsInput): SecretsConfig {\n if (input === null || typeof input !== \"object\" || !Array.isArray(input.secrets)) {\n throw new Error(\"defineSecrets expects { secrets: [secret(\\\"NAME\\\"), ...] }\");\n }\n\n const byName = new Map<string, SecretDef>();\n for (const def of input.secrets) {\n if (\n def === null ||\n typeof def !== \"object\" ||\n typeof def.name !== \"string\" ||\n typeof def.required !== \"boolean\"\n ) {\n throw new Error(\n `defineSecrets: every entry must come from secret() — got ${JSON.stringify(def)}`,\n );\n }\n if (byName.has(def.name)) {\n throw new Error(\n `secret \"${def.name}\" is declared twice in config/secrets.ts — remove one; a name has exactly one requirement`,\n );\n }\n byName.set(def.name, def);\n }\n\n // Sorted by name so the emitted document depends on WHAT was declared, not the\n // order it was typed in. `sort()`'s default comparator is code-unit order,\n // which for this alphabet ([A-Z0-9_]) is stable across every locale.\n const secrets = [...byName.values()].sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));\n return { __config: SECRETS_CONFIG_KIND, secrets };\n}\n","// Method decorators: `@Get` / `@Post` / `@Put` / `@Patch` / `@Delete` /\n// `@Query` declare a route (verb + subpath + options) on a controller method. These are LEGACY\n// method decorators (`experimentalDecorators`), receiving\n// `(prototype, methodName, descriptor)`. They write into the per-class registry\n// (registry.ts). The success-response schema is NOT declared here: it is derived\n// from the method's RETURN TYPE by a codegen step and injected onto the route at\n// runtime via `recordReturn` (registry.ts).\nimport {\n recordRoute,\n type HttpMethodUpper,\n type RouteOptions,\n} from \"./registry.js\";\n\n/** A legacy method decorator. */\ntype MethodDecorator = (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n) => void;\n\n/** Build a method decorator for one HTTP verb. The decorated method's name is\n * the route `fnName` — and it is PUBLIC API, not authoring sugar: the runtime\n * derives the operationId as `<controllerName>.<fnName>` (the dotted namespace\n * the SDKs expose as `pb.todos.list()`), so renaming this method renames every\n * client call. The flat verb+path id is only the fallback for routes with no\n * controller metadata. See openapi/discover.ts. */\nfunction makeMethodDecorator(method: HttpMethodUpper) {\n return function (subpath: string, options: RouteOptions = {}): MethodDecorator {\n // Runtime guard for stale pre-9.0.0 code: `@Query(zodSchema)` used to be\n // the query-string PARAM decorator. Applied against this SDK it would\n // silently record a garbage route (schema-as-subpath) and fail the deploy\n // with a baffling self-conflict — fail loud and name the migration instead.\n if (typeof subpath !== \"string\") {\n throw new Error(\n `@${method[0]}${method.slice(1).toLowerCase()}(subpath) expects a string subpath, got ${typeof subpath}.` +\n (method === \"QUERY\"\n ? \" If this is a zod schema on a method parameter: the query-string param decorator was renamed @QueryParams(schema) in @palbase/backend 9.0.0.\"\n : \"\"),\n );\n }\n return function (target, propertyKey) {\n recordRoute(target, String(propertyKey), method, subpath, options);\n };\n };\n}\n\n/** `@Get(subpath, options?)` — declare a GET route. */\nexport const Get = makeMethodDecorator(\"GET\");\n/** `@Post(subpath, options?)` — declare a POST route. */\nexport const Post = makeMethodDecorator(\"POST\");\n/** `@Put(subpath, options?)` — declare a PUT route. */\nexport const Put = makeMethodDecorator(\"PUT\");\n/** `@Patch(subpath, options?)` — declare a PATCH route. */\nexport const Patch = makeMethodDecorator(\"PATCH\");\n/** `@Delete(subpath, options?)` — declare a DELETE route. */\nexport const Delete = makeMethodDecorator(\"DELETE\");\n/** `@Query(subpath, options?)` — declare an HTTP QUERY route (RFC 10008):\n * safe + idempotent like GET, body-carrying like POST. Input rides `@Body`. */\nexport const Query = makeMethodDecorator(\"QUERY\");\n","// @Webhook / @On — the inbound-webhook half of the decorator surface.\n//\n// Mirrors decorators/controller.ts exactly: symbol-keyed, non-enumerable\n// metadata on the constructor plus a `__palbase` discriminant, read back by a\n// resolver. The resolver is the ONLY translation point — it returns the shape\n// the runtime already consumes, so the isolate's dispatch and the signature\n// engine's cross-binding golden are untouched by the authoring change.\nimport type { WebhookMeta, WebhookProvider } from \"../webhook.js\";\n\n/** A signature scheme spelled out, for a service with no preset. The presets\n * (`provider`) are named configurations of this same shape. */\nexport interface SignatureSpec {\n /** Header carrying the signature. */\n header: string;\n /** Stripped before comparison (e.g. `sha256=`). Omit when absent. */\n prefix?: string;\n algo: \"hmac-sha256\" | \"hmac-sha1\";\n encoding: \"hex\" | \"base64\";\n /** What the HMAC covers. Exactly two placeholders: `{body}` and `{ts}`.\n * Everything else is literal. `{ts}` requires `timestampHeader` and brings\n * the five-minute replay window with it. */\n signs: string;\n timestampHeader?: string;\n}\n\nexport interface WebhookOptions {\n provider?: WebhookProvider;\n signature?: SignatureSpec;\n /** Env-var REFERENCE for the signing secret — the platform never holds it. */\n secret: { env: string };\n}\n\nexport type WebhookEventHandler = (event: unknown, meta: WebhookMeta) => Promise<void>;\n\nexport interface ResolvedWebhook {\n provider?: WebhookProvider;\n signature?: SignatureSpec;\n secret: { env: string };\n events: Record<string, WebhookEventHandler>;\n}\n\nexport const WEBHOOK_META: unique symbol = Symbol.for(\"palbase.backend.webhookMeta\");\nexport const WEBHOOK_EVENTS: unique symbol = Symbol.for(\"palbase.backend.webhookEvents\");\n\ninterface EventEntry {\n event: string;\n fnName: string;\n}\n\ninterface WebhookCarrier {\n __palbase?: \"webhook\";\n [WEBHOOK_META]?: WebhookOptions;\n [WEBHOOK_EVENTS]?: EventEntry[];\n}\n\nfunction carrierOf(ctor: object): WebhookCarrier {\n return ctor as WebhookCarrier;\n}\n\n/** Mark a class as an inbound webhook. The mount name is the FILE name — there\n * is deliberately no `name` option, because the file name IS the public URL. */\nexport function Webhook(options: WebhookOptions) {\n return function <T extends abstract new (...args: never[]) => object>(ctor: T): T {\n const carrier = carrierOf(ctor);\n Object.defineProperty(carrier, WEBHOOK_META, {\n value: options,\n enumerable: false,\n configurable: true,\n writable: false,\n });\n Object.defineProperty(carrier, \"__palbase\", {\n value: \"webhook\",\n enumerable: false,\n configurable: true,\n writable: false,\n });\n return ctor;\n };\n}\n\n/** Bind a method to one event name. Any string is valid: presets provide\n * autocomplete, never a constraint, because we do not carry provider catalogs. */\nexport function On(event: string) {\n return function (target: object, fnName: string | symbol): void {\n // Method decorators receive the PROTOTYPE; metadata belongs on the ctor.\n const carrier = carrierOf((target as { constructor: object }).constructor);\n const existing = carrier[WEBHOOK_EVENTS];\n const entries: EventEntry[] = existing ? [...existing] : [];\n entries.push({ event, fnName: String(fnName) });\n Object.defineProperty(carrier, WEBHOOK_EVENTS, {\n value: entries,\n enumerable: false,\n configurable: true,\n writable: false,\n });\n };\n}\n\n/** Read a decorated class back as the resolved config the runtime consumes.\n * Every misuse throws HERE, at build time, rather than becoming a webhook that\n * answers 200 and does nothing. */\nexport function getWebhookConfig(ctor: object): ResolvedWebhook {\n const carrier = carrierOf(ctor);\n const meta = carrier[WEBHOOK_META];\n const entries = carrier[WEBHOOK_EVENTS] ?? [];\n\n if (!meta) {\n throw new Error(\n `@On used on a class that is not decorated with @Webhook (${(ctor as { name?: string }).name ?? \"anonymous\"})`,\n );\n }\n if (!meta.provider && !meta.signature) {\n throw new Error(\n \"@Webhook requires either a `provider` preset or an explicit `signature` — \" +\n \"an endpoint with no verification would accept forged deliveries\",\n );\n }\n // EITHER, not both. The isolate picks `provider` when both are present and\n // never looks at `signature`, so a tenant that wrote both gets deliveries\n // verified against a scheme they did not choose — silently, and with no way to\n // tell from the outside which one ran. Ambiguity about WHICH signature check\n // guards an endpoint is not something to resolve by precedence.\n if (meta.provider && meta.signature) {\n throw new Error(\n \"@Webhook declares BOTH a `provider` preset and an explicit `signature` — \" +\n \"these are alternatives; keep the one that describes the sender, because only `provider` would be used\",\n );\n }\n if (meta.signature) {\n const sig = meta.signature;\n // Mirrors Go's NewTemplateVerifier (internal/webhook/verify.go). Both sides\n // reject the same specs; this one rejects at build, which is the only place\n // a tenant can still act on it.\n if (!sig.header) {\n throw new Error(\"@Webhook signature requires `header` — the header the signature arrives in\");\n }\n if (sig.algo !== \"hmac-sha256\" && sig.algo !== \"hmac-sha1\") {\n throw new Error(`@Webhook signature has an unsupported algo \"${sig.algo}\"`);\n }\n if (sig.encoding !== \"hex\" && sig.encoding !== \"base64\") {\n throw new Error(`@Webhook signature has an unsupported encoding \"${sig.encoding}\"`);\n }\n if (!sig.signs?.includes(\"{body}\")) {\n throw new Error(\"@Webhook signature `signs` must contain {body} — signing a constant is not a signature\");\n }\n if (sig.signs.includes(\"{ts}\") && !sig.timestampHeader) {\n throw new Error(\"@Webhook signature uses {ts} but declares no `timestampHeader` to read it from\");\n }\n }\n if (!meta.secret?.env) {\n throw new Error(\"@Webhook requires `secret: { env: \\\"VAR_NAME\\\" }`\");\n }\n if (entries.length === 0) {\n throw new Error(\"@Webhook requires at least one @On handler\");\n }\n\n const instance = new (ctor as new () => Record<string, WebhookEventHandler>)();\n // Object.create(null), not {} — event names are free-form, so `@On(\"constructor\")`\n // and `@On(\"toString\")` are legal. A plain literal inherits those keys from\n // Object.prototype, and the duplicate check below would reject the FIRST and\n // only handler for them as a redeclaration.\n const events: Record<string, WebhookEventHandler> = Object.create(null) as Record<string, WebhookEventHandler>;\n for (const entry of entries) {\n if (Object.prototype.hasOwnProperty.call(events, entry.event)) {\n throw new Error(`@On(\"${entry.event}\") declared twice on the same webhook`);\n }\n events[entry.event] = (event, metaArg) =>\n (instance[entry.fnName] as WebhookEventHandler).call(instance, event, metaArg);\n }\n\n return {\n ...(meta.provider ? { provider: meta.provider } : {}),\n ...(meta.signature ? { signature: meta.signature } : {}),\n secret: meta.secret,\n events,\n };\n}\n","// @Hook — the BLOCKING half of the internal-event surface.\n//\n// Two axes decide which decorator a handler wants. Where does the event come\n// from, and can the handler stop it?\n//\n// @Webhook + @On an OUTSIDE service (Stripe, GitHub…) — cannot block\n// @Hook an event this stack raised — CAN block: `throw` cancels it\n// @On an event this stack raised — listens only, a monitor\n//\n// The blocking power lives in the NAME `@Hook`, not in the method decorator's\n// shape, which is why `@On` keeps meaning \"listener\" in both worlds and needs\n// no change. `@Upload` is the same pattern already shipped: the storage module\n// calls the tenant's method, and a method that answers 4xx discards the object\n// and hands its exact status, body and content-type back to the client.\n//\n// Mirrors decorators/webhook.ts: symbol-keyed, non-enumerable metadata on the\n// constructor, read back by one resolver. The resolver is the only translation\n// point, so the runtime consumes a shape the authoring surface never leaks.\nimport type { HookMeta } from \"../hooks.js\";\nimport { WEBHOOK_EVENTS } from \"./webhook.js\";\n\n/** A hook handler. Returning quietly ALLOWS; throwing DENIES (blocking hooks). */\nexport type HookFn = (event: unknown, meta: HookMeta) => Promise<unknown>;\n\nexport interface ResolvedHookClass {\n /** `@Hook` handlers, by event. A throw here cancels the operation. */\n blocking: Record<string, HookFn>;\n /** `@On` handlers, by event. A throw here reaches nobody but the log. */\n listeners: Record<string, HookFn>;\n}\n\n/** A hook's refusal, with the reason the caller will see.\n *\n * Any thrown error denies — this class exists so the REASON travels as a\n * deliberate message rather than as whatever a stray TypeError happened to say.\n * The engine is fail-closed by design (an unreachable hook denies), so a hook\n * body should stay narrow: an accidental throw refuses a real user. */\nexport class Deny extends Error {\n constructor(reason: string) {\n super(reason);\n this.name = \"Deny\";\n }\n}\n\nexport const HOOK_BLOCKING: unique symbol = Symbol.for(\"palbase.backend.hookBlocking\");\n\ninterface EventEntry {\n event: string;\n fnName: string;\n}\n\n/** `@Hook(\"before.user.create\")` — a blocking handler for one stack event. */\nexport function Hook(event: string) {\n return function (target: object, fnName: string | symbol): void {\n const carrier = (target as { constructor: object }).constructor as Record<symbol, unknown>;\n const existing = carrier[HOOK_BLOCKING] as EventEntry[] | undefined;\n const entries: EventEntry[] = existing ? [...existing] : [];\n entries.push({ event, fnName: String(fnName) });\n Object.defineProperty(carrier, HOOK_BLOCKING, {\n value: entries,\n enumerable: false,\n configurable: true,\n writable: false,\n });\n };\n}\n\n/** Binds one decorator's entries onto a single instance of the class.\n *\n * ONE instance for the whole class, built here rather than per call: a hook\n * that opens a client or reads a list in its constructor would otherwise pay\n * for it on every signup. */\nfunction bind(instance: Record<string, HookFn>, entries: EventEntry[], kind: string) {\n const out: Record<string, HookFn> = Object.create(null) as Record<string, HookFn>;\n for (const entry of entries) {\n if (Object.prototype.hasOwnProperty.call(out, entry.event)) {\n throw new Error(`${kind}(\"${entry.event}\") declared twice on the same hook class`);\n }\n // Resolved ONCE, here, so a decorator naming a method that does not exist\n // fails at build time with the name in the message — rather than at the\n // first signup, as \"instance[fnName] is not a function\".\n const fn = instance[entry.fnName];\n if (typeof fn !== \"function\") {\n throw new Error(`${kind}(\"${entry.event}\") names no method \"${entry.fnName}\" on the class`);\n }\n out[entry.event] = (event, meta) => fn.call(instance, event, meta);\n }\n return out;\n}\n\n/** Resolves a hook class into the two maps the runtime dispatches from.\n *\n * Every misuse throws HERE, at build time, rather than becoming a hook that is\n * silently never called — the failure mode this whole change exists to end. */\nexport function getHookConfig(ctor: object): ResolvedHookClass {\n const carrier = ctor as Record<symbol, unknown>;\n const blockingEntries = (carrier[HOOK_BLOCKING] ?? []) as EventEntry[];\n const listenerEntries = (carrier[WEBHOOK_EVENTS] ?? []) as EventEntry[];\n\n if (blockingEntries.length === 0 && listenerEntries.length === 0) {\n throw new Error(\n `${(ctor as { name?: string }).name ?? \"a hook class\"} carries no handler — ` +\n \"a hook file must declare at least one @Hook (blocking) or @On (listener) method\",\n );\n }\n\n const instance = new (ctor as new () => Record<string, HookFn>)();\n return {\n blocking: bind(instance, blockingEntries, \"@Hook\"),\n listeners: bind(instance, listenerEntries, \"@On\"),\n };\n}\n","// `@Upload` — the single-method direct-storage upload decorator, and its\n// `@UploadedObject` parameter companion + `UploadConfig`/`UploadedObject` types.\n//\n// Unlike `@Get`/`@Post`/… (where bytes flow THROUGH the br-pod), an `@Upload`\n// route never sees the file bytes: the client uploads DIRECTLY to storage via a\n// signed URL the br-pod mints in an authorize pre-flight. The decorated method\n// body is the COMPLETION handler — it runs once, after storage confirms the\n// object landed (via an HMAC-signed completion webhook), and returns the typed\n// result the client awaits. There is exactly one method: it is BOTH the\n// authorize gate (its uploadConfig drives the guard + signed-URL pinning) AND\n// the completion handler (its body).\n//\n// On the wire the authorize pre-flight is a POST; what marks a route as an\n// upload route through the whole pipeline (registry → flatten → openapi →\n// codegen) is the PRESENCE of `uploadConfig` on the route — never a special HTTP\n// verb. The `@Get`/`@Post`/… decorators never set it.\nimport { recordRoute, recordParam } from \"./registry.js\";\nimport type { RouteOptions } from \"./registry.js\";\nimport type { StorageConfig } from \"../config/storage.js\";\n\n/** A legacy method decorator (`experimentalDecorators`): `(prototype, name,\n * descriptor)`. */\ntype MethodDecorator = (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n) => void;\n\n/** A legacy parameter decorator: `(prototype, name, paramIndex)`. */\ntype ParameterDecorator = (\n target: object,\n propertyKey: string | symbol,\n parameterIndex: number,\n) => void;\n\n/**\n * Direct-storage upload settings for an `@Upload` route. The br-pod validates an\n * authorize request against these (size/type), then mints a signed upload URL\n * that PINS the limits so storage itself rejects an over-limit / wrong-type PUT\n * — the client cannot exceed what it declared.\n */\nexport interface UploadConfig {\n /**\n * Target bucket NAME. MUST exist in `config/storage.ts` `defineStorage(...)`.\n *\n * The bucket is the SINGLE SOURCE OF TRUTH for the size limit + MIME allowlist:\n * `bucket({ fileSizeLimit, allowedMimeTypes })`. Storage enforces those at the\n * actual PUT (the only guard a client cannot skip), so `@Upload` deliberately\n * does NOT take its own `maxSize`/`allowedTypes` — duplicating them here would\n * let a route declare a tighter limit than its bucket that storage would not\n * enforce (a real bypass: declare 10 bytes at authorize, then PUT up to the\n * bucket ceiling straight at the signed URL). One bucket, one limit, enforced.\n */\n bucket: string;\n /**\n * SERVER-side object key template. The client NEVER chooses the path. Tokens:\n * `{userId}` (authenticated user id), `{uploadId}` (server-minted), and\n * `{filename}` (the client-declared filename, sanitized). e.g.\n * `\"{userId}/{uploadId}-{filename}\"`.\n */\n pathTemplate: string;\n}\n\n/**\n * The uploaded object, injected into an `@Upload` method body by\n * `@UploadedObject()` once storage confirms the upload. Bytes are NOT present\n * (they went straight to storage) — this is the metadata the completion handler\n * persists.\n */\nexport interface UploadedObject {\n /** Server-minted id correlating authorize ↔ completion (idempotency key). */\n uploadId: string;\n /** Final object key in the bucket (rendered from `pathTemplate`). */\n path: string;\n /** Bucket the object landed in. */\n bucket: string;\n /** Object size in bytes, as reported by storage. */\n size: number;\n /** Object MIME type, as reported by storage — detected from the BYTES, not\n * from the filename or from what the client claimed. */\n contentType: string;\n /** SHA-256 of the stored bytes, hex. The same value the object's ETag is\n * derived from, so a client that has it can tell whether it already holds\n * these bytes. */\n checksum: string;\n /** Pixel width, for an image. Absent otherwise — a PDF has no dimensions,\n * and reporting 0 would be a measurement rather than an absence. */\n width?: number;\n /** Pixel height, for an image. */\n height?: number;\n /**\n * A ~25-byte placeholder the client paints INSTANTLY while the real image\n * downloads — the thing that replaces a grey skeleton with something already\n * shaped like the picture. Absent for non-images.\n *\n * Persist it beside the object's path: it costs a column and saves a request\n * per picture on every gallery render.\n */\n thumbhash?: string;\n /**\n * The renditions the bucket declared, by name, as URLs ready to use.\n *\n * Present on the completion input so the handler that stores the row has\n * everything it needs in one place — asking for them afterwards would be a\n * second call per upload, and per picture on every read.\n */\n variants: Record<string, string>;\n}\n\n/**\n * `@Upload(subpath, config)` — declare a direct-storage upload route. The method\n * body is the completion handler; `config.uploadConfig` drives the authorize\n * guard + signed-URL pinning.\n *\n * @example\n * @Upload(\"/\", { bucket: \"docs\", pathTemplate: \"{userId}/{uploadId}-{filename}\" })\n * async upload(@UploadedObject() obj: UploadedObject, @User() user): Promise<DocResult> { ... }\n * // The size limit + MIME allowlist come from the \"docs\" bucket in\n * // config/storage.ts — storage enforces them at the PUT.\n */\nexport function Upload(\n subpath: string,\n config: UploadConfig & Pick<RouteOptions, \"auth\" | \"rateLimit\">,\n): MethodDecorator {\n const { auth, rateLimit, ...uploadConfig } = config;\n validateUploadConfigShape(uploadConfig);\n const options: RouteOptions = {\n uploadConfig,\n ...(auth !== undefined ? { auth } : {}),\n ...(rateLimit !== undefined ? { rateLimit } : {}),\n };\n return function (target, propertyKey) {\n // On the wire the authorize pre-flight is a POST; `uploadConfig` is what\n // marks this as an upload route downstream.\n recordRoute(target, String(propertyKey), \"POST\", subpath, options);\n };\n}\n\n/**\n * `@UploadedObject()` — inject the uploaded object (`: UploadedObject`) into an\n * `@Upload` method body (the completion input). Only valid on an `@Upload`\n * route; the bytes are NOT present (they went directly to storage), this is the\n * confirmed object's metadata.\n *\n * Co-located with the {@link UploadedObject} TYPE so a single exported name\n * `UploadedObject` carries BOTH the decorator value and the type annotation.\n */\nexport function UploadedObject(): ParameterDecorator {\n return function (target, propertyKey, parameterIndex) {\n recordParam(target, String(propertyKey), {\n index: parameterIndex,\n kind: \"uploadedObject\",\n });\n };\n}\n\n/**\n * Shape-validate an UploadConfig at decoration time (author-time failure beats a\n * silent deploy bug). Does NOT cross-check against the storage config — that is\n * `validateUploadAgainstStorage`, run at flatten/deploy time when the storage\n * config is available.\n */\nexport function validateUploadConfigShape(c: UploadConfig): void {\n if (c === null || typeof c !== \"object\") {\n throw new Error(\"@Upload config must be an object { bucket, pathTemplate, ... }\");\n }\n if (typeof c.bucket !== \"string\" || c.bucket.length === 0) {\n throw new Error(\"@Upload config.bucket must be a non-empty bucket name\");\n }\n if (typeof c.pathTemplate !== \"string\" || c.pathTemplate.length === 0) {\n throw new Error(\"@Upload config.pathTemplate must be a non-empty key template\");\n }\n}\n\n/**\n * Cross-check one `@Upload` route's uploadConfig against the project's\n * {@link StorageConfig}: the named bucket MUST exist in `defineStorage(...)`.\n * Throws a precise error so a typo fails at deploy, not at the first user upload.\n *\n * That is the ONLY cross-check: the size limit + MIME allowlist live on the\n * bucket (`bucket({ fileSizeLimit, allowedMimeTypes })`) and are enforced by\n * storage at the PUT. `@Upload` carries no `maxSize`/`allowedTypes` of its own,\n * so there is nothing to compare — one bucket, one limit, no drift.\n *\n * `routeLabel` is used only for error messages (e.g. `docs.upload`).\n */\nexport function validateUploadAgainstStorage(\n uploadConfig: UploadConfig,\n storage: StorageConfig,\n routeLabel: string,\n): void {\n const def = storage.buckets[uploadConfig.bucket];\n if (def === undefined) {\n const known = Object.keys(storage.buckets);\n throw new Error(\n `@Upload route ${routeLabel} targets bucket \"${uploadConfig.bucket}\" which is not declared in defineStorage(...). ` +\n (known.length ? `Known buckets: ${known.join(\", \")}.` : \"No buckets are declared.\"),\n );\n }\n}\n","// Parameter decorators: `@Body` / `@QueryParams` / `@Param` / `@Headers` / `@User` /\n// `@OptionalUser` / `@Client` / `@RequestId` / `@TraceId` / `@Req`. Each records\n// `{ index, kind, schema?, name? }` into the per-class registry for the method\n// it decorates. These are LEGACY parameter decorators\n// (`experimentalDecorators`), receiving `(prototype, methodName, paramIndex)` —\n// esbuild/tsc preserve the param index at runtime (verified, design §0), which\n// is how dispatch injects positionally. No type reflection\n// (`emitDecoratorMetadata`) is used: validation comes from the zod schema, the\n// type annotation the developer writes is purely for autocomplete.\nimport type { ZodTypeAny } from \"zod\";\nimport { recordParam, type ParamKind } from \"./registry.js\";\n\n/** A legacy parameter decorator. */\ntype ParameterDecorator = (\n target: object,\n propertyKey: string | symbol,\n parameterIndex: number,\n) => void;\n\n/** Build a parameter decorator that records the given kind (+ optional schema /\n * name) at the decorated parameter's index. */\nfunction makeParamDecorator(\n kind: ParamKind,\n extra?: { schema?: ZodTypeAny; name?: string },\n): ParameterDecorator {\n return function (target, propertyKey, parameterIndex) {\n recordParam(target, String(propertyKey), {\n index: parameterIndex,\n kind,\n ...(extra?.schema !== undefined ? { schema: extra.schema } : {}),\n ...(extra?.name !== undefined ? { name: extra.name } : {}),\n });\n };\n}\n\n/** `@Body(schema)` — inject the request body, validated against `schema`. The\n * developer writes `: T` (= `z.infer<schema>`, same name) for autocomplete. */\nexport function Body(schema: ZodTypeAny): ParameterDecorator {\n return makeParamDecorator(\"body\", { schema });\n}\n\n/** `@QueryParams(schema)` — inject the parsed query params, validated against\n * `schema`. */\nexport function QueryParams(schema: ZodTypeAny): ParameterDecorator {\n return makeParamDecorator(\"query\", { schema });\n}\n\n/** `@Headers(schema?)` — inject the request headers (lowercase keys). With a\n * schema, headers are validated + the codegen emits header parameters. */\nexport function Headers(schema?: ZodTypeAny): ParameterDecorator {\n return makeParamDecorator(\"headers\", schema !== undefined ? { schema } : undefined);\n}\n\n/** `@Param(\"id\")` — inject one matched path param by name. */\nexport function Param(name: string): ParameterDecorator {\n return makeParamDecorator(\"param\", { name });\n}\n\n/** `@User()` — inject the authenticated user (`: User`, non-null for an\n * effective-required route). The runtime resolves the effective auth. */\nexport function User(): ParameterDecorator {\n return makeParamDecorator(\"user\");\n}\n\n/** `@OptionalUser()` — inject the user as `User | null` (for routes whose\n * effective auth is `false` / `{ required: false }`). */\nexport function OptionalUser(): ParameterDecorator {\n return makeParamDecorator(\"optionalUser\");\n}\n\n/** `@Client()` — inject the parsed calling-client metadata (`: ClientInfo`). */\nexport function Client(): ParameterDecorator {\n return makeParamDecorator(\"client\");\n}\n\n/** `@RequestId()` — inject the per-request id (`: string`). */\nexport function RequestId(): ParameterDecorator {\n return makeParamDecorator(\"requestId\");\n}\n\n/** `@TraceId()` — inject the W3C trace id (`: string`). */\nexport function TraceId(): ParameterDecorator {\n return makeParamDecorator(\"traceId\");\n}\n\n/** `@Req()` — inject the raw request object (escape hatch, `: PBRequest`). */\nexport function Req(): ParameterDecorator {\n return makeParamDecorator(\"req\");\n}\n\n// NOTE: `@UploadedObject()` lives in decorators/upload.ts (co-located with the\n// `UploadedObject` TYPE) so a single exported name carries both the value (the\n// decorator) and the type — TS can only merge value+type under one export name\n// when both are declared in the SAME module.\n","import type { DBClient, Logger, CacheClient, PalbaseModuleClients } from \"./endpoint.js\";\nimport type { User } from \"./types.js\";\n\n/** Middleware context — subset of EndpointContext without input (not yet validated). */\nexport interface MiddlewareContext extends PalbaseModuleClients {\n params: Record<string, string>;\n query: Record<string, string>;\n headers: Record<string, string>;\n user: User | null;\n db: DBClient;\n env: Record<string, string>;\n log: Logger;\n cache: CacheClient;\n requestId: string;\n environmentId: string;\n}\n\n/** Middleware function signature — receives context and next function. */\nexport type MiddlewareHandler = (\n ctx: MiddlewareContext,\n next: () => Promise<void>,\n) => Promise<void>;\n\n/**\n * Define a middleware function for use in the middleware/ directory or\n * as endpoint-specific middleware.\n *\n * Middleware runs before the handler. Call `next()` to pass control\n * to the next middleware or handler. If `next()` is not called, the\n * handler will not execute.\n *\n * Errors thrown in middleware are caught by the pipeline and returned\n * as error responses.\n */\nexport function defineMiddleware(fn: MiddlewareHandler): MiddlewareHandler {\n return fn;\n}\n","/** Non-service, per-invocation data for job handlers.\n * Services (Database, Log, …) are imported as singletons, not passed here. */\nexport interface JobMeta {\n /** Environment-scoped env vars. */\n env: Record<string, string>;\n /** The globally unique Environment runtime identifier. */\n environmentId: string;\n}\n\n/**\n * Cron expression validation.\n * Supports standard 5-field cron: minute hour day-of-month month day-of-week.\n * Each field allows: number, *, ranges (1-5), steps (star/2), lists (1,3,5).\n */\nexport function validateCronExpression(expression: string): string | null {\n const trimmed = expression.trim();\n if (trimmed === \"\") {\n return \"Cron expression is required\";\n }\n\n const parts = trimmed.split(/\\s+/);\n if (parts.length !== 5) {\n return `Invalid cron expression \"${trimmed}\": expected 5 fields (minute hour day month weekday), got ${parts.length}`;\n }\n\n const fieldNames = [\"minute\", \"hour\", \"day of month\", \"month\", \"day of week\"];\n const fieldRanges: [number, number][] = [\n [0, 59],\n [0, 23],\n [1, 31],\n [1, 12],\n [0, 7],\n ];\n\n for (let i = 0; i < 5; i++) {\n const field = parts[i]!;\n const name = fieldNames[i]!;\n const [min, max] = fieldRanges[i]!;\n\n const error = validateCronField(field, name, min, max);\n if (error !== null) {\n return error;\n }\n }\n\n return null;\n}\n\nfunction validateCronField(\n field: string,\n name: string,\n min: number,\n max: number,\n): string | null {\n // Split by comma for lists\n const listParts = field.split(\",\");\n for (const part of listParts) {\n // Check for step: */2, 1-5/2\n const stepParts = part.split(\"/\");\n if (stepParts.length > 2) {\n return `Invalid ${name} field: \"${field}\"`;\n }\n\n const base = stepParts[0]!;\n const step = stepParts[1];\n\n if (step !== undefined) {\n const stepNum = Number(step);\n if (!Number.isInteger(stepNum) || stepNum < 1) {\n return `Invalid step value in ${name} field: \"${field}\"`;\n }\n }\n\n if (base === \"*\") {\n continue;\n }\n\n // Check for range: 1-5\n if (base.includes(\"-\")) {\n const rangeParts = base.split(\"-\");\n if (rangeParts.length !== 2) {\n return `Invalid range in ${name} field: \"${field}\"`;\n }\n const rangeStart = Number(rangeParts[0]);\n const rangeEnd = Number(rangeParts[1]);\n if (\n !Number.isInteger(rangeStart) ||\n !Number.isInteger(rangeEnd) ||\n rangeStart < min ||\n rangeEnd > max ||\n rangeStart > rangeEnd\n ) {\n return `Invalid range in ${name} field: \"${field}\"`;\n }\n continue;\n }\n\n // Single number\n const num = Number(base);\n if (!Number.isInteger(num) || num < min || num > max) {\n return `Invalid value in ${name} field: \"${field}\"`;\n }\n }\n\n return null;\n}\n","// @Job — the cron half of the decorator surface. Same metadata mechanism as\n// @Webhook/@Controller. The job's NAME is not here on purpose: it is the file\n// name, which is also what the Temporal schedule id is built from. Two names\n// with nothing reconciling them is what this replaces.\nimport type { JobMeta } from \"../job.js\";\nimport { validateCronExpression } from \"../job.js\";\n\nexport interface JobOptions {\n /** Cron expression, five fields (e.g. \"0 3 * * *\"). */\n schedule: string;\n /** Execution timeout in seconds. Defaults to 30, ceiling 300 (sandbox limit). */\n timeout?: number;\n /**\n * How many times a FAILED run is retried before the run is recorded failed.\n * Defaults to 5, ceiling 10; 0 disables retrying entirely.\n *\n * Retries exist for the transient half of the failure space — the runtime\n * still waking, a network blip — not for a job that is wrong. A permanent\n * failure still lands in the run history, it just lands after the retries\n * are spent rather than instead of them.\n */\n retry?: number;\n}\n\nexport interface ResolvedJob {\n schedule: string;\n timeout: number;\n retry: number;\n handler: (meta: JobMeta) => Promise<void>;\n}\n\nconst DEFAULT_TIMEOUT_SECONDS = 30;\nconst MAX_TIMEOUT_SECONDS = 300;\nconst DEFAULT_RETRY = 5;\nconst MAX_RETRY = 10;\n\nexport const JOB_META: unique symbol = Symbol.for(\"palbase.backend.jobMeta\");\n\ninterface JobCarrier {\n __palbase?: \"job\";\n [JOB_META]?: JobOptions;\n}\n\nexport function Job(options: JobOptions) {\n return function <T extends abstract new (...args: never[]) => object>(ctor: T): T {\n const carrier = ctor as unknown as JobCarrier;\n Object.defineProperty(carrier, JOB_META, {\n value: options,\n enumerable: false,\n configurable: true,\n writable: false,\n });\n Object.defineProperty(carrier, \"__palbase\", {\n value: \"job\",\n enumerable: false,\n configurable: true,\n writable: false,\n });\n return ctor;\n };\n}\n\nexport function getJobConfig(ctor: object): ResolvedJob {\n const meta = (ctor as JobCarrier)[JOB_META];\n if (!meta) {\n throw new Error(\n `getJobConfig on a class with no @Job decorator (${(ctor as { name?: string }).name ?? \"anonymous\"})`,\n );\n }\n if (!meta.schedule || meta.schedule.trim() === \"\") {\n throw new Error(\"@Job requires a `schedule` cron expression\");\n }\n const cronError = validateCronExpression(meta.schedule);\n if (cronError) {\n throw new Error(`@Job has an invalid cron schedule: ${cronError}`);\n }\n\n const timeout = meta.timeout ?? DEFAULT_TIMEOUT_SECONDS;\n if (!Number.isInteger(timeout) || timeout <= 0) {\n throw new Error(\"@Job `timeout` must be a positive whole number of seconds\");\n }\n if (timeout > MAX_TIMEOUT_SECONDS) {\n throw new Error(`@Job \\`timeout\\` exceeds the ${MAX_TIMEOUT_SECONDS}s sandbox ceiling`);\n }\n\n const retry = meta.retry ?? DEFAULT_RETRY;\n if (!Number.isInteger(retry) || retry < 0) {\n throw new Error(\"@Job `retry` must be a whole number of attempts, zero or more\");\n }\n if (retry > MAX_RETRY) {\n throw new Error(`@Job \\`retry\\` exceeds the ceiling of ${MAX_RETRY}`);\n }\n\n const instance = new (ctor as new () => { run?: (meta: JobMeta) => Promise<void> })();\n if (typeof instance.run !== \"function\") {\n throw new Error(\"@Job class must declare an async run() method\");\n }\n const run = instance.run.bind(instance);\n\n return { schedule: meta.schedule, timeout, retry, handler: run };\n}\n","/**\n * resource.ts — external connections as lifecycle-managed classes.\n *\n * A `Resource` subclass models one external connection (a pooled datastore, a\n * stateless API client, or a per-user factory). The framework discovers each\n * instance, calls `init(env)` ONCE at boot with the declared secret subset, and\n * `shutdown()` (reverse order) on SIGTERM. On top of that lifecycle the author\n * exposes their own clean facade methods.\n *\n * // resources/neo4j.ts\n * import { Resource } from \"@palbase/backend\";\n * import neo4j, { type Driver, type Session } from \"neo4j-driver\";\n *\n * export class Neo4jResource extends Resource {\n * static secrets = [\"NEO4J_URL\", \"NEO4J_USER\", \"NEO4J_PASSWORD\"] as const;\n * private driver!: Driver;\n * async init(env: { NEO4J_URL: string; NEO4J_USER: string; NEO4J_PASSWORD: string }) {\n * this.driver = neo4j.driver(env.NEO4J_URL, neo4j.auth.basic(env.NEO4J_USER, env.NEO4J_PASSWORD));\n * }\n * async shutdown() { await this.driver.close(); }\n * session(): Session { return this.driver.session(); }\n * }\n * export const neo4j = new Neo4jResource(); // framework finds + manages it\n *\n * # Boot scope (NOT request-ALS)\n *\n * Resources are instantiated once at process boot. This is deliberately NOT the\n * per-request {@link AsyncLocalStorage} scope used for `Database`/`Cache`/… — a\n * connection pool must outlive a single request. The runtime discovers\n * resources from the project's `resources/` directory, registers each via\n * {@link __registerResource}, then calls {@link __runResourceBoot} before\n * serving and {@link __shutdownResources} on SIGTERM. Discovery is a runtime\n * concern; the SDK provides the base class + registry + boot/shutdown hooks.\n */\n\n/** Map a declared `secrets` tuple to the `init(env)` argument type — a record\n * over the secret names, each `string`. An empty tuple maps to an empty\n * record. */\nexport type ResourceEnv<Secrets extends readonly string[]> = {\n [K in Secrets[number]]: string;\n};\n\n/**\n * Base class for external connections.\n *\n * - `static secrets` — OPTIONAL readonly tuple of env-var names this resource\n * needs. Drives (a) the `env` type passed to `init` and (b) the\n * missing-secret check at boot (deploy fails naming the absent secret).\n * - `init(env)` — called ONCE at boot with the declared secret subset. May be\n * sync (`void`) or async (`Promise<void>`).\n * - `shutdown()` — OPTIONAL drain hook, called on SIGTERM in reverse boot\n * order.\n *\n * @example\n * import { Resource } from \"@palbase/backend\";\n * import { Client } from \"@googlemaps/google-maps-services-js\";\n *\n * export class GoogleResource extends Resource {\n * static secrets = [\"GOOGLE_MAPS_KEY\"] as const;\n * private client = new Client();\n * private key = \"\";\n * init(env: { GOOGLE_MAPS_KEY: string }) { this.key = env.GOOGLE_MAPS_KEY; }\n * }\n * export const google = new GoogleResource();\n */\nexport abstract class Resource {\n /** The env-var names this resource needs. Optional; omit for none. */\n static secrets?: readonly string[];\n\n /** Set up the connection from the declared secrets. Called once at boot. */\n abstract init(env: Record<string, string>): void | Promise<void>;\n\n /** Drain/close the connection on SIGTERM. Optional. */\n shutdown?(): void | Promise<void>;\n}\n\n/** A value carrying an optional readonly `secrets` tuple — the constructor side\n * of a Resource subclass. Narrowed from `unknown` via {@link hasSecrets}. */\ninterface WithSecrets {\n secrets?: readonly string[];\n}\n\n/** Guard: does this value carry a `secrets` array (the static on a Resource\n * subclass)? Lets us read `secrets` off `resource.constructor` (typed\n * `Function`) without a cast — narrows from `unknown` instead. */\nfunction hasSecrets(value: unknown): value is WithSecrets {\n if (typeof value !== \"object\" && typeof value !== \"function\") return false;\n const secrets = (value as { secrets?: unknown }).secrets;\n return secrets === undefined || Array.isArray(secrets);\n}\n\n/** A registered resource plus whether its `init` has already run. The\n * `booted` flag makes {@link __runResourceBoot} idempotent (re-running boot,\n * e.g. across a re-entrant deploy path, never re-inits). */\ninterface RegistryEntry {\n resource: Resource;\n booted: boolean;\n}\n\n/** Module-level boot registry. Single per process (the br-pod is\n * single-project). Order is registration order; shutdown reverses it. */\nconst registry: RegistryEntry[] = [];\n\n/**\n * Register a resource instance with the boot registry. The runtime calls this\n * for each instance discovered under the project's `resources/` directory.\n * NOT part of the public author-facing API (prefixed `__`).\n */\nexport function __registerResource(resource: Resource): void {\n registry.push({ resource, booted: false });\n}\n\n/** Read the declared `secrets` tuple off a resource instance's constructor. */\nfunction declaredSecrets(resource: Resource): readonly string[] {\n const ctor: unknown = resource.constructor;\n return hasSecrets(ctor) ? (ctor.secrets ?? []) : [];\n}\n\n/**\n * Boot every registered resource that has not yet been booted: resolve its\n * declared secret subset from `envMap`, then await its `init(env)`. Idempotent\n * — an already-booted resource is skipped. Throws (failing deploy/boot) when a\n * declared secret is absent, naming the missing secret. NOT part of the public\n * author-facing API.\n */\nexport async function __runResourceBoot(envMap: Record<string, string>): Promise<void> {\n for (const entry of registry) {\n if (entry.booted) continue;\n const secrets = declaredSecrets(entry.resource);\n const env: Record<string, string> = {};\n for (const name of secrets) {\n const value = envMap[name];\n if (value === undefined) {\n throw new Error(\n `Resource ${entry.resource.constructor.name} requires secret \"${name}\" but it is not set. ` +\n `Set it with \\`palbase secret set ${name} ...\\` (or in Studio) and redeploy.`,\n );\n }\n env[name] = value;\n }\n await entry.resource.init(env);\n entry.booted = true;\n }\n}\n\n/**\n * Shut down every booted resource in REVERSE registration order, awaiting each\n * `shutdown()` (a no-op when undefined). Clears the registry afterwards so a\n * second call is a no-op. NOT part of the public author-facing API.\n */\nexport async function __shutdownResources(): Promise<void> {\n for (let i = registry.length - 1; i >= 0; i -= 1) {\n const entry = registry[i]!;\n if (entry.booted && entry.resource.shutdown) {\n await entry.resource.shutdown();\n }\n }\n registry.length = 0;\n}\n\n/** Clear the registry without running shutdown. TEST-only helper so each test\n * starts from a clean registry. NOT part of the public author-facing API. */\nexport function __resetResources(): void {\n registry.length = 0;\n}\n","export type {\n PBRequest,\n ClientInfo,\n RateLimitConfig,\n DBClient,\n DBOps,\n FileContext,\n Logger,\n CacheClient,\n SecretsService,\n PalbaseDocsClient,\n PalbaseCollectionRef,\n PalbaseDocumentRef,\n PalbaseDocumentSnapshot,\n PalbaseQuerySnapshot,\n PalbaseWhereOperator,\n PalbaseResult,\n Middleware,\n ErrorDef,\n ErrorMap,\n ErrorThrowers,\n} from \"./endpoint.js\";\nexport {\n Database,\n Documents,\n Storage,\n Cache,\n Secrets,\n Log,\n Notifications,\n Flags,\n Realtime,\n Purchases,\n __setRuntime,\n __runWithRuntime,\n __requestALS,\n __getRuntime,\n} from \"./runtime.js\";\nexport type { RuntimeServices, RequestStore } from \"./runtime.js\";\n// Purchases: entitlement gate + metered spend, at the decorator level.\nexport { RequireEntitlement, Spend } from \"./purchases/decorators.js\";\nexport type { PurchasesService, LimitState, SpendOptions, StoreEnv } from \"./purchases/service.js\";\n\n// The module clients and their composition root. The PROCESS calls\n// buildModuleClients once at boot and hands the result to createApp — which is\n// the whole reason this package now contains the implementations and not just\n// the interfaces they were being checked against by nobody.\nexport { buildModuleClients } from \"./clients/index.js\";\nexport type { ModuleClientsConfig } from \"./clients/index.js\";\nexport { makeHttpClient, PalbaseModuleError } from \"./clients/http.js\";\nexport type { ModuleTransport, RequestOptions, TransportConfig } from \"./clients/http.js\";\n\nexport type { EntitlementKey, LimitKey } from \"./purchases/keys.js\";\n// The codegen twin of makeEnvDts — emits the project's `palbase-purchases.d.ts`.\nexport { makePurchasesDts } from \"./purchases/keys-gen.js\";\nexport type { PurchasesManifest } from \"./purchases/keys-gen.js\";\n// Per-route purchases metadata, read by the OpenAPI step to declare 403/429.\nexport { entitlementFor, spendFor } from \"./purchases/registry.js\";\nexport type { SpendMeta } from \"./purchases/registry.js\";\nexport type {\n PalbaseAuthClient,\n PalbaseStorageClient,\n PalbaseBucketClient,\n PalbaseRealtimeClient,\n PalbaseFunctionsClient,\n PalbaseInvokeOptions,\n PalbaseFlagsClient,\n PalbaseFlagsServiceClient,\n PalbaseFlagContext,\n PalbaseFlagVariant,\n PalbaseFlag,\n PalbaseFlagValue,\n PalbaseFlagSource,\n PalbaseSetOverrideResult,\n PalbaseSetOverridesResult,\n PalbaseClearOverrideResult,\n PalbaseClearAllOverridesResult,\n PalbaseBatchOverrideOperation,\n PalbaseBatchSetOverridesResult,\n PalbaseNotificationsClient,\n PalbasePushClient,\n PalbaseEmailClient,\n PalbaseSmsClient,\n PalbaseInboxClient,\n PalbasePreferencesClient,\n PalbaseAnalyticsClient,\n PalbaseAnalyticsQueryNamespace,\n PalbaseAnalyticsManagementNamespace,\n PalbaseLinksClient,\n // Shared local types\n PalbaseUser,\n PalbaseSession,\n PalbaseDeviceInfo,\n PalbaseAttestAndroidParams,\n PalbaseAttestAndroidResult,\n PalbaseAttestiOSParams,\n PalbaseAttestiOSResult,\n PalbaseBindDeviceParams,\n PalbaseVerifyRequestSignatureParams,\n PalbaseFileObject,\n PalbaseSignedUrlResponse,\n PalbaseUploadOptions,\n PalbaseTransformOptions,\n PalbaseListOptions,\n PalbasePushSendParams,\n PalbasePushSendResponse,\n PalbaseEmailSendParams,\n PalbaseEmailSendResponse,\n PalbaseSmsSendParams,\n PalbaseSmsSendResponse,\n PalbaseInboxSendParams,\n PalbaseInboxSendResponse,\n PalbaseInboxMessage,\n PalbaseInboxListOptions,\n PalbaseInboxListResult,\n PalbasePreferences,\n PalbaseRegisterDeviceParams,\n PalbaseDeviceTokenView,\n PalbaseMultiChannelResponse,\n PalbaseAnalyticsProperties,\n PalbaseIdentifyTraits,\n PalbaseCountQueryInput,\n PalbaseCountResult,\n PalbaseEventsQueryInput,\n PalbaseEventsResult,\n PalbaseUsersQueryInput,\n PalbaseUsersResult,\n PalbaseFunnelQueryInput,\n PalbaseFunnelResult,\n PalbaseRetentionQueryInput,\n PalbaseRetentionResult,\n PalbaseCohortQueryInput,\n PalbaseCohortResult,\n PalbaseOverviewResult,\n PalbaseEventNamesResult,\n PalbaseUserDetailResult,\n PalbaseCreateLinkParams,\n PalbaseUpdateLinkParams,\n PalbaseLink,\n PalbaseLinkDetails,\n PalbaseLinkAnalytics,\n PalbaseQrCodeOptions,\n PalbaseMatchParams,\n PalbaseInitialLink,\n PalbaseListLinksOptions,\n PalbaseListLinksResult,\n} from \"./clients.js\";\nexport { defineSchema } from \"./db/schema.js\";\n// The declaration as DATA — what the deploy reads to build the database. The\n// bundler calls this; a project never has to.\nexport { toSchemaJSON } from \"./db/schema-json.js\";\nexport type { SchemaJSON, TableJSON, ColumnJSON, PolicyJSON } from \"./db/schema-json.js\";\nexport type { SchemaDef, TableDef, TableInput, ColumnMap, SchemaInput } from \"./db/schema.js\";\nexport { policy, PolicyBuilder } from \"./db/policy.js\";\nexport type { PolicyDef, PolicyCommand, PolicyMode } from \"./db/policy.js\";\nexport { PALBASE_EXTENSIONS, EXTENSION_DEPENDENCIES, isPalbaseExtension } from \"./db/extensions.js\";\nexport type { PalbaseExtension } from \"./db/extensions.js\";\nexport { uuid, text, integer, bigint, numeric, boolean, timestamp, jsonb, enumType } from \"./db/columns.js\";\nexport type { ColumnBuilder, ColumnDef, ColumnType, OnDeleteAction } from \"./db/columns.js\";\nexport { raw } from \"./db/raw.js\";\nexport type { RawConstraintDef } from \"./db/raw.js\";\nexport { makeTypedDB } from \"./db/typed-db.js\";\nexport type {\n TypedDB,\n TypedTx,\n TypedTable,\n InsertShape,\n RowShape,\n EnvTypedDatabase,\n EnvServiceDatabase,\n EnvTypedTable,\n EnvTables,\n TxPlan,\n TxTables,\n} from \"./db/typed-db.js\";\n// Transaction plans: the `tx.tables.*` operation surface, its handles, and the\n// expressions a plan may write. `Database.transaction()` is on `Database`.\nexport { inc, dec, now, TxRefError, TxPlanError } from \"./db/tx-plan.js\";\nexport type {\n Ref,\n TxRow,\n TxRows,\n TxTable,\n TxPlanHandle,\n Materialized,\n TxNow,\n TxColumnExpr,\n TxInsertValue,\n TxSetValue,\n TxInsertShape,\n TxSetShape,\n TxWhere,\n TxSelectOptions,\n TxPlanBody,\n TxPlanResponse,\n TxPlanOpResult,\n TxPlanRejection,\n TxWireOp,\n TxWireRef,\n TxWireExpr,\n TxWireGuard,\n TxWireValue,\n} from \"./db/tx-plan.js\";\nexport type { Tables, TableTypes } from \"./db/env.js\";\nexport { makeEnvDts } from \"./db/env-gen.js\";\n// Module config-as-code DSLs (sibling of defineSchema). config/storage.ts\n// default-exports defineStorage(...); the deploy evals + applies the buckets.\nexport { defineStorage, bucket, parseFileSizeLimit, STORAGE_CONFIG_KIND } from \"./config/storage.js\";\nexport type { BucketDef, BucketOptions, ImageVariant, StorageConfig, StorageInput } from \"./config/storage.js\";\nexport {\n defineEgress,\n EGRESS_CONFIG_KIND,\n EGRESS_TIMEOUT_DEFAULT_MS,\n EGRESS_TIMEOUT_MAX_MS,\n EGRESS_TIMEOUT_MIN_MS,\n} from \"./config/egress.js\";\nexport type { EgressConfig, EgressInput } from \"./config/egress.js\";\n// config/notifications.ts default-exports defineNotifications(...); the deploy\n// evals + applies the providers (non-secret fields here, cert/key secrets bound\n// by convention to reserved PB_NOTIFICATIONS_* env vars resolved at deploy).\nexport {\n defineNotifications,\n buildProvider,\n extractVariables,\n reservedSecretKey,\n PROVIDER_CATALOG,\n NOTIFICATIONS_CONFIG_KIND,\n RESERVED_SECRET_PREFIX,\n DEFAULT_TEMPLATE_LOCALE,\n} from \"./config/notifications.js\";\nexport type {\n NotificationsConfig,\n NotificationsInput,\n ProviderDef,\n ProviderName,\n ProviderOptions,\n ProviderCatalogEntry,\n ApnsOptions,\n FcmOptions,\n SendgridOptions,\n SesOptions,\n SmtpOptions,\n AcsOptions,\n TwilioOptions,\n TemplatesInput,\n TemplatesConfig,\n EmailTemplateOptions,\n EmailTemplateContent,\n EmailTemplateDef,\n SmsTemplateOptions,\n SmsTemplateContent,\n SmsTemplateDef,\n} from \"./config/notifications.js\";\n// config/flags.ts default-exports defineFlags(...); the deploy evals + UPSERTS\n// the declared flag DEFINITIONS into PalFlags (upsert-only, never auto-deleted).\n// The simplest module config — pure declarative data, no secrets.\n// config/test-users.ts default-exports defineTestUsers(...); the deploy evals it\n// and hands the JSON to Studio's single apply engine (mint + seed). A fixture\n// (email+password given) is materialized create-if-missing; a template (no\n// credentials) is only registered for Studio/CLI to mint from.\nexport { defineTestUsers, testUser, TEST_USERS_CONFIG_KIND } from \"./config/test-users.js\";\nexport type {\n OwnedTablesOf,\n Seed,\n SeedFor,\n SeedJson,\n SeedRowFor,\n TableGraph,\n TestUserDef,\n TestUserOptions,\n TestUsersConfig,\n TestUsersInput,\n} from \"./config/test-users.js\";\nexport { defineFlags, flag, FLAGS_CONFIG_KIND } from \"./config/flags.js\";\nexport type {\n FlagDef,\n FlagJsonObject,\n FlagJsonValue,\n FlagOptions,\n FlagsConfig,\n FlagsInput,\n FlagType,\n FlagValue,\n} from \"./config/flags.js\";\n// config/secrets.ts default-exports defineSecrets(...); the deploy evals it and\n// checks the declared NAMES against the target environment's vault before\n// shipping. Values never appear here — only the requirement travels with the code.\nexport { defineSecrets, secret, SECRETS_CONFIG_KIND } from \"./config/secrets.js\";\nexport type { SecretDef, SecretOptions, SecretsConfig, SecretsInput } from \"./config/secrets.js\";\n// Class-controller decorator model (replaces defineController/defineHandler/route).\n// `getRegisteredControllers` is what makes exporting a controller OPTIONAL:\n// importing the file registers it. `Controller` stays exported for authoring.\nexport { Controller, getRegisteredControllers, __resetRegisteredControllers } from \"./decorators/controller.js\";\nexport type { ControllerOptions } from \"./decorators/controller.js\";\nexport { Get, Post, Put, Patch, Delete, Query } from \"./decorators/methods.js\";\nexport { Deny, getHookConfig, Hook } from \"./decorators/hook.js\";\nexport type { HookFn, ResolvedHookClass } from \"./decorators/hook.js\";\nexport { Upload, validateUploadAgainstStorage } from \"./decorators/upload.js\";\nexport type { UploadConfig } from \"./decorators/upload.js\";\n// `UploadedObject` is exported from upload.js, where BOTH the `@UploadedObject()`\n// decorator value AND the `UploadedObject` type are declared. One module → one\n// export name carries both — authors write `@UploadedObject()` (value) and\n// `: UploadedObject` (type) with a single imported name.\nexport { UploadedObject } from \"./decorators/upload.js\";\nexport {\n Body,\n QueryParams,\n Headers,\n Param,\n User,\n OptionalUser,\n Client,\n RequestId,\n TraceId,\n Req,\n} from \"./decorators/params.js\";\nexport type { RouteOptions, HttpMethodUpper, ThrowDescriptor, RouteMeta, ParamMeta, ParamKind } from \"./decorators/registry.js\";\n// recordThrows is the stager-injected carrier for inferred throw descriptors\n// (the recordReturn twin) — public so the injected IIFE in a deployed bundle\n// can call it via `require(\"@palbase/backend\").recordThrows(...)`.\nexport { recordThrows } from \"./decorators/registry.js\";\n// getRoutes reads a controller's RouteMeta[] straight from the registry — the\n// isolate runtime enumerates routes with it instead of the worker.js raw-Symbol\n// fallback (the ROUTES symbol stays, both fallbacks keep reading it).\nexport { getRoutes } from \"./decorators/registry.js\";\nexport { defineMiddleware } from \"./middleware.js\";\nexport type { MiddlewareContext, MiddlewareHandler } from \"./middleware.js\";\n// The authenticated-user TYPE is exported as `UserT` (not `User`) because the\n// value name `User` is the @User() parameter decorator (exported above). A\n// controller annotates `@User() user: UserT` — decorator for the value\n// position, `UserT` for the type. (NestJS-style: same name as the decorator\n// would collide in the value+type namespaces.)\nexport type { User as UserT, VerifiedDevice, HttpMethod, AuthConfig } from \"./types.js\";\nexport {\n HttpError,\n PalError,\n BadRequest,\n Unauthorized,\n Forbidden,\n NotFound,\n Conflict,\n TooManyRequests,\n} from \"./errors.js\";\n// Typed project errors — defineError returns an HttpError subclass and\n// self-registers {code, status, dataSchema} in the project-global error\n// registry (the OpenAPI spec twins join `RouteMeta.throws` against it).\nexport { defineError, getErrorRegistry } from \"./error-registry.js\";\nexport type { RegisteredError, DefinedError, DefinedErrorWithData } from \"./error-registry.js\";\nexport type { JobMeta } from \"./job.js\";\nexport type { WebhookProvider, WebhookMeta, WebhookRequest } from \"./webhook.js\";\n// Webhooks and jobs are classes: `@Webhook`/`@On` for inbound webhooks,\n// `@Job` for cron. Both take their name from their file — see decorators/*.\nexport { getWebhookConfig, On, Webhook } from \"./decorators/webhook.js\";\nexport type { ResolvedWebhook, SignatureSpec, WebhookEventHandler, WebhookOptions } from \"./decorators/webhook.js\";\nexport { getJobConfig, Job } from \"./decorators/job.js\";\nexport type { JobOptions, ResolvedJob } from \"./decorators/job.js\";\nexport {\n Resource,\n __registerResource,\n __runResourceBoot,\n __shutdownResources,\n} from \"./resource.js\";\nexport type { ResourceEnv } from \"./resource.js\";\n// Types only. A hook is declared with @Hook/@On in hooks/*.ts.\n//\n// The `auth`/`storage`/`documents` helpers that used to live here are gone, not\n// deprecated: they returned a record nothing in the runtime or the bundler ever\n// read, so a project that called one got a handler that never ran and no error\n// anywhere. api-surface.mjs asks for a deprecation bridge because a major locks\n// every tenant's deploy — a real cost, and the reason this shipped as a bridge\n// in 20.0.0. There are no production tenants to lock yet (owner's call,\n// 2026-08-22), so the bridge is spending a release to soften a break nobody can\n// feel, and the honest surface is the one with no dead names in it.\nexport type {\n HookMeta,\n AuthHookEvent,\n DocumentHookEvent,\n FileUploadedEvent,\n FileDeletedEvent,\n} from \"./hooks.js\";\nexport { z } from \"zod\";\n"],"mappings":"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","names":["raw","raw","flag","text","secret","now","bucket","policy","bucket","raw"]}
1
+ {"version":3,"sources":["../src/clients/http.ts","../src/clients/documents.ts","../src/clients/flags.ts","../src/clients/notifications.ts","../src/clients/realtime.ts","../src/clients/storage.ts","../src/clients/index.ts","../src/db/schema-json.ts","../src/channels.ts","../src/db/env-gen.ts","../src/stack-gen.ts","../src/decorators/methods.ts","../src/decorators/webhook.ts","../src/decorators/hook.ts","../src/decorators/upload.ts","../src/decorators/params.ts","../src/middleware.ts","../src/job.ts","../src/decorators/job.ts","../src/index.ts"],"sourcesContent":["/**\n * http.ts — the transport every module client speaks over.\n *\n * WHY IT IS HERE. This code, and the five clients built on it, spent their life\n * in `v2/runtime/internal/runtime/module-clients.js`: 1,768 lines of untyped\n * CommonJS that entered the SDK through an `@ts-expect-error` and left through\n * `unknown` casts. The interfaces those clients implement were always in this\n * package — only the implementations were outside it, where nothing checked one\n * against the other. Two defects came through that gap on 2026-08-15 (a type\n * that described a different server's columns; an accessor that was `undefined`\n * in a deployed handler), and both were green on each side alone.\n *\n * WHAT IT IS NOT. Nothing Bun-specific lives here. The transport is a `fetch`\n * the caller may supply, so this package stays runtime-agnostic and the process\n * that knows which runtime it is decides what to hand in.\n */\n\nimport type { PalbaseResult } from \"../endpoint.js\";\n\n/** Per-request options a module client may pass. */\nexport interface RequestOptions {\n /** JSON-serialised unless it is a string, a Uint8Array, a Blob or FormData. */\n body?: unknown;\n headers?: Record<string, string>;\n signal?: AbortSignal;\n}\n\n/**\n * What a module client is given. An INTERFACE rather than a class, because the\n * clients depend on this shape and not on the thing that implements it — which\n * is what lets a test drive a whole client without a server.\n */\nexport interface ModuleTransport {\n /** The platform's base URL, for the rare client that must build a URL. */\n readonly baseUrl: string;\n request<T = unknown>(\n method: string,\n path: string,\n options?: RequestOptions,\n ): Promise<PalbaseResult<T>>;\n}\n\nexport interface TransportConfig {\n baseUrl: string;\n apiKey: string;\n /**\n * The `fetch` to use. Omitted means the ambient one — resolved at CALL time,\n * never captured here: the egress fence replaces `globalThis.fetch` after the\n * clients are built, and a captured reference would keep calling the\n * un-fenced original.\n */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * A module call that failed.\n *\n * `code` is the platform's own error code (`forbidden`, `not_found`, …) so a\n * caller can branch on it without matching message text.\n */\nexport class PalbaseModuleError extends Error {\n readonly code: string;\n readonly status: number;\n readonly details: Record<string, unknown>;\n\n constructor(code: string, message: string, status: number, details: Record<string, unknown> = {}) {\n super(message);\n this.name = \"PalbaseModuleError\";\n this.code = code;\n this.status = status;\n this.details = details;\n }\n}\n\nexport function makeHttpClient(cfg: TransportConfig): ModuleTransport {\n async function request<T>(\n method: string,\n path: string,\n options: RequestOptions = {},\n ): Promise<PalbaseResult<T>> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...(options.headers ?? {}),\n };\n if (cfg.apiKey) headers[\"apikey\"] = cfg.apiKey;\n\n const init: RequestInit = { method, headers };\n if (options.body !== undefined) {\n if (typeof options.body === \"string\" || options.body instanceof Uint8Array) {\n init.body = options.body as RequestInit[\"body\"];\n } else if (typeof FormData !== \"undefined\" && options.body instanceof FormData) {\n // The platform writes Content-Type itself, WITH the multipart boundary.\n // Setting it here omits the boundary, and the server then parses zero\n // parts from a request that looks perfectly well formed.\n delete headers[\"Content-Type\"];\n init.body = options.body;\n } else if (typeof Blob !== \"undefined\" && options.body instanceof Blob) {\n delete headers[\"Content-Type\"];\n init.body = options.body;\n } else {\n init.body = JSON.stringify(options.body);\n }\n }\n if (options.signal) init.signal = options.signal;\n\n // Resolved HERE, per call. See TransportConfig.fetchImpl.\n const doFetch = cfg.fetchImpl ?? globalThis.fetch;\n\n let response: Response;\n try {\n response = await doFetch(`${cfg.baseUrl}${path}`, init);\n } catch (err) {\n // AN ENVELOPE, not an exception.\n //\n // This threw until 2026-08-15, and the throw made three separate claims\n // false at once:\n //\n // 1. The package's own rule — \"Response: { data, error }, no thrown API\n // errors\". Every client here is written to that contract.\n // 2. `Flags.get(key, default)`, whose documented behaviour is that the\n // default applies when the flag is absent AND when the service is\n // unreachable. It reads `resp.error !== null` to decide, and a throw\n // never reaches that branch: measured, `get(\"beta\", \"DEFAULT\")`\n // raised `connect ECONNREFUSED` instead of answering \"DEFAULT\". The\n // test that was supposed to cover it handed the client a hand-made\n // error envelope — a shape this code could not produce.\n // 3. Consistency with the Realtime client, which already envelopes a\n // network failure so a handler that wrote a row does not lose it\n // because pubsub was down.\n //\n // A caller destructuring { data, error } and checking `error` was being\n // defeated by an exception: the defensive code existed and did not help,\n // which is the worst kind of surprise to leave in a package.\n return {\n data: null,\n error: new PalbaseModuleError(\n \"network_error\",\n err instanceof Error ? err.message : \"Network request failed\",\n 0,\n ),\n status: 0,\n };\n }\n\n const contentType = response.headers.get(\"Content-Type\") ?? \"\";\n let parsed: unknown = null;\n if (method !== \"HEAD\" && contentType.includes(\"json\")) {\n parsed = await response.json().catch(() => null);\n } else if (method !== \"HEAD\" && contentType.startsWith(\"image/\")) {\n // QR codes and the like: hand back bytes the caller can write or forward.\n parsed = new Uint8Array(await response.arrayBuffer());\n } else if (method !== \"HEAD\" && response.body) {\n // A non-JSON error still says something; \"request failed\" says nothing.\n parsed = await response.text().catch(() => null);\n }\n\n if (!response.ok) {\n const body = (parsed && typeof parsed === \"object\" ? parsed : {}) as Record<string, unknown>;\n const code = typeof body.error === \"string\" && body.error ? body.error : \"unknown_error\";\n const message =\n (typeof body.error_description === \"string\" && body.error_description) ||\n response.statusText ||\n \"request failed\";\n return {\n data: null,\n error: new PalbaseModuleError(code, message, response.status, body),\n status: response.status,\n };\n }\n\n return { data: parsed as T, error: null, status: response.status };\n }\n\n return { baseUrl: cfg.baseUrl, request };\n}\n","/**\n * documents.ts — the Documents client, Firestore-shaped.\n *\n * Moved in from `v2/runtime/internal/runtime/module-clients.js:705-773` (plus\n * the `buildDocumentRef` / `buildCollectionRef` helpers above it) with its\n * behaviour intact: the same methods, the same paths, the same bodies. What\n * changed is that it now sits beside the interface it implements, so a drift\n * between the two is a compile error rather than a runtime surprise.\n */\n\nimport type {\n PalbaseCollectionRef,\n PalbaseDocsClient,\n PalbaseDocumentRef,\n PalbaseDocumentSnapshot,\n PalbaseQuerySnapshot,\n PalbaseResult,\n PalbaseWhereOperator,\n} from \"../endpoint.js\";\nimport { PalbaseModuleError, type ModuleTransport } from \"./http.js\";\n\n/**\n * A path segment the platform will accept.\n *\n * Validated HERE rather than at the server, because a rejected segment is a\n * programming mistake and the useful moment to hear about it is the call.\n */\nconst SEGMENT_RE = /^[A-Za-z0-9_-]+$/;\n\nfunction validateSegment(segment: string, label: string): void {\n if (!SEGMENT_RE.test(segment)) {\n throw new Error(`Invalid ${label}: \"${segment}\". Must match ${SEGMENT_RE.source}`);\n }\n}\n\ninterface WhereClause {\n field: string;\n op: PalbaseWhereOperator;\n value: unknown;\n}\ninterface OrderClause {\n field: string;\n direction: \"asc\" | \"desc\";\n}\ninterface ChainState {\n where: WhereClause[];\n orderBy: OrderClause[];\n limit?: number;\n}\n\ninterface RawDocument {\n id?: string;\n exists?: boolean;\n data?: Record<string, unknown>;\n}\n\nfunction buildDocumentRef<T extends Record<string, unknown>>(\n http: ModuleTransport,\n path: string,\n): PalbaseDocumentRef<T> {\n return {\n path,\n async set(data: T) {\n return http.request<void>(\"PUT\", `/v1/docs/${path}`, { body: data });\n },\n async get(): Promise<PalbaseResult<PalbaseDocumentSnapshot<T>>> {\n const response = await http.request<RawDocument>(\"GET\", `/v1/docs/${path}`);\n if (response.error) return { data: null, error: response.error, status: response.status };\n const raw = response.data ?? {};\n const exists = raw.exists !== undefined ? raw.exists : Boolean(raw.data || raw.id);\n const segments = path.split(\"/\");\n const id = raw.id || segments[segments.length - 1] || \"\";\n return {\n data: { id, exists, data: () => raw.data as T | undefined, ref: { path } },\n error: null,\n status: response.status,\n };\n },\n async update(data: Partial<T>) {\n return http.request<void>(\"PATCH\", `/v1/docs/${path}`, { body: data });\n },\n async delete() {\n return http.request<void>(\"DELETE\", `/v1/docs/${path}`);\n },\n collection<C extends Record<string, unknown>>(name: string): PalbaseCollectionRef<C> {\n validateSegment(name, \"subcollection name\");\n return buildCollectionRef<C>(http, `${path}/${name}`);\n },\n };\n}\n\nfunction buildCollectionRef<T extends Record<string, unknown>>(\n http: ModuleTransport,\n path: string,\n state: ChainState = { where: [], orderBy: [] },\n): PalbaseCollectionRef<T> {\n function snapshot(doc: { id: string; data: Record<string, unknown> }): PalbaseDocumentSnapshot<T> {\n return {\n id: doc.id,\n exists: true,\n data: () => doc.data as T,\n ref: { path: `${path}/${doc.id}` },\n };\n }\n\n function querySnapshot(docs: PalbaseDocumentSnapshot<T>[]): PalbaseQuerySnapshot<T> {\n return {\n docs,\n empty: docs.length === 0,\n size: docs.length,\n docChanges: () => docs.map((doc) => ({ type: \"added\" as const, doc })),\n };\n }\n\n return {\n path,\n\n doc(id: string) {\n validateSegment(id, \"document ID\");\n return buildDocumentRef<T>(http, `${path}/${id}`);\n },\n\n async add(data: T) {\n const resp = await http.request<{ id: string }>(\"POST\", `/v1/docs/${path}`, { body: data });\n if (resp.error || !resp.data) {\n return { data: null, error: resp.error, status: resp.status };\n }\n return {\n data: buildDocumentRef<T>(http, `${path}/${resp.data.id}`),\n error: null,\n status: resp.status,\n };\n },\n\n // Each narrowing returns a NEW ref. A builder that mutated in place would\n // leak one caller's filter into a query another caller had already held.\n where(field: string, op: PalbaseWhereOperator, value: unknown) {\n return buildCollectionRef<T>(http, path, {\n ...state,\n where: [...state.where, { field, op, value }],\n });\n },\n orderBy(field: string, direction: \"asc\" | \"desc\" = \"asc\") {\n return buildCollectionRef<T>(http, path, {\n ...state,\n orderBy: [...state.orderBy, { field, direction }],\n });\n },\n limit(n: number) {\n return buildCollectionRef<T>(http, path, { ...state, limit: n });\n },\n\n async get(): Promise<PalbaseResult<PalbaseQuerySnapshot<T>>> {\n const narrowed =\n state.where.length > 0 || state.orderBy.length > 0 || state.limit !== undefined;\n\n const resp = narrowed\n ? await http.request<{ documents?: { id: string; data: Record<string, unknown> }[] }>(\n \"POST\",\n `/v1/docs/${path}/query`,\n { body: queryBody(state) },\n )\n : await http.request<{ documents?: { id: string; data: Record<string, unknown> }[] }>(\n \"GET\",\n `/v1/docs/${path}`,\n );\n\n if (resp.error) return { data: null, error: resp.error, status: resp.status };\n const docs = (resp.data?.documents ?? []).map(snapshot);\n return { data: querySnapshot(docs), error: null, status: resp.status };\n },\n };\n}\n\nfunction queryBody(state: ChainState): Record<string, unknown> {\n const body: Record<string, unknown> = {};\n if (state.where.length > 0) {\n body.where = state.where.map((w) => ({ field: w.field, op: w.op, value: w.value }));\n }\n if (state.orderBy.length > 0) {\n body.orderBy = state.orderBy.map((o) => ({ field: o.field, direction: o.direction }));\n }\n if (state.limit !== undefined) body.limit = state.limit;\n return body;\n}\n\n/** The largest batch the platform accepts in one call. */\nconst MAX_BATCH = 500;\n\nexport function buildDocumentsClient(http: ModuleTransport): PalbaseDocsClient {\n return {\n /**\n * `Documents.doc(\"users/alice\")` — segments are collection/documentId PAIRS,\n * so an odd count addresses a COLLECTION and is refused. Accepting it would\n * write a document whose id happens to be a collection's name.\n */\n doc<T extends Record<string, unknown>>(path: string): PalbaseDocumentRef<T> {\n const segments = String(path)\n .split(\"/\")\n .filter((s) => s.length > 0);\n if (segments.length === 0 || segments.length % 2 !== 0) {\n throw new Error(\n `Invalid document path: \"${path}\". Expected collection/documentId pairs, got ${segments.length} segment(s).`,\n );\n }\n segments.forEach((s, i) => validateSegment(s, i % 2 === 0 ? \"collection name\" : \"document ID\"));\n return buildDocumentRef<T>(http, segments.join(\"/\"));\n },\n\n collection<T extends Record<string, unknown>>(name: string): PalbaseCollectionRef<T> {\n validateSegment(name, \"collection name\");\n return buildCollectionRef<T>(http, name);\n },\n\n async batch(operations) {\n // Refused HERE, without a request: the server would refuse it too, and\n // spending a round trip to be told so is the caller's time.\n if (operations.length > MAX_BATCH) {\n return {\n data: null,\n error: new PalbaseModuleError(\n \"batch_too_large\",\n `Batch size ${operations.length} exceeds maximum of ${MAX_BATCH}`,\n 400,\n ),\n status: 400,\n };\n }\n if (operations.length === 0) return { data: null, error: null, status: 200 };\n\n return http.request<void>(\"POST\", \"/v1/docs/batch\", {\n body: operations.map((op) => ({ op: op.op, path: op.ref.path, data: op.data })),\n });\n },\n };\n}\n","/**\n * flags.ts — feature flags, resolved for the request's own user.\n *\n * Moved in from `v2/runtime/internal/runtime/module-clients.js:941-1164`.\n *\n * THE ONE RULE WORTH STATING: the user a flag resolves for comes from the\n * SDK's own request scope, never from anything the caller passed on the wire.\n * A handler can pass an explicit context (including an explicit `null` for a\n * deliberate anonymous read) and that wins — but the default is the person the\n * request is being served for, which is what makes `Flags.get(\"x\")` mean the\n * obvious thing inside a handler.\n *\n * Writes mirror the Database model: `setOverride` writes for the CURRENT user\n * and needs no admin power; cross-user writes live behind `asService()` so they\n * are explicit and greppable.\n */\n\nimport type {\n PalbaseBatchOverrideOperation,\n PalbaseFlagContext,\n PalbaseFlagValue,\n PalbaseFlagsClient,\n PalbaseFlagsServiceClient,\n} from \"../clients.js\";\nimport type { PalbaseResult } from \"../endpoint.js\";\nimport type { ModuleTransport } from \"./http.js\";\n\nconst FLAG_NAME_RE = /^[A-Za-z0-9_.-]+$/;\n\nexport interface FlagsConfig {\n /** The request's user, read from the SDK's ALS box — never from the caller. */\n getCurrentUserId: () => string | null;\n}\n\nfunction assertFlagName(flagName: string): void {\n if (!FLAG_NAME_RE.test(flagName)) {\n throw new Error(`Invalid flag name: \"${flagName}\". Flag names must match ${FLAG_NAME_RE.source}`);\n }\n}\n\n/** A truthy flag value, in the platform's own terms. */\nfunction flagEnabled(value: unknown): boolean {\n if (typeof value === \"boolean\") return value;\n return value != null && value !== 0 && value !== \"\";\n}\n\nfunction flagVariant(value: unknown): { name: string } | null {\n return typeof value === \"string\" ? { name: value } : null;\n}\n\n/**\n * A context object carries `userId`/`properties`; anything else passed in that\n * position is a DEFAULT VALUE. This is what tells `Flags.get(key, ctx)` apart\n * from `Flags.get(key, someObjectDefault)`.\n */\nfunction isContextObject(v: unknown): v is PalbaseFlagContext {\n return (\n v !== null && typeof v === \"object\" && !Array.isArray(v) && (\"userId\" in v || \"properties\" in v)\n );\n}\n\ninterface MergedSnapshot {\n values?: Record<string, PalbaseFlagValue>;\n}\n\nexport function buildFlagsClient(http: ModuleTransport, cfg: FlagsConfig): PalbaseFlagsClient {\n /**\n * The effective user for a call. An explicit `userId` in the context wins —\n * INCLUDING an explicit `null`, which is a deliberate anonymous read.\n */\n function resolveUserId(context?: PalbaseFlagContext): string | null | undefined {\n if (context && \"userId\" in context) return context.userId ?? null;\n return cfg.getCurrentUserId() || undefined;\n }\n\n function mergedPath(context?: PalbaseFlagContext): string {\n const uid = resolveUserId(context);\n return uid ? `/v1/user-flags/users/${encodeURIComponent(uid)}` : \"/v1/user-flags\";\n }\n\n function fetchMerged(context?: PalbaseFlagContext) {\n return http.request<MergedSnapshot>(\"GET\", mergedPath(context));\n }\n\n const service: PalbaseFlagsServiceClient = {\n async setOverrideForUser(userId, key, value) {\n return http.request(\n \"PUT\",\n `/v1/user-flags/users/${encodeURIComponent(userId)}/${encodeURIComponent(key)}`,\n { body: { value } },\n );\n },\n async setOverridesForUser(userId, values) {\n return http.request(\"PUT\", `/v1/user-flags/users/${encodeURIComponent(userId)}`, {\n body: { values },\n });\n },\n async clearOverrideForUser(userId, key) {\n return http.request(\n \"DELETE\",\n `/v1/user-flags/users/${encodeURIComponent(userId)}/${encodeURIComponent(key)}`,\n );\n },\n async clearAllOverridesForUser(userId) {\n return http.request(\"DELETE\", `/v1/user-flags/users/${encodeURIComponent(userId)}`);\n },\n async batchSetOverrides(operations: ReadonlyArray<PalbaseBatchOverrideOperation>) {\n // The argument is camelCase, the wire is snake_case. Mapped here so a\n // stray `userId` never reaches the server — and an explicit `user_id`, if\n // a caller already wrote one, is preserved.\n const ops = (operations ?? []).map((op) => {\n const raw = op as unknown as { userId?: string; user_id?: string; values: unknown };\n return { user_id: raw.userId ?? raw.user_id, values: raw.values };\n });\n return http.request(\"POST\", \"/v1/user-flags/batch\", { body: { operations: ops } });\n },\n };\n\n return {\n async isEnabled(flagName: string, context?: PalbaseFlagContext) {\n assertFlagName(flagName);\n const res = await fetchMerged(context);\n if (res.error || res.data == null) return { data: null, error: res.error, status: res.status };\n return { data: flagEnabled(res.data.values?.[flagName]), error: null, status: res.status };\n },\n\n async getVariant(flagName: string, context?: PalbaseFlagContext) {\n assertFlagName(flagName);\n const res = await fetchMerged(context);\n // A missing or non-string value is a NULL variant on a successful read;\n // errors and empty bodies pass through as null too, which is why this is\n // written out rather than mapped.\n if (res.error || res.data == null) return { data: null, error: res.error, status: res.status };\n return { data: flagVariant(res.data.values?.[flagName]), error: null, status: res.status };\n },\n\n /**\n * `get(key)` · `get(key, default)` · `get(key, default, ctx)` · `get(key, ctx)`.\n *\n * The default is substituted when the flag is ABSENT or when the flags\n * service is unreachable — a product that hides a feature because a lookup\n * timed out is behaving correctly; one that crashes is not.\n */\n async get(\n flagName: string,\n defaultOrContext?: PalbaseFlagValue | PalbaseFlagContext,\n maybeContext?: PalbaseFlagContext,\n ): Promise<PalbaseResult<PalbaseFlagValue>> {\n assertFlagName(flagName);\n\n let defaultValue: PalbaseFlagValue | undefined;\n let context: PalbaseFlagContext | undefined;\n let hasDefault = false;\n if (maybeContext !== undefined) {\n defaultValue = defaultOrContext as PalbaseFlagValue;\n hasDefault = true;\n context = maybeContext;\n } else if (isContextObject(defaultOrContext)) {\n context = defaultOrContext;\n } else if (defaultOrContext !== undefined) {\n defaultValue = defaultOrContext as PalbaseFlagValue;\n hasDefault = true;\n }\n\n const resp = await fetchMerged(context);\n if (resp.error !== null) {\n if (hasDefault) return { data: defaultValue ?? null, error: null, status: resp.status };\n return { data: null, error: resp.error, status: resp.status };\n }\n const values = resp.data?.values ?? {};\n const value = values[flagName];\n // An absent key on a SUCCESSFUL read is not an error.\n if (value === undefined) {\n return { data: hasDefault ? (defaultValue ?? null) : null, error: null, status: resp.status };\n }\n return { data: value, error: null, status: resp.status };\n },\n\n async getAll(context?: PalbaseFlagContext) {\n const res = await fetchMerged(context);\n if (res.error || res.data == null) return { data: null, error: res.error, status: res.status };\n const values = res.data.values ?? {};\n return {\n data: Object.keys(values).map((name) => {\n const value = values[name];\n const flag: { name: string; enabled: boolean; variant?: { name: string } } = {\n name,\n enabled: flagEnabled(value),\n };\n if (typeof value === \"string\") flag.variant = { name: value };\n return flag;\n }),\n error: null,\n status: res.status,\n };\n },\n\n /**\n * Override a flag for the CURRENT request user.\n *\n * On an anonymous request this does not silently no-op and does not write\n * for nobody: it refuses and names the call that does cross-user writes.\n */\n async setOverride(key: string, value: PalbaseFlagValue) {\n const uid = cfg.getCurrentUserId();\n if (!uid) {\n return {\n data: null,\n error: {\n message:\n \"setOverride requires a signed-in user; use Flags.asService().setOverrideForUser(userId, key, value) for cross-user writes\",\n },\n status: 400,\n };\n }\n return http.request(\n \"PUT\",\n `/v1/user-flags/users/${encodeURIComponent(uid)}/${encodeURIComponent(key)}`,\n { body: { value } },\n );\n },\n\n asService() {\n return service;\n },\n };\n}\n","/**\n * notifications.ts — push, email, SMS, verifications, inbox, preferences and\n * the two template surfaces.\n *\n * Moved in from `v2/runtime/internal/runtime/module-clients.js:1180-1379`.\n *\n * The theme of this file is a NAME GAP: the SDK speaks camelCase and palnotify\n * speaks snake_case, and every place they meet is a place a field can be\n * dropped in silence. One of them cost a live afternoon — `email.send({ html })`\n * was forwarded verbatim, palnotify reads `html_body`, and the answer was a 400\n * about a field the caller had supplied. The mappings below are that lesson,\n * and they are now checked against the declared parameter types instead of\n * being hand-carried across a package boundary.\n */\n\nimport type {\n PalbaseEmailClient,\n PalbaseEmailTemplate,\n PalbaseEmailTemplatesClient,\n PalbaseInboxClient,\n PalbaseNotificationsClient,\n PalbasePreferencesClient,\n PalbasePushClient,\n PalbaseSMSTemplate,\n PalbaseSMSTemplatesClient,\n PalbaseSmsClient,\n PalbaseVerificationsClient,\n} from \"../clients.js\";\nimport type { PalbaseResult } from \"../endpoint.js\";\nimport type { ModuleTransport } from \"./http.js\";\n\n/** Re-map the data of a SUCCESSFUL envelope; errors pass through untouched. */\nfunction mapEnvelope<In, Out>(res: PalbaseResult<In>, map: (data: In) => Out): PalbaseResult<Out> {\n if (res.error !== null || res.data === null || res.data === undefined) {\n return { data: null, error: res.error, status: res.status };\n }\n return { data: map(res.data), error: null, status: res.status };\n}\n\ntype Wire = Record<string, unknown>;\n\nfunction toEmailTemplate(wire: Wire): PalbaseEmailTemplate {\n const view: PalbaseEmailTemplate = {\n id: wire.id as string,\n slug: wire.slug as string,\n locale: wire.locale as string,\n subject: wire.subject as string,\n htmlBody: wire.html_body as string,\n variables: (wire.variables as string[]) ?? [],\n isDefault: wire.is_default as boolean,\n createdAt: wire.created_at as string,\n updatedAt: wire.updated_at as string,\n };\n if (wire.text_body !== undefined) view.textBody = wire.text_body as string;\n return view;\n}\n\nfunction toSmsTemplate(wire: Wire): PalbaseSMSTemplate {\n return {\n id: wire.id as string,\n slug: wire.slug as string,\n locale: wire.locale as string,\n body: wire.body as string,\n variables: (wire.variables as string[]) ?? [],\n isDefault: wire.is_default as boolean,\n createdAt: wire.created_at as string,\n updatedAt: wire.updated_at as string,\n };\n}\n\nexport function buildNotificationsClient(http: ModuleTransport): PalbaseNotificationsClient {\n const push: PalbasePushClient = {\n async send(params) {\n return http.request(\"POST\", \"/v1/notifications/push\", { body: params });\n },\n };\n\n const email: PalbaseEmailClient = {\n async send(params) {\n // `html`/`text` are what the SDK declares; palnotify reads\n // `html_body`/`text_body`. Forwarding them verbatim answered 400 about a\n // field the caller HAD supplied — live on todoapp, 2026-07-30.\n const { templateSlug, html, text, ...rest } = params;\n const body: Record<string, unknown> = { ...rest };\n if (templateSlug !== undefined) body.template_slug = templateSlug;\n if (html !== undefined) body.html_body = html;\n if (text !== undefined) body.text_body = text;\n return http.request(\"POST\", \"/v1/notifications/email\", { body });\n },\n };\n\n const sms: PalbaseSmsClient = {\n async send(params) {\n const { templateSlug, ...rest } = params;\n const body = templateSlug !== undefined ? { ...rest, template_slug: templateSlug } : rest;\n return http.request(\"POST\", \"/v1/notifications/sms\", { body });\n },\n };\n\n // Phone verification (OTP). Separate from sms.send on purpose: there is no\n // body here — the provider generates the code and the message text itself.\n const verifications: PalbaseVerificationsClient = {\n async start(params) {\n return http.request(\"POST\", \"/v1/notifications/verifications\", { body: params });\n },\n async check(params) {\n return http.request(\"POST\", \"/v1/notifications/verifications/check\", { body: params });\n },\n };\n\n const inbox: PalbaseInboxClient = {\n async send(params) {\n return http.request(\"POST\", \"/v1/notifications/inbox\", { body: params });\n },\n async list(options?: {\n cursor?: string;\n limit?: number;\n is_read?: boolean;\n category?: string;\n include_archived?: boolean;\n }) {\n const opts = options ?? {};\n const params = new URLSearchParams();\n if (opts.cursor) params.set(\"cursor\", opts.cursor);\n if (opts.limit !== undefined) params.set(\"limit\", String(opts.limit));\n if (opts.is_read !== undefined) params.set(\"is_read\", opts.is_read ? \"true\" : \"false\");\n if (opts.category) params.set(\"category\", opts.category);\n if (opts.include_archived) params.set(\"include_archived\", \"true\");\n const query = params.toString();\n return http.request(\"GET\", `/v1/notifications/inbox${query ? `?${query}` : \"\"}`);\n },\n async unreadCount() {\n return http.request(\"GET\", \"/v1/notifications/inbox/unread-count\");\n },\n async markRead(id: string) {\n return http.request(\"PATCH\", `/v1/notifications/inbox/${encodeURIComponent(id)}/read`);\n },\n async markAllRead() {\n return http.request(\"POST\", \"/v1/notifications/inbox/read-all\");\n },\n async archive(id: string) {\n return http.request(\"DELETE\", `/v1/notifications/inbox/${encodeURIComponent(id)}`);\n },\n };\n\n const preferences: PalbasePreferencesClient = {\n async get() {\n return http.request(\"GET\", \"/v1/notifications/preferences\");\n },\n async update(params) {\n return http.request(\"PUT\", \"/v1/notifications/preferences\", { body: params });\n },\n };\n\n const emailTemplates: PalbaseEmailTemplatesClient = {\n async list() {\n const resp = await http.request<Wire[]>(\"GET\", \"/v1/notifications/templates\");\n return mapEnvelope(resp, (rows) => (rows ?? []).map(toEmailTemplate));\n },\n async get(id: string) {\n const resp = await http.request<Wire>(\n \"GET\",\n `/v1/notifications/templates/${encodeURIComponent(id)}`,\n );\n return mapEnvelope(resp, toEmailTemplate);\n },\n async create(input: { slug: string; subject: string; htmlBody: string; textBody?: string; variables?: string[] }) {\n const body: Record<string, unknown> = {\n slug: input.slug,\n subject: input.subject,\n html_body: input.htmlBody,\n };\n if (input.textBody !== undefined) body.text_body = input.textBody;\n if (input.variables !== undefined) body.variables = input.variables;\n const resp = await http.request<Wire>(\"POST\", \"/v1/notifications/templates\", { body });\n return mapEnvelope(resp, toEmailTemplate);\n },\n async update(\n id: string,\n input: { subject?: string; htmlBody?: string; textBody?: string; variables?: string[] },\n ) {\n const body: Record<string, unknown> = {};\n if (input.subject !== undefined) body.subject = input.subject;\n if (input.htmlBody !== undefined) body.html_body = input.htmlBody;\n if (input.textBody !== undefined) body.text_body = input.textBody;\n if (input.variables !== undefined) body.variables = input.variables;\n const resp = await http.request<Wire>(\n \"PUT\",\n `/v1/notifications/templates/${encodeURIComponent(id)}`,\n { body },\n );\n return mapEnvelope(resp, toEmailTemplate);\n },\n async delete(id: string) {\n return http.request(\"DELETE\", `/v1/notifications/templates/${encodeURIComponent(id)}`);\n },\n };\n\n const smsTemplates: PalbaseSMSTemplatesClient = {\n async list() {\n const resp = await http.request<Wire[]>(\"GET\", \"/v1/notifications/sms-templates\");\n return mapEnvelope(resp, (rows) => (rows ?? []).map(toSmsTemplate));\n },\n async get(id: string) {\n const resp = await http.request<Wire>(\n \"GET\",\n `/v1/notifications/sms-templates/${encodeURIComponent(id)}`,\n );\n return mapEnvelope(resp, toSmsTemplate);\n },\n async create(input: { slug: string; body: string; variables?: string[] }) {\n const body: Record<string, unknown> = { slug: input.slug, body: input.body };\n if (input.variables !== undefined) body.variables = input.variables;\n const resp = await http.request<Wire>(\"POST\", \"/v1/notifications/sms-templates\", { body });\n return mapEnvelope(resp, toSmsTemplate);\n },\n async update(id: string, input: { body?: string; variables?: string[] }) {\n const body: Record<string, unknown> = {};\n if (input.body !== undefined) body.body = input.body;\n if (input.variables !== undefined) body.variables = input.variables;\n const resp = await http.request<Wire>(\n \"PUT\",\n `/v1/notifications/sms-templates/${encodeURIComponent(id)}`,\n { body },\n );\n return mapEnvelope(resp, toSmsTemplate);\n },\n async delete(id: string) {\n return http.request(\"DELETE\", `/v1/notifications/sms-templates/${encodeURIComponent(id)}`);\n },\n };\n\n return {\n push,\n email,\n sms,\n verifications,\n inbox,\n preferences,\n templates: { email: emailTemplates, sms: smsTemplates },\n async registerDevice(params) {\n return http.request(\"POST\", \"/v1/notifications/devices\", { body: params });\n },\n async unregisterDevice(deviceId: string) {\n return http.request(\"DELETE\", `/v1/notifications/devices/${encodeURIComponent(deviceId)}`);\n },\n };\n}\n","/**\n * realtime.ts — broadcast, and only broadcast.\n *\n * Moved in from `v2/runtime/internal/runtime/module-clients.js:811-883`.\n *\n * There is no `subscribe()` here, deliberately: a backend handler answers one\n * request and ends, so there is no honest place to hold a long-lived socket.\n * Subscription lives in the client SDKs; this side pushes.\n *\n * The V1 host/executor branch is GONE. It existed so an isolate could delegate\n * the secret-bearing token mint to a host that held the credential — and the\n * isolate was removed on 2026-08-14. A single-tenant process has nobody to hide\n * its own tenant's key from.\n */\n\nimport { createHmac } from \"node:crypto\";\n\nimport type { PalbaseRealtimeClient } from \"../clients.js\";\nimport { PalbaseModuleError } from \"./http.js\";\n\nexport interface RealtimeConfig {\n baseUrl: string;\n /**\n * The shared Realtime API secret. Empty means realtime is not provisioned for\n * this environment, and broadcast says so by name rather than failing oddly.\n */\n apiJwtSecret: string;\n /** Resolved at CALL time — see the note in http.ts. */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * A short-lived HS256 token Realtime's broadcast pipeline accepts.\n *\n * It needs a valid signature and a future `exp`, nothing more — this is a\n * service-to-service hop inside the stack, not a user session.\n */\nfunction mintToken(secret: string): string {\n const now = Math.floor(Date.now() / 1000);\n const header = Buffer.from(JSON.stringify({ alg: \"HS256\", typ: \"JWT\" })).toString(\"base64url\");\n const payload = Buffer.from(\n JSON.stringify({ iss: \"backend-runtime\", role: \"service_role\", iat: now, exp: now + 60 }),\n ).toString(\"base64url\");\n const sig = createHmac(\"sha256\", secret).update(`${header}.${payload}`).digest(\"base64url\");\n return `${header}.${payload}.${sig}`;\n}\n\nexport function buildRealtimeClient(cfg: RealtimeConfig): PalbaseRealtimeClient {\n const url = `${cfg.baseUrl}/realtime/api/broadcast`;\n const stateUrl = `${cfg.baseUrl}/realtime/api/state`;\n\n /** One state write or clear. Same credential, same fire-and-forget contract\n * as broadcast: a handler that wrote a row must not lose it because the\n * pubsub layer was unreachable. */\n async function writeState(\n topic: string,\n key: string,\n value: Record<string, unknown> | undefined,\n del: boolean,\n ) {\n if (typeof topic !== \"string\" || topic.length === 0) {\n return {\n data: null,\n error: new PalbaseModuleError(\"invalid_argument\", \"topic must be a non-empty string\", 400),\n };\n }\n if (typeof key !== \"string\" || key.length === 0) {\n return {\n data: null,\n error: new PalbaseModuleError(\"invalid_argument\", \"key must be a non-empty string\", 400),\n };\n }\n if (!cfg.apiJwtSecret) {\n return {\n data: null,\n error: new PalbaseModuleError(\n \"realtime_unconfigured\",\n \"Realtime.state is unavailable: realtime is not provisioned for this Environment \" +\n \"(PALBASE_REALTIME_API_JWT_SECRET unset).\",\n 503,\n ),\n };\n }\n\n let token: string;\n try {\n token = mintToken(cfg.apiJwtSecret);\n } catch (err) {\n return {\n data: null,\n error: new PalbaseModuleError(\n \"realtime_token_error\",\n err instanceof Error ? err.message : \"token mint failed\",\n 500,\n ),\n };\n }\n\n const op = del ? { topic, key, del: true } : { topic, key, value: value ?? {} };\n const doFetch = cfg.fetchImpl ?? globalThis.fetch;\n let response: Response;\n try {\n response = await doFetch(stateUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Authorization: `Bearer ${token}` },\n body: JSON.stringify({ ops: [op] }),\n });\n } catch (err) {\n return {\n data: null,\n error: new PalbaseModuleError(\n \"network_error\",\n err instanceof Error ? err.message : \"state request failed\",\n 0,\n ),\n };\n }\n if (response.status === 202 || response.status === 200) {\n return { data: undefined, error: null };\n }\n const detail = await response.text().catch(() => \"\");\n return {\n data: null,\n error: new PalbaseModuleError(\n \"realtime_state_failed\",\n `realtime state write returned ${response.status}${detail ? `: ${detail}` : \"\"}`,\n response.status,\n ),\n };\n }\n\n return {\n state: {\n /** Write one DURABLE entry on a channel's shared state.\n *\n * The difference from broadcast is WHO it reaches: a broadcast reaches\n * whoever is listening at that instant, while state is also handed to\n * whoever joins afterwards. \"This value is now X\" wants the second — a\n * client connecting a second later should not have to wait for the next\n * change to learn X. */\n set: (topic: string, key: string, value: Record<string, unknown>) =>\n writeState(topic, key, value, false),\n /** Remove one entry. */\n clear: (topic: string, key: string) => writeState(topic, key, undefined, true),\n },\n\n async broadcast(channel: string, event: string, payload?: Record<string, unknown>) {\n // Cheap argument checks first, locally: a bad call gets an answer without\n // spending a round trip to be told the obvious.\n if (typeof channel !== \"string\" || channel.length === 0) {\n return {\n data: null,\n error: new PalbaseModuleError(\"invalid_argument\", \"channel must be a non-empty string\", 400),\n };\n }\n if (typeof event !== \"string\" || event.length === 0) {\n return {\n data: null,\n error: new PalbaseModuleError(\"invalid_argument\", \"event must be a non-empty string\", 400),\n };\n }\n if (!cfg.apiJwtSecret) {\n return {\n data: null,\n error: new PalbaseModuleError(\n \"realtime_unconfigured\",\n \"Realtime.broadcast is unavailable: realtime is not provisioned for this Environment \" +\n \"(PALBASE_REALTIME_API_JWT_SECRET unset).\",\n 503,\n ),\n };\n }\n\n let token: string;\n try {\n token = mintToken(cfg.apiJwtSecret);\n } catch (err) {\n return {\n data: null,\n error: new PalbaseModuleError(\n \"realtime_token_error\",\n err instanceof Error ? err.message : \"token mint failed\",\n 500,\n ),\n };\n }\n\n // The BARE sub-topic. Realtime prepends \"realtime:\" on delivery, and a\n // pre-prefixed topic double-prefixes and is silently dropped — proven live.\n const body = JSON.stringify({\n messages: [{ topic: channel, event, payload: payload ?? {}, private: false }],\n });\n\n const doFetch = cfg.fetchImpl ?? globalThis.fetch;\n let response: Response;\n try {\n response = await doFetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Authorization: `Bearer ${token}` },\n body,\n });\n } catch (err) {\n // FIRE AND FORGET: a handler that wrote a row and then broadcast must\n // not lose the row because the pubsub layer was unreachable. This is the\n // one client that answers with an envelope on a network failure rather\n // than throwing, and it is why.\n return {\n data: null,\n error: new PalbaseModuleError(\n \"network_error\",\n err instanceof Error ? err.message : \"broadcast request failed\",\n 0,\n ),\n };\n }\n\n if (response.status === 202 || response.status === 200) {\n return { data: undefined, error: null };\n }\n\n const detail = await response.text().catch(() => \"\");\n return {\n data: null,\n error: new PalbaseModuleError(\n \"realtime_broadcast_failed\",\n `broadcast returned ${response.status}: ${detail.slice(0, 200)}`,\n response.status,\n ),\n };\n },\n };\n}\n","/**\n * storage.ts — the Storage client.\n *\n * Moved in from `v2/runtime/internal/runtime/module-clients.js:474-589`. That\n * code addressed the native Supabase Storage wire under `/storage/v1` until\n * 2026-08-15, when it was repointed at this stack's own module — measured\n * against the live stack, where the old path answers 404 and the new one 200.\n * It arrives here so the SHAPE it returns and the type that declares that shape\n * are checked against each other: they were not, and the type spent a major\n * version describing another server's columns.\n */\n\nimport type {\n PalbaseBucketClient,\n PalbaseFileObject,\n PalbaseListOptions,\n PalbaseSignedUrlResponse,\n PalbaseStorageClient,\n PalbaseUploadOptions,\n} from \"../clients.js\";\nimport type { PalbaseResult } from \"../endpoint.js\";\nimport type { ModuleTransport } from \"./http.js\";\n\n/** What the platform accepts as a bucket name (schema: `^[a-z][a-z0-9-]{1,62}$`). */\nconst BUCKET_NAME_RE = /^[a-zA-Z0-9_-]+$/;\n/** What the platform accepts as an object path. */\nconst STORAGE_PATH_RE = /^[a-zA-Z0-9_./-]+$/;\nconst STORAGE_TRAVERSAL_RE = /(?:^|\\/)\\.\\.(?:\\/|$)/;\n\n/**\n * Refused HERE, before any request.\n *\n * A traversing path is a programming mistake, and the useful moment to hear\n * about it is the call that made it — not a 400 three layers away.\n */\nfunction validateStoragePath(p: string): void {\n if (!STORAGE_PATH_RE.test(p) || STORAGE_TRAVERSAL_RE.test(p)) {\n throw new Error(\n `Invalid file path: \"${p}\". Paths must not contain traversal sequences and must match ${STORAGE_PATH_RE.source}`,\n );\n }\n}\n\n/**\n * The wire's own shape, mapped onto what this package declares.\n *\n * v2's storage answers in camelCase with the variants and the thumbhash already\n * in it, so this maps rather than translates. The snake_case unwrapping that\n * used to live here (`metadata.mimetype`, `bucket_id`, `created_at`) belonged to\n * a different server, and reading those names off this wire produced an object\n * whose size was 0 and whose content type was \"\".\n */\nfunction toFileObject(bucket: string, row: Record<string, unknown>): PalbaseFileObject {\n return {\n name: (row.path as string) ?? \"\",\n path: (row.path as string) ?? \"\",\n bucket: (row.bucket as string) ?? bucket,\n size: typeof row.size === \"number\" ? row.size : 0,\n contentType: (row.contentType as string) ?? \"\",\n checksum: (row.checksum as string) ?? \"\",\n width: row.width as number | undefined,\n height: row.height as number | undefined,\n thumbhash: row.thumbhash as string | undefined,\n variants: (row.variants as Record<string, string>) ?? {},\n };\n}\n\n/** Re-map the data of a SUCCESSFUL envelope; pass errors through untouched. */\nfunction mapResponse<In, Out>(\n res: PalbaseResult<In>,\n map: (data: In) => Out,\n): PalbaseResult<Out> {\n if (res.error || res.data === null || res.data === undefined) {\n return { data: null, error: res.error, status: res.status };\n }\n return { data: map(res.data), error: null, status: res.status };\n}\n\nfunction buildBucketClient(\n http: ModuleTransport,\n bucketName: string,\n publicOrigin: string,\n): PalbaseBucketClient {\n const objectPath = (path: string) => `/v1/storage/object/${bucketName}/${path}`;\n\n return {\n async upload(path, file, options?: PalbaseUploadOptions) {\n validateStoragePath(path);\n const headers: Record<string, string> = {\n \"Content-Type\": options?.contentType ?? \"application/octet-stream\",\n };\n if (options?.upsert) headers[\"x-upsert\"] = \"true\";\n // The BYTES, as the body. Storage sniffs the content and decides for\n // itself what this is; the declared type is a hint it may overrule,\n // because a name and a header are both things a caller can be wrong about.\n const body = file instanceof ArrayBuffer ? new Uint8Array(file) : file;\n const res = await http.request<Record<string, unknown>>(\"PUT\", objectPath(path), {\n body,\n headers,\n });\n return mapResponse(res, (r) => toFileObject(bucketName, r ?? {}));\n },\n\n async download(path) {\n validateStoragePath(path);\n // The AUTHENTICATED read: the project already holds a credential this\n // stack verified, so it does not have to mint a signature to open its own\n // object — and this route serves private buckets, which the public one\n // refuses on purpose.\n return http.request<Blob>(\"GET\", objectPath(path), { headers: { Accept: \"*/*\" } });\n },\n\n getPublicUrl(path, options) {\n validateStoragePath(path);\n const variant = options?.variant ? `?variant=${encodeURIComponent(options.variant)}` : \"\";\n // ABSOLUTE — and the origin is a value the stack is TOLD, not the\n // transport's baseUrl.\n //\n // Those are two different addresses and conflating them is how this broke\n // once already: the transport points at palsvc over the loopback\n // (`http://127.0.0.1:8080`), and a URL built from it resolves nowhere\n // outside the pod. So this used to return the path alone.\n //\n // The path alone is not a smaller answer, it is a wrong one. A public URL\n // LEAVES the response body — into an <img>, an email, another app on\n // another host — and none of those have a base to resolve it against.\n // Measured live 24.08.2026: an iOS client handed the returned\n // `/v1/files/post-images/…` straight to URLSession and got\n // NSURLErrorUnsupportedURL (-1002). The upload had worked; only the URL\n // was unusable.\n //\n // `PALBASE_PUBLIC_ORIGIN` is set by whoever publishes the stack, because\n // only they know it: in the cloud the operator writes\n // `https://<ref>.<domain>`, and a self-hosted stack carries whatever\n // domain its certificate is for.\n if (!publicOrigin) {\n // NAMED, not silent — the same doctrine as the other unconfigured\n // modules in engine/config.ts (\"throw a named error on first use rather\n // than silently no-op\"). A returned path would pass every test here and\n // fail in the one place nobody is watching.\n throw new Error(\n `Storage.bucket(\"${bucketName}\").getPublicUrl() needs this stack's public origin, ` +\n \"and it was not configured. Set PALBASE_PUBLIC_ORIGIN to the address clients reach \" +\n \"this stack at (e.g. https://myproject.palbase.studio).\",\n );\n }\n return `${publicOrigin}/v1/files/${bucketName}/${path}${variant}`;\n },\n\n async createSignedUrl(path, options): Promise<PalbaseResult<PalbaseSignedUrlResponse>> {\n validateStoragePath(path);\n // A DURATION — `{ expiresIn: \"1h\" }`. A bare number is ambiguous between\n // seconds and minutes at every call site that reads it, and the ambiguity\n // is only discovered when a link outlives the object it opened.\n return http.request<PalbaseSignedUrlResponse>(\"POST\", `/v1/storage/sign/${bucketName}/${path}`, {\n body: { expiresIn: options.expiresIn },\n });\n },\n\n async list(prefix?: string, options?: PalbaseListOptions) {\n if (prefix) validateStoragePath(prefix);\n const params = new URLSearchParams();\n if (prefix) params.set(\"prefix\", prefix);\n if (options?.limit !== undefined) params.set(\"limit\", String(options.limit));\n const query = params.toString();\n const res = await http.request<{ objects?: Record<string, unknown>[] }>(\n \"GET\",\n `/v1/storage/bucket/${bucketName}${query ? `?${query}` : \"\"}`,\n );\n // `{objects: [...]}`, not a bare array: the envelope leaves room for the\n // paging this will grow, and unwrapping it here keeps that off callers.\n return mapResponse(res, (body) => (body?.objects ?? []).map((row) => toFileObject(bucketName, row)));\n },\n\n async remove(paths) {\n for (const p of paths) validateStoragePath(p);\n // One request per object: the module deletes an object WITH its variants,\n // and a batch endpoint reporting partial success would need a result shape\n // nobody would read. The first refusal ends it — continuing would report a\n // partial delete as a whole one.\n const removed: PalbaseFileObject[] = [];\n for (const p of paths) {\n const res = await http.request<void>(\"DELETE\", objectPath(p));\n if (res.error) return { data: null, error: res.error, status: res.status };\n removed.push(toFileObject(bucketName, { path: p }));\n }\n return { data: removed, error: null, status: 200 };\n },\n\n async move(from, to) {\n validateStoragePath(from);\n validateStoragePath(to);\n return http.request<void>(\"POST\", `/v1/storage/move/${bucketName}`, { body: { from, to } });\n },\n\n async copy(from, to) {\n validateStoragePath(from);\n validateStoragePath(to);\n return http.request<void>(\"POST\", `/v1/storage/copy/${bucketName}`, { body: { from, to } });\n },\n };\n}\n\n/**\n * @param publicOrigin the address CLIENTS reach this stack at — never the\n * transport's base, which is this process's internal route to palsvc. Empty\n * means it was not configured, and `getPublicUrl` refuses by name.\n */\nexport function buildStorageClient(\n http: ModuleTransport,\n publicOrigin: string,\n): PalbaseStorageClient {\n return {\n bucket(name: string) {\n if (!BUCKET_NAME_RE.test(name)) {\n throw new Error(`Invalid bucket name: \"${name}\". Bucket names must match ${BUCKET_NAME_RE.source}`);\n }\n // Sondaki eğik çizgi BURADA kırpılır: `${origin}/v1/files/...` iki\n // eğik çizgiyle biten bir yol üretirdi ve bazı sunucular onu ayrı bir\n // nesne sayar.\n return buildBucketClient(http, name, publicOrigin.replace(/\\/+$/, \"\"));\n },\n };\n}\n","/**\n * clients/index.ts — the composition root for the module clients.\n *\n * This is what the process calls once at boot. It builds the five clients the\n * engine injects and nothing else.\n *\n * WHAT IS NOT BUILT HERE, and why each one is absent rather than forgotten:\n *\n * - `auth`, `functions`, `analytics`, `links` — the SDK exports no singleton\n * for any of them (`runtime.ts` exports ten, and these four are not among\n * them), so no handler could reach them. They were constructed on every\n * boot and thrown away.\n * - `Purchases` — its client talked to palstore, and v2 contains no palstore\n * at all. The surface was unbacked before it was untyped. Dropped from v2\n * by the user's decision on 2026-08-15, with the SDK's `src/purchases/`\n * tree left in place because that decision was \"deferred, not silently\n * taken\". It is taken now: the tree is GONE (2026-08-29), because a\n * decorator standing in front of a service nothing serves is the same\n * defect as `Resource` and `config/*`, which went with it.\n * - The V1 host/executor transport — the isolate it existed for was removed\n * on 2026-08-14. A single-tenant process has nobody to hide its own\n * tenant's credentials from.\n */\n\nimport type { ModuleClients } from \"../engine/index.js\";\nimport { buildDocumentsClient } from \"./documents.js\";\nimport { buildFlagsClient } from \"./flags.js\";\nimport { makeHttpClient } from \"./http.js\";\nimport { buildNotificationsClient } from \"./notifications.js\";\nimport { buildRealtimeClient } from \"./realtime.js\";\nimport { buildStorageClient } from \"./storage.js\";\n\nexport interface ModuleClientsConfig {\n /** Where the platform answers. Empty means \"not configured\" — see below. */\n baseUrl: string;\n /** The publishable key. Used only when no service-role key is supplied. */\n apiKey: string;\n /**\n * The service-role key, which is what a backend actually holds. Preferred\n * over `apiKey`: this process IS the project's server.\n */\n serviceRoleKey: string;\n /** The shared Realtime secret. Empty means realtime is not provisioned. */\n realtimeApiJwtSecret: string;\n /**\n * The address CLIENTS reach this stack at. Used ONLY to build public object\n * URLs; every request this bundle makes still goes over `baseUrl`.\n */\n publicOrigin: string;\n /** The request's user, read from the SDK's own scope — never from a caller. */\n getCurrentUserId: () => string | null;\n /** Injected in tests; resolved at call time in production. */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * Build the module clients.\n *\n * Returns an EMPTY bundle when there is no base URL, deliberately: the engine\n * then injects its named stubs, so a handler that reaches for `Storage` gets an\n * error saying which module is unconfigured rather than a crash reading a\n * property of undefined. Booting is not blocked — a project that never touches\n * a module runs fine without one.\n */\nexport function buildModuleClients(cfg: ModuleClientsConfig): ModuleClients {\n const baseUrl = (cfg.baseUrl || \"\").replace(/\\/+$/, \"\");\n if (!baseUrl) return {};\n\n // The service-role key when present: this process is the project's own\n // server, and the publishable key would refuse half of what it needs.\n const apiKey = cfg.serviceRoleKey || cfg.apiKey || \"\";\n const http = makeHttpClient({ baseUrl, apiKey, fetchImpl: cfg.fetchImpl });\n\n return {\n Documents: buildDocumentsClient(http),\n Storage: buildStorageClient(http, cfg.publicOrigin),\n Notifications: buildNotificationsClient(http),\n Flags: buildFlagsClient(http, { getCurrentUserId: cfg.getCurrentUserId }),\n Realtime: buildRealtimeClient({\n baseUrl,\n apiJwtSecret: cfg.realtimeApiJwtSecret,\n fetchImpl: cfg.fetchImpl,\n }),\n };\n}\n","// The wire shape of a declared schema — what the deploy reads.\n//\n// `defineSchema(...)` produces a value full of builders and phantom types, which\n// is the right shape for authoring and the wrong shape for anything outside this\n// process. The deploy is Go: it introspects the live database, diffs it against\n// the declaration, and applies the difference. So the declaration has to leave\n// TypeScript as data, and this file is where that happens.\n//\n// It lives in the SDK because the SDK owns the DSL. The alternative — a script\n// beside the deploy that reaches into `._def` — is a second reading of a private\n// shape, and it drifts the moment a column gains a property: the DSL keeps\n// working, the emitter silently omits it, and the database is missing something\n// nobody can see in the source.\n//\n// The field names below are a CONTRACT with Go's `schema.SchemaJSON`. Renaming\n// one here without renaming it there produces a declaration that parses to\n// something emptier than it was — the failure mode being a column, a policy, or\n// a whole table that quietly never gets created.\nimport type { ColumnBuilder, ColumnDef } from \"./columns.js\";\nimport type { PolicyDef } from \"./policy.js\";\nimport type { MemoryDecl, SchemaDef, SearchDecl, TableDef } from \"./schema.js\";\n\n/** One column, flattened. Mirrors Go's `schema.ColumnJSON`. */\nexport interface ColumnJSON {\n type: string;\n nullable: boolean;\n primaryKey: boolean;\n defaultValue?: unknown;\n defaultRandom?: boolean;\n defaultNow?: boolean;\n renamedFrom?: string;\n references?: { table: string; column: string };\n onDeleteAction?: string;\n enumName?: string;\n enumValues?: string[];\n unique?: boolean;\n dimensions?: number;\n}\n\n/** One RLS policy. Mirrors Go's `schema.PolicyJSON`. */\nexport interface PolicyJSON {\n name: string;\n command: string;\n roles: string[];\n using: string | null;\n withCheck: string | null;\n permissive: boolean;\n}\n\n/** One table. Mirrors Go's `schema.TableJSON`. */\nexport interface TableJSON {\n name: string;\n columns: Record<string, ColumnJSON>;\n rls: boolean;\n policies: PolicyJSON[];\n primaryKey?: string[];\n uniqueConstraints?: { name: string; columns: string[] }[];\n rawConstraints?: { name: string; up: string; down: string | null }[];\n checks?: { name: string; expr: string }[];\n indexes?: { name: string; columns: string[] }[];\n search?: SearchJSON;\n memory?: MemoryJSON;\n}\n\n/** C-11 wire şekli — Go'nun MemoryJSON'ıyla alan-adı sözleşmesi (D-019).\n * Beyansız tablolarda alan OMIT — eski şemalar bayt-aynı (NFR-B1). */\nexport interface MemoryJSON {\n from: string[];\n into: string;\n subject?: string;\n extract: { provider: string; model: string };\n}\n\n/** A whole declaration. Mirrors Go's `schema.SchemaJSON`. */\nexport interface SchemaJSON {\n tables: Record<string, TableJSON>;\n extensions: string[];\n}\n\n/** The definition behind a column, whichever side of the builder it arrives on. */\nfunction defOf(column: ColumnBuilder | ColumnDef): ColumnDef {\n return \"_def\" in column ? column._def : column;\n}\n\nfunction columnToJSON(column: ColumnBuilder | ColumnDef): ColumnJSON {\n const def = defOf(column);\n const out: ColumnJSON = {\n type: def.type,\n nullable: def.nullable,\n primaryKey: def.primaryKey,\n };\n // Every optional field is omitted rather than emitted as undefined: Go\n // distinguishes \"absent\" from \"present and empty\" on several of these, and a\n // `defaultValue: null` is a real default that says NULL.\n if (def.defaultValue !== undefined) out.defaultValue = def.defaultValue;\n if (def.defaultRandom === true) out.defaultRandom = true;\n if (def.defaultNow === true) out.defaultNow = true;\n if (def.renamedFrom !== undefined) out.renamedFrom = def.renamedFrom;\n if (def.references !== undefined) {\n out.references = { table: def.references.table, column: def.references.column };\n }\n if (def.onDeleteAction !== undefined) out.onDeleteAction = def.onDeleteAction;\n if (def.enumName !== undefined) out.enumName = def.enumName;\n if (def.enumValues !== undefined) out.enumValues = [...def.enumValues];\n if (def.unique === true) out.unique = true;\n if (def.dimensions !== undefined) out.dimensions = def.dimensions;\n return out;\n}\n\nfunction policyToJSON(policy: PolicyDef): PolicyJSON {\n return {\n name: policy.name,\n command: policy.command ?? \"all\",\n roles: policy.roles ? [...policy.roles] : [],\n // null rather than omitted: a policy with no USING clause is a different\n // thing from one whose clause the emitter forgot, and Go reads the\n // difference.\n using: policy.using ?? null,\n withCheck: policy.withCheck ?? null,\n permissive: policy.permissive !== false,\n };\n}\n\n/** C-4 wire şekli — Go'nun SearchJSON'ıyla ALAN ADI sözleşmesi (C-5).\n * `mode`/`chunks` yalnız yeni-biçim chunk-modunda emit edilir (D-010);\n * satır-modu ve eski biçim bayt-aynı kalır (NFR-B1). */\nexport interface SearchJSON {\n text?: { columns: string[] };\n vector?: {\n column?: string;\n metric: string;\n embed?: { provider: string; model: string; from: string[]; apiKeyName?: string; dimensions?: number; baseURL?: string };\n staleness?: \"null\" | \"keep\";\n mode?: \"row\" | \"chunks\";\n chunks?: { sizeChars?: number; overlapChars?: number };\n }[];\n /** FR-026: sorgu-yeniden-yazımı haritası — beyan yoksa OMIT (NFR-B1). */\n synonyms?: Record<string, string[]>;\n /** C-1: sonuç yeniden-sıralama beyanı — beyan yoksa OMIT. */\n /** FR-029: geçerlilik türevleri — beyan yoksa OMIT. */\n validity?: boolean;\n}\n\n/** T020 (C-1): iki biçimin de üst-düzey ortak alanları — beyan yoksa OMIT,\n * boş synonyms haritası da OMIT (NFR-B1 baytları kımıldamaz). */\nfunction commonSearchFields(search: SearchDecl, out: SearchJSON): void {\n if (search.synonyms !== undefined && Object.keys(search.synonyms).length > 0) {\n out.synonyms = Object.fromEntries(\n Object.entries(search.synonyms).map(([word, alts]) => [word, [...alts]]),\n );\n }\n if (search.validity === true) out.validity = true;\n}\n\n/** Beyanı normalize eder: vector her zaman DİZİ, metric her zaman dolu (vars. cosine),\n * authoring'deki `from`/`model` wire'da `embed` altında toplanır. Alan yoksa OMIT —\n * search'süz şema bayt-aynı kalır (NFR-006). */\nfunction searchToJSON(search: SearchDecl, vectorColumn: string | undefined): SearchJSON {\n if (search.from !== undefined && search.model !== undefined) {\n // YENİ biçim (D-007): from tek listedir — FTS'i de embed'i de besler.\n // Mod ŞEMADAN türer (D-010): tabloda vector kolonu varsa satır-modu\n // (column yazılır, mode OMIT — eski davranışla aynı wire), yoksa\n // chunk-modu (mode:\"chunks\", column yok — vektörler türev tabloda).\n const out: SearchJSON = {};\n const textCols =\n search.text === false ? undefined : Array.isArray(search.text) && search.text.length > 0 ? search.text : search.from;\n if (textCols !== undefined) out.text = { columns: [...textCols] };\n const v: NonNullable<SearchJSON[\"vector\"]>[number] = { metric: search.metric ?? \"cosine\" };\n if (vectorColumn !== undefined) v.column = vectorColumn;\n v.embed = {\n provider: search.model.provider,\n model: search.model.model,\n from: [...search.from],\n ...(search.model.apiKeyName !== undefined ? { apiKeyName: search.model.apiKeyName } : {}),\n ...(search.model.dimensions !== undefined ? { dimensions: search.model.dimensions } : {}),\n ...(search.model.baseURL !== undefined ? { baseURL: search.model.baseURL } : {}),\n };\n if (search.staleness !== undefined) v.staleness = search.staleness;\n if (vectorColumn === undefined) {\n v.mode = \"chunks\";\n if (search.chunks !== undefined) {\n const c: NonNullable<typeof v.chunks> = {};\n if (search.chunks.size !== undefined && search.chunks.size > 0) c.sizeChars = search.chunks.size;\n if (search.chunks.overlap !== undefined && search.chunks.overlap > 0) c.overlapChars = search.chunks.overlap;\n if (Object.keys(c).length > 0) v.chunks = c;\n }\n }\n out.vector = [v];\n commonSearchFields(search, out);\n return out;\n }\n const out: SearchJSON = {};\n // Eski biçimde text yalnız dizi olabilir (boolean'ı defineSchema zaten\n // reddediyor); Array.isArray hem tipi daraltır hem o sözleşmeyi belgeler.\n if (Array.isArray(search.text) && search.text.length > 0) out.text = { columns: [...search.text] };\n const legs = search.vector === undefined ? []\n : Array.isArray(search.vector) ? search.vector : [search.vector];\n if (legs.length > 0) {\n out.vector = legs.map((leg) => {\n const v: NonNullable<SearchJSON[\"vector\"]>[number] = { metric: leg.metric ?? \"cosine\" };\n if (leg.column !== undefined) v.column = leg.column;\n if (leg.staleness !== undefined) v.staleness = leg.staleness;\n if (leg.model !== undefined) {\n v.embed = {\n provider: leg.model.provider,\n model: leg.model.model,\n from: [...(leg.from ?? [])],\n ...(leg.model.apiKeyName !== undefined ? { apiKeyName: leg.model.apiKeyName } : {}),\n ...(leg.model.dimensions !== undefined ? { dimensions: leg.model.dimensions } : {}),\n ...(leg.model.baseURL !== undefined ? { baseURL: leg.model.baseURL } : {}),\n };\n }\n return v;\n });\n }\n commonSearchFields(search, out);\n return out;\n}\n\nfunction memoryToJSON(m: MemoryDecl): MemoryJSON {\n return {\n from: [...m.from],\n into: m.into,\n ...(m.subject !== undefined ? { subject: m.subject } : {}),\n extract: { provider: m.extract.provider, model: m.extract.model },\n };\n}\n\nfunction tableToJSON(table: TableDef): TableJSON {\n const columns: Record<string, ColumnJSON> = {};\n for (const [name, column] of Object.entries(table.columns)) {\n columns[name] = columnToJSON(column);\n }\n\n const out: TableJSON = {\n name: table.name,\n columns,\n // Read, not re-derived. `defineSchema` already resolves the fail-closed\n // default (RLS on unless the author wrote `rls: false`, and forced on by any\n // policy), and a second copy of a SECURITY default is exactly the thing that\n // drifts — the direction it drifted last time was \"expose everything\", and\n // the live proof was one user reading another's rows.\n rls: table.rls,\n policies: (table.policies ?? []).map(policyToJSON),\n };\n\n if (table.primaryKey !== undefined && table.primaryKey.length > 0) {\n out.primaryKey = [...table.primaryKey];\n }\n if (table.unique !== undefined && table.unique.length > 0) {\n out.uniqueConstraints = table.unique.map((u) => ({ name: u.name, columns: [...u.columns] }));\n }\n if (table.raw !== undefined && table.raw.length > 0) {\n out.rawConstraints = table.raw.map((r) => ({\n name: r.name,\n up: r.up,\n down: r.down ?? null,\n }));\n }\n if (table.checks !== undefined && table.checks.length > 0) {\n out.checks = table.checks.map((c) => ({ name: c.name, expr: c.expr }));\n }\n if (table.indexes !== undefined && table.indexes.length > 0) {\n out.indexes = table.indexes.map((i) => ({ name: i.name, columns: [...i.columns] }));\n }\n if (table.search !== undefined) {\n // D-010 mod kararının tek girdisi: tabloda dimensions'lı (vector) kolon\n // adı. Birden çoksa ilkini yazmak YANLIŞ olurdu — o durum eski biçimin\n // işidir ve yeni biçim + çoklu vector kolonu apply'da reddedilir.\n const vectorColumn = Object.entries(columns).find(([, c]) => c.dimensions !== undefined)?.[0];\n const sj = searchToJSON(table.search, vectorColumn);\n if (sj.text !== undefined || sj.vector !== undefined) out.search = sj;\n }\n if (table.memory !== undefined) {\n out.memory = memoryToJSON(table.memory);\n }\n return out;\n}\n\n/**\n * Serialize a `defineSchema(...)` result into the JSON the deploy applies.\n *\n * Keyed by the SQL table name rather than by the author's object key, because\n * that is the name the live database answers to — and the diff on the other side\n * compares against what it introspected.\n */\nexport function toSchemaJSON(schema: SchemaDef): SchemaJSON {\n const tables: Record<string, TableJSON> = {};\n for (const table of Object.values(schema.tables)) {\n const json = tableToJSON(table);\n tables[json.name] = json;\n }\n return { tables, extensions: [...new Set(schema.extensions ?? [])] };\n}\n","/**\n * channels.ts — the realtime channel authorization DSL (spec C-5).\n *\n * `defineChannels({...})` is evaluated at bundle load; the declaration is\n * anchored on globalThis under Symbol.for (the error-registry.ts pattern) so\n * the runtime — a separate module instance — reads the SAME object. The runtime\n * empties that slot before each bundle import and puts it back afterwards, so\n * the declaration belongs to the bundle that made it and not to the process.\n * Entry ORDER is the object's key order and is semantic: first match wins.\n *\n * Undeclared channels are DENIED by the server (fail-closed). ownerOnly()\n * patterns resolve with ZERO server hops; custom entries' authorize() runs\n * in the customer's own runtime with the request scope a controller gets.\n */\n\nconst CHANNELS: unique symbol = Symbol.for(\"palbase.backend.channels\") as never;\n\nexport interface ChannelGrant {\n subscribe: boolean;\n publish?: boolean;\n state?: { read?: boolean; write?: boolean };\n}\n\nexport interface ChannelAuthorizeCtx {\n user: { id: string };\n params: Record<string, string>;\n}\n\ninterface OwnerEntry { kind: \"owner\" }\ninterface PublicEntry {\n kind: \"public\";\n publish?: boolean;\n state?: { read?: boolean; write?: boolean };\n}\n/** What a handler receives: who published, on which channel, and what. */\nexport interface ChannelHandlerCtx {\n user: { id: string };\n params: Record<string, string>;\n channel: string;\n event: string;\n payload: Record<string, unknown>;\n}\n\ninterface CustomEntry {\n authorize: (ctx: ChannelAuthorizeCtx) => ChannelGrant | null | Promise<ChannelGrant | null>;\n /**\n * Take over publishes on this channel instead of fanning them out.\n *\n * Without it, `channel.send(...)` is relayed to the other subscribers\n * verbatim — fine for a chat message, wrong for anything the client should\n * not be trusted to assert. A bid, a vote, a game move is a REQUEST, and the\n * result is whatever this function decides and then publishes (through\n * `Realtime.broadcast` or `Realtime.state.set`).\n *\n * A function rather than the name of a route: `authorize` is already one and\n * runs in this same scope, so naming an endpoint would mean inventing a\n * resolution step for no gain.\n */\n handler?: (ctx: ChannelHandlerCtx) => void | Promise<void>;\n}\nexport type ChannelEntry = OwnerEntry | PublicEntry | CustomEntry;\nexport type ChannelsInput = Record<string, ChannelEntry>;\n\nexport interface ChannelsDef {\n entries: Array<{\n pattern: string;\n kind: \"owner\" | \"public\" | \"custom\";\n publish?: boolean;\n state?: { read?: boolean; write?: boolean };\n authorize?: CustomEntry[\"authorize\"];\n handler?: CustomEntry[\"handler\"];\n }>;\n}\n\n/** Full-access-to-the-owner pattern: the pattern must carry EXACTLY one {param};\n * the server compares its value to the verified token subject with zero hops. */\nexport function ownerOnly(): OwnerEntry {\n return { kind: \"owner\" };\n}\n\n/** Anyone with a valid token may subscribe; publish/state are explicit opt-ins. */\nexport function publicChannel(\n opts: { publish?: boolean; state?: { read?: boolean; write?: boolean } } = {},\n): PublicEntry {\n return { kind: \"public\", publish: opts.publish ?? false, state: opts.state };\n}\n\nfunction paramCount(pattern: string): number {\n return pattern.split(\":\").filter((s) => s.startsWith(\"{\") && s.endsWith(\"}\")).length;\n}\n\nexport function defineChannels(map: ChannelsInput): ChannelsDef {\n const entries: ChannelsDef[\"entries\"] = [];\n for (const [pattern, entry] of Object.entries(map)) {\n if (\"kind\" in entry && entry.kind === \"owner\") {\n if (paramCount(pattern) !== 1) {\n throw new Error(\n `defineChannels: ownerOnly() pattern \"${pattern}\" must carry exactly one {param} ` +\n `(its value is compared to the token subject)`,\n );\n }\n entries.push({ pattern, kind: \"owner\" });\n } else if (\"kind\" in entry && entry.kind === \"public\") {\n entries.push({ pattern, kind: \"public\", publish: entry.publish, state: entry.state });\n } else {\n const c = entry as CustomEntry;\n entries.push({ pattern, kind: \"custom\", authorize: c.authorize, handler: c.handler });\n }\n }\n const def: ChannelsDef = { entries };\n\n // A SECOND, DIFFERENT declaration is a hard error rather than an overwrite.\n //\n // The same bundle can legitimately be evaluated twice in one process — the\n // error registry beside this file documents exactly that case — so an\n // identical re-declaration passes silently. But two DIFFERENT declarations\n // mean two channels files, and overwriting would delete the first one's\n // channels. Undeclared channels are DENIED, so the symptom would be joins\n // refused in production for channels the developer can see declared in their\n // own source, with nothing anywhere saying why. Loud here beats silent there.\n //\n // \"Already\" means WITHIN ONE BUNDLE LOAD. The runtime hands each import an\n // empty slot, so this compares two calls from the same bundle — which is what\n // it was written for. It used to reach across imports as well, and then a\n // deploy that merely ADDED a channel was refused as a second channels file,\n // with a message pointing at a file the customer did not have.\n const carrier = globalThis as Record<symbol, unknown>;\n const existing = carrier[CHANNELS] as ChannelsDef | undefined;\n if (existing && !sameDeclaration(existing, def)) {\n throw new Error(\n `defineChannels: channels were already declared (${existing.entries.length} ` +\n `pattern(s): ${existing.entries.map((e) => e.pattern).join(\", \")}). ` +\n `A project declares its channels ONCE — a second call would overwrite the ` +\n `first, and channels nobody declared are refused.`,\n );\n }\n carrier[CHANNELS] = def;\n return def;\n}\n\n/**\n * One entry as the runtime will compile it, rendered for comparison.\n *\n * NORMALIZED, because the runtime normalizes: `collectChannels` applies\n * `?? false` to publish and both state flags before the table goes on the wire.\n * Comparing the raw entries called two spellings of ONE entry a conflict —\n * `publicChannel()` fills `publish: false` where a hand-written\n * `{ kind: \"public\" }` leaves it undefined, and the two produce a byte-identical\n * table. There is one source of truth for what an entry IS, and it is the row.\n *\n * The authorize function is compared by SOURCE TEXT. Comparing the closures\n * themselves is wrong — two evaluations of one module produce two distinct\n * functions for the same source, which is the case this guard has to let\n * through — but comparing only `Boolean(fn)` called two unrelated\n * authorization rules \"the same declaration\", so the guard stayed silent while\n * one channel's access rule was swapped for another's. Same source, same text;\n * different logic, different text. Not exhaustive (two closures over different\n * captured values share a source), and better than a boolean by the whole\n * distance between \"some rule\" and \"this rule\".\n */\nfunction wireRow(e: ChannelsDef[\"entries\"][number]): string {\n return JSON.stringify([\n e.pattern,\n e.kind,\n e.publish ?? false,\n e.state?.read ?? false,\n e.state?.write ?? false,\n // The handler is compared by SOURCE, like authorize: two evaluations of one\n // module give the same text, while different logic gives different text.\n e.handler ? e.handler.toString() : \"\",\n e.authorize ? e.authorize.toString() : \"\",\n ]);\n}\n\n/** Two declarations are the same when they compile to the same rows in the same\n * ORDER — order is semantic here (first match wins). */\nfunction sameDeclaration(a: ChannelsDef, b: ChannelsDef): boolean {\n if (a.entries.length !== b.entries.length) return false;\n return a.entries.every((x, i) => wireRow(x) === wireRow(b.entries[i]!));\n}\n","/**\n * env-gen.ts — generate the `palbase-env.d.ts` text from a `defineSchema()`\n * result.\n *\n * The CLI (`palbase build`) and the deploy pipeline call\n * {@link makeEnvDts} with the project's schema and write the returned string to\n * `palbase-env.d.ts` at the project root. That file AUGMENTS the\n * `@palbase/backend/env` `Tables` interface (controlled global augmentation,\n * C5) so `Database.tables.<name>` is typed with no import and no generic.\n *\n * The output is FLAT: each table gets a `{ row: {...}; insert: {...} }` entry\n * with plain TypeScript object types. The phantom `ColumnBuilder<...>` type\n * NEVER appears in the generated `.d.ts` — that type only lives at authoring\n * time inside `db/schema.ts`.\n */\n\nimport type { ColumnDef } from \"./columns.js\";\nimport type { SchemaDef, TableDef } from \"./schema.js\";\n\n/** The TypeScript value type for a column, ignoring nullability (added by the\n * caller). Mirrors the `ColValue` mapped type in columns.ts exactly. */\nfunction baseTsType(def: ColumnDef): string {\n switch (def.type) {\n case \"uuid\":\n case \"text\":\n case \"timestamp\":\n return \"string\";\n case \"integer\":\n return \"number\";\n // Both are exact-precision in Postgres and lossy as a JSON number, so the\n // database proxy serializes them as strings — measured: 9007199254740993\n // used to arrive as ...992 and 41.00821234567890123 as 41.0082123456789.\n // numeric had no case at all and fell through to `unknown`, which typed\n // every numeric column out of existence.\n case \"bigint\":\n case \"numeric\":\n return \"string\";\n case \"boolean\":\n return \"boolean\";\n case \"jsonb\":\n return \"unknown\";\n // FR-008: the authoring type of a pgvector column. The default `unknown`\n // branch below STAYS — an unknown wire type is refused on the Go side\n // (FR-005), never papered over here.\n case \"vector\":\n return \"number[]\";\n case \"enum\": {\n const values = def.enumValues ?? [];\n if (values.length === 0) return \"string\";\n return values.map((v) => JSON.stringify(v)).join(\" | \");\n }\n default:\n return \"unknown\";\n }\n}\n\n/** The full row type for a column: base type, `| null` when nullable. */\nfunction rowType(def: ColumnDef): string {\n const base = baseTsType(def);\n return def.nullable ? `${base} | null` : base;\n}\n\n/** True when a column may be omitted on INSERT — nullable OR has any default.\n * Mirrors `ColIsOptionalOnInsert` in columns.ts. */\nfunction optionalOnInsert(def: ColumnDef): boolean {\n return (\n def.nullable === true ||\n def.defaultRandom === true ||\n def.defaultNow === true ||\n def.defaultValue !== undefined\n );\n}\n\n/** The table a foreign key must target for its column to be the OWNER column —\n * what `.referencesAuthUser(...)` writes into `ColumnDef.references.table`. */\nconst AUTH_USERS_TABLE = \"auth.users\";\n\n/**\n * The table's owner column: the one that foreign-keys `auth.users`, i.e. the\n * column a row is \"owned by\". Declared in `db/schema.ts` via\n * `.referencesAuthUser(...)` — we read the declaration rather than parsing the\n * RLS policy body, because the FK IS the ownership statement.\n *\n * When several columns reference `auth.users` (e.g. `user_id` and `created_by`)\n * the FIRST in declaration order wins — deterministic, and the remaining ones\n * stay ordinary writable columns.\n */\nfunction ownerColumnOf(table: TableDef): string | null {\n for (const [col, builder] of Object.entries(table.columns)) {\n if (builder._def.references?.table === AUTH_USERS_TABLE) return col;\n }\n return null;\n}\n\n/** One FK edge: `child.column` points at the parent table this edge hangs off. */\ntype ChildEdge = { child: string; column: string };\n\n/**\n * Collect the raw parent → children FK edges across the schema.\n *\n * Only edges between tables IN this schema participate — a reference to\n * `auth.users` / `auth.installations` (or any table the project doesn't\n * declare) has no parent bucket and is skipped. Self-FKs are skipped outright.\n *\n * A child that references the same parent through TWO columns is recorded once,\n * on the first column in declaration order: `children` maps a child table to a\n * single FK column, and the second FK stays an ordinary writable column.\n */\nfunction buildChildEdges(schema: SchemaDef): Map<string, ChildEdge[]> {\n const edges = new Map<string, ChildEdge[]>();\n for (const name of Object.keys(schema.tables)) edges.set(name, []);\n\n for (const childName of Object.keys(schema.tables)) {\n const table = schema.tables[childName];\n if (table === undefined) continue;\n for (const [col, builder] of Object.entries(table.columns)) {\n const ref = builder._def.references;\n if (ref === undefined) continue;\n if (ref.table === childName) continue; // self-FK\n const bucket = edges.get(ref.table);\n if (bucket === undefined) continue; // targets a table outside this schema\n if (bucket.some((e) => e.child === childName)) continue; // already linked\n bucket.push({ child: childName, column: col });\n }\n }\n return edges;\n}\n\n/**\n * Drop cycle back-edges from the FK graph.\n *\n * `children` feeds a RECURSIVE type in the seed/fixture DSL\n * (`SeedRow<T>` expands each child's own `children`). A cycle — `lists → todos`\n * plus `todos → lists` through a second FK — would make that type infinite\n * (\"Type instantiation is excessively deep\"). So we walk the graph depth-first\n * in declaration order and drop any edge pointing back at a table currently on\n * the DFS stack. Cross-edges into an already-FINISHED subtree are KEPT: they\n * re-expand a finite subtree, which terminates.\n *\n * Declaration order makes the choice of which edge to drop deterministic (the\n * generated .d.ts is golden-tested).\n */\nfunction pruneCycles(raw: Map<string, ChildEdge[]>): Map<string, ChildEdge[]> {\n const pruned = new Map<string, ChildEdge[]>();\n for (const table of raw.keys()) pruned.set(table, []);\n const state = new Map<string, \"visiting\" | \"done\">();\n\n function visit(table: string): void {\n state.set(table, \"visiting\");\n for (const edge of raw.get(table) ?? []) {\n if (state.get(edge.child) === \"visiting\") continue; // back-edge → drop\n pruned.get(table)?.push(edge);\n if (state.get(edge.child) === undefined) visit(edge.child);\n }\n state.set(table, \"done\");\n }\n\n for (const table of raw.keys()) {\n if (state.get(table) === undefined) visit(table);\n }\n return pruned;\n}\n\n/** Emit the `row` / `insert` / `owner` / `children` blocks for one table at the\n * given base indentation. */\nfunction tableBlock(table: TableDef, children: ChildEdge[], indent: string): string {\n const cols = Object.entries(table.columns);\n const rowLines = cols.map(([col, builder]) => {\n return `${indent} ${col}: ${rowType(builder._def)};`;\n });\n const insertLines = cols.map(([col, builder]) => {\n const def = builder._def;\n const opt = optionalOnInsert(def) ? \"?\" : \"\";\n return `${indent} ${col}${opt}: ${rowType(def)};`;\n });\n const owner = ownerColumnOf(table);\n const childEntries = children\n .map((e) => `${JSON.stringify(e.child)}: ${JSON.stringify(e.column)}`)\n .join(\"; \");\n return [\n `${indent}${table.name}: {`,\n `${indent} row: {`,\n ...rowLines,\n `${indent} };`,\n `${indent} insert: {`,\n ...insertLines,\n `${indent} };`,\n `${indent} owner: ${owner === null ? \"null\" : JSON.stringify(owner)};`,\n `${indent} children: {${childEntries === \"\" ? \"\" : ` ${childEntries} `}};`,\n // searchable: vector kolonu YA DA search beyanı → EnvTypedTable'da search()\n // üyesini açan yapısal bayrak (FR-013). Yokken satır hiç üretilmez ki\n // mevcut şemaların d.ts'i bayt-aynı kalsın.\n ...(cols.some(([, b]) => b._def.type === \"vector\") || table.search !== undefined\n ? [`${indent} searchable: true;`]\n : []),\n `${indent}};`,\n ].join(\"\\n\");\n}\n\n/**\n * Generate the full `palbase-env.d.ts` text for a schema.\n *\n * @example\n * import { makeEnvDts } from \"@palbase/backend\";\n * import schema from \"./db/schema.js\";\n * writeFileSync(\"palbase-env.d.ts\", makeEnvDts(schema));\n */\nexport function makeEnvDts(schema: SchemaDef): string {\n const tableNames = Object.keys(schema.tables);\n const children = pruneCycles(buildChildEdges(schema));\n const blocks = tableNames.map((name) =>\n tableBlock(schema.tables[name]!, children.get(name) ?? [], \" \"),\n );\n const body = blocks.length > 0 ? `\\n${blocks.join(\"\\n\")}\\n ` : \"\";\n return `// AUTO-GENERATED by @palbase/backend — DO NOT EDIT.\n// Regenerated from db/schema.ts by \\`palbase build\\` and by every deploy.\n// Augments the @palbase/backend/env \\`Tables\\` interface so \\`Database.tables.*\\`\n// is typed with no import and no generic.\n\ndeclare module \"@palbase/backend/env\" {\n interface Tables {${body}}\n}\n\nexport {};\n`;\n}\n","/**\n * stack-gen.ts — generate the `palbase-stack.d.ts` text from the names the\n * linked environment's stack holds.\n *\n * The twin of `db/env-gen.ts`: the CLI calls\n * {@link makeStackDts} with the three name sets it read off the stack and\n * writes the result to `palbase-stack.d.ts` at the project root. That file\n * augments the `@palbase/backend/stack` interfaces, so `Secrets.get(...)`, the\n * Flags client and `@Upload({ bucket })` accept the project's real names and\n * nothing else.\n *\n * The generator does NOT reach the network and does NOT decide what a name is:\n * it renders what it is handed. The stack is the authority on which names exist\n * (`GET /v1/management/secrets`, `/flags`, `/storage/buckets`); re-deciding that\n * here would be a second, weaker copy of it.\n *\n * The emitted file ends in `export {};` — same as `makeEnvDts` and\n * `makePurchasesDts`. Without it the `.d.ts` is a global script, and\n * `declare module \"…\"` there DECLARES an ambient module (shadowing the real one,\n * so every name silently becomes invalid) instead of AUGMENTING it.\n */\n\n/** The three name sets read off the stack. Order is irrelevant — each set is\n * sorted here so the same stack always renders the same bytes and a diff shows\n * what CHANGED rather than how the API happened to order its answer. */\n/** One bucket and the renditions it declares. */\nexport interface BucketInput {\n name: string;\n variants: readonly string[];\n}\n\nexport interface StackNames {\n /** Secret names from the project's vault. */\n secrets: readonly string[];\n /** Flag keys from the project's flag store. */\n flags: readonly string[];\n /**\n * Buckets from the project's storage — a bare name, or a name with the\n * renditions it declares.\n *\n * A bucket is not only a NAME: `Storage.buckets.docs.getPublicUrl(p, {\n * variant })` refuses a rendition the bucket does not have, so the variant\n * union has to travel with it. The bare-string form is shorthand for \"no\n * variants\", which renders `never` and accepts none.\n */\n buckets: readonly (string | BucketInput)[];\n}\n\n/** Sorted, de-duplicated names. A stack that reports one twice (two pages of a\n * listing overlapping, say) must not render a duplicate member — TypeScript\n * accepts it, but the file stops being a function of the stack's contents. */\nfunction liveNames(names: readonly string[]): string[] {\n return [...new Set(names)].sort();\n}\n\n/** A bare identifier stays bare; anything else is quoted. Bucket names carry\n * dashes and dots (the Storage module's allowed shape), and an unquoted\n * `my-bucket` parses as a subtraction rather than a member name. */\nfunction memberName(name: string): string {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);\n}\n\nfunction members(names: string[]): string {\n if (names.length === 0) return \"\";\n return `\\n${names.map((n) => ` ${memberName(n)}: true;`).join(\"\\n\")}\\n `;\n}\n\n/** Buckets render a SHAPE rather than a marker, because each carries its variant\n * union. `never` for a bucket with none: the type then accepts no variant name\n * at all, which is exactly what a bucket without renditions offers. */\nfunction bucketMembers(buckets: readonly (string | BucketInput)[]): string {\n const normalized = buckets.map((b) => (typeof b === \"string\" ? { name: b, variants: [] as readonly string[] } : b));\n const byName = new Map<string, readonly string[]>();\n for (const b of normalized) byName.set(b.name, b.variants);\n const names = [...byName.keys()].sort();\n if (names.length === 0) return \"\";\n const rows = names.map((name) => {\n const variants = [...new Set(byName.get(name) ?? [])].sort();\n const union = variants.length === 0 ? \"never\" : variants.map((v) => JSON.stringify(v)).join(\" | \");\n return ` ${memberName(name)}: { variants: ${union} };`;\n });\n return `\\n${rows.join(\"\\n\")}\\n `;\n}\n\n/**\n * Render the project's `palbase-stack.d.ts`.\n *\n * An empty set renders an empty interface, which is a MEANINGFUL value: the\n * stack holds no such names, so the corresponding union is `never` and every\n * call spelling one fails to compile. It is not the same as \"the file was never\n * generated\" only in that the file exists — both states refuse every name, and\n * both are correct.\n */\nexport function makeStackDts(names: StackNames): string {\n const secrets = liveNames(names.secrets);\n const flags = liveNames(names.flags);\n\n\n return `// palbase-stack.d.ts — GENERATED by @palbase/backend. Do not edit.\n// Source: the linked environment's stack.\n\ndeclare module \"@palbase/backend/stack\" {\n interface Secrets {${members(secrets)}}\n\n interface Flags {${members(flags)}}\n\n interface Buckets {${bucketMembers(names.buckets)}}\n}\n\nexport {};\n`;\n}\n","// Method decorators: `@Get` / `@Post` / `@Put` / `@Patch` / `@Delete` /\n// `@Query` declare a route (verb + subpath + options) on a controller method. These are LEGACY\n// method decorators (`experimentalDecorators`), receiving\n// `(prototype, methodName, descriptor)`. They write into the per-class registry\n// (registry.ts). The success-response schema is NOT declared here: it is derived\n// from the method's RETURN TYPE by a codegen step and injected onto the route at\n// runtime via `recordReturn` (registry.ts).\nimport {\n recordRoute,\n type HttpMethodUpper,\n type RouteOptions,\n} from \"./registry.js\";\n\n/** A legacy method decorator. */\ntype MethodDecorator = (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n) => void;\n\n/** Build a method decorator for one HTTP verb. The decorated method's name is\n * the route `fnName` — and it is PUBLIC API, not authoring sugar: the runtime\n * derives the operationId as `<controllerName>.<fnName>` (the dotted namespace\n * the SDKs expose as `pb.todos.list()`), so renaming this method renames every\n * client call. The flat verb+path id is only the fallback for routes with no\n * controller metadata. See openapi/discover.ts. */\nfunction makeMethodDecorator(method: HttpMethodUpper) {\n return function (subpath: string, options: RouteOptions = {}): MethodDecorator {\n // Runtime guard for stale pre-9.0.0 code: `@Query(zodSchema)` used to be\n // the query-string PARAM decorator. Applied against this SDK it would\n // silently record a garbage route (schema-as-subpath) and fail the deploy\n // with a baffling self-conflict — fail loud and name the migration instead.\n if (typeof subpath !== \"string\") {\n throw new Error(\n `@${method[0]}${method.slice(1).toLowerCase()}(subpath) expects a string subpath, got ${typeof subpath}.` +\n (method === \"QUERY\"\n ? \" If this is a zod schema on a method parameter: the query-string param decorator was renamed @QueryParams(schema) in @palbase/backend 9.0.0.\"\n : \"\"),\n );\n }\n return function (target, propertyKey) {\n recordRoute(target, String(propertyKey), method, subpath, options);\n };\n };\n}\n\n/** `@Get(subpath, options?)` — declare a GET route. */\nexport const Get = makeMethodDecorator(\"GET\");\n/** `@Post(subpath, options?)` — declare a POST route. */\nexport const Post = makeMethodDecorator(\"POST\");\n/** `@Put(subpath, options?)` — declare a PUT route. */\nexport const Put = makeMethodDecorator(\"PUT\");\n/** `@Patch(subpath, options?)` — declare a PATCH route. */\nexport const Patch = makeMethodDecorator(\"PATCH\");\n/** `@Delete(subpath, options?)` — declare a DELETE route. */\nexport const Delete = makeMethodDecorator(\"DELETE\");\n/** `@Query(subpath, options?)` — declare an HTTP QUERY route (RFC 10008):\n * safe + idempotent like GET, body-carrying like POST. Input rides `@Body`. */\nexport const Query = makeMethodDecorator(\"QUERY\");\n","// @Webhook / @On — the inbound-webhook half of the decorator surface.\n//\n// Mirrors decorators/controller.ts exactly: symbol-keyed, non-enumerable\n// metadata on the constructor plus a `__palbase` discriminant, read back by a\n// resolver. The resolver is the ONLY translation point — it returns the shape\n// the runtime already consumes, so the isolate's dispatch and the signature\n// engine's cross-binding golden are untouched by the authoring change.\nimport type { WebhookMeta, WebhookProvider } from \"../webhook.js\";\n\n/** A signature scheme spelled out, for a service with no preset. The presets\n * (`provider`) are named configurations of this same shape. */\nexport interface SignatureSpec {\n /** Header carrying the signature. */\n header: string;\n /** Stripped before comparison (e.g. `sha256=`). Omit when absent. */\n prefix?: string;\n algo: \"hmac-sha256\" | \"hmac-sha1\";\n encoding: \"hex\" | \"base64\";\n /** What the HMAC covers. Exactly two placeholders: `{body}` and `{ts}`.\n * Everything else is literal. `{ts}` requires `timestampHeader` and brings\n * the five-minute replay window with it. */\n signs: string;\n timestampHeader?: string;\n}\n\nexport interface WebhookOptions {\n provider?: WebhookProvider;\n signature?: SignatureSpec;\n /** Env-var REFERENCE for the signing secret — the platform never holds it. */\n secret: { env: string };\n}\n\nexport type WebhookEventHandler = (event: unknown, meta: WebhookMeta) => Promise<void>;\n\nexport interface ResolvedWebhook {\n provider?: WebhookProvider;\n signature?: SignatureSpec;\n secret: { env: string };\n events: Record<string, WebhookEventHandler>;\n}\n\nexport const WEBHOOK_META: unique symbol = Symbol.for(\"palbase.backend.webhookMeta\");\nexport const WEBHOOK_EVENTS: unique symbol = Symbol.for(\"palbase.backend.webhookEvents\");\n\ninterface EventEntry {\n event: string;\n fnName: string;\n}\n\ninterface WebhookCarrier {\n __palbase?: \"webhook\";\n [WEBHOOK_META]?: WebhookOptions;\n [WEBHOOK_EVENTS]?: EventEntry[];\n}\n\nfunction carrierOf(ctor: object): WebhookCarrier {\n return ctor as WebhookCarrier;\n}\n\n/** Mark a class as an inbound webhook. The mount name is the FILE name — there\n * is deliberately no `name` option, because the file name IS the public URL. */\nexport function Webhook(options: WebhookOptions) {\n return function <T extends abstract new (...args: never[]) => object>(ctor: T): T {\n const carrier = carrierOf(ctor);\n Object.defineProperty(carrier, WEBHOOK_META, {\n value: options,\n enumerable: false,\n configurable: true,\n writable: false,\n });\n Object.defineProperty(carrier, \"__palbase\", {\n value: \"webhook\",\n enumerable: false,\n configurable: true,\n writable: false,\n });\n return ctor;\n };\n}\n\n/** Bind a method to one event name. Any string is valid: presets provide\n * autocomplete, never a constraint, because we do not carry provider catalogs. */\nexport function On(event: string) {\n return function (target: object, fnName: string | symbol): void {\n // Method decorators receive the PROTOTYPE; metadata belongs on the ctor.\n const carrier = carrierOf((target as { constructor: object }).constructor);\n const existing = carrier[WEBHOOK_EVENTS];\n const entries: EventEntry[] = existing ? [...existing] : [];\n entries.push({ event, fnName: String(fnName) });\n Object.defineProperty(carrier, WEBHOOK_EVENTS, {\n value: entries,\n enumerable: false,\n configurable: true,\n writable: false,\n });\n };\n}\n\n/** Read a decorated class back as the resolved config the runtime consumes.\n * Every misuse throws HERE, at build time, rather than becoming a webhook that\n * answers 200 and does nothing. */\nexport function getWebhookConfig(ctor: object): ResolvedWebhook {\n const carrier = carrierOf(ctor);\n const meta = carrier[WEBHOOK_META];\n const entries = carrier[WEBHOOK_EVENTS] ?? [];\n\n if (!meta) {\n throw new Error(\n `@On used on a class that is not decorated with @Webhook (${(ctor as { name?: string }).name ?? \"anonymous\"})`,\n );\n }\n if (!meta.provider && !meta.signature) {\n throw new Error(\n \"@Webhook requires either a `provider` preset or an explicit `signature` — \" +\n \"an endpoint with no verification would accept forged deliveries\",\n );\n }\n // EITHER, not both. The isolate picks `provider` when both are present and\n // never looks at `signature`, so a tenant that wrote both gets deliveries\n // verified against a scheme they did not choose — silently, and with no way to\n // tell from the outside which one ran. Ambiguity about WHICH signature check\n // guards an endpoint is not something to resolve by precedence.\n if (meta.provider && meta.signature) {\n throw new Error(\n \"@Webhook declares BOTH a `provider` preset and an explicit `signature` — \" +\n \"these are alternatives; keep the one that describes the sender, because only `provider` would be used\",\n );\n }\n if (meta.signature) {\n const sig = meta.signature;\n // Mirrors Go's NewTemplateVerifier (internal/webhook/verify.go). Both sides\n // reject the same specs; this one rejects at build, which is the only place\n // a tenant can still act on it.\n if (!sig.header) {\n throw new Error(\"@Webhook signature requires `header` — the header the signature arrives in\");\n }\n if (sig.algo !== \"hmac-sha256\" && sig.algo !== \"hmac-sha1\") {\n throw new Error(`@Webhook signature has an unsupported algo \"${sig.algo}\"`);\n }\n if (sig.encoding !== \"hex\" && sig.encoding !== \"base64\") {\n throw new Error(`@Webhook signature has an unsupported encoding \"${sig.encoding}\"`);\n }\n if (!sig.signs?.includes(\"{body}\")) {\n throw new Error(\"@Webhook signature `signs` must contain {body} — signing a constant is not a signature\");\n }\n if (sig.signs.includes(\"{ts}\") && !sig.timestampHeader) {\n throw new Error(\"@Webhook signature uses {ts} but declares no `timestampHeader` to read it from\");\n }\n }\n if (!meta.secret?.env) {\n throw new Error(\"@Webhook requires `secret: { env: \\\"VAR_NAME\\\" }`\");\n }\n if (entries.length === 0) {\n throw new Error(\"@Webhook requires at least one @On handler\");\n }\n\n const instance = new (ctor as new () => Record<string, WebhookEventHandler>)();\n // Object.create(null), not {} — event names are free-form, so `@On(\"constructor\")`\n // and `@On(\"toString\")` are legal. A plain literal inherits those keys from\n // Object.prototype, and the duplicate check below would reject the FIRST and\n // only handler for them as a redeclaration.\n const events: Record<string, WebhookEventHandler> = Object.create(null) as Record<string, WebhookEventHandler>;\n for (const entry of entries) {\n if (Object.prototype.hasOwnProperty.call(events, entry.event)) {\n throw new Error(`@On(\"${entry.event}\") declared twice on the same webhook`);\n }\n events[entry.event] = (event, metaArg) =>\n (instance[entry.fnName] as WebhookEventHandler).call(instance, event, metaArg);\n }\n\n return {\n ...(meta.provider ? { provider: meta.provider } : {}),\n ...(meta.signature ? { signature: meta.signature } : {}),\n secret: meta.secret,\n events,\n };\n}\n","// @Hook — the BLOCKING half of the internal-event surface.\n//\n// Two axes decide which decorator a handler wants. Where does the event come\n// from, and can the handler stop it?\n//\n// @Webhook + @On an OUTSIDE service (Stripe, GitHub…) — cannot block\n// @Hook an event this stack raised — CAN block: `throw` cancels it\n// @On an event this stack raised — listens only, a monitor\n//\n// The blocking power lives in the NAME `@Hook`, not in the method decorator's\n// shape, which is why `@On` keeps meaning \"listener\" in both worlds and needs\n// no change. `@Upload` is the same pattern already shipped: the storage module\n// calls the tenant's method, and a method that answers 4xx discards the object\n// and hands its exact status, body and content-type back to the client.\n//\n// Mirrors decorators/webhook.ts: symbol-keyed, non-enumerable metadata on the\n// constructor, read back by one resolver. The resolver is the only translation\n// point, so the runtime consumes a shape the authoring surface never leaks.\nimport type { HookMeta } from \"../hooks.js\";\nimport { WEBHOOK_EVENTS } from \"./webhook.js\";\n\n/** A hook handler. Returning quietly ALLOWS; throwing DENIES (blocking hooks). */\nexport type HookFn = (event: unknown, meta: HookMeta) => Promise<unknown>;\n\nexport interface ResolvedHookClass {\n /** `@Hook` handlers, by event. A throw here cancels the operation. */\n blocking: Record<string, HookFn>;\n /** `@On` handlers, by event. A throw here reaches nobody but the log. */\n listeners: Record<string, HookFn>;\n}\n\n/** A hook's refusal, with the reason the caller will see.\n *\n * Any thrown error denies — this class exists so the REASON travels as a\n * deliberate message rather than as whatever a stray TypeError happened to say.\n * The engine is fail-closed by design (an unreachable hook denies), so a hook\n * body should stay narrow: an accidental throw refuses a real user. */\nexport class Deny extends Error {\n constructor(reason: string) {\n super(reason);\n this.name = \"Deny\";\n }\n}\n\nexport const HOOK_BLOCKING: unique symbol = Symbol.for(\"palbase.backend.hookBlocking\");\n\ninterface EventEntry {\n event: string;\n fnName: string;\n}\n\n/** `@Hook(\"before.user.create\")` — a blocking handler for one stack event. */\nexport function Hook(event: string) {\n return function (target: object, fnName: string | symbol): void {\n const carrier = (target as { constructor: object }).constructor as Record<symbol, unknown>;\n const existing = carrier[HOOK_BLOCKING] as EventEntry[] | undefined;\n const entries: EventEntry[] = existing ? [...existing] : [];\n entries.push({ event, fnName: String(fnName) });\n Object.defineProperty(carrier, HOOK_BLOCKING, {\n value: entries,\n enumerable: false,\n configurable: true,\n writable: false,\n });\n };\n}\n\n/** Binds one decorator's entries onto a single instance of the class.\n *\n * ONE instance for the whole class, built here rather than per call: a hook\n * that opens a client or reads a list in its constructor would otherwise pay\n * for it on every signup. */\nfunction bind(instance: Record<string, HookFn>, entries: EventEntry[], kind: string) {\n const out: Record<string, HookFn> = Object.create(null) as Record<string, HookFn>;\n for (const entry of entries) {\n if (Object.prototype.hasOwnProperty.call(out, entry.event)) {\n throw new Error(`${kind}(\"${entry.event}\") declared twice on the same hook class`);\n }\n // Resolved ONCE, here, so a decorator naming a method that does not exist\n // fails at build time with the name in the message — rather than at the\n // first signup, as \"instance[fnName] is not a function\".\n const fn = instance[entry.fnName];\n if (typeof fn !== \"function\") {\n throw new Error(`${kind}(\"${entry.event}\") names no method \"${entry.fnName}\" on the class`);\n }\n out[entry.event] = (event, meta) => fn.call(instance, event, meta);\n }\n return out;\n}\n\n/** Resolves a hook class into the two maps the runtime dispatches from.\n *\n * Every misuse throws HERE, at build time, rather than becoming a hook that is\n * silently never called — the failure mode this whole change exists to end. */\nexport function getHookConfig(ctor: object): ResolvedHookClass {\n const carrier = ctor as Record<symbol, unknown>;\n const blockingEntries = (carrier[HOOK_BLOCKING] ?? []) as EventEntry[];\n const listenerEntries = (carrier[WEBHOOK_EVENTS] ?? []) as EventEntry[];\n\n if (blockingEntries.length === 0 && listenerEntries.length === 0) {\n throw new Error(\n `${(ctor as { name?: string }).name ?? \"a hook class\"} carries no handler — ` +\n \"a hook file must declare at least one @Hook (blocking) or @On (listener) method\",\n );\n }\n\n const instance = new (ctor as new () => Record<string, HookFn>)();\n return {\n blocking: bind(instance, blockingEntries, \"@Hook\"),\n listeners: bind(instance, listenerEntries, \"@On\"),\n };\n}\n","// `@Upload` — the single-method direct-storage upload decorator, and its\n// `@UploadedObject` parameter companion + `UploadConfig`/`UploadedObject` types.\n//\n// Unlike `@Get`/`@Post`/… (where bytes flow THROUGH the br-pod), an `@Upload`\n// route never sees the file bytes: the client uploads DIRECTLY to storage via a\n// signed URL the br-pod mints in an authorize pre-flight. The decorated method\n// body is the COMPLETION handler — it runs once, after storage confirms the\n// object landed (via an HMAC-signed completion webhook), and returns the typed\n// result the client awaits. There is exactly one method: it is BOTH the\n// authorize gate (its uploadConfig drives the guard + signed-URL pinning) AND\n// the completion handler (its body).\n//\n// On the wire the authorize pre-flight is a POST; what marks a route as an\n// upload route through the whole pipeline (registry → flatten → openapi →\n// codegen) is the PRESENCE of `uploadConfig` on the route — never a special HTTP\n// verb. The `@Get`/`@Post`/… decorators never set it.\nimport { recordRoute, recordParam } from \"./registry.js\";\nimport type { RouteOptions } from \"./registry.js\";\nimport type { PalbaseBucketName } from \"../stack.js\";\n\n/** A legacy method decorator (`experimentalDecorators`): `(prototype, name,\n * descriptor)`. */\ntype MethodDecorator = (\n target: object,\n propertyKey: string | symbol,\n descriptor: PropertyDescriptor,\n) => void;\n\n/** A legacy parameter decorator: `(prototype, name, paramIndex)`. */\ntype ParameterDecorator = (\n target: object,\n propertyKey: string | symbol,\n parameterIndex: number,\n) => void;\n\n/**\n * Direct-storage upload settings for an `@Upload` route. The br-pod validates an\n * authorize request against these (size/type), then mints a signed upload URL\n * that PINS the limits so storage itself rejects an over-limit / wrong-type PUT\n * — the client cannot exceed what it declared.\n */\nexport interface UploadConfig {\n /**\n * Target bucket NAME — one the STACK holds.\n *\n * The union comes from the generated `palbase-stack.d.ts`, so a bucket the\n * stack does not carry is a compile error. It used to say \"MUST exist in\n * `config/storage.ts` defineStorage(...)\", and that invariant was carried by\n * this sentence plus a cross-check nothing called; it is carried by the type\n * now.\n *\n * The bucket is the SINGLE SOURCE OF TRUTH for the size limit + MIME allowlist:\n * `bucket({ fileSizeLimit, allowedMimeTypes })`. Storage enforces those at the\n * actual PUT (the only guard a client cannot skip), so `@Upload` deliberately\n * does NOT take its own `maxSize`/`allowedTypes` — duplicating them here would\n * let a route declare a tighter limit than its bucket that storage would not\n * enforce (a real bypass: declare 10 bytes at authorize, then PUT up to the\n * bucket ceiling straight at the signed URL). One bucket, one limit, enforced.\n */\n bucket: PalbaseBucketName;\n /**\n * SERVER-side object key template. The client NEVER chooses the path. Tokens:\n * `{userId}` (authenticated user id), `{uploadId}` (server-minted), and\n * `{filename}` (the client-declared filename, sanitized). e.g.\n * `\"{userId}/{uploadId}-{filename}\"`.\n */\n pathTemplate: string;\n}\n\n/**\n * The uploaded object, injected into an `@Upload` method body by\n * `@UploadedObject()` once storage confirms the upload. Bytes are NOT present\n * (they went straight to storage) — this is the metadata the completion handler\n * persists.\n */\nexport interface UploadedObject {\n /** Server-minted id correlating authorize ↔ completion (idempotency key). */\n uploadId: string;\n /** Final object key in the bucket (rendered from `pathTemplate`). */\n path: string;\n /** Bucket the object landed in. */\n bucket: string;\n /** Object size in bytes, as reported by storage. */\n size: number;\n /** Object MIME type, as reported by storage — detected from the BYTES, not\n * from the filename or from what the client claimed. */\n contentType: string;\n /** SHA-256 of the stored bytes, hex. The same value the object's ETag is\n * derived from, so a client that has it can tell whether it already holds\n * these bytes. */\n checksum: string;\n /** Pixel width, for an image. Absent otherwise — a PDF has no dimensions,\n * and reporting 0 would be a measurement rather than an absence. */\n width?: number;\n /** Pixel height, for an image. */\n height?: number;\n /**\n * A ~25-byte placeholder the client paints INSTANTLY while the real image\n * downloads — the thing that replaces a grey skeleton with something already\n * shaped like the picture. Absent for non-images.\n *\n * Persist it beside the object's path: it costs a column and saves a request\n * per picture on every gallery render.\n */\n thumbhash?: string;\n /**\n * The renditions the bucket declared, by name, as URLs ready to use.\n *\n * Present on the completion input so the handler that stores the row has\n * everything it needs in one place — asking for them afterwards would be a\n * second call per upload, and per picture on every read.\n */\n variants: Record<string, string>;\n}\n\n/**\n * `@Upload(subpath, config)` — declare a direct-storage upload route. The method\n * body is the completion handler; `config.uploadConfig` drives the authorize\n * guard + signed-URL pinning.\n *\n * @example\n * @Upload(\"/\", { bucket: \"docs\", pathTemplate: \"{userId}/{uploadId}-{filename}\" })\n * async upload(@UploadedObject() obj: UploadedObject, @User() user): Promise<DocResult> { ... }\n * // The size limit + MIME allowlist come from the \"docs\" bucket ON THE STACK\n * // — storage enforces them at the PUT.\n */\nexport function Upload(\n subpath: string,\n config: UploadConfig & Pick<RouteOptions, \"auth\" | \"rateLimit\">,\n): MethodDecorator {\n const { auth, rateLimit, ...uploadConfig } = config;\n validateUploadConfigShape(uploadConfig);\n const options: RouteOptions = {\n uploadConfig,\n ...(auth !== undefined ? { auth } : {}),\n ...(rateLimit !== undefined ? { rateLimit } : {}),\n };\n return function (target, propertyKey) {\n // On the wire the authorize pre-flight is a POST; `uploadConfig` is what\n // marks this as an upload route downstream.\n recordRoute(target, String(propertyKey), \"POST\", subpath, options);\n };\n}\n\n/**\n * `@UploadedObject()` — inject the uploaded object (`: UploadedObject`) into an\n * `@Upload` method body (the completion input). Only valid on an `@Upload`\n * route; the bytes are NOT present (they went directly to storage), this is the\n * confirmed object's metadata.\n *\n * Co-located with the {@link UploadedObject} TYPE so a single exported name\n * `UploadedObject` carries BOTH the decorator value and the type annotation.\n */\nexport function UploadedObject(): ParameterDecorator {\n return function (target, propertyKey, parameterIndex) {\n recordParam(target, String(propertyKey), {\n index: parameterIndex,\n kind: \"uploadedObject\",\n });\n };\n}\n\n/**\n * Shape-validate an UploadConfig at decoration time (author-time failure beats a\n * silent deploy bug). Does NOT check that the bucket EXISTS — the generated\n * `palbase-stack.d.ts` union does that, and it does it at compile time rather\n * than at deploy.\n */\nexport function validateUploadConfigShape(c: UploadConfig): void {\n if (c === null || typeof c !== \"object\") {\n throw new Error(\"@Upload config must be an object { bucket, pathTemplate, ... }\");\n }\n // Read the bucket through a WIDENED view on purpose. Its declared type is\n // `PalbaseBucketName`, which is `never` until the project generates\n // `palbase-stack.d.ts` — and `never.length` does not typecheck. This function\n // is a RUNTIME guard against a shape the compiler never saw (a plain-JS\n // caller, a bundle boundary), so the value arriving here is genuinely unknown\n // and reading it as such is the honest signature, not a cast to dodge an error.\n const bucket: unknown = (c as { bucket?: unknown }).bucket;\n if (typeof bucket !== \"string\" || bucket.length === 0) {\n throw new Error(\"@Upload config.bucket must be a non-empty bucket name\");\n }\n if (typeof c.pathTemplate !== \"string\" || c.pathTemplate.length === 0) {\n throw new Error(\"@Upload config.pathTemplate must be a non-empty key template\");\n }\n}\n\n","// Parameter decorators: `@Body` / `@QueryParams` / `@Param` / `@Headers` / `@User` /\n// `@OptionalUser` / `@Client` / `@RequestId` / `@TraceId` / `@Req`. Each records\n// `{ index, kind, schema?, name? }` into the per-class registry for the method\n// it decorates. These are LEGACY parameter decorators\n// (`experimentalDecorators`), receiving `(prototype, methodName, paramIndex)` —\n// esbuild/tsc preserve the param index at runtime (verified, design §0), which\n// is how dispatch injects positionally. No type reflection\n// (`emitDecoratorMetadata`) is used: validation comes from the zod schema, the\n// type annotation the developer writes is purely for autocomplete.\nimport type { ZodTypeAny } from \"zod\";\nimport { recordParam, type ParamKind } from \"./registry.js\";\n\n/** A legacy parameter decorator. */\ntype ParameterDecorator = (\n target: object,\n propertyKey: string | symbol,\n parameterIndex: number,\n) => void;\n\n/** Build a parameter decorator that records the given kind (+ optional schema /\n * name) at the decorated parameter's index. */\nfunction makeParamDecorator(\n kind: ParamKind,\n extra?: { schema?: ZodTypeAny; name?: string },\n): ParameterDecorator {\n return function (target, propertyKey, parameterIndex) {\n recordParam(target, String(propertyKey), {\n index: parameterIndex,\n kind,\n ...(extra?.schema !== undefined ? { schema: extra.schema } : {}),\n ...(extra?.name !== undefined ? { name: extra.name } : {}),\n });\n };\n}\n\n/** `@Body(schema)` — inject the request body, validated against `schema`. The\n * developer writes `: T` (= `z.infer<schema>`, same name) for autocomplete. */\nexport function Body(schema: ZodTypeAny): ParameterDecorator {\n return makeParamDecorator(\"body\", { schema });\n}\n\n/** `@QueryParams(schema)` — inject the parsed query params, validated against\n * `schema`. */\nexport function QueryParams(schema: ZodTypeAny): ParameterDecorator {\n return makeParamDecorator(\"query\", { schema });\n}\n\n/** `@Headers(schema?)` — inject the request headers (lowercase keys). With a\n * schema, headers are validated + the codegen emits header parameters. */\nexport function Headers(schema?: ZodTypeAny): ParameterDecorator {\n return makeParamDecorator(\"headers\", schema !== undefined ? { schema } : undefined);\n}\n\n/** `@Param(\"id\")` — inject one matched path param by name. */\nexport function Param(name: string): ParameterDecorator {\n return makeParamDecorator(\"param\", { name });\n}\n\n/** `@User()` — inject the authenticated user (`: User`, non-null for an\n * effective-required route). The runtime resolves the effective auth. */\nexport function User(): ParameterDecorator {\n return makeParamDecorator(\"user\");\n}\n\n/** `@OptionalUser()` — inject the user as `User | null` (for routes whose\n * effective auth is `false` / `{ required: false }`). */\nexport function OptionalUser(): ParameterDecorator {\n return makeParamDecorator(\"optionalUser\");\n}\n\n/** `@Client()` — inject the parsed calling-client metadata (`: ClientInfo`). */\nexport function Client(): ParameterDecorator {\n return makeParamDecorator(\"client\");\n}\n\n/** `@RequestId()` — inject the per-request id (`: string`). */\nexport function RequestId(): ParameterDecorator {\n return makeParamDecorator(\"requestId\");\n}\n\n/** `@TraceId()` — inject the W3C trace id (`: string`). */\nexport function TraceId(): ParameterDecorator {\n return makeParamDecorator(\"traceId\");\n}\n\n/** `@Req()` — inject the raw request object (escape hatch, `: PBRequest`). */\nexport function Req(): ParameterDecorator {\n return makeParamDecorator(\"req\");\n}\n\n// NOTE: `@UploadedObject()` lives in decorators/upload.ts (co-located with the\n// `UploadedObject` TYPE) so a single exported name carries both the value (the\n// decorator) and the type — TS can only merge value+type under one export name\n// when both are declared in the SAME module.\n","import type { DBClient, Logger, CacheClient, PalbaseModuleClients } from \"./endpoint.js\";\nimport type { User } from \"./types.js\";\n\n/** Middleware context — subset of EndpointContext without input (not yet validated). */\nexport interface MiddlewareContext extends PalbaseModuleClients {\n params: Record<string, string>;\n query: Record<string, string>;\n headers: Record<string, string>;\n user: User | null;\n db: DBClient;\n env: Record<string, string>;\n log: Logger;\n cache: CacheClient;\n requestId: string;\n environmentId: string;\n}\n\n/** Middleware function signature — receives context and next function. */\nexport type MiddlewareHandler = (\n ctx: MiddlewareContext,\n next: () => Promise<void>,\n) => Promise<void>;\n\n/**\n * Define a middleware function for use in the middleware/ directory or\n * as endpoint-specific middleware.\n *\n * Middleware runs before the handler. Call `next()` to pass control\n * to the next middleware or handler. If `next()` is not called, the\n * handler will not execute.\n *\n * Errors thrown in middleware are caught by the pipeline and returned\n * as error responses.\n */\nexport function defineMiddleware(fn: MiddlewareHandler): MiddlewareHandler {\n return fn;\n}\n","/** Non-service, per-invocation data for job handlers.\n * Services (Database, Log, …) are imported as singletons, not passed here. */\nexport interface JobMeta {\n /** Environment-scoped env vars. */\n env: Record<string, string>;\n /** The globally unique Environment runtime identifier. */\n environmentId: string;\n}\n\n/**\n * Cron expression validation.\n * Supports standard 5-field cron: minute hour day-of-month month day-of-week.\n * Each field allows: number, *, ranges (1-5), steps (star/2), lists (1,3,5).\n */\nexport function validateCronExpression(expression: string): string | null {\n const trimmed = expression.trim();\n if (trimmed === \"\") {\n return \"Cron expression is required\";\n }\n\n const parts = trimmed.split(/\\s+/);\n if (parts.length !== 5) {\n return `Invalid cron expression \"${trimmed}\": expected 5 fields (minute hour day month weekday), got ${parts.length}`;\n }\n\n const fieldNames = [\"minute\", \"hour\", \"day of month\", \"month\", \"day of week\"];\n const fieldRanges: [number, number][] = [\n [0, 59],\n [0, 23],\n [1, 31],\n [1, 12],\n [0, 7],\n ];\n\n for (let i = 0; i < 5; i++) {\n const field = parts[i]!;\n const name = fieldNames[i]!;\n const [min, max] = fieldRanges[i]!;\n\n const error = validateCronField(field, name, min, max);\n if (error !== null) {\n return error;\n }\n }\n\n return null;\n}\n\nfunction validateCronField(\n field: string,\n name: string,\n min: number,\n max: number,\n): string | null {\n // Split by comma for lists\n const listParts = field.split(\",\");\n for (const part of listParts) {\n // Check for step: */2, 1-5/2\n const stepParts = part.split(\"/\");\n if (stepParts.length > 2) {\n return `Invalid ${name} field: \"${field}\"`;\n }\n\n const base = stepParts[0]!;\n const step = stepParts[1];\n\n if (step !== undefined) {\n const stepNum = Number(step);\n if (!Number.isInteger(stepNum) || stepNum < 1) {\n return `Invalid step value in ${name} field: \"${field}\"`;\n }\n }\n\n if (base === \"*\") {\n continue;\n }\n\n // Check for range: 1-5\n if (base.includes(\"-\")) {\n const rangeParts = base.split(\"-\");\n if (rangeParts.length !== 2) {\n return `Invalid range in ${name} field: \"${field}\"`;\n }\n const rangeStart = Number(rangeParts[0]);\n const rangeEnd = Number(rangeParts[1]);\n if (\n !Number.isInteger(rangeStart) ||\n !Number.isInteger(rangeEnd) ||\n rangeStart < min ||\n rangeEnd > max ||\n rangeStart > rangeEnd\n ) {\n return `Invalid range in ${name} field: \"${field}\"`;\n }\n continue;\n }\n\n // Single number\n const num = Number(base);\n if (!Number.isInteger(num) || num < min || num > max) {\n return `Invalid value in ${name} field: \"${field}\"`;\n }\n }\n\n return null;\n}\n","// @Job — the cron half of the decorator surface. Same metadata mechanism as\n// @Webhook/@Controller. The job's NAME is not here on purpose: it is the file\n// name, which is also what the Temporal schedule id is built from. Two names\n// with nothing reconciling them is what this replaces.\nimport type { JobMeta } from \"../job.js\";\nimport { validateCronExpression } from \"../job.js\";\n\nexport interface JobOptions {\n /** Cron expression, five fields (e.g. \"0 3 * * *\"). */\n schedule: string;\n /** Execution timeout in seconds. Defaults to 30, ceiling 300 (sandbox limit). */\n timeout?: number;\n /**\n * How many times a FAILED run is retried before the run is recorded failed.\n * Defaults to 5, ceiling 10; 0 disables retrying entirely.\n *\n * Retries exist for the transient half of the failure space — the runtime\n * still waking, a network blip — not for a job that is wrong. A permanent\n * failure still lands in the run history, it just lands after the retries\n * are spent rather than instead of them.\n */\n retry?: number;\n}\n\nexport interface ResolvedJob {\n schedule: string;\n timeout: number;\n retry: number;\n handler: (meta: JobMeta) => Promise<void>;\n}\n\nconst DEFAULT_TIMEOUT_SECONDS = 30;\nconst MAX_TIMEOUT_SECONDS = 300;\nconst DEFAULT_RETRY = 5;\nconst MAX_RETRY = 10;\n\nexport const JOB_META: unique symbol = Symbol.for(\"palbase.backend.jobMeta\");\n\ninterface JobCarrier {\n __palbase?: \"job\";\n [JOB_META]?: JobOptions;\n}\n\nexport function Job(options: JobOptions) {\n return function <T extends abstract new (...args: never[]) => object>(ctor: T): T {\n const carrier = ctor as unknown as JobCarrier;\n Object.defineProperty(carrier, JOB_META, {\n value: options,\n enumerable: false,\n configurable: true,\n writable: false,\n });\n Object.defineProperty(carrier, \"__palbase\", {\n value: \"job\",\n enumerable: false,\n configurable: true,\n writable: false,\n });\n return ctor;\n };\n}\n\nexport function getJobConfig(ctor: object): ResolvedJob {\n const meta = (ctor as JobCarrier)[JOB_META];\n if (!meta) {\n throw new Error(\n `getJobConfig on a class with no @Job decorator (${(ctor as { name?: string }).name ?? \"anonymous\"})`,\n );\n }\n if (!meta.schedule || meta.schedule.trim() === \"\") {\n throw new Error(\"@Job requires a `schedule` cron expression\");\n }\n const cronError = validateCronExpression(meta.schedule);\n if (cronError) {\n throw new Error(`@Job has an invalid cron schedule: ${cronError}`);\n }\n\n const timeout = meta.timeout ?? DEFAULT_TIMEOUT_SECONDS;\n if (!Number.isInteger(timeout) || timeout <= 0) {\n throw new Error(\"@Job `timeout` must be a positive whole number of seconds\");\n }\n if (timeout > MAX_TIMEOUT_SECONDS) {\n throw new Error(`@Job \\`timeout\\` exceeds the ${MAX_TIMEOUT_SECONDS}s sandbox ceiling`);\n }\n\n const retry = meta.retry ?? DEFAULT_RETRY;\n if (!Number.isInteger(retry) || retry < 0) {\n throw new Error(\"@Job `retry` must be a whole number of attempts, zero or more\");\n }\n if (retry > MAX_RETRY) {\n throw new Error(`@Job \\`retry\\` exceeds the ceiling of ${MAX_RETRY}`);\n }\n\n const instance = new (ctor as new () => { run?: (meta: JobMeta) => Promise<void> })();\n if (typeof instance.run !== \"function\") {\n throw new Error(\"@Job class must declare an async run() method\");\n }\n const run = instance.run.bind(instance);\n\n return { schedule: meta.schedule, timeout, retry, handler: run };\n}\n","export type {\n PBRequest,\n ClientInfo,\n RateLimitConfig,\n DBClient,\n DBOps,\n FileContext,\n Logger,\n CacheClient,\n SecretsService,\n PalbaseDocsClient,\n PalbaseCollectionRef,\n PalbaseDocumentRef,\n PalbaseDocumentSnapshot,\n PalbaseQuerySnapshot,\n PalbaseWhereOperator,\n PalbaseResult,\n Middleware,\n ErrorDef,\n ErrorMap,\n ErrorThrowers,\n} from \"./endpoint.js\";\nexport {\n Database,\n Documents,\n Storage,\n Cache,\n Secrets,\n Log,\n Notifications,\n Flags,\n Realtime,\n __setRuntime,\n __runWithRuntime,\n __requestALS,\n __getRuntime,\n} from \"./runtime.js\";\nexport type { RuntimeServices, RequestStore } from \"./runtime.js\";\n\n// The module clients and their composition root. The PROCESS calls\n// buildModuleClients once at boot and hands the result to createApp — which is\n// the whole reason this package now contains the implementations and not just\n// the interfaces they were being checked against by nobody.\nexport { buildModuleClients } from \"./clients/index.js\";\nexport type { ModuleClientsConfig } from \"./clients/index.js\";\nexport { makeHttpClient, PalbaseModuleError } from \"./clients/http.js\";\nexport type { ModuleTransport, RequestOptions, TransportConfig } from \"./clients/http.js\";\n\nexport type {\n PalbaseAuthClient,\n PalbaseStorageClient,\n PalbaseBucketClient,\n PalbaseRealtimeClient,\n PalbaseFunctionsClient,\n PalbaseInvokeOptions,\n PalbaseFlagsClient,\n PalbaseFlagsServiceClient,\n PalbaseFlagContext,\n PalbaseFlagVariant,\n PalbaseFlag,\n PalbaseFlagValue,\n PalbaseFlagSource,\n PalbaseSetOverrideResult,\n PalbaseSetOverridesResult,\n PalbaseClearOverrideResult,\n PalbaseClearAllOverridesResult,\n PalbaseBatchOverrideOperation,\n PalbaseBatchSetOverridesResult,\n PalbaseNotificationsClient,\n PalbasePushClient,\n PalbaseEmailClient,\n PalbaseSmsClient,\n PalbaseInboxClient,\n PalbasePreferencesClient,\n PalbaseAnalyticsClient,\n PalbaseAnalyticsQueryNamespace,\n PalbaseAnalyticsManagementNamespace,\n PalbaseLinksClient,\n // Shared local types\n PalbaseUser,\n PalbaseSession,\n PalbaseDeviceInfo,\n PalbaseAttestAndroidParams,\n PalbaseAttestAndroidResult,\n PalbaseAttestiOSParams,\n PalbaseAttestiOSResult,\n PalbaseBindDeviceParams,\n PalbaseVerifyRequestSignatureParams,\n PalbaseFileObject,\n PalbaseSignedUrlResponse,\n PalbaseUploadOptions,\n PalbaseTransformOptions,\n PalbaseListOptions,\n PalbasePushSendParams,\n PalbasePushSendResponse,\n PalbaseEmailSendParams,\n PalbaseEmailSendResponse,\n PalbaseSmsSendParams,\n PalbaseSmsSendResponse,\n PalbaseInboxSendParams,\n PalbaseInboxSendResponse,\n PalbaseInboxMessage,\n PalbaseInboxListOptions,\n PalbaseInboxListResult,\n PalbasePreferences,\n PalbaseRegisterDeviceParams,\n PalbaseDeviceTokenView,\n PalbaseMultiChannelResponse,\n PalbaseAnalyticsProperties,\n PalbaseIdentifyTraits,\n PalbaseCountQueryInput,\n PalbaseCountResult,\n PalbaseEventsQueryInput,\n PalbaseEventsResult,\n PalbaseUsersQueryInput,\n PalbaseUsersResult,\n PalbaseFunnelQueryInput,\n PalbaseFunnelResult,\n PalbaseRetentionQueryInput,\n PalbaseRetentionResult,\n PalbaseCohortQueryInput,\n PalbaseCohortResult,\n PalbaseOverviewResult,\n PalbaseEventNamesResult,\n PalbaseUserDetailResult,\n PalbaseCreateLinkParams,\n PalbaseUpdateLinkParams,\n PalbaseLink,\n PalbaseLinkDetails,\n PalbaseLinkAnalytics,\n PalbaseQrCodeOptions,\n PalbaseMatchParams,\n PalbaseInitialLink,\n PalbaseListLinksOptions,\n PalbaseListLinksResult,\n} from \"./clients.js\";\nexport { defineSchema } from \"./db/schema.js\";\n// The declaration as DATA — what the deploy reads to build the database. The\n// bundler calls this; a project never has to.\nexport { toSchemaJSON } from \"./db/schema-json.js\";\nexport type { SchemaJSON, TableJSON, ColumnJSON, PolicyJSON } from \"./db/schema-json.js\";\nexport type { SchemaDef, TableDef, TableInput, ColumnMap, SchemaInput } from \"./db/schema.js\";\nexport { policy, PolicyBuilder } from \"./db/policy.js\";\nexport type { PolicyDef, PolicyCommand, PolicyMode } from \"./db/policy.js\";\n// The realtime twin of `policy`: which channels exist and who may join them.\n// Undeclared channels are denied by the server, so this declaration is the\n// whole surface — the runtime reads it back off globalThis at boot.\nexport { defineChannels, ownerOnly, publicChannel } from \"./channels.js\";\nexport type { ChannelsDef, ChannelEntry, ChannelsInput, ChannelGrant, ChannelAuthorizeCtx } from \"./channels.js\";\nexport { PALBASE_EXTENSIONS, EXTENSION_DEPENDENCIES, isPalbaseExtension } from \"./db/extensions.js\";\nexport type { PalbaseExtension } from \"./db/extensions.js\";\nexport { uuid, text, integer, bigint, numeric, boolean, timestamp, jsonb, enumType, vector } from \"./db/columns.js\";\nexport type { ColumnBuilder, ColumnDef, ColumnType, OnDeleteAction } from \"./db/columns.js\";\nexport { raw } from \"./db/raw.js\";\nexport type { RawConstraintDef } from \"./db/raw.js\";\nexport { openai } from \"./db/embedding.js\";\nexport type { EmbeddingModelRef } from \"./db/embedding.js\";\nexport { makeTypedDB } from \"./db/typed-db.js\";\nexport type {\n TypedDB,\n TypedTx,\n TypedTable,\n InsertShape,\n RowShape,\n EnvTypedDatabase,\n EnvServiceDatabase,\n EnvTypedTable,\n EnvTables,\n TxPlan,\n TxTables,\n} from \"./db/typed-db.js\";\n// Transaction plans: the `tx.tables.*` operation surface, its handles, and the\n// expressions a plan may write. `Database.transaction()` is on `Database`.\nexport { inc, dec, now, TxRefError, TxPlanError } from \"./db/tx-plan.js\";\nexport type {\n Ref,\n TxRow,\n TxRows,\n TxTable,\n TxPlanHandle,\n Materialized,\n TxNow,\n TxColumnExpr,\n TxInsertValue,\n TxSetValue,\n TxInsertShape,\n TxSetShape,\n TxWhere,\n TxSelectOptions,\n TxPlanBody,\n TxPlanResponse,\n TxPlanOpResult,\n TxPlanRejection,\n TxWireOp,\n TxWireRef,\n TxWireExpr,\n TxWireGuard,\n TxWireValue,\n} from \"./db/tx-plan.js\";\nexport type { Tables, TableTypes } from \"./db/env.js\";\nexport { makeEnvDts } from \"./db/env-gen.js\";\n// `config/` IS GONE, and so is the purchases family. Both were author-facing\n// surfaces with nothing behind them.\n//\n// The five config declarations nobody applied — storage, flags, notifications,\n// egress, auth — stopped being applied when the server-side declaration applier\n// was retired (v2 S-005, \"settings have one door, and a second one is how the\n// two disagree\"); `contract_lock_test.go` keeps it retired, and its own comment\n// records that the applier produced that silent failure FIVE times. The two that\n// still worked travelled by CLI courier: `config/secrets.ts` gated the push and\n// `config/test-users.ts` was PUT at the stack. Both jobs are now done where the\n// setting lives — `palbase secret set`, `palbase test-user templates set` — and\n// what a controller may SPELL comes back as a type instead of a declaration.\n//\n// `purchases` never had a v2 backend at all: v2 contains no palstore, which\n// `clients/index.ts` recorded on 2026-08-15 while deliberately leaving the tree\n// in place. It is taken now.\n//\n// The rule that replaced all of it: `db/schema.ts` and behaviour-carrying code\n// live in the repo; everything else is CONFIGURATION and is set through the CLI\n// (later MCP) against the stack. Codegen exists so that code can be written\n// against it — a generated type is not a declaration, and it produces no file an\n// author edits.\nexport type { PalbaseSecretName, PalbaseFlagKey, PalbaseBucketName } from \"./stack.js\";\nexport { makeStackDts } from \"./stack-gen.js\";\nexport type { StackNames } from \"./stack-gen.js\";\n// Class-controller decorator model (replaces defineController/defineHandler/route).\n// `getRegisteredControllers` is what makes exporting a controller OPTIONAL:\n// importing the file registers it. `Controller` stays exported for authoring.\nexport { Controller, getRegisteredControllers, __resetRegisteredControllers } from \"./decorators/controller.js\";\nexport type { ControllerOptions } from \"./decorators/controller.js\";\nexport { Get, Post, Put, Patch, Delete, Query } from \"./decorators/methods.js\";\nexport { Deny, getHookConfig, Hook } from \"./decorators/hook.js\";\nexport type { HookFn, ResolvedHookClass } from \"./decorators/hook.js\";\nexport { Upload } from \"./decorators/upload.js\";\nexport type { UploadConfig } from \"./decorators/upload.js\";\n// `UploadedObject` is exported from upload.js, where BOTH the `@UploadedObject()`\n// decorator value AND the `UploadedObject` type are declared. One module → one\n// export name carries both — authors write `@UploadedObject()` (value) and\n// `: UploadedObject` (type) with a single imported name.\nexport { UploadedObject } from \"./decorators/upload.js\";\nexport {\n Body,\n QueryParams,\n Headers,\n Param,\n User,\n OptionalUser,\n Client,\n RequestId,\n TraceId,\n Req,\n} from \"./decorators/params.js\";\nexport type { RouteOptions, HttpMethodUpper, ThrowDescriptor, RouteMeta, ParamMeta, ParamKind } from \"./decorators/registry.js\";\n// recordThrows is the stager-injected carrier for inferred throw descriptors\n// (the recordReturn twin) — public so the injected IIFE in a deployed bundle\n// can call it via `require(\"@palbase/backend\").recordThrows(...)`.\nexport { recordThrows } from \"./decorators/registry.js\";\n// getRoutes reads a controller's RouteMeta[] straight from the registry — the\n// isolate runtime enumerates routes with it instead of the worker.js raw-Symbol\n// fallback (the ROUTES symbol stays, both fallbacks keep reading it).\nexport { getRoutes } from \"./decorators/registry.js\";\nexport { defineMiddleware } from \"./middleware.js\";\nexport type { MiddlewareContext, MiddlewareHandler } from \"./middleware.js\";\n// The authenticated-user TYPE is exported as `UserT` (not `User`) because the\n// value name `User` is the @User() parameter decorator (exported above). A\n// controller annotates `@User() user: UserT` — decorator for the value\n// position, `UserT` for the type. (NestJS-style: same name as the decorator\n// would collide in the value+type namespaces.)\nexport type { User as UserT, VerifiedDevice, HttpMethod, AuthConfig } from \"./types.js\";\nexport {\n HttpError,\n PalError,\n BadRequest,\n Unauthorized,\n Forbidden,\n NotFound,\n Conflict,\n TooManyRequests,\n} from \"./errors.js\";\n// Typed project errors — defineError returns an HttpError subclass and\n// self-registers {code, status, dataSchema} in the project-global error\n// registry (the OpenAPI spec twins join `RouteMeta.throws` against it).\nexport { defineError, getErrorRegistry } from \"./error-registry.js\";\nexport type { RegisteredError, DefinedError, DefinedErrorWithData } from \"./error-registry.js\";\nexport type { JobMeta } from \"./job.js\";\nexport type { WebhookProvider, WebhookMeta, WebhookRequest } from \"./webhook.js\";\n// Webhooks and jobs are classes: `@Webhook`/`@On` for inbound webhooks,\n// `@Job` for cron. Both take their name from their file — see decorators/*.\nexport { getWebhookConfig, On, Webhook } from \"./decorators/webhook.js\";\nexport type { ResolvedWebhook, SignatureSpec, WebhookEventHandler, WebhookOptions } from \"./decorators/webhook.js\";\nexport { getJobConfig, Job } from \"./decorators/job.js\";\nexport type { JobOptions, ResolvedJob } from \"./decorators/job.js\";\n// `Resource` is GONE, not deprecated. Its boot registry was never wired: nothing\n// in the runtime ever called `__runResourceBoot` (measured 2026-08-29 —\n// `grep -rn \"ResourceBoot\"` across v2/runtime and palsvc returned nothing), so\n// `init(env)` never ran, the declared secrets never arrived, and a project that\n// wrote one got an object whose fields sat at their initializers with no error\n// anywhere. That is the same silence the `auth`/`storage`/`documents` hook\n// helpers were removed for, one surface down.\n//\n// Nothing replaces it, because the thing it was ceremony around is already the\n// stack's: the VAULT holds what a backend may read, the runtime lists those names\n// off it and mirrors them into `process.env` at boot, and `Secrets.get()` reads a\n// value with the rotation the deploy generation already carries. A field frozen\n// once inside `init(env)` could not have that. `static secrets` was therefore a\n// third list of names, behind the vault and behind `config/secrets.ts` — which is\n// itself down to a hint rather than a constraint (v2/runtime/src/server.ts:517).\n// `config/egress.ts` fences the calls a resource would have made and\n// `openai.embedding(...)` in the schema puts the one vendor client the platform\n// actually runs where the platform runs it. `resources/` stays exactly what the\n// bundler already treats it as — a directory of plain modules a controller\n// imports.\n// Types only. A hook is declared with @Hook/@On in hooks/*.ts.\n//\n// The `auth`/`storage`/`documents` helpers that used to live here are gone, not\n// deprecated: they returned a record nothing in the runtime or the bundler ever\n// read, so a project that called one got a handler that never ran and no error\n// anywhere. api-surface.mjs asks for a deprecation bridge because a major locks\n// every tenant's deploy — a real cost, and the reason this shipped as a bridge\n// in 20.0.0. There are no production tenants to lock yet (owner's call,\n// 2026-08-22), so the bridge is spending a release to soften a break nobody can\n// feel, and the honest surface is the one with no dead names in it.\nexport type {\n HookMeta,\n AuthHookEvent,\n DocumentHookEvent,\n FileUploadedEvent,\n FileDeletedEvent,\n} from \"./hooks.js\";\nexport { z } from \"zod\";\n"],"mappings":"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","names":["raw","raw","text","now","policy","out","raw"]}