@tinycloud/sdk-services 3.8.0-beta.9 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{BaseService-DO7vZ67k.d.ts → BaseService-Ma2MwJAd.d.ts} +1 -1
- package/dist/{BaseService-D-29xShG.d.cts → BaseService-O0iyuFLk.d.cts} +1 -1
- package/dist/IHooksService-4QNODVy6.d.cts +120 -0
- package/dist/IHooksService-CvTpJbQD.d.ts +120 -0
- package/dist/ISQLService-Aly1CBsW.d.ts +242 -0
- package/dist/ISQLService-BOgWzHLT.d.cts +242 -0
- package/dist/context.d.cts +1 -1
- package/dist/context.d.ts +1 -1
- package/dist/encryption/index.cjs +80 -7
- package/dist/encryption/index.cjs.map +1 -1
- package/dist/encryption/index.d.cts +23 -11
- package/dist/encryption/index.d.ts +23 -11
- package/dist/encryption/index.js +79 -7
- package/dist/encryption/index.js.map +1 -1
- package/dist/encryption/named-keys.cjs.map +1 -1
- package/dist/encryption/named-keys.d.cts +2 -2
- package/dist/encryption/named-keys.d.ts +2 -2
- package/dist/encryption/named-keys.js.map +1 -1
- package/dist/encryption/resource.cjs.map +1 -1
- package/dist/encryption/resource.js.map +1 -1
- package/dist/feed/index.cjs +1309 -0
- package/dist/feed/index.cjs.map +1 -0
- package/dist/feed/index.d.cts +238 -0
- package/dist/feed/index.d.ts +238 -0
- package/dist/feed/index.js +1258 -0
- package/dist/feed/index.js.map +1 -0
- package/dist/index.cjs +131 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -116
- package/dist/index.d.ts +16 -116
- package/dist/index.js +130 -15
- package/dist/index.js.map +1 -1
- package/dist/internal/decrypt-transport-response-error.d.cts +1 -1
- package/dist/internal/decrypt-transport-response-error.d.ts +1 -1
- package/dist/kv/index.cjs.map +1 -1
- package/dist/kv/index.d.cts +4 -4
- package/dist/kv/index.d.ts +4 -4
- package/dist/kv/index.js.map +1 -1
- package/dist/kv/replication/index.d.cts +3 -3
- package/dist/kv/replication/index.d.ts +3 -3
- package/dist/{scope-1-8skVDk.d.ts → scope-BZr0QwxX.d.ts} +1 -1
- package/dist/{scope-Dv3IAXMr.d.cts → scope-DEgc9f-W.d.cts} +1 -1
- package/dist/sql/index.cjs +21 -6
- package/dist/sql/index.cjs.map +1 -1
- package/dist/sql/index.d.cts +6 -236
- package/dist/sql/index.d.ts +6 -236
- package/dist/sql/index.js +21 -6
- package/dist/sql/index.js.map +1 -1
- package/dist/telemetry/requestLog.d.cts +1 -1
- package/dist/telemetry/requestLog.d.ts +1 -1
- package/dist/{types-BGRzS1ob.d.ts → types-Bf91gup6.d.ts} +7 -2
- package/dist/{types-DAOyIbXu.d.cts → types-CSd0RYir.d.cts} +1 -1
- package/dist/{types-DAOyIbXu.d.ts → types-CSd0RYir.d.ts} +1 -1
- package/dist/{types-B_rbS4XE.d.cts → types-D4XbIfFJ.d.cts} +7 -2
- package/package.json +6 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/types.ts","../../src/feed/schemas.ts","../../src/feed/dispatch.ts","../../src/feed/notification.ts","../../src/feed/store.ts","../../src/feed/handoff.ts","../../src/feed/restore-metadata.ts","../../src/feed/delivery-policy.ts","../../src/feed/listener.ts","../../src/feed/resources.ts","../../src/feed/restore.ts","../../src/feed/history.ts"],"sourcesContent":["/**\n * SDK Services - Core Types\n *\n * These types define the service architecture for TinyCloud SDK.\n * Services use dependency injection via IServiceContext for platform independence.\n */\n\n// =============================================================================\n// Result Type Pattern\n// =============================================================================\n\n/**\n * Result type for service operations.\n * Services return Result instead of throwing, making error handling explicit.\n *\n * @template T - The success data type\n * @template E - The error type (defaults to ServiceError)\n *\n * @example\n * ```typescript\n * const result = await kv.get('key');\n * if (result.ok) {\n * console.log(result.data);\n * } else {\n * console.error(result.error.code);\n * }\n * ```\n */\nexport type Result<T, E = ServiceError> =\n | { ok: true; data: T }\n | { ok: false; error: E };\n\n/**\n * Service error with structured information.\n */\nexport interface ServiceError {\n /** Error code for programmatic handling (e.g., 'KV_NOT_FOUND', 'AUTH_EXPIRED') */\n code: string;\n /** Human-readable error message */\n message: string;\n /** Service that produced the error (e.g., 'kv', 'sql') */\n service: string;\n /** Original error if this wraps another error */\n cause?: Error;\n /** Additional metadata about the error */\n meta?: Record<string, unknown>;\n}\n\n/**\n * A node-supplied permission hint after strict SDK validation. This is\n * deliberately narrower than a general capability: no wildcards, caveats,\n * descriptions, or transport metadata can cross the service boundary.\n */\nexport interface PermissionHint {\n readonly service: \"tinycloud.kv\" | \"tinycloud.encryption\";\n readonly space?: string;\n readonly path: string;\n readonly actions: readonly string[];\n}\n\n/**\n * Storage quota information returned with quota-related errors.\n * @deprecated Read `usedBytes`, `limitBytes` and `account` from the error's\n * `meta`, or use `StorageFullEvent` from `tc.on(\"storage.full\", handler)`.\n */\nexport interface StorageQuotaInfo {\n usedBytes: number;\n limitBytes: number;\n service: string;\n}\n\n/**\n * Standard error codes used across services.\n */\nexport const ErrorCodes = {\n // Common errors\n NOT_FOUND: \"NOT_FOUND\",\n AUTH_EXPIRED: \"AUTH_EXPIRED\",\n AUTH_REQUIRED: \"AUTH_REQUIRED\",\n AUTH_UNAUTHORIZED: \"AUTH_UNAUTHORIZED\",\n /** HTTP 401: the delegation the invocation cites was revoked. */\n AUTH_DELEGATION_REVOKED: \"AUTH_DELEGATION_REVOKED\",\n /** HTTP 401: a delegation the cited one rests on was revoked. */\n AUTH_DELEGATION_ANCESTOR_REVOKED: \"AUTH_DELEGATION_ANCESTOR_REVOKED\",\n NETWORK_ERROR: \"NETWORK_ERROR\",\n TIMEOUT: \"TIMEOUT\",\n ABORTED: \"ABORTED\",\n INVALID_INPUT: \"INVALID_INPUT\",\n PERMISSION_DENIED: \"PERMISSION_DENIED\",\n\n // Node retry signals (tinycloud-node #347). `meta.retryable` says whether a\n // retry is safe; `meta.retryAfterMs` carries the node's Retry-After.\n /** HTTP 503 `sql_busy:<stage>` / `unavailable_retryable`/`read_audit_busy`: nothing was applied; retry after `meta.retryAfterMs`. */\n NODE_BUSY: \"NODE_BUSY\",\n /** HTTP 503 `request_timeout`: the node's deadline passed before any write began; nothing was applied. */\n REQUEST_TIMEOUT: \"REQUEST_TIMEOUT\",\n /** HTTP 500 `outcome_unknown`: a write may have been applied; read back before retrying a non-idempotent operation. */\n OUTCOME_UNKNOWN: \"OUTCOME_UNKNOWN\",\n\n // KV-specific errors\n KV_NOT_FOUND: \"KV_NOT_FOUND\",\n KV_WRITE_FAILED: \"KV_WRITE_FAILED\",\n KV_PRECONDITION_FAILED: \"KV_PRECONDITION_FAILED\",\n KV_CONFLICT: \"KV_CONFLICT\",\n KV_RESPONSE_TOO_LARGE: \"KV_RESPONSE_TOO_LARGE\",\n /** HTTP 410 from the change feed: discard sync state and restart without a cursor; `meta.reason` says why. */\n KV_SYNC_RESET_REQUIRED: \"KV_SYNC_RESET_REQUIRED\",\n /** HTTP 403 from the change feed: the retention grant was refused; `meta.reason` says why. */\n KV_RETENTION_GRANT_REFUSED: \"KV_RETENTION_GRANT_REFUSED\",\n\n // SQL-specific errors\n SQL_ERROR: \"SQL_ERROR\",\n SQL_PERMISSION_DENIED: \"SQL_PERMISSION_DENIED\",\n SQL_DATABASE_NOT_FOUND: \"SQL_DATABASE_NOT_FOUND\",\n SQL_RESPONSE_TOO_LARGE: \"SQL_RESPONSE_TOO_LARGE\",\n SQL_QUOTA_EXCEEDED: \"SQL_QUOTA_EXCEEDED\",\n SQL_INVALID_STATEMENT: \"SQL_INVALID_STATEMENT\",\n SQL_SCHEMA_ERROR: \"SQL_SCHEMA_ERROR\",\n SQL_READONLY_VIOLATION: \"SQL_READONLY_VIOLATION\",\n\n // Storage quota errors\n STORAGE_QUOTA_EXCEEDED: \"STORAGE_QUOTA_EXCEEDED\",\n STORAGE_LIMIT_REACHED: \"STORAGE_LIMIT_REACHED\",\n /** The node answered the usage read without usage numbers (it predates the read). */\n STORAGE_STATUS_UNAVAILABLE: \"STORAGE_STATUS_UNAVAILABLE\",\n\n // DuckDB-specific errors\n DUCKDB_ERROR: \"DUCKDB_ERROR\",\n DUCKDB_PERMISSION_DENIED: \"DUCKDB_PERMISSION_DENIED\",\n DUCKDB_DATABASE_NOT_FOUND: \"DUCKDB_DATABASE_NOT_FOUND\",\n DUCKDB_RESPONSE_TOO_LARGE: \"DUCKDB_RESPONSE_TOO_LARGE\",\n DUCKDB_QUOTA_EXCEEDED: \"DUCKDB_QUOTA_EXCEEDED\",\n DUCKDB_INVALID_STATEMENT: \"DUCKDB_INVALID_STATEMENT\",\n DUCKDB_SCHEMA_ERROR: \"DUCKDB_SCHEMA_ERROR\",\n DUCKDB_READONLY_VIOLATION: \"DUCKDB_READONLY_VIOLATION\",\n} as const;\n\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];\n\n// =============================================================================\n// Service Session\n// =============================================================================\n\n/**\n * Session data required for authenticated service operations.\n * Both TinyCloudSession and web-sdk Session can be cast to this interface.\n */\nexport interface ServiceSession {\n /** The delegation header containing the UCAN */\n delegationHeader: { Authorization: string };\n /** The delegation CID */\n delegationCid: string;\n /** The space ID for this session */\n spaceId: string;\n /** The verification method DID */\n verificationMethod: string;\n /** The session key JWK (required for invoke) */\n jwk: object;\n}\n\n// =============================================================================\n// Platform Dependencies (Injected)\n// =============================================================================\n\n/**\n * Headers type - compatible with both browser and Node.js.\n */\nexport type ServiceHeaders = Record<string, string> | [string, string][];\n\n/**\n * A single fact object to include in the UCAN invocation.\n * Facts are key-value objects that the server reads from the UCAN facts field.\n */\nexport interface InvocationFact {\n [key: string]: unknown;\n}\n\n/**\n * Facts to include in the UCAN invocation.\n * This is an array of fact objects per the UCAN spec.\n * Used to pass additional parameters that the server reads from the UCAN facts field.\n */\nexport type InvocationFacts = InvocationFact[];\n\n/**\n * Invoke function signature - platform-specific implementation injected via DI.\n * Both node-sdk-wasm and web-sdk-wasm export this with identical signature.\n *\n * @param session - The service session with delegation data\n * @param service - Service name (e.g., \"kv\")\n * @param path - Resource path or key\n * @param action - Action to perform (e.g., \"tinycloud.kv/get\")\n * @param facts - Optional facts to include in the UCAN (e.g., for capabilities/read params)\n * @returns Headers to include in the request\n */\nexport type InvokeFunction = (\n session: ServiceSession,\n service: string,\n path: string,\n action: string,\n facts?: InvocationFacts,\n) => ServiceHeaders;\n\n/**\n * Multi-resource invocation entry.\n */\nexport interface InvokeAnyEntry {\n /**\n * Legacy space-scoped resource. Optional when `resource` is provided.\n */\n spaceId?: string;\n service: string;\n path: string;\n action: string;\n /** Optional raw resource URI. When set, WASM signs this URI directly. */\n resource?: string;\n /** Capability caveats that must remain on this invocation attenuation. */\n caveats?: Record<string, unknown>[];\n}\n\n/**\n * Invoke function for minting a single authorization header that covers\n * multiple capabilities across one effective invoker.\n */\nexport type InvokeAnyFunction = (\n session: ServiceSession,\n entries: InvokeAnyEntry[],\n facts?: InvocationFacts,\n) => ServiceHeaders;\n\n/**\n * Fetch request options - compatible with standard fetch API.\n */\nexport interface FetchRequestInit {\n method?: string;\n headers?: ServiceHeaders;\n body?: Blob | FormData | string;\n signal?: AbortSignal;\n redirect?: \"error\";\n}\n\n/**\n * Fetch response interface - compatible with standard Response.\n */\nexport interface FetchResponse {\n ok: boolean;\n status: number;\n statusText: string;\n body?: unknown;\n headers: {\n get(name: string): string | null;\n };\n json(): Promise<unknown>;\n text(): Promise<string>;\n arrayBuffer(): Promise<ArrayBuffer>;\n blob(): Promise<Blob>;\n /** Present on standard Responses; the retry reads a clone so the caller's body stays intact. */\n clone?(): FetchResponse;\n /** Set by `ServiceContext.invokeWithRetry` on the response it returns: how many requests it took. */\n retry?: RetryStats;\n}\n\n/** What automatic retry cost one request, so latency can be split from backoff. */\nexport interface RetryStats {\n /** Requests sent, including the first (1 means no retry). */\n attempts: number;\n /** Total milliseconds spent waiting between attempts. */\n backoffMs: number;\n}\n\n/**\n * Fetch function signature - allows for custom fetch implementations.\n * Compatible with both browser fetch and Node.js fetch.\n */\nexport type FetchFunction = (\n url: string,\n init?: FetchRequestInit,\n) => Promise<FetchResponse>;\n\n// =============================================================================\n// Retry Policy\n// =============================================================================\n\n/**\n * Automatic retry of node responses that guarantee nothing was applied\n * (`NODE_BUSY`, `REQUEST_TIMEOUT`). Applied once, in the service context's\n * `invokeWithRetry`, which re-mints the signed invocation per attempt. Backoff\n * is full-jitter: each delay is uniform in `[0, step]`, where\n * `step` is the strategy's delay capped at `maxDelayMs`. A node `Retry-After`\n * replaces the delay. Opt out with `{ maxAttempts: 1 }`.\n */\nexport interface RetryPolicy {\n /** Maximum number of attempts (including initial) */\n maxAttempts: number;\n /** Backoff strategy between retries */\n backoff: \"none\" | \"linear\" | \"exponential\";\n /** Base delay in milliseconds for backoff calculation */\n baseDelayMs: number;\n /** Maximum delay in milliseconds between retries */\n maxDelayMs: number;\n /** Node error codes that trigger a retry. `OUTCOME_UNKNOWN` is never retried. */\n retryableErrors: string[];\n /** Total time budget for all attempts and waits, in milliseconds. Unset: no cap. */\n maxTotalMs?: number;\n}\n\n/**\n * Default retry policy.\n */\nexport const defaultRetryPolicy: RetryPolicy = {\n maxAttempts: 4,\n backoff: \"exponential\",\n baseDelayMs: 250,\n maxDelayMs: 4000,\n retryableErrors: [ErrorCodes.NODE_BUSY, ErrorCodes.REQUEST_TIMEOUT],\n maxTotalMs: 12000,\n};\n\n// =============================================================================\n// Service Context\n// =============================================================================\n\n/**\n * Event handler function type.\n */\nexport type EventHandler = (data: unknown) => void;\n\n/**\n * SDK telemetry event handler.\n */\nexport type TelemetryEventHandler = (event: string, data: unknown) => void;\n\n/**\n * Default-off telemetry configuration.\n */\nexport type TelemetryConfig =\n | boolean\n | {\n enabled?: boolean;\n onEvent?: TelemetryEventHandler;\n };\n\n/**\n * Service interface - base contract for all services.\n */\nexport interface IService {\n /** Initialize service with context */\n initialize(context: IServiceContext): void;\n\n /** Called when session changes (sign-in, sign-out, refresh) */\n onSessionChange(session: ServiceSession | null): void;\n\n /** Called when SDK signs out - should abort pending operations */\n onSignOut(): void;\n\n /** Service-specific configuration */\n readonly config: Record<string, unknown>;\n}\n\n/**\n * Context provided to services for accessing platform dependencies.\n * The SDK creates this context and passes it to services during initialization.\n */\nexport interface IServiceContext {\n // Session management\n /** Current active session, or null if not authenticated */\n readonly session: ServiceSession | null;\n /** Whether there is an active authenticated session */\n readonly isAuthenticated: boolean;\n\n // Platform dependencies (injected by SDK)\n /** Platform-specific invoke function from WASM binding */\n readonly invoke: InvokeFunction;\n /** Optional multi-resource invoke function */\n readonly invokeAny?: InvokeAnyFunction;\n /** Fetch function (defaults to globalThis.fetch) */\n readonly fetch: FetchFunction;\n /** Send a signed invocation, retrying a busy node; `build` re-signs per attempt. Absent: sends once. */\n invokeWithRetry?(\n url: string,\n build: () => FetchRequestInit | Promise<FetchRequestInit>,\n ): Promise<FetchResponse>;\n /** Available TinyCloud host URLs */\n readonly hosts: string[];\n\n // Cross-service access\n /** Get another registered service by name */\n getService<T extends IService>(name: string): T | undefined;\n\n // Telemetry/Events\n /** Emit a telemetry event */\n emit(event: string, data: unknown): void;\n /** Subscribe to events */\n on(event: string, handler: EventHandler): () => void;\n\n // Lifecycle\n /** Abort signal that fires when SDK signs out. */\n readonly abortSignal: AbortSignal;\n /** Additional abort signal for a scoped operation, when active. */\n readonly operationAbortSignal?: AbortSignal;\n /** Install an additional signal for the duration of a scoped operation. */\n setOperationAbortSignal?(signal: AbortSignal | undefined): void;\n // Retry policy\n /** Retry policy for failed requests */\n readonly retryPolicy: RetryPolicy;\n}\n\n// =============================================================================\n// Telemetry Events\n// =============================================================================\n\n/**\n * Event emitted before a service request.\n */\nexport interface ServiceRequestEvent {\n service: string;\n action: string;\n span?: string;\n key?: string;\n timestamp: number;\n}\n\n/**\n * Event emitted after a service response.\n */\nexport interface ServiceResponseEvent {\n service: string;\n action: string;\n span?: string;\n ok: boolean;\n duration: number;\n durationMs?: number;\n status?: number;\n}\n\n/**\n * Event emitted on service error.\n */\nexport interface ServiceErrorEvent {\n service: string;\n span?: string;\n error: ServiceError;\n}\n\n/**\n * Event emitted on retry attempt.\n */\nexport interface ServiceRetryEvent {\n service: string;\n attempt: number;\n maxAttempts: number;\n error: ServiceError;\n}\n\n/**\n * Generic named span event for aggregating operation timings.\n */\nexport interface TelemetrySpanEvent {\n span: string;\n ok: boolean;\n durationMs: number;\n service?: string;\n action?: string;\n status?: number;\n error?: ServiceError;\n}\n\n/**\n * Telemetry event names.\n */\nexport const TelemetryEvents = {\n SPAN: \"telemetry.span\",\n SERVICE_REQUEST: \"service.request\",\n SERVICE_RESPONSE: \"service.response\",\n SERVICE_ERROR: \"service.error\",\n SERVICE_RETRY: \"service.retry\",\n SESSION_CHANGED: \"session.changed\",\n SESSION_EXPIRED: \"session.expired\",\n REPLICATION_READ: \"replication.read\",\n REPLICATION_WRITE: \"replication.write\",\n REPLICATION_SYNC: \"replication.sync\",\n REPLICATION_STATE: \"replication.state\",\n REPLICATION_DIVERGENCE: \"replication.divergence\",\n REPLICATION_GRANT: \"replication.grant\",\n REPLICATION_LIFECYCLE: \"replication.lifecycle\",\n /** Emitted once, on the first write rejected because storage is full. */\n STORAGE_FULL: \"storage.full\",\n} as const;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Create a success result.\n */\nexport function ok<T>(data: T): Result<T> {\n return { ok: true, data };\n}\n\n/**\n * Create an error result.\n */\nexport function err<E = ServiceError>(error: E): Result<never, E> {\n return { ok: false, error };\n}\n\n/**\n * Create a ServiceError.\n */\nexport function serviceError(\n code: string,\n message: string,\n service: string,\n options?: { cause?: Error; meta?: Record<string, unknown> },\n): ServiceError {\n return {\n code,\n message,\n service,\n cause: options?.cause,\n meta: options?.meta,\n };\n}\n","import { z } from \"zod\";\nimport type { FeedCard, FeedHandling, FeedResponsePayload, JSONValue, NewFeedMessage, NewFeedResponse } from \"./types\";\n\nfunction isJSONValue(value: unknown, active = new Set<object>()): value is JSONValue {\n if (value === null || typeof value === \"boolean\" || typeof value === \"string\") return true;\n if (typeof value === \"number\") return Number.isFinite(value);\n if (typeof value !== \"object\" || active.has(value)) return false;\n if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return false;\n active.add(value);\n let valid = true;\n for (const child of Array.isArray(value) ? value : Object.values(value)) {\n if (!isJSONValue(child, active)) { valid = false; break; }\n }\n active.delete(value);\n return valid;\n}\n\n// Validate without cloning or dropping literal JSON keys such as \"__proto__\".\nconst jsonValueSchema = z.custom<JSONValue>((value) => isJSONValue(value));\n\nexport const feedResponsePayloadSchema: z.ZodType<FeedResponsePayload> = z.object({\n type: z.string().min(1), version: z.number().int().positive(), data: jsonValueSchema,\n}).strict();\n\nconst identity = {\n cardId: z.string().min(1), revision: z.number().int().positive(), issuanceId: z.string().min(1),\n};\nexport const feedCardSchema: z.ZodType<FeedCard> = z.object({\n ...identity, kind: z.string().min(1), needsResponse: z.boolean(), title: z.string(), body: z.string(),\n choices: z.array(z.object({ id: z.string().min(1), label: z.string() })).optional(),\n urgency: z.number().finite(), createdAt: z.string().min(1), payload: z.record(z.unknown()).optional(),\n});\nexport const newFeedResponseSchema: z.ZodType<NewFeedResponse> = z.object({\n ...identity, responseId: z.string().min(1), kind: z.enum([\"answer\", \"followup\"]),\n choiceId: z.string().min(1).optional(), text: z.string().optional(),\n supersedesResponseId: z.string().min(1).optional(), createdAt: z.string().min(1),\n});\nexport const newFeedMessageSchema: z.ZodType<NewFeedMessage> = z.object({\n ...identity, responseId: z.string().min(1), kind: z.literal(\"message\"),\n text: z.string(), createdAt: z.string().min(1),\n}).strict();\nexport const feedResponseHeaderSchema = z.union([newFeedResponseSchema, newFeedMessageSchema]);\nexport const feedHandlingSchema: z.ZodType<FeedHandling> = z.object({\n ...identity, handlingId: z.string().min(1), responseId: z.string().min(1),\n phase: z.enum([\"acknowledged\", \"succeeded\", \"failed\"]), createdAt: z.string().min(1),\n detail: z.record(z.unknown()).optional(),\n});\n","import { z } from \"zod\";\nimport { ErrorCodes, err } from \"../types\";\nimport type { Result, ServiceError } from \"../types\";\nimport type { FeedResponse } from \"./types\";\n\nconst timestamp = z.string().datetime({ offset: true });\nexport function validDispatchBefore(value: unknown): value is string | null {\n return value === null || (typeof value === \"string\" && timestamp.safeParse(value).success && Number.isFinite(Date.parse(value)));\n}\nexport function dispatchDeadlineDenied(response: FeedResponse): boolean {\n const cutoff: unknown = response.dispatchBefore;\n return cutoff !== undefined && (!validDispatchBefore(cutoff) || (typeof cutoff === \"string\" && Date.now() >= Date.parse(cutoff)));\n}\nexport function dispatchDeadlineFailure(): Result<never> {\n return err({ code: ErrorCodes.PERMISSION_DENIED, service: \"feed\", message: \"The response dispatch deadline does not permit a new handoff.\", meta: { reason: \"dispatch_deadline\" } });\n}\nexport function isDispatchDeadlineFailure(error: ServiceError): boolean {\n return error.service === \"feed\" && error.code === ErrorCodes.PERMISSION_DENIED && error.meta?.reason === \"dispatch_deadline\";\n}\n","import type { FeedApi, FeedResponse } from \"./types\";\nimport { validDispatchBefore } from \"./dispatch\";\n\n/** A notification is an allowlisted header, never a copy of private payload data. */\nexport const projectFeedResponseNotification: FeedApi[\"projectFeedResponseNotification\"] = (response) => {\n const notification: FeedResponse = {\n responseId: response.responseId,\n cardId: response.cardId,\n revision: response.revision,\n issuanceId: response.issuanceId,\n kind: response.kind,\n createdAt: response.createdAt,\n sequence: response.sequence,\n };\n if (response.kind !== \"message\" && response.choiceId !== undefined) notification.choiceId = response.choiceId;\n if (response.text !== undefined) notification.text = response.text;\n if (response.kind !== \"message\" && response.supersedesResponseId !== undefined) notification.supersedesResponseId = response.supersedesResponseId;\n if (response.payloadType !== undefined) notification.payloadType = response.payloadType;\n if (response.payloadVersion !== undefined) notification.payloadVersion = response.payloadVersion;\n if (validDispatchBefore(response.dispatchBefore)) notification.dispatchBefore = response.dispatchBefore;\n return notification;\n};\n","import { ErrorCodes, err, ok } from \"../types\";\nimport type { Result } from \"../types\";\nimport type { QueryOptions, SqlStatement, SqlValue } from \"../sql/types\";\nimport type {\n FeedApi, FeedCard, FeedCardIdentity, FeedDatabase, FeedHandling, FeedReadDatabase, FeedResponse,\n FeedResponseHandling, FeedResponseIdentity, FeedResponsePayload, NewFeedMessage, NewFeedResponse,\n} from \"./types\";\nimport { feedResponseHeaderSchema, feedResponsePayloadSchema, newFeedMessageSchema, newFeedResponseSchema } from \"./schemas\";\nimport { projectFeedResponseNotification } from \"./notification\";\n\nconst PRIVATE_RESPONSE_OPTIONS: QueryOptions & { redactErrors: true } = { redactErrors: true };\n\nexport function feedError(code: string, message: string): Result<never> {\n return err({ code, message, service: \"feed\" });\n}\n\n// Canonical JSON makes identity replay independent of object-key insertion order.\nexport function feedJson(value: unknown): string {\n return JSON.stringify(value, (_key, item: unknown) => {\n if (item && typeof item === \"object\" && !Array.isArray(item)) {\n const sorted: Record<string, unknown> = Object.create(null);\n for (const key of Object.keys(item).sort()) sorted[key] = (item as Record<string, unknown>)[key];\n return sorted;\n }\n return item;\n });\n}\n\nfunction validIdentity(identity: FeedCardIdentity): boolean {\n return typeof identity.cardId === \"string\" && identity.cardId.length > 0 &&\n Number.isSafeInteger(identity.revision) && identity.revision > 0 &&\n typeof identity.issuanceId === \"string\" && identity.issuanceId.length > 0;\n}\n\nexport function sameFeedIdentity(a: FeedCardIdentity, b: FeedCardIdentity): boolean {\n return a.cardId === b.cardId && a.revision === b.revision && a.issuanceId === b.issuanceId;\n}\n\nasync function jsonRows<T>(\n db: FeedReadDatabase, sql: string, params: SqlValue[] = [], options?: QueryOptions,\n): Promise<Result<T[]>> {\n const result = await db.query<string>(sql, params, options);\n if (!result.ok) return result;\n try {\n return ok(result.data.rows.map((row) => JSON.parse(row[0]) as T));\n } catch {\n return feedError(\"INVALID_INPUT\", \"Feed record contains invalid JSON\");\n }\n}\n\nexport const RESPONSE_HEADER_SELECT = `SELECT r.sequence, r.response_json, p.payload_type, p.payload_version\n FROM feed_responses r LEFT JOIN feed_response_payloads p ON p.response_id = r.response_id`;\n\nexport function responseDataFailure(message: string, error?: unknown): Result<never> {\n let code: string = ErrorCodes.SQL_ERROR;\n if (error !== null && typeof error === \"object\" && \"code\" in error) {\n const candidate = error.code;\n if (typeof candidate === \"string\" && Object.values(ErrorCodes).some((known) => known === candidate)) code = candidate;\n }\n // Never retain raw payload-bearing SQL messages, causes, stacks, or metadata.\n return feedError(code, message);\n}\n\nexport function responseFromRow(row: unknown[]): FeedResponse {\n return responseFromHeader(row, feedResponseHeaderSchema.parse(JSON.parse(String(row[1]))));\n}\n\nfunction responseFromHeader(row: unknown[], header: NewFeedResponse | NewFeedMessage): FeedResponse {\n const response: FeedResponse = { ...header, sequence: Number(row[0]) };\n if (row[2] !== null && row[2] !== undefined) {\n response.payloadType = String(row[2]);\n response.payloadVersion = Number(row[3]);\n }\n return projectFeedResponseNotification(response);\n}\n\nexport async function storedResponse(db: FeedReadDatabase, responseId: string, options: QueryOptions = PRIVATE_RESPONSE_OPTIONS) {\n try {\n const result = await db.query<unknown>(`SELECT r.sequence, r.response_json, p.payload_type, p.payload_version, p.payload_json\n FROM feed_responses r LEFT JOIN feed_response_payloads p ON p.response_id = r.response_id\n WHERE r.response_id = ?`, [responseId], options);\n if (!result.ok) return responseDataFailure(\"Could not read the saved feed response\", result.error);\n const row = result.data.rows[0];\n if (!row) return ok(undefined);\n const header = feedResponseHeaderSchema.parse(JSON.parse(String(row[1])));\n const response = responseFromHeader(row, header);\n const payload: FeedResponsePayload | undefined = row[2] === null || row[2] === undefined ? undefined\n : feedResponsePayloadSchema.parse({ type: row[2], version: Number(row[3]), data: JSON.parse(String(row[4])) });\n return ok({ response, rawHeaderJson: String(row[1]), headerJson: feedJson(header), payload });\n } catch (error) {\n return responseDataFailure(\"Could not read the saved feed response\", error);\n }\n}\n\nexport const initializeFeedDatabases: FeedApi[\"initializeFeedDatabases\"] = async ({ output, responses }) => {\n const initialized = await output.batch([\n { sql: `CREATE TABLE IF NOT EXISTS feed_cards (\n sequence INTEGER PRIMARY KEY AUTOINCREMENT,\n card_id TEXT NOT NULL, revision INTEGER NOT NULL CHECK (revision > 0), issuance_id TEXT NOT NULL,\n card_json TEXT NOT NULL, UNIQUE (card_id, revision, issuance_id)\n )` },\n { sql: `CREATE TABLE IF NOT EXISTS feed_handling (\n sequence INTEGER PRIMARY KEY AUTOINCREMENT, handling_id TEXT NOT NULL UNIQUE,\n response_id TEXT NOT NULL, card_id TEXT NOT NULL, revision INTEGER NOT NULL, issuance_id TEXT NOT NULL,\n phase TEXT NOT NULL CHECK (phase IN ('acknowledged', 'succeeded', 'failed')),\n handling_json TEXT NOT NULL\n )` },\n { sql: \"CREATE INDEX IF NOT EXISTS feed_handling_response ON feed_handling (response_id, sequence)\" },\n ]);\n if (!initialized.ok) return initialized;\n const responseSchema = await responses.batch([\n { sql: `CREATE TABLE IF NOT EXISTS feed_responses (\n sequence INTEGER PRIMARY KEY AUTOINCREMENT, response_id TEXT NOT NULL UNIQUE,\n card_id TEXT NOT NULL, revision INTEGER NOT NULL, issuance_id TEXT NOT NULL,\n response_json TEXT NOT NULL\n )` },\n { sql: \"CREATE INDEX IF NOT EXISTS feed_responses_card ON feed_responses (card_id, revision, issuance_id, sequence)\" },\n { sql: `CREATE TABLE IF NOT EXISTS feed_response_payloads (\n response_id TEXT PRIMARY KEY, payload_type TEXT NOT NULL, payload_version INTEGER NOT NULL, payload_json TEXT NOT NULL\n )` },\n { sql: `CREATE TABLE IF NOT EXISTS feed_response_imports (\n response_id TEXT PRIMARY KEY, card_id TEXT NOT NULL, revision INTEGER NOT NULL, issuance_id TEXT NOT NULL,\n content_sha256 TEXT NOT NULL\n )` },\n { sql: `CREATE TABLE IF NOT EXISTS feed_response_origins (\n response_id TEXT NOT NULL, source_json TEXT NOT NULL, PRIMARY KEY (response_id, source_json)\n )` },\n { sql: `CREATE TABLE IF NOT EXISTS feed_response_delivery_policies (\n response_id TEXT NOT NULL, recipient TEXT NOT NULL, policy_json TEXT NOT NULL,\n PRIMARY KEY (response_id, recipient, policy_json)\n )` },\n ]);\n return responseSchema.ok ? ok(undefined) : responseSchema;\n};\n\nexport const publishFeedCard: FeedApi[\"publishFeedCard\"] = (output, card) => storeFeedCard(output, card);\n\nexport async function storeFeedCard(output: FeedDatabase, card: FeedCard, options?: QueryOptions): Promise<Result<FeedCard>> {\n if (!validIdentity(card)) return feedError(\"INVALID_INPUT\", \"A card requires its full ID, positive revision and issuance ID\");\n const encoded = feedJson(card);\n const inserted = await output.execute(\n `INSERT INTO feed_cards (card_id, revision, issuance_id, card_json) VALUES (?, ?, ?, ?)\n ON CONFLICT (card_id, revision, issuance_id) DO NOTHING`,\n [card.cardId, card.revision, card.issuanceId, encoded], options,\n );\n if (!inserted.ok) return inserted;\n const stored = await jsonRows<FeedCard>(output,\n \"SELECT card_json FROM feed_cards WHERE card_id = ? AND revision = ? AND issuance_id = ?\",\n [card.cardId, card.revision, card.issuanceId], options);\n if (!stored.ok) return stored;\n if (!stored.data[0] || feedJson(stored.data[0]) !== encoded) {\n return feedError(\"INVALID_INPUT\", \"A published card identity cannot be silently changed\");\n }\n return ok(stored.data[0]);\n}\n\nexport const listFeedCards: FeedApi[\"listFeedCards\"] = async (output) => {\n return jsonRows<FeedCard>(output, `SELECT card_json FROM feed_cards\n WHERE sequence IN (SELECT MAX(sequence) FROM feed_cards GROUP BY card_id) ORDER BY sequence DESC`);\n};\n\nexport const appendFeedResponse: FeedApi[\"appendFeedResponse\"] = async (output, responses, input, payload) => {\n try {\n const header = newFeedResponseSchema.safeParse(input);\n if (!header.success) return feedError(\"INVALID_INPUT\", \"Invalid feed response header\");\n return appendResponse(output, responses, header.data, payload);\n } catch {\n return feedError(\"INVALID_INPUT\", \"Invalid feed response header\");\n }\n};\n\nexport const appendFeedMessage: FeedApi[\"appendFeedMessage\"] = async (output, responses, input, payload) => {\n try {\n const header = newFeedMessageSchema.safeParse(input);\n if (!header.success) return feedError(\"INVALID_INPUT\", \"Invalid feed message header\");\n return appendResponse(output, responses, header.data, payload);\n } catch {\n return feedError(\"INVALID_INPUT\", \"Invalid feed message header\");\n }\n};\n\nasync function appendResponse(\n output: FeedReadDatabase,\n responses: FeedDatabase,\n response: NewFeedResponse | NewFeedMessage,\n inputPayload?: FeedResponsePayload,\n): Promise<Result<FeedResponse>> {\n let payload: FeedResponsePayload | undefined;\n try {\n if (inputPayload !== undefined) {\n const parsed = feedResponsePayloadSchema.safeParse(inputPayload);\n if (!parsed.success) return feedError(\"INVALID_INPUT\", \"Invalid private feed response payload\");\n payload = parsed.data;\n }\n } catch {\n return feedError(\"INVALID_INPUT\", \"Invalid feed response or private payload\");\n }\n try {\n const cards = await jsonRows<FeedCard>(output,\n \"SELECT card_json FROM feed_cards WHERE card_id = ? AND revision = ? AND issuance_id = ?\",\n [response.cardId, response.revision, response.issuanceId], PRIVATE_RESPONSE_OPTIONS);\n if (!cards.ok) return responseDataFailure(\"Could not verify the response card issuance\", cards.error);\n const card = cards.data[0];\n if (!card || !sameFeedIdentity(card, response)) {\n return feedError(\"INVALID_INPUT\", \"The response does not identify a published card issuance\");\n }\n if (response.kind !== \"message\") {\n if (!card.needsResponse) {\n return feedError(\"INVALID_INPUT\", \"The response does not identify a published actionable card issuance\");\n }\n if (response.choiceId !== undefined && !card.choices?.some((choice) => choice.id === response.choiceId)) {\n return feedError(\"INVALID_INPUT\", \"The response choice is not part of this card issuance\");\n }\n if (response.supersedesResponseId) {\n const previous = await jsonRows<FeedResponse>(responses,\n \"SELECT response_json FROM feed_responses WHERE response_id = ?\", [response.supersedesResponseId], PRIVATE_RESPONSE_OPTIONS);\n if (!previous.ok) return responseDataFailure(\"Could not verify the corrected response\", previous.error);\n if (!previous.data[0] || !sameFeedIdentity(previous.data[0], response)) {\n return feedError(\"INVALID_INPUT\", \"A correction must reference a response to the same card issuance\");\n }\n }\n }\n const encoded = feedJson(response);\n const match = (stored: { response: FeedResponse; headerJson: string; payload?: FeedResponsePayload }) => {\n const samePayload = payload === undefined ? stored.payload === undefined\n : stored.payload !== undefined && feedJson(stored.payload) === feedJson(payload);\n return stored.headerJson === encoded && samePayload ? ok(stored.response)\n : feedError(\"INVALID_INPUT\", \"A response ID cannot be reused for different header or private payload content\");\n };\n const existing = await storedResponse(responses, response.responseId);\n if (!existing.ok) return existing;\n if (existing.data) return match(existing.data);\n const statements: SqlStatement[] = [{\n sql: \"INSERT INTO feed_responses (response_id, card_id, revision, issuance_id, response_json) VALUES (?, ?, ?, ?, ?)\",\n params: [response.responseId, response.cardId, response.revision, response.issuanceId, encoded],\n }];\n if (payload !== undefined) statements.push({\n sql: \"INSERT INTO feed_response_payloads (response_id, payload_type, payload_version, payload_json) VALUES (?, ?, ?, ?)\",\n params: [response.responseId, payload.type, payload.version, feedJson(payload.data)],\n });\n let failed = false;\n let failure: unknown;\n try {\n // A duplicate header aborts this entire transaction; it cannot attach a late payload.\n const saved = await responses.batch(statements, PRIVATE_RESPONSE_OPTIONS);\n if (!saved.ok) { failed = true; failure = saved.error; }\n } catch (error) { failed = true; failure = error; }\n const committed = await storedResponse(responses, response.responseId);\n if (!committed.ok) return failed\n ? responseDataFailure(\"Could not save the feed response and private payload\", failure) : committed;\n if (!committed.data) return responseDataFailure(\"Could not save the feed response and private payload\", failure);\n // Concurrent identical creation is an idempotent replay only after both records match.\n return match(committed.data);\n } catch (error) {\n return responseDataFailure(\"Could not save the feed response and private payload\", error);\n }\n}\n\nexport const readFeedResponsePayload: FeedApi[\"readFeedResponsePayload\"] = async (responses, identity) => {\n if (!validIdentity(identity) || typeof identity.responseId !== \"string\" || !identity.responseId) {\n return feedError(\"INVALID_INPUT\", \"A private payload read requires the full response and card identity\");\n }\n try {\n const result = await responses.query<unknown>(`SELECT p.payload_type, p.payload_version, p.payload_json\n FROM feed_responses r LEFT JOIN feed_response_payloads p ON p.response_id = r.response_id\n WHERE r.response_id = ? AND r.card_id = ? AND r.revision = ? AND r.issuance_id = ?`,\n [identity.responseId, identity.cardId, identity.revision, identity.issuanceId], PRIVATE_RESPONSE_OPTIONS);\n if (!result.ok) return responseDataFailure(\"Could not read the private feed response payload\", result.error);\n const row = result.data.rows[0];\n if (!row) return feedError(\"NOT_FOUND\", \"The response identity does not match a saved response\");\n if (row[0] === null || row[0] === undefined) return ok(undefined);\n const parsed = feedResponsePayloadSchema.safeParse({ type: row[0], version: Number(row[1]), data: JSON.parse(String(row[2])) });\n return parsed.success ? ok(parsed.data) : feedError(\"INVALID_INPUT\", \"The saved private response payload is invalid\");\n } catch (error) {\n return responseDataFailure(\"Could not read the private feed response payload\", error);\n }\n};\n\nexport const listFeedResponses: FeedApi[\"listFeedResponses\"] = async (responses, options = {}) => {\n const after = options.afterSequence ?? 0;\n const limit = options.limit ?? 100;\n if (!Number.isSafeInteger(after) || after < 0 || !Number.isSafeInteger(limit) || limit < 1 || limit > 1000) {\n return feedError(\"INVALID_INPUT\", \"Response pagination requires a nonnegative sequence and limit between 1 and 1000\");\n }\n try {\n const result = await responses.query<unknown>(\n `${RESPONSE_HEADER_SELECT} WHERE r.sequence > ? ORDER BY r.sequence LIMIT ?`, [after, limit],\n { ...PRIVATE_RESPONSE_OPTIONS, signal: options.signal });\n if (!result.ok) return responseDataFailure(\"Could not list feed responses\", result.error);\n return ok(result.data.rows.map(responseFromRow));\n } catch (error) {\n return responseDataFailure(\"Could not list feed responses\", error);\n }\n};\n\nexport const recordFeedHandling: FeedApi[\"recordFeedHandling\"] = async (output, handling) => {\n if (!validIdentity(handling) || !handling.handlingId || !handling.responseId ||\n ![\"acknowledged\", \"succeeded\", \"failed\"].includes(handling.phase)) {\n return feedError(\"INVALID_INPUT\", \"Handling requires full response and card identities and a known phase\");\n }\n const previous = await jsonRows<FeedHandling>(output,\n \"SELECT handling_json FROM feed_handling WHERE response_id = ? ORDER BY sequence\", [handling.responseId]);\n if (!previous.ok) return previous;\n if (previous.data.some((item) => !sameFeedIdentity(item, handling))) {\n return feedError(\"INVALID_INPUT\", \"Handling cannot move a response to another card issuance\");\n }\n const encoded = feedJson(handling);\n const duplicate = previous.data.find((item) => item.handlingId === handling.handlingId);\n if (duplicate) {\n return feedJson(duplicate) === encoded ? ok(duplicate) : feedError(\"INVALID_INPUT\", \"A handling ID cannot change content\");\n }\n const knownOutcome = previous.data.find((item) => item.phase !== \"acknowledged\");\n if (knownOutcome && handling.phase !== \"acknowledged\") {\n return feedError(\"INVALID_INPUT\", \"An existing outcome requires an explicit follow-up response, not a replacement\");\n }\n // The predicate runs inside the write statement, not before its lock is acquired.\n const inserted = await output.execute(\n `INSERT INTO feed_handling (handling_id, response_id, card_id, revision, issuance_id, phase, handling_json)\n SELECT ?, ?, ?, ?, ?, ?, ?\n WHERE NOT EXISTS (\n SELECT 1 FROM feed_handling WHERE response_id = ? AND (card_id <> ? OR revision <> ? OR issuance_id <> ?)\n ) AND (? = 'acknowledged' OR NOT EXISTS (\n SELECT 1 FROM feed_handling WHERE response_id = ? AND phase IN ('succeeded', 'failed')\n )) ON CONFLICT (handling_id) DO NOTHING`,\n [handling.handlingId, handling.responseId, handling.cardId, handling.revision, handling.issuanceId, handling.phase, encoded,\n handling.responseId, handling.cardId, handling.revision, handling.issuanceId, handling.phase, handling.responseId],\n );\n if (!inserted.ok) return inserted;\n const stored = await jsonRows<FeedHandling>(output,\n \"SELECT handling_json FROM feed_handling WHERE handling_id = ?\", [handling.handlingId]);\n if (!stored.ok) return stored;\n if (!stored.data[0]) return feedError(\"INVALID_INPUT\", \"Handling conflicts with an existing outcome or response issuance\");\n return feedJson(stored.data[0]) === encoded\n ? ok(stored.data[0]) : feedError(\"INVALID_INPUT\", \"A handling ID cannot change content\");\n};\n\nasync function selectResponseHandling(\n output: FeedReadDatabase,\n identity: FeedResponseIdentity,\n): Promise<Result<FeedResponseHandling | undefined>> {\n const records = await jsonRows<FeedHandling>(output,\n `SELECT handling_json FROM feed_handling WHERE response_id = ? AND card_id = ? AND revision = ? AND issuance_id = ?\n ORDER BY sequence`, [identity.responseId, identity.cardId, identity.revision, identity.issuanceId]);\n if (!records.ok) return records;\n if (records.data.length === 0) return ok(undefined);\n const handling: FeedResponseHandling = { acknowledgement: null, outcome: null };\n for (const item of records.data) {\n if (item.responseId !== identity.responseId || !sameFeedIdentity(item, identity)) {\n return feedError(\"INVALID_INPUT\", \"Stored handling does not match the response identity\");\n }\n if (item.phase === \"acknowledged\") handling.acknowledgement = item;\n else if (item.phase === \"succeeded\" || item.phase === \"failed\") handling.outcome = item;\n else return feedError(\"INVALID_INPUT\", \"Stored handling has an unknown phase\");\n }\n return ok(handling);\n}\n\nexport const readFeedResponseHandling: FeedApi[\"readFeedResponseHandling\"] = async (output, identity) => {\n if (!validIdentity(identity) || typeof identity.responseId !== \"string\" || !identity.responseId) {\n return feedError(\"INVALID_INPUT\", \"Handling reads require full response and card identities\");\n }\n const handling = await selectResponseHandling(output, identity);\n if (!handling.ok) return handling;\n return handling.data ? ok(handling.data) : feedError(\"NOT_FOUND\", \"Matching response handling not found\");\n};\n\nexport const getFeedCardState: FeedApi[\"getFeedCardState\"] = async (output, responses, identity) => {\n const params = [identity.cardId, identity.revision, identity.issuanceId];\n const cards = await jsonRows<FeedCard>(output,\n \"SELECT card_json FROM feed_cards WHERE card_id = ? AND revision = ? AND issuance_id = ?\", params);\n if (!cards.ok) return cards;\n if (!cards.data[0]) return feedError(\"NOT_FOUND\", \"Card issuance not found\");\n const saved = await responses.query<unknown>(\n `${RESPONSE_HEADER_SELECT} WHERE r.card_id = ? AND r.revision = ? AND r.issuance_id = ?\n AND json_extract(r.response_json, '$.kind') IN ('answer', 'followup')\n ORDER BY r.sequence DESC LIMIT 1`, params, PRIVATE_RESPONSE_OPTIONS);\n if (!saved.ok) return responseDataFailure(\"Could not read the card's saved response\", saved.error);\n const row = saved.data.rows[0];\n let response: FeedResponse | null;\n try { response = row ? responseFromRow(row) : null; }\n catch (error) { return responseDataFailure(\"Could not read the card's saved response\", error); }\n const handling = response ? await selectResponseHandling(output, response) : ok(undefined);\n if (!handling.ok) return handling;\n return ok({\n card: cards.data[0], response,\n acknowledgement: handling.data?.acknowledgement ?? null,\n outcome: handling.data?.outcome ?? null,\n });\n};\n\nexport const resolveFeedCard: FeedApi[\"resolveFeedCard\"] = async (output, reference) => {\n if (!reference) return feedError(\"INVALID_INPUT\", \"A card reference is required\");\n const rows = await output.query<unknown>(\n `SELECT card_id, revision, issuance_id FROM feed_cards\n WHERE card_id = ? ORDER BY sequence DESC LIMIT 1`, [reference]);\n if (!rows.ok) return rows;\n let row = rows.data.rows[0];\n if (!row) {\n const matches = await output.query<unknown>(\n `SELECT card_id, revision, issuance_id FROM feed_cards\n WHERE substr(card_id, 1, length(?)) = ? AND sequence IN\n (SELECT MAX(sequence) FROM feed_cards GROUP BY card_id) LIMIT 2`, [reference, reference]);\n if (!matches.ok) return matches;\n if (matches.data.rows.length !== 1) return feedError(\"NOT_FOUND\", \"Card reference is absent or ambiguous; use its full ID\");\n row = matches.data.rows[0];\n }\n return ok({ cardId: String(row[0]), revision: Number(row[1]), issuanceId: String(row[2]) });\n};\n","import { ok } from \"../types\";\nimport { feedError, feedJson } from \"./store\";\nimport { projectFeedResponseNotification } from \"./notification\";\nimport { dispatchDeadlineDenied, dispatchDeadlineFailure, validDispatchBefore } from \"./dispatch\";\nimport type { FeedApi, FeedHandoff } from \"./types\";\n\nexport const initializeFeedHandoff: FeedApi[\"initializeFeedHandoff\"] = async (handoff) => {\n const result = await handoff.execute(`CREATE TABLE IF NOT EXISTS feed_handoffs (\n response_id TEXT NOT NULL, recipient TEXT NOT NULL, response_json TEXT NOT NULL,\n state TEXT NOT NULL CHECK (state IN ('prepared', 'unconfirmed', 'delivered')),\n PRIMARY KEY (response_id, recipient)\n )`);\n return result.ok ? ok(undefined) : result;\n};\n\nexport const getFeedHandoff: FeedApi[\"getFeedHandoff\"] = async (handoff, responseId, recipient) => {\n const result = await handoff.query<string>(\n \"SELECT response_json, state FROM feed_handoffs WHERE response_id = ? AND recipient = ?\", [responseId, recipient]);\n if (!result.ok) return result;\n const row = result.data.rows[0];\n if (!row) return ok(null);\n try {\n const parsed = JSON.parse(row[0]);\n if (parsed.dispatchBefore !== undefined && !validDispatchBefore(parsed.dispatchBefore)) {\n return feedError(\"INVALID_INPUT\", \"Handoff contains invalid dispatch metadata\");\n }\n return ok({ responseId, recipient, response: projectFeedResponseNotification(parsed), state: row[1] as FeedHandoff[\"state\"] });\n } catch {\n return feedError(\"INVALID_INPUT\", \"Handoff contains invalid response JSON\");\n }\n};\n\nexport const deliverFeedResponse: FeedApi[\"deliverFeedResponse\"] = async ({ handoff, recipient, response: input, deliver }) => {\n // Validate before projection: an invalid supplied cutoff must not disappear into ordinary live behavior.\n if (dispatchDeadlineDenied(input)) return dispatchDeadlineFailure();\n const response = projectFeedResponseNotification(input);\n if (!recipient || !response.responseId) return feedError(\"INVALID_INPUT\", \"Handoff requires a recipient and full response ID\");\n if (dispatchDeadlineDenied(response)) return dispatchDeadlineFailure();\n const inserted = await handoff.execute(\n `INSERT INTO feed_handoffs (response_id, recipient, response_json, state) VALUES (?, ?, ?, 'prepared')\n ON CONFLICT (response_id, recipient) DO NOTHING`, [response.responseId, recipient, feedJson(response)]);\n if (!inserted.ok) return inserted;\n const existing = await getFeedHandoff(handoff, response.responseId, recipient);\n if (!existing.ok) return existing;\n if (!existing.data || feedJson(existing.data.response) !== feedJson(response)) {\n return feedError(\"INVALID_INPUT\", \"A response handoff identity cannot change its payload\");\n }\n if (existing.data.state !== \"prepared\") return ok(existing.data);\n if (dispatchDeadlineDenied(response)) return dispatchDeadlineFailure();\n\n // This durable compare-and-set is the only permission to attempt the send.\n // Crash after this point is ambiguous, even if the callback never started.\n const claimed = await handoff.execute(\n \"UPDATE feed_handoffs SET state = 'unconfirmed' WHERE response_id = ? AND recipient = ? AND state = 'prepared'\",\n [response.responseId, recipient]);\n if (!claimed.ok) return claimed;\n if (claimed.data.changes === 0) {\n const current = await getFeedHandoff(handoff, response.responseId, recipient);\n return current.ok && current.data ? ok(current.data) : current.ok\n ? feedError(\"NOT_FOUND\", \"Handoff disappeared before delivery\") : current;\n }\n if (dispatchDeadlineDenied(response)) return dispatchDeadlineFailure();\n let state: FeedHandoff[\"state\"] = \"unconfirmed\";\n try {\n const delivered = await deliver(response);\n if (delivered === \"delivered\") state = \"delivered\";\n } catch {\n // The runtime may already have accepted it. Keep the response ID and do not resend.\n }\n if (state === \"delivered\") {\n const saved = await handoff.execute(\n \"UPDATE feed_handoffs SET state = 'delivered' WHERE response_id = ? AND recipient = ? AND state = 'unconfirmed'\",\n [response.responseId, recipient]);\n if (!saved.ok) return saved;\n }\n return ok({ ...existing.data, state });\n};\n","import { z } from \"zod\";\nimport { ErrorCodes, ok } from \"../types\";\nimport type { Result } from \"../types\";\nimport type { QueryOptions } from \"../sql/types\";\nimport { feedError, feedJson, responseDataFailure, sameFeedIdentity } from \"./store\";\nimport { feedResponseHeaderSchema, feedResponsePayloadSchema } from \"./schemas\";\nimport { validDispatchBefore } from \"./dispatch\";\nimport type { FeedReadDatabase, FeedResponseIdentity, FeedResponsePayload, NewFeedMessage, NewFeedResponse } from \"./types\";\nimport type { FeedRestoreDeliveryPolicy, FeedRestoreOrigin } from \"./restore-types\";\n\nexport const restoreOriginSchema: z.ZodType<FeedRestoreOrigin> = z.object({\n sourceSpaceId: z.string().min(1), namespace: z.string().min(1), snapshotId: z.string().min(1),\n sourceKey: z.string().min(1), eventKey: z.string().min(1).optional(),\n}).strict();\nexport const restorePolicySchema: z.ZodType<FeedRestoreDeliveryPolicy> = z.object({\n recipient: z.string().min(1), state: z.enum([\"pending\", \"held\", \"delivered\", \"unconfirmed\", \"refused\", \"unknown\"]),\n dispatch: z.enum([\"never\", \"resolved-pending\", \"held\"]), resolvedOwnerMapping: z.boolean(),\n dispatchBefore: z.custom<string | null>(validDispatchBefore), source: restoreOriginSchema,\n}).strict();\n\nexport interface RestoreContent {\n response: NewFeedResponse | NewFeedMessage;\n headerJson: string;\n payload?: FeedResponsePayload;\n payloadJson?: string;\n canonical: string;\n}\nexport function restoreContent(input: unknown, inputPayload?: unknown): RestoreContent {\n const response = feedResponseHeaderSchema.parse(input);\n const headerJson = feedJson(response);\n if (feedJson(input) !== headerJson) throw new Error(\"Invalid restored response header fields\");\n const payload = inputPayload === undefined ? undefined : feedResponsePayloadSchema.parse(inputPayload);\n const payloadJson = payload === undefined ? undefined : feedJson(payload.data);\n const envelope = payload === undefined ? \"null\"\n : `{\"data\":${payloadJson},\"type\":${JSON.stringify(payload.type)},\"version\":${payload.version}}`;\n return { response, headerJson, payload, payloadJson, canonical: `{\"payload\":${envelope},\"response\":${headerJson}}` };\n}\nexport async function contentSha256(content: string): Promise<string> {\n const digest = new Uint8Array(await globalThis.crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(content)));\n let hex = \"\";\n for (const byte of digest) hex += byte.toString(16).padStart(2, \"0\");\n return hex;\n}\nexport function sameOriginBinding(a: FeedRestoreOrigin, b: FeedRestoreOrigin): boolean {\n return a.sourceSpaceId === b.sourceSpaceId && a.namespace === b.namespace && a.sourceKey === b.sourceKey && a.eventKey === b.eventKey;\n}\nexport function restoreCancelled(signal?: AbortSignal): Result<never> | undefined {\n return signal?.aborted ? feedError(ErrorCodes.ABORTED, \"Feed restore or policy read was aborted\") : undefined;\n}\nexport function baselinePolicy(source: FeedRestoreOrigin): FeedRestoreDeliveryPolicy {\n return { recipient: \"*\", state: \"unknown\", dispatch: \"never\", resolvedOwnerMapping: false, dispatchBefore: null, source };\n}\nexport interface RestoreMarker {\n cardId: string;\n revision: number;\n issuanceId: string;\n contentSha256: string;\n}\nexport interface RestoreMetadata {\n marker?: RestoreMarker;\n origins: Map<string, FeedRestoreOrigin>;\n policies: FeedRestoreDeliveryPolicy[];\n}\n\n/** One metadata query for the entire already-limited header page, independent of evidence fanout. */\nexport async function readRestoreMetadata(\n responses: FeedReadDatabase, responseIds: string[], options: QueryOptions,\n): Promise<Result<Map<string, RestoreMetadata>>> {\n const cancelled = restoreCancelled(options.signal);\n if (cancelled) return cancelled;\n const metadata = new Map<string, RestoreMetadata>();\n for (const id of responseIds) metadata.set(id, { origins: new Map(), policies: [] });\n const selected = responseIds.length ? `VALUES ${responseIds.map(() => \"(?)\").join(\",\")}` : \"SELECT CAST(NULL AS TEXT) WHERE 0\";\n try {\n const result = await responses.query<unknown>(`WITH selected(response_id) AS (${selected})\n SELECT response_id, 'import', card_id, revision, issuance_id, content_sha256\n FROM feed_response_imports WHERE response_id IN (SELECT response_id FROM selected)\n UNION ALL SELECT response_id, 'origin', source_json, NULL, NULL, NULL\n FROM feed_response_origins WHERE response_id IN (SELECT response_id FROM selected)\n UNION ALL SELECT response_id, 'policy', recipient, policy_json, NULL, NULL\n FROM feed_response_delivery_policies WHERE response_id IN (SELECT response_id FROM selected)`, responseIds, options);\n if (!result.ok) return responseDataFailure(\"Could not read feed restore policy metadata\", result.error);\n const aborted = restoreCancelled(options.signal);\n if (aborted) return aborted;\n for (const row of result.data.rows) {\n const target = metadata.get(String(row[0]));\n if (!target) throw new Error(\"Policy metadata does not belong to its response page\");\n if (row[1] === \"import\") {\n if (target.marker || typeof row[2] !== \"string\" || !row[2] || !Number.isSafeInteger(row[3]) || Number(row[3]) < 1 ||\n typeof row[4] !== \"string\" || !row[4] || typeof row[5] !== \"string\" || !/^[a-f0-9]{64}$/.test(row[5])) {\n throw new Error(\"Invalid import marker\");\n }\n target.marker = { cardId: row[2], revision: Number(row[3]), issuanceId: row[4], contentSha256: row[5] };\n } else if (row[1] === \"origin\") {\n const source = restoreOriginSchema.parse(JSON.parse(String(row[2])));\n target.origins.set(feedJson(source), source);\n } else if (row[1] === \"policy\") {\n const policy = restorePolicySchema.parse(JSON.parse(String(row[3])));\n if (row[2] !== policy.recipient) throw new Error(\"Policy recipient does not match its stored key\");\n target.policies.push(policy);\n } else throw new Error(\"Unknown restore metadata row\");\n }\n return ok(metadata);\n } catch (error) {\n return responseDataFailure(\"Could not verify feed restore policy metadata\", error);\n }\n}\n\n/** False means positively verified ordinary live data, never a missing-table fallback. */\nexport function verifyRestoreMetadata(metadata: RestoreMetadata, response: FeedResponseIdentity, contentHash?: string): boolean {\n if (!metadata.marker) {\n if (metadata.origins.size || metadata.policies.length) throw new Error(\"Orphan restore metadata\");\n return false;\n }\n if (!sameFeedIdentity(metadata.marker, response) || (contentHash !== undefined && metadata.marker.contentSha256 !== contentHash) || !metadata.origins.size) {\n throw new Error(\"Import identity, content or source reference is unverified\");\n }\n let binding: FeedRestoreOrigin | undefined;\n const defaults = new Set<string>();\n for (const source of metadata.origins.values()) {\n if (binding && !sameOriginBinding(binding, source)) throw new Error(\"Conflicting import source bindings\");\n binding = source;\n }\n for (const policy of metadata.policies) {\n const source = feedJson(policy.source);\n if (!metadata.origins.has(source)) throw new Error(\"Policy references an unregistered import origin\");\n if (policy.recipient === \"*\") {\n if (feedJson(policy) !== feedJson(baselinePolicy(policy.source))) throw new Error(\"Invalid default import policy\");\n defaults.add(source);\n }\n }\n for (const source of metadata.origins.keys()) if (!defaults.has(source)) throw new Error(\"Missing default import policy\");\n return true;\n}\n","import { ok } from \"../types\";\nimport type { QueryOptions } from \"../sql/types\";\nimport { feedError, feedJson, responseDataFailure, responseFromRow, sameFeedIdentity } from \"./store\";\nimport {\n contentSha256, readRestoreMetadata, restoreCancelled, restoreContent, verifyRestoreMetadata,\n} from \"./restore-metadata\";\nimport type { RestoreMetadata } from \"./restore-metadata\";\nimport { feedResponsePayloadSchema } from \"./schemas\";\nimport { projectFeedResponseNotification } from \"./notification\";\nimport type { FeedApi, FeedResponse, FeedResponsePayload } from \"./types\";\nimport type { FeedRestoreDeliveryPolicy } from \"./restore-types\";\n\nfunction permittedDeadline(metadata: RestoreMetadata, recipient: string): { allowed: false } | { allowed: true; cutoff: string | null } {\n const evidence = new Map<string, FeedRestoreDeliveryPolicy[]>();\n for (const policy of metadata.policies) {\n if (policy.recipient !== recipient) continue;\n const source = feedJson(policy.source);\n const rows = evidence.get(source);\n if (rows) rows.push(policy); else evidence.set(source, [policy]);\n }\n let cutoff: string | null | undefined;\n for (const source of metadata.origins.keys()) {\n const rows = evidence.get(source);\n // One snapshot's exception never overrides another origin's default deny.\n if (!rows?.length) return { allowed: false };\n for (const policy of rows) {\n if (policy.state !== \"pending\" || policy.dispatch !== \"resolved-pending\" || !policy.resolvedOwnerMapping) return { allowed: false };\n if (cutoff === undefined) cutoff = policy.dispatchBefore;\n else if (cutoff !== policy.dispatchBefore) return { allowed: false };\n if (typeof policy.dispatchBefore === \"string\" && Date.now() >= Date.parse(policy.dispatchBefore)) return { allowed: false };\n }\n }\n return cutoff === undefined ? { allowed: false } : { allowed: true, cutoff };\n}\n\nexport const listFeedResponseDeliveries: FeedApi[\"listFeedResponseDeliveries\"] = async (responses, options) => {\n try {\n const after = options.afterSequence ?? 0;\n const limit = options.limit ?? 100;\n if (!options.recipient || options.recipient === \"*\" || !Number.isSafeInteger(after) || after < 0 ||\n !Number.isSafeInteger(limit) || limit < 1 || limit > 1000) {\n return feedError(\"INVALID_INPUT\", \"Delivery pages require an exact recipient and valid sequence pagination\");\n }\n const privateOptions: QueryOptions = { redactErrors: true, signal: options.signal };\n const cancelled = restoreCancelled(options.signal);\n if (cancelled) return cancelled;\n // Limit headers before evidence fanout. The extra header only reports whether another page exists.\n const result = await responses.query<unknown>(`SELECT r.sequence, r.response_json, p.payload_type, p.payload_version,\n p.payload_json, r.card_id, r.revision, r.issuance_id, r.response_id\n FROM feed_responses r LEFT JOIN feed_response_payloads p ON p.response_id = r.response_id\n WHERE r.sequence > ? ORDER BY r.sequence LIMIT ?`, [after, limit + 1], privateOptions);\n if (!result.ok) return responseDataFailure(\"Could not read feed response delivery headers\", result.error);\n const stopped = restoreCancelled(options.signal);\n if (stopped) return stopped;\n const rows = result.data.rows.slice(0, limit);\n const headers: FeedResponse[] = [];\n const ids: string[] = [];\n const seen = new Set<string>();\n let nextSequence = after;\n for (const row of rows) {\n const response = responseFromRow(row);\n if (!Number.isSafeInteger(response.sequence) || response.sequence <= nextSequence || seen.has(response.responseId) || row[8] !== response.responseId ||\n !sameFeedIdentity(response, { cardId: String(row[5]), revision: Number(row[6]), issuanceId: String(row[7]) })) {\n throw new Error(\"Response page identity or ordering is unverified\");\n }\n seen.add(response.responseId);\n nextSequence = response.sequence;\n headers.push(response); ids.push(response.responseId);\n }\n const metadataResult = await readRestoreMetadata(responses, ids, privateOptions);\n if (!metadataResult.ok) return metadataResult;\n const deliveries: FeedResponse[] = [];\n for (let index = 0; index < headers.length; index += 1) {\n const response = headers[index];\n const metadata = metadataResult.data.get(response.responseId)!;\n if (!verifyRestoreMetadata(metadata, response)) {\n deliveries.push(response); // Positive absence in all present metadata tables is ordinary live data.\n continue;\n }\n const row = rows[index];\n let payload: FeedResponsePayload | undefined;\n if (row[2] !== null && row[2] !== undefined) {\n payload = feedResponsePayloadSchema.parse({ type: row[2], version: row[3], data: JSON.parse(String(row[4])) });\n } else if ((row[3] !== null && row[3] !== undefined) || (row[4] !== null && row[4] !== undefined)) {\n throw new Error(\"Imported payload presence is unverified\");\n }\n const content = restoreContent(JSON.parse(String(row[1])), payload);\n const hash = await contentSha256(content.canonical);\n const aborted = restoreCancelled(options.signal);\n if (aborted) return aborted;\n verifyRestoreMetadata(metadata, response, hash);\n const permission = permittedDeadline(metadata, options.recipient);\n if (permission.allowed) {\n deliveries.push(projectFeedResponseNotification({ ...response, dispatchBefore: permission.cutoff }));\n }\n }\n const aborted = restoreCancelled(options.signal);\n if (aborted) return aborted;\n return ok({ responses: deliveries, nextSequence, hasMore: result.data.rows.length > limit });\n } catch (error) {\n return responseDataFailure(\"Could not verify feed response delivery policy\", error);\n }\n};\n","import { ErrorCodes } from \"../types\";\nimport { initializeFeedHandoff, deliverFeedResponse } from \"./handoff\";\nimport { listFeedResponseDeliveries } from \"./delivery-policy\";\nimport { isDispatchDeadlineFailure } from \"./dispatch\";\nimport type { FeedApi } from \"./types\";\n\nexport const listenFeedResponses: FeedApi[\"listenFeedResponses\"] = async (options) => {\n const { signal } = options;\n const renewalSeconds = options.renewalSeconds ?? 300;\n if (!Number.isInteger(renewalSeconds) || renewalSeconds < 60 || renewalSeconds > 300) {\n throw new Error(\"Feed renewal must be between 60 and 300 seconds\");\n }\n if (options.subscription.service !== \"sql\" || !options.subscription.pathPrefix) {\n throw new Error(\"Feed listener requires the exact response SQL resource subscription\");\n }\n if (signal.aborted) return;\n const initialized = await initializeFeedHandoff(options.handoff);\n if (!initialized.ok) throw initialized.error;\n let ready = false;\n let dirty = false;\n let draining: Promise<void> | undefined;\n let failed = false;\n let failure: unknown;\n let current: AbortController | undefined;\n\n const drain = async (): Promise<void> => {\n do {\n dirty = false;\n let afterSequence = 0;\n while (!signal.aborted) {\n const page = await listFeedResponseDeliveries(options.responses, { recipient: options.recipient, afterSequence, limit: 100, signal });\n if (!page.ok) {\n if (signal.aborted && page.error.code === ErrorCodes.ABORTED) return;\n throw page.error;\n }\n for (const response of page.data.responses) {\n if (signal.aborted) return;\n const handoff = await deliverFeedResponse({\n handoff: options.handoff, recipient: options.recipient, response, deliver: options.deliver,\n });\n if (!handoff.ok && !isDispatchDeadlineFailure(handoff.error)) throw handoff.error;\n }\n if (page.data.hasMore && page.data.nextSequence <= afterSequence) throw new Error(\"Delivery page did not advance a verified cursor\");\n afterSequence = page.data.nextSequence;\n if (!page.data.hasMore) break;\n }\n } while (dirty && !signal.aborted);\n };\n const schedule = (): void => {\n if (!ready || signal.aborted || failed) return;\n dirty = true;\n if (draining) return;\n draining = drain().catch((error: unknown) => {\n failed = true;\n failure = error;\n current?.abort();\n }).finally(() => {\n draining = undefined;\n if (dirty && !failed) schedule();\n });\n };\n\n while (!signal.aborted && !failed) {\n const connection = new AbortController();\n current = connection;\n const stop = () => connection.abort();\n signal.addEventListener(\"abort\", stop, { once: true });\n // Periodic subscription renewal also bounds recovery of a missed wakeup.\n // No response query runs until the new stream's authorized ready callback.\n const renewal = setTimeout(stop, renewalSeconds * 1000);\n renewal.unref?.();\n try {\n for await (const _event of options.hooks.subscribe([options.subscription], {\n signal: connection.signal,\n ttlSeconds: renewalSeconds,\n onReady: () => {\n if (current !== connection || connection.signal.aborted || signal.aborted) return;\n ready = true;\n schedule();\n },\n })) schedule();\n } finally {\n ready = false;\n clearTimeout(renewal);\n signal.removeEventListener(\"abort\", stop);\n await draining;\n }\n if (failed) throw failure;\n // Sign-out/terminal completion belongs to hooks; do not restart it as a retry.\n if (!connection.signal.aborted) return;\n }\n if (failed) throw failure;\n};\n","import { ok } from \"../types\";\nimport { feedError } from \"./store\";\nimport type { FeedApi } from \"./types\";\n\nexport const feedResourceNames: FeedApi[\"feedResourceNames\"] = (prefix, stableToken) => {\n if (!/^[A-Za-z0-9_-]+$/.test(stableToken) || !prefix || prefix.endsWith(\"/\") ||\n prefix.split(\"/\").some((part) => !part || part === \".\" || part === \"..\" || !/^[A-Za-z0-9._-]+$/.test(part))) {\n return feedError(\"INVALID_INPUT\", \"Feed resources require a canonical prefix and a stable alphanumeric, underscore or hyphen agent token\");\n }\n return ok({\n outputResource: `${prefix}/feed_output_${stableToken}`,\n responseResource: `${prefix}/feed_responses_${stableToken}`,\n });\n};\n","import { z } from \"zod\";\nimport { ErrorCodes, ok } from \"../types\";\nimport type { Result } from \"../types\";\nimport type { QueryOptions, SqlStatement, SqlValue } from \"../sql/types\";\nimport { feedCardSchema } from \"./schemas\";\nimport { feedError, feedJson, responseDataFailure, sameFeedIdentity, storedResponse, storeFeedCard } from \"./store\";\nimport {\n baselinePolicy, contentSha256, readRestoreMetadata, restoreCancelled, restoreContent,\n restoreOriginSchema, restorePolicySchema, sameOriginBinding, verifyRestoreMetadata,\n} from \"./restore-metadata\";\nimport type { RestoreContent } from \"./restore-metadata\";\nimport type { FeedApi, FeedCard, FeedDatabase } from \"./types\";\nimport type { FeedRestoreDeliveryPolicy, FeedRestoreOrigin } from \"./restore-types\";\n\nconst envelopeSchema = z.object({\n response: z.unknown(), payload: z.unknown().optional(), origin: restoreOriginSchema,\n deliveries: z.array(restorePolicySchema).optional(),\n}).strict();\nconst recordsSchema = z.object({ cards: z.array(z.unknown()), responses: z.array(envelopeSchema) }).strict();\ninterface RestoreOriginEvidence { origin: FeedRestoreOrigin; policies: Map<string, FeedRestoreDeliveryPolicy> }\ninterface RestoreGroup { content: RestoreContent; origins: Map<string, RestoreOriginEvidence> }\ninterface Guard { sql: string; params: SqlValue[] }\n\nfunction markerGuard(content: RestoreContent, hash: string): Guard {\n const response = content.response;\n return { sql: `EXISTS (SELECT 1 FROM feed_response_imports WHERE response_id = ? AND card_id = ?\n AND revision = ? AND issuance_id = ? AND content_sha256 = ?)`,\n params: [response.responseId, response.cardId, response.revision, response.issuanceId, hash] };\n}\nfunction bindingGuard(responseId: string, source: FeedRestoreOrigin): Guard {\n return { sql: `NOT EXISTS (SELECT 1 FROM feed_response_origins WHERE response_id = ? AND (\n json_extract(source_json, '$.sourceSpaceId') IS NOT ? OR json_extract(source_json, '$.namespace') IS NOT ?\n OR json_extract(source_json, '$.sourceKey') IS NOT ? OR json_extract(source_json, '$.eventKey') IS NOT ?))`,\n params: [responseId, source.sourceSpaceId, source.namespace, source.sourceKey, source.eventKey ?? null] };\n}\nfunction headerGuard(content: RestoreContent): Guard {\n const response = content.response;\n return { sql: `EXISTS (SELECT 1 FROM feed_responses r WHERE r.response_id = ? AND r.card_id = ? AND r.revision = ?\n AND r.issuance_id = ? AND r.response_json = ?)`,\n params: [response.responseId, response.cardId, response.revision, response.issuanceId, content.headerJson] };\n}\nfunction payloadGuard(content: RestoreContent): Guard {\n const responseId = content.response.responseId;\n return content.payload === undefined\n ? { sql: \"NOT EXISTS (SELECT 1 FROM feed_response_payloads WHERE response_id = ?)\", params: [responseId] }\n : { sql: `EXISTS (SELECT 1 FROM feed_response_payloads WHERE response_id = ? AND payload_type = ?\n AND payload_version = ? AND payload_json = ?)`,\n params: [responseId, content.payload.type, content.payload.version, content.payloadJson!] };\n}\nfunction combined(...guards: Guard[]): Guard {\n return { sql: guards.map((guard) => `(${guard.sql})`).join(\" AND \"), params: guards.flatMap((guard) => guard.params) };\n}\nfunction restoreStatements(group: RestoreGroup, hash: string): SqlStatement[] {\n const { content } = group;\n const response = content.response;\n const first = group.origins.values().next().value as RestoreOriginEvidence;\n const claim = combined(markerGuard(content, hash), bindingGuard(response.responseId, first.origin));\n const header = headerGuard(content);\n const complete = combined(claim, header, payloadGuard(content));\n const committed: Guard[] = [complete];\n const statements: SqlStatement[] = [{\n // Claim precedes the header under the same transaction. A committed live header cannot be reclassified.\n sql: `INSERT INTO feed_response_imports (response_id, card_id, revision, issuance_id, content_sha256)\n SELECT ?, ?, ?, ?, ? WHERE NOT EXISTS (SELECT 1 FROM feed_responses WHERE response_id = ?)\n AND NOT EXISTS (SELECT 1 FROM feed_response_payloads WHERE response_id = ?)\n AND NOT EXISTS (SELECT 1 FROM feed_response_origins WHERE response_id = ?)\n AND NOT EXISTS (SELECT 1 FROM feed_response_delivery_policies WHERE response_id = ?)\n ON CONFLICT (response_id) DO NOTHING`,\n params: [response.responseId, response.cardId, response.revision, response.issuanceId, hash,\n response.responseId, response.responseId, response.responseId, response.responseId],\n }, {\n sql: `INSERT INTO feed_responses (response_id, card_id, revision, issuance_id, response_json)\n SELECT ?, ?, ?, ?, ? WHERE ${claim.sql} ON CONFLICT (response_id) DO NOTHING`,\n params: [response.responseId, response.cardId, response.revision, response.issuanceId, content.headerJson, ...claim.params],\n }];\n if (content.payload !== undefined) statements.push({\n sql: `INSERT INTO feed_response_payloads (response_id, payload_type, payload_version, payload_json)\n SELECT ?, ?, ?, ? WHERE ${combined(claim, header).sql} ON CONFLICT (response_id) DO NOTHING`,\n params: [response.responseId, content.payload.type, content.payload.version, content.payloadJson!, ...claim.params, ...header.params],\n });\n for (const [sourceJson, evidence] of group.origins) {\n statements.push({ sql: `INSERT INTO feed_response_origins (response_id, source_json)\n SELECT ?, ? WHERE ${complete.sql} ON CONFLICT (response_id, source_json) DO NOTHING`,\n params: [response.responseId, sourceJson, ...complete.params] });\n committed.push({ sql: \"EXISTS (SELECT 1 FROM feed_response_origins WHERE response_id = ? AND source_json = ?)\",\n params: [response.responseId, sourceJson] });\n for (const policy of [baselinePolicy(evidence.origin), ...evidence.policies.values()]) {\n statements.push({ sql: `INSERT INTO feed_response_delivery_policies (response_id, recipient, policy_json)\n SELECT ?, ?, ? WHERE ${complete.sql} AND EXISTS (\n SELECT 1 FROM feed_response_origins WHERE response_id = ? AND source_json = ?)\n ON CONFLICT (response_id, recipient, policy_json) DO NOTHING`,\n params: [response.responseId, policy.recipient, feedJson(policy), ...complete.params, response.responseId, sourceJson] });\n committed.push({ sql: \"EXISTS (SELECT 1 FROM feed_response_delivery_policies WHERE response_id = ? AND recipient = ? AND policy_json = ?)\",\n params: [response.responseId, policy.recipient, feedJson(policy)] });\n }\n }\n const proof = combined(...committed);\n // Fail the transaction, rather than committing a header whose conditional metadata writes were skipped.\n statements.push({\n sql: `INSERT INTO feed_response_imports (response_id, card_id, revision, issuance_id, content_sha256)\n SELECT ?, NULL, NULL, NULL, NULL WHERE NOT (${proof.sql})`,\n params: [response.responseId, ...proof.params],\n });\n return statements;\n}\n\nasync function restoreGroup(output: FeedDatabase, responses: FeedDatabase, group: RestoreGroup, options: QueryOptions): Promise<Result<void>> {\n const { content } = group;\n const response = content.response;\n const card = await output.query<string>(\"SELECT card_json FROM feed_cards WHERE card_id = ? AND revision = ? AND issuance_id = ?\",\n [response.cardId, response.revision, response.issuanceId], options);\n if (!card.ok) return responseDataFailure(\"Could not verify a restored response card issuance\", card.error);\n const cardReadCancelled = restoreCancelled(options.signal);\n if (cardReadCancelled) return cardReadCancelled;\n if (!card.data.rows[0] || !sameFeedIdentity(feedCardSchema.parse(JSON.parse(card.data.rows[0][0])), response)) {\n return feedError(\"INVALID_INPUT\", \"Restored response requires a published full card issuance\");\n }\n const hash = await contentSha256(content.canonical);\n const cancelled = restoreCancelled(options.signal);\n if (cancelled) return cancelled;\n const previous = await storedResponse(responses, response.responseId, options);\n if (!previous.ok) return previous;\n const previousMetadata = await readRestoreMetadata(responses, [response.responseId], options);\n if (!previousMetadata.ok) return previousMetadata;\n const before = previousMetadata.data.get(response.responseId)!;\n if (previous.data) {\n if (!verifyRestoreMetadata(before, response, hash)) return feedError(\"INVALID_INPUT\", \"A live response ID cannot be restored or reclassified\");\n if (restoreContent(JSON.parse(previous.data.rawHeaderJson), previous.data.payload).canonical !== content.canonical) {\n return feedError(\"INVALID_INPUT\", \"A restored response ID cannot change header or private payload\");\n }\n const known = before.origins.values().next().value as FeedRestoreOrigin;\n for (const evidence of group.origins.values()) if (!sameOriginBinding(known, evidence.origin)) {\n return feedError(\"INVALID_INPUT\", \"A restored response cannot alias its source binding\");\n }\n } else if (before.marker || before.origins.size || before.policies.length) {\n return feedError(\"INVALID_INPUT\", \"Orphan restore metadata cannot authorize a new header\");\n }\n const aborted = restoreCancelled(options.signal);\n if (aborted) return aborted;\n let failure: unknown;\n let failed = false;\n try {\n const saved = await responses.batch(restoreStatements(group, hash), options);\n if (!saved.ok) { failed = true; failure = saved.error; }\n } catch (error) { failed = true; failure = error; }\n const stopped = restoreCancelled(options.signal);\n // Cancellation prevents verification; retain a completed failure, including its ABORTED code.\n if (stopped) return failed ? responseDataFailure(\"Could not restore response and atomic import policy\", failure) : stopped;\n const stored = await storedResponse(responses, response.responseId, options);\n if (!stored.ok) return failed && options.signal?.aborted && stored.error.code === ErrorCodes.ABORTED\n ? responseDataFailure(\"Could not restore response and atomic import policy\", failure) : stored;\n const metadata = await readRestoreMetadata(responses, [response.responseId], options);\n if (!metadata.ok) return failed && options.signal?.aborted && metadata.error.code === ErrorCodes.ABORTED\n ? responseDataFailure(\"Could not restore response and atomic import policy\", failure) : metadata;\n const actual = metadata.data.get(response.responseId)!;\n if (!stored.data) return responseDataFailure(\"Could not restore response and atomic import policy\", failure);\n if (!verifyRestoreMetadata(actual, response, hash) || restoreContent(JSON.parse(stored.data.rawHeaderJson), stored.data.payload).canonical !== content.canonical) {\n return feedError(\"INVALID_INPUT\", \"Restore conflicts with an existing live or different response\");\n }\n const policies = new Set(actual.policies.map(feedJson));\n for (const [sourceJson, evidence] of group.origins) {\n if (!actual.origins.has(sourceJson) || !policies.has(feedJson(baselinePolicy(evidence.origin)))) {\n return failed ? responseDataFailure(\"Could not restore atomic provenance and default policy\", failure)\n : feedError(\"INVALID_INPUT\", \"Restore source binding conflicts with existing provenance\");\n }\n for (const policy of evidence.policies.keys()) if (!policies.has(policy)) {\n return responseDataFailure(\"Could not retain requested immutable delivery evidence\", failure);\n }\n }\n const readbackCancelled = restoreCancelled(options.signal);\n if (readbackCancelled) return failed ? responseDataFailure(\"Could not restore response and atomic import policy\", failure) : readbackCancelled;\n return ok(undefined);\n}\n\nexport const restoreFeedRecords: FeedApi[\"restoreFeedRecords\"] = async (ownerPair, input, options = {}) => {\n const privateOptions: QueryOptions = { redactErrors: true, signal: options.signal };\n try {\n const cancelled = restoreCancelled(options.signal);\n if (cancelled) return cancelled;\n const parsed = recordsSchema.parse(input);\n const cards: FeedCard[] = parsed.cards.map((card) => {\n const valid = feedCardSchema.parse(card);\n // Validate the envelope, but retain literal keys in its opaque payload.\n if (valid.payload !== undefined) valid.payload = (card as FeedCard).payload;\n if (feedJson(valid) !== feedJson(card)) throw new Error(\"Invalid restored card fields\");\n return valid;\n });\n const groups = new Map<string, RestoreGroup>();\n for (const record of parsed.responses) {\n const content = restoreContent(record.response, record.payload);\n const id = content.response.responseId;\n let group = groups.get(id);\n if (group && group.content.canonical !== content.canonical) throw new Error(\"Conflicting restored response content\");\n if (!group) { group = { content, origins: new Map() }; groups.set(id, group); }\n const first = group.origins.values().next().value as RestoreOriginEvidence | undefined;\n if (first && !sameOriginBinding(first.origin, record.origin)) throw new Error(\"Conflicting restored response binding\");\n const sourceJson = feedJson(record.origin);\n let evidence = group.origins.get(sourceJson);\n if (!evidence) { evidence = { origin: record.origin, policies: new Map() }; group.origins.set(sourceJson, evidence); }\n for (const policy of record.deliveries ?? []) {\n if (policy.recipient === \"*\" || feedJson(policy.source) !== sourceJson) throw new Error(\"Policy must belong to its exact origin and recipient\");\n evidence.policies.set(feedJson(policy), policy);\n }\n }\n // Cross-database progress is repeatable, not a fictional transaction across output and response files.\n for (const card of cards) {\n const stopped = restoreCancelled(options.signal);\n if (stopped) return stopped;\n const saved = await storeFeedCard(ownerPair.output, card, privateOptions);\n if (!saved.ok) return responseDataFailure(\"Could not publish a restored card\", saved.error);\n }\n for (const group of groups.values()) {\n const stopped = restoreCancelled(options.signal);\n if (stopped) return stopped;\n const saved = await restoreGroup(ownerPair.output, ownerPair.responses, group, privateOptions);\n if (!saved.ok) return saved;\n }\n return restoreCancelled(options.signal) ?? ok(undefined);\n } catch (error) {\n return responseDataFailure(\"Could not validate or restore generic feed records\", error);\n }\n};\n","import { ErrorCodes, ok } from \"../types\";\nimport type { SqlValue } from \"../sql/types\";\nimport { feedCardSchema } from \"./schemas\";\nimport { feedError, responseDataFailure } from \"./store\";\nimport type { FeedApi, FeedCard, FeedCardIdentity } from \"./types\";\n\nfunction validIdentity(value: FeedCardIdentity): boolean {\n return value !== null && typeof value === \"object\" &&\n typeof value.cardId === \"string\" && value.cardId.length > 0 &&\n Number.isSafeInteger(value.revision) && value.revision > 0 &&\n typeof value.issuanceId === \"string\" && value.issuanceId.length > 0;\n}\n\nexport const listFeedCardHistory: FeedApi[\"listFeedCardHistory\"] = async (output, options = {}) => {\n try {\n const { afterIdentity, signal } = options;\n const limit = options.limit === undefined ? 100 : options.limit;\n if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1000 ||\n (afterIdentity !== undefined && !validIdentity(afterIdentity))) {\n return feedError(ErrorCodes.INVALID_INPUT, \"Card history requires a full identity cursor and valid page limit\");\n }\n if (signal?.aborted) return feedError(ErrorCodes.ABORTED, \"Card history read was cancelled\");\n const params: SqlValue[] = afterIdentity\n ? [afterIdentity.cardId, afterIdentity.revision, afterIdentity.issuanceId, limit + 1]\n : [limit + 1];\n // This full-tuple snapshot cursor is not a monotonic publication cursor.\n const result = await output.query<unknown>(`SELECT card_id, revision, issuance_id, card_json FROM feed_cards\n ${afterIdentity ? \"WHERE (card_id COLLATE BINARY, revision, issuance_id COLLATE BINARY) > (?, ?, ?)\" : \"\"}\n ORDER BY card_id COLLATE BINARY, revision, issuance_id COLLATE BINARY LIMIT ?`, params, { redactErrors: true, signal });\n if (!result.ok) return responseDataFailure(\"Could not read feed card history\", result.error);\n if (signal?.aborted) return feedError(ErrorCodes.ABORTED, \"Card history read was cancelled\");\n const cards: FeedCard[] = [];\n const count = Math.min(limit, result.data.rows.length);\n for (let index = 0; index < count; index += 1) {\n const row = result.data.rows[index];\n if (typeof row[3] !== \"string\") throw new Error(\"Stored card envelope is invalid\");\n const card: FeedCard = JSON.parse(row[3]);\n // Validate without replacing the stored envelope: Zod drops literal \"__proto__\" record keys.\n feedCardSchema.parse(card);\n if (!validIdentity(card) || row[0] !== card.cardId || row[1] !== card.revision || row[2] !== card.issuanceId) {\n throw new Error(\"Stored card identity does not match its key\");\n }\n cards.push(card);\n }\n const last = cards[cards.length - 1];\n return ok({\n cards,\n nextIdentity: last ? { cardId: last.cardId, revision: last.revision, issuanceId: last.issuanceId } : null,\n hasMore: result.data.rows.length > limit,\n });\n } catch (error) {\n return responseDataFailure(\"Could not verify feed card history\", error);\n }\n};\n"],"mappings":"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","names":["z","z","identity","z","z","aborted","z","z","validIdentity"]}
|
package/dist/index.cjs
CHANGED
|
@@ -128,6 +128,7 @@ __export(src_exports, {
|
|
|
128
128
|
openWrappedKey: () => openWrappedKey,
|
|
129
129
|
parseAuthError: () => parseAuthError,
|
|
130
130
|
parseCapabilityResource: () => parseCapabilityResource,
|
|
131
|
+
parseEncryptionResource: () => parseEncryptionResource,
|
|
131
132
|
parseNetworkId: () => parseNetworkId,
|
|
132
133
|
parsePermissionHint: () => parsePermissionHint,
|
|
133
134
|
parsePermissionHintFromErrorText: () => parsePermissionHintFromErrorText,
|
|
@@ -879,6 +880,26 @@ function parseNetworkId(networkId) {
|
|
|
879
880
|
}
|
|
880
881
|
return { networkId, ownerDid, name };
|
|
881
882
|
}
|
|
883
|
+
function parseEncryptionResource(resource) {
|
|
884
|
+
const networkSeparator = resource.lastIndexOf(":");
|
|
885
|
+
const nameAndPath = resource.slice(networkSeparator + 1);
|
|
886
|
+
const pathSeparator = nameAndPath.indexOf("/");
|
|
887
|
+
const name = pathSeparator === -1 ? nameAndPath : nameAndPath.slice(0, pathSeparator);
|
|
888
|
+
const networkId = pathSeparator === -1 ? resource : `${resource.slice(0, networkSeparator + 1)}${name}`;
|
|
889
|
+
const parsed = parseNetworkId(networkId);
|
|
890
|
+
if (pathSeparator === -1) return parsed;
|
|
891
|
+
const keyPath = nameAndPath.slice(pathSeparator + 1);
|
|
892
|
+
const segments = keyPath.split("/");
|
|
893
|
+
const prefix = keyPath.endsWith("/");
|
|
894
|
+
if (keyPath.length === 0 || /[\u0000-\u001f\u007f\\]/.test(keyPath) || segments.some(
|
|
895
|
+
(segment, index) => segment === "." || segment === ".." || segment.length === 0 && !(prefix && index === segments.length - 1)
|
|
896
|
+
)) {
|
|
897
|
+
throw new NetworkIdError(
|
|
898
|
+
`encryption resource has an invalid keyPath (got ${JSON.stringify(resource)})`
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
return { ...parsed, keyPath };
|
|
902
|
+
}
|
|
882
903
|
function buildNetworkId(ownerDid, name) {
|
|
883
904
|
if (typeof ownerDid !== "string" || !ownerDid.startsWith("did:")) {
|
|
884
905
|
throw new NetworkIdError("ownerDid must be a DID");
|
|
@@ -3777,12 +3798,13 @@ var SQLService = class extends BaseService {
|
|
|
3777
3798
|
request.signal
|
|
3778
3799
|
);
|
|
3779
3800
|
if (!response.ok) {
|
|
3780
|
-
|
|
3801
|
+
const failure = await this.handleErrorResponse(response, "query", dbName, [action]);
|
|
3802
|
+
return this.redactFailure(failure, options?.redactErrors, response.status);
|
|
3781
3803
|
}
|
|
3782
3804
|
const data = await response.json();
|
|
3783
3805
|
return ok(data);
|
|
3784
3806
|
} catch (error) {
|
|
3785
|
-
return err(wrapError("sql", error));
|
|
3807
|
+
return this.redactFailure(err(wrapError("sql", error)), options?.redactErrors);
|
|
3786
3808
|
} finally {
|
|
3787
3809
|
request.dispose();
|
|
3788
3810
|
}
|
|
@@ -3817,12 +3839,13 @@ var SQLService = class extends BaseService {
|
|
|
3817
3839
|
request.signal
|
|
3818
3840
|
);
|
|
3819
3841
|
if (!response.ok) {
|
|
3820
|
-
|
|
3842
|
+
const failure = await this.handleErrorResponse(response, "execute", dbName, requestedActions);
|
|
3843
|
+
return this.redactFailure(failure, options?.redactErrors, response.status);
|
|
3821
3844
|
}
|
|
3822
3845
|
const data = await response.json();
|
|
3823
3846
|
return ok(data);
|
|
3824
3847
|
} catch (error) {
|
|
3825
|
-
return err(wrapError("sql", error));
|
|
3848
|
+
return this.redactFailure(err(wrapError("sql", error)), options?.redactErrors);
|
|
3826
3849
|
} finally {
|
|
3827
3850
|
request.dispose();
|
|
3828
3851
|
}
|
|
@@ -3843,12 +3866,13 @@ var SQLService = class extends BaseService {
|
|
|
3843
3866
|
request.signal
|
|
3844
3867
|
);
|
|
3845
3868
|
if (!response.ok) {
|
|
3846
|
-
|
|
3869
|
+
const failure = await this.handleErrorResponse(response, "batch", dbName, requestedActions);
|
|
3870
|
+
return this.redactFailure(failure, options?.redactErrors, response.status);
|
|
3847
3871
|
}
|
|
3848
3872
|
const data = await response.json();
|
|
3849
3873
|
return ok(data);
|
|
3850
3874
|
} catch (error) {
|
|
3851
|
-
return err(wrapError("sql", error));
|
|
3875
|
+
return this.redactFailure(err(wrapError("sql", error)), options?.redactErrors);
|
|
3852
3876
|
} finally {
|
|
3853
3877
|
request.dispose();
|
|
3854
3878
|
}
|
|
@@ -4044,6 +4068,18 @@ var SQLService = class extends BaseService {
|
|
|
4044
4068
|
}))
|
|
4045
4069
|
);
|
|
4046
4070
|
}
|
|
4071
|
+
redactFailure(result, redactErrors, status) {
|
|
4072
|
+
if (!redactErrors || result.ok) return result;
|
|
4073
|
+
const candidate = result.error.code;
|
|
4074
|
+
const code = typeof candidate === "string" && Object.prototype.hasOwnProperty.call(ErrorCodes, candidate) ? candidate : ErrorCodes.SQL_ERROR;
|
|
4075
|
+
const safeStatus = typeof status === "number" && Number.isInteger(status) && status >= 400 && status <= 599 ? status : void 0;
|
|
4076
|
+
return err(serviceError(
|
|
4077
|
+
code,
|
|
4078
|
+
"SQL operation failed",
|
|
4079
|
+
"sql",
|
|
4080
|
+
safeStatus === void 0 ? void 0 : { meta: { status: safeStatus } }
|
|
4081
|
+
));
|
|
4082
|
+
}
|
|
4047
4083
|
async handleErrorResponse(response, operation, dbName, requestedActions) {
|
|
4048
4084
|
const errorText = await response.text();
|
|
4049
4085
|
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
@@ -4641,6 +4677,7 @@ var HooksService = class extends BaseService {
|
|
|
4641
4677
|
this._supervising = false;
|
|
4642
4678
|
/** Bumped on every session change; part of the plan key. */
|
|
4643
4679
|
this._sessionGeneration = 0;
|
|
4680
|
+
this._streamGeneration = 0;
|
|
4644
4681
|
this._config = config;
|
|
4645
4682
|
}
|
|
4646
4683
|
get config() {
|
|
@@ -4661,6 +4698,7 @@ var HooksService = class extends BaseService {
|
|
|
4661
4698
|
requested,
|
|
4662
4699
|
signatures: requested.map(subscriptionSignature),
|
|
4663
4700
|
ttlSeconds: options.ttlSeconds,
|
|
4701
|
+
onReady: options.onReady,
|
|
4664
4702
|
queue: new AsyncQueue()
|
|
4665
4703
|
};
|
|
4666
4704
|
const leave = () => {
|
|
@@ -4675,6 +4713,7 @@ var HooksService = class extends BaseService {
|
|
|
4675
4713
|
signal?.addEventListener("abort", leave, { once: true });
|
|
4676
4714
|
this._subscribers.add(subscriber);
|
|
4677
4715
|
this.wake();
|
|
4716
|
+
if (this._readyStream) this.notifyReady(subscriber, this._readyStream);
|
|
4678
4717
|
try {
|
|
4679
4718
|
for await (const event of subscriber.queue) {
|
|
4680
4719
|
yield event;
|
|
@@ -4907,6 +4946,7 @@ var HooksService = class extends BaseService {
|
|
|
4907
4946
|
async attempt(plan, signal, health) {
|
|
4908
4947
|
let phase = "mint";
|
|
4909
4948
|
let request;
|
|
4949
|
+
const generation = ++this._streamGeneration;
|
|
4910
4950
|
const owns = () => !signal.aborted && !request?.signal.aborted && this.plan()?.key === plan.key;
|
|
4911
4951
|
try {
|
|
4912
4952
|
const context = this.context;
|
|
@@ -4971,6 +5011,14 @@ var HooksService = class extends BaseService {
|
|
|
4971
5011
|
if (next.done) break;
|
|
4972
5012
|
const message = next.value;
|
|
4973
5013
|
if (!message.data) continue;
|
|
5014
|
+
if (message.event === "ready") {
|
|
5015
|
+
const marker = JSON.parse(message.data);
|
|
5016
|
+
if (marker !== null && typeof marker === "object" && "type" in marker && marker.type === "ready") {
|
|
5017
|
+
this._readyStream = { key: plan.key, generation };
|
|
5018
|
+
for (const subscriber of this._subscribers) this.notifyReady(subscriber, this._readyStream);
|
|
5019
|
+
}
|
|
5020
|
+
continue;
|
|
5021
|
+
}
|
|
4974
5022
|
const event = parseHookEvent(message);
|
|
4975
5023
|
if (!owns()) return { kind: "stopped" };
|
|
4976
5024
|
this.dispatch(event);
|
|
@@ -4983,6 +5031,8 @@ var HooksService = class extends BaseService {
|
|
|
4983
5031
|
return owns() ? { kind: "ended" } : { kind: "stopped" };
|
|
4984
5032
|
} catch (thrown) {
|
|
4985
5033
|
return request?.signal.aborted || thrown === SUPERSEDED ? { kind: "stopped" } : { kind: "failed", error: hookStreamFailure(phase, thrown) };
|
|
5034
|
+
} finally {
|
|
5035
|
+
if (this._readyStream?.generation === generation) this._readyStream = void 0;
|
|
4986
5036
|
}
|
|
4987
5037
|
}
|
|
4988
5038
|
/**
|
|
@@ -5038,6 +5088,15 @@ var HooksService = class extends BaseService {
|
|
|
5038
5088
|
ttlSeconds
|
|
5039
5089
|
};
|
|
5040
5090
|
}
|
|
5091
|
+
notifyReady(subscriber, ready) {
|
|
5092
|
+
if (!this._subscribers.has(subscriber) || subscriber.readyGeneration === ready.generation || this.plan()?.key !== ready.key || this._phase?.interrupt.signal.aborted) return;
|
|
5093
|
+
subscriber.readyGeneration = ready.generation;
|
|
5094
|
+
try {
|
|
5095
|
+
subscriber.onReady?.();
|
|
5096
|
+
} catch {
|
|
5097
|
+
this.report(serviceError(ErrorCodes.INVALID_INPUT, "Hook readiness callback failed", "hooks"));
|
|
5098
|
+
}
|
|
5099
|
+
}
|
|
5041
5100
|
dispatch(event) {
|
|
5042
5101
|
for (const subscriber of this._subscribers) {
|
|
5043
5102
|
if (matchesAnySubscription(event, subscriber.requested)) {
|
|
@@ -5272,7 +5331,7 @@ function abortPromise(signal) {
|
|
|
5272
5331
|
function normalizeSubscription(subscription) {
|
|
5273
5332
|
return {
|
|
5274
5333
|
...subscription,
|
|
5275
|
-
pathPrefix: normalizePathPrefix(subscription.pathPrefix),
|
|
5334
|
+
pathPrefix: subscription.service === "kv" ? normalizePathPrefix(subscription.pathPrefix) : subscription.pathPrefix?.replace(/^\/+/, "") || void 0,
|
|
5276
5335
|
abilities: subscription.abilities ? [...subscription.abilities] : []
|
|
5277
5336
|
};
|
|
5278
5337
|
}
|
|
@@ -5296,7 +5355,11 @@ function matchesSubscription(event, subscription) {
|
|
|
5296
5355
|
if (event.service !== subscription.service) {
|
|
5297
5356
|
return false;
|
|
5298
5357
|
}
|
|
5299
|
-
if (
|
|
5358
|
+
if (event.service === "sql" || event.service === "duckdb") {
|
|
5359
|
+
const scope = subscription.pathPrefix;
|
|
5360
|
+
const database = event.databasePath ?? event.path;
|
|
5361
|
+
if (scope && scope !== "/" && (!database || (scope.endsWith("/") ? !database.startsWith(scope) : database !== scope))) return false;
|
|
5362
|
+
} else if (subscription.pathPrefix) {
|
|
5300
5363
|
const prefix = subscription.pathPrefix.endsWith("/") ? subscription.pathPrefix : `${subscription.pathPrefix}/`;
|
|
5301
5364
|
if (event.path && event.path !== subscription.pathPrefix && !event.path.startsWith(prefix)) {
|
|
5302
5365
|
return false;
|
|
@@ -5456,6 +5519,7 @@ function parseHookEvent(message) {
|
|
|
5456
5519
|
service: parsed.service ?? "",
|
|
5457
5520
|
ability: parsed.ability ?? "",
|
|
5458
5521
|
path: parsed.path,
|
|
5522
|
+
databasePath: typeof parsed.databasePath === "string" ? parsed.databasePath : void 0,
|
|
5459
5523
|
actor: parsed.actor ?? "",
|
|
5460
5524
|
epoch: parsed.epoch ?? "",
|
|
5461
5525
|
eventIndex: parsed.eventIndex ?? 0,
|
|
@@ -7976,7 +8040,12 @@ function ensureNetworkUsableForDecrypt(descriptor) {
|
|
|
7976
8040
|
|
|
7977
8041
|
// src/encryption/envelope.ts
|
|
7978
8042
|
function encryptToNetwork(crypto2, input) {
|
|
7979
|
-
|
|
8043
|
+
const parsedResource = parseEncryptionResource(
|
|
8044
|
+
input.keyPath === void 0 ? input.networkId : `${input.networkId}/${input.keyPath}`
|
|
8045
|
+
);
|
|
8046
|
+
if (parsedResource.keyPath !== input.keyPath || input.keyPath?.endsWith("/")) {
|
|
8047
|
+
throw new NetworkIdError("keyPath must name an exact encryption key");
|
|
8048
|
+
}
|
|
7980
8049
|
const alg = input.alg ?? DEFAULT_ENCRYPTION_ALG;
|
|
7981
8050
|
const keyVersion = input.keyVersion ?? DEFAULT_KEY_VERSION;
|
|
7982
8051
|
const symmetricKey = crypto2.randomBytes(32);
|
|
@@ -7990,6 +8059,7 @@ function encryptToNetwork(crypto2, input) {
|
|
|
7990
8059
|
const envelope = {
|
|
7991
8060
|
v: ENVELOPE_VERSION,
|
|
7992
8061
|
networkId: input.networkId,
|
|
8062
|
+
...input.keyPath !== void 0 ? { keyPath: input.keyPath } : {},
|
|
7993
8063
|
alg,
|
|
7994
8064
|
keyVersion,
|
|
7995
8065
|
encryptedSymmetricKey,
|
|
@@ -8021,13 +8091,24 @@ function validateEnvelope(crypto2, envelope) {
|
|
|
8021
8091
|
};
|
|
8022
8092
|
}
|
|
8023
8093
|
try {
|
|
8024
|
-
|
|
8094
|
+
if (parseEncryptionResource(e.networkId).keyPath !== void 0) {
|
|
8095
|
+
throw new Error("networkId must identify the network root");
|
|
8096
|
+
}
|
|
8097
|
+
if (e.keyPath !== void 0) {
|
|
8098
|
+
if (typeof e.keyPath !== "string") {
|
|
8099
|
+
throw new Error("keyPath must be a string");
|
|
8100
|
+
}
|
|
8101
|
+
const parsed = parseEncryptionResource(`${e.networkId}/${e.keyPath}`);
|
|
8102
|
+
if (parsed.keyPath !== e.keyPath || e.keyPath.endsWith("/")) {
|
|
8103
|
+
throw new Error("keyPath must name an exact encryption key");
|
|
8104
|
+
}
|
|
8105
|
+
}
|
|
8025
8106
|
} catch (err3) {
|
|
8026
8107
|
return {
|
|
8027
8108
|
ok: false,
|
|
8028
8109
|
error: encryptionError({
|
|
8029
8110
|
code: "INVALID_ENVELOPE",
|
|
8030
|
-
message: `envelope
|
|
8111
|
+
message: `envelope encryption resource is malformed: ${err3 instanceof Error ? err3.message : String(err3)}`
|
|
8031
8112
|
})
|
|
8032
8113
|
};
|
|
8033
8114
|
}
|
|
@@ -8100,6 +8181,7 @@ function buildDecryptFacts(input) {
|
|
|
8100
8181
|
type: DECRYPT_FACT_TYPE,
|
|
8101
8182
|
targetNode: input.body.targetNode,
|
|
8102
8183
|
networkId: input.body.networkId,
|
|
8184
|
+
...input.body.keyPath !== void 0 ? { keyPath: input.body.keyPath } : {},
|
|
8103
8185
|
bodyHash,
|
|
8104
8186
|
encryptedSymmetricKeyHash: input.encryptedSymmetricKeyHash,
|
|
8105
8187
|
receiverPublicKeyHash,
|
|
@@ -8107,10 +8189,14 @@ function buildDecryptFacts(input) {
|
|
|
8107
8189
|
keyVersion: input.body.keyVersion
|
|
8108
8190
|
};
|
|
8109
8191
|
}
|
|
8110
|
-
function buildDecryptAttenuation(networkId) {
|
|
8111
|
-
|
|
8192
|
+
function buildDecryptAttenuation(networkId, keyPath) {
|
|
8193
|
+
const resource = keyPath === void 0 ? networkId : `${networkId}/${keyPath}`;
|
|
8194
|
+
const parsed = parseEncryptionResource(resource);
|
|
8195
|
+
if (parsed.networkId !== networkId || parsed.keyPath !== keyPath || keyPath?.endsWith("/")) {
|
|
8196
|
+
throw new NetworkIdError("keyPath must name an exact encryption key");
|
|
8197
|
+
}
|
|
8112
8198
|
return {
|
|
8113
|
-
[
|
|
8199
|
+
[resource]: {
|
|
8114
8200
|
[DECRYPT_ACTION]: {}
|
|
8115
8201
|
}
|
|
8116
8202
|
};
|
|
@@ -8170,6 +8256,15 @@ function checkDecryptInvocationInput(crypto2, input) {
|
|
|
8170
8256
|
})
|
|
8171
8257
|
};
|
|
8172
8258
|
}
|
|
8259
|
+
if (input.facts.keyPath !== input.body.keyPath) {
|
|
8260
|
+
return {
|
|
8261
|
+
ok: false,
|
|
8262
|
+
error: encryptionError({
|
|
8263
|
+
code: "INVALID_INPUT",
|
|
8264
|
+
message: "facts.keyPath must equal body.keyPath"
|
|
8265
|
+
})
|
|
8266
|
+
};
|
|
8267
|
+
}
|
|
8173
8268
|
if (input.facts.alg !== input.body.alg) {
|
|
8174
8269
|
return {
|
|
8175
8270
|
ok: false,
|
|
@@ -8207,7 +8302,9 @@ function checkDecryptInvocationInput(crypto2, input) {
|
|
|
8207
8302
|
};
|
|
8208
8303
|
}
|
|
8209
8304
|
try {
|
|
8210
|
-
|
|
8305
|
+
if (parseEncryptionResource(input.networkId).keyPath !== void 0) {
|
|
8306
|
+
throw new NetworkIdError("networkId must identify the network root");
|
|
8307
|
+
}
|
|
8211
8308
|
} catch (err3) {
|
|
8212
8309
|
return {
|
|
8213
8310
|
ok: false,
|
|
@@ -8217,6 +8314,22 @@ function checkDecryptInvocationInput(crypto2, input) {
|
|
|
8217
8314
|
})
|
|
8218
8315
|
};
|
|
8219
8316
|
}
|
|
8317
|
+
try {
|
|
8318
|
+
const resource = parseEncryptionResource(
|
|
8319
|
+
input.body.keyPath === void 0 ? input.body.networkId : `${input.body.networkId}/${input.body.keyPath}`
|
|
8320
|
+
);
|
|
8321
|
+
if (resource.keyPath !== input.body.keyPath || input.body.keyPath?.endsWith("/")) {
|
|
8322
|
+
throw new NetworkIdError("keyPath must name an exact encryption key");
|
|
8323
|
+
}
|
|
8324
|
+
} catch (err3) {
|
|
8325
|
+
return {
|
|
8326
|
+
ok: false,
|
|
8327
|
+
error: encryptionError({
|
|
8328
|
+
code: "INVALID_INPUT",
|
|
8329
|
+
message: err3 instanceof Error ? err3.message : String(err3)
|
|
8330
|
+
})
|
|
8331
|
+
};
|
|
8332
|
+
}
|
|
8220
8333
|
const canonicalBody = canonicalize(
|
|
8221
8334
|
input.body
|
|
8222
8335
|
);
|
|
@@ -8457,6 +8570,7 @@ var EncryptionService = class extends BaseService {
|
|
|
8457
8570
|
// that spelling in the envelope so a later response can be compared
|
|
8458
8571
|
// byte-for-byte (notably for checksummed did:pkh principals).
|
|
8459
8572
|
networkId: descriptor.networkId,
|
|
8573
|
+
...options?.keyPath !== void 0 ? { keyPath: options.keyPath } : {},
|
|
8460
8574
|
networkPublicKey,
|
|
8461
8575
|
plaintext,
|
|
8462
8576
|
...options?.aad !== void 0 ? { aad: options.aad } : {},
|
|
@@ -8516,6 +8630,7 @@ var EncryptionService = class extends BaseService {
|
|
|
8516
8630
|
type: DECRYPT_FACT_TYPE,
|
|
8517
8631
|
targetNode,
|
|
8518
8632
|
networkId: envelope.networkId,
|
|
8633
|
+
...envelope.keyPath !== void 0 ? { keyPath: envelope.keyPath } : {},
|
|
8519
8634
|
alg: envelope.alg,
|
|
8520
8635
|
keyVersion: envelope.keyVersion,
|
|
8521
8636
|
encryptedSymmetricKey: envelope.encryptedSymmetricKey,
|
|
@@ -8732,6 +8847,7 @@ var import_decrypt_transport_response_error3 = require("@tinycloud/sdk-services/
|
|
|
8732
8847
|
openWrappedKey,
|
|
8733
8848
|
parseAuthError,
|
|
8734
8849
|
parseCapabilityResource,
|
|
8850
|
+
parseEncryptionResource,
|
|
8735
8851
|
parseNetworkId,
|
|
8736
8852
|
parsePermissionHint,
|
|
8737
8853
|
parsePermissionHintFromErrorText,
|