@oaath/server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["HASH"],"sources":["../src/artifact/claim.ts","../src/authorization/code.ts","../src/authorization/resume.ts","../src/authorization/pickup.ts","../src/security/authentication.ts","../src/security/rate-limit.ts","../src/relay/handler.ts","../src/security/redact.ts","../src/session-signer/kms-provider.ts","../src/store/memory.ts"],"sourcesContent":["/**\n * One-time encrypted artifact release.\n *\n * ```text\n * state and owner the artifact record's `claimedAt` owns \"released\"\n * transitions sealed -> claimed, exactly once\n * terminal claimed; a second claim fails closed\n * retry positively safe? no. The claim commits before the KMS is asked to\n * decrypt, so a decrypt or transport failure burns the\n * artifact instead of risking a second release\n * crash/reload a crash before commit leaves the artifact claimable\n * ```\n *\n * @author taek <leekt216@gmail.com>\n */\n\nimport { type RelayClock, relayNow } from \"../clock.js\";\nimport { relayFailure } from \"../relay/errors.js\";\nimport type { RelayCaller } from \"../security/authentication.js\";\nimport type { RelayKms } from \"../security/kms.js\";\nimport type { RelayStore } from \"../store/interface.js\";\nimport { withRelayTransaction } from \"../store/interface.js\";\nimport { openArtifact } from \"./encrypt.js\";\n\nexport interface ClaimEncryptedArtifactInput {\n readonly store: RelayStore;\n readonly clock: RelayClock;\n readonly kms: RelayKms;\n /** Authenticated `client` caller; only the bound client may claim. */\n readonly caller: RelayCaller;\n /** Released only by a successful code consume. */\n readonly artifactId: string;\n}\n\nexport interface ClaimedEncryptedArtifact {\n readonly requestId: string;\n readonly artifact: string;\n}\n\nexport async function claimEncryptedArtifact(\n input: ClaimEncryptedArtifactInput,\n): Promise<ClaimedEncryptedArtifact> {\n const claimedAt = relayNow(input.clock);\n const claimed = await withRelayTransaction(input.store, async (transaction) => {\n const record = await transaction.lockEncryptedArtifact(input.artifactId);\n // An artifact bound to another client is indistinguishable from an unknown one.\n if (!record || record.clientId !== input.caller.clientId) {\n return relayFailure(\"relay_not_found\", \"encrypted artifact does not exist\");\n }\n if (record.claimedAt !== null) {\n relayFailure(\"relay_artifact_already_claimed\", \"encrypted artifact was already claimed\");\n }\n if (!(await transaction.claimEncryptedArtifact(input.artifactId, claimedAt))) {\n relayFailure(\"relay_state_ambiguous\", \"one-time claim did not apply under its row lock\");\n }\n return record;\n });\n return Object.freeze({\n requestId: claimed.requestId,\n artifact: await openArtifact(input.kms, claimed.ciphertextRef),\n });\n}\n","/**\n * One-time authorization code consume.\n *\n * ```text\n * state and owner the code record's `consumedAt` owns \"used\"\n * transitions issued -> consumed, exactly once\n * terminal consumed; a second consume fails closed\n * retry positively safe? no, in either direction: a released code is never\n * re-released, and an ambiguous commit is never retried\n * crash/reload the guarded update and the release decide together in one\n * transaction under the code's row lock\n * ```\n *\n * A failed PKCE or redirect binding still burns the code, so a stolen code\n * cannot be brute-forced against the stored challenge.\n *\n * The endpoint is not an oracle for whether a guessed code was correct: an\n * unknown code, a code bound to another client, a wrong redirect URI, and a\n * wrong verifier all leave as the single `relay_code_invalid` code and status.\n *\n * @author taek <leekt216@gmail.com>\n */\n\nimport { type RelayClock, relayNow } from \"../clock.js\";\nimport { type RelayErrorCode, relayFailure } from \"../relay/errors.js\";\nimport type { RelayCaller } from \"../security/authentication.js\";\nimport type { RelayStore } from \"../store/interface.js\";\nimport { sha256Base64Url, verifyPkceS256 } from \"./challenge.js\";\n\nexport interface ConsumeAuthorizationCodeInput {\n readonly store: RelayStore;\n readonly clock: RelayClock;\n /** Authenticated `client` caller; only the bound client may consume. */\n readonly caller: RelayCaller;\n readonly code: string;\n readonly codeVerifier: string;\n readonly redirectUri: string;\n}\n\nexport interface ConsumedAuthorizationCode {\n readonly requestId: string;\n /** One-time claim handle for the encrypted artifact. */\n readonly artifactId: string;\n}\n\ntype ConsumeOutcome =\n | Readonly<{ kind: \"released\"; released: ConsumedAuthorizationCode }>\n | Readonly<{ kind: \"burned\"; code: RelayErrorCode }>;\n\nexport async function consumeAuthorizationCode(\n input: ConsumeAuthorizationCodeInput,\n): Promise<ConsumedAuthorizationCode> {\n const consumedAt = relayNow(input.clock);\n const codeHash = await sha256Base64Url(input.code);\n const transaction = await input.store.begin();\n let outcome: ConsumeOutcome;\n try {\n const record = await transaction.lockAuthorizationCode(codeHash);\n // An unknown code and a code bound to another client are indistinguishable\n // from a code whose binding failed below.\n if (!record || record.clientId !== input.caller.clientId) {\n relayFailure(\"relay_code_invalid\", \"authorization code redemption failed\");\n }\n if (record.consumedAt !== null) {\n relayFailure(\"relay_code_already_consumed\", \"authorization code was already consumed\");\n }\n if (consumedAt >= record.expiresAt) {\n // Already dead; nothing left to burn.\n relayFailure(\"relay_expired\", \"authorization code expired\");\n }\n const bound =\n record.redirectUri === input.redirectUri &&\n (await verifyPkceS256(input.codeVerifier, record.codeChallenge));\n if (!(await transaction.consumeAuthorizationCode(codeHash, consumedAt))) {\n relayFailure(\"relay_state_ambiguous\", \"one-time consume did not apply under its row lock\");\n }\n if (!bound) {\n // Void the artifact with the code that would have released it. A `false`\n // result means it was already terminal, which is the same outcome.\n await transaction.lockEncryptedArtifact(record.artifactId);\n await transaction.claimEncryptedArtifact(record.artifactId, consumedAt);\n }\n outcome = bound\n ? Object.freeze({\n kind: \"released\",\n released: Object.freeze({\n requestId: record.requestId,\n artifactId: record.artifactId,\n }),\n })\n : Object.freeze({ kind: \"burned\", code: \"relay_code_invalid\" });\n } catch (error) {\n await transaction.rollback();\n throw error;\n }\n // The burn is committed before the failure is reported.\n await transaction.commit();\n if (outcome.kind === \"burned\") {\n relayFailure(outcome.code, \"authorization code redemption failed and the code was burned\");\n }\n return outcome.released;\n}\n","/**\n * Resume: fresh authentication plus a grant recovery read.\n *\n * Resume never transitions anything and never re-releases a code or an artifact.\n * The caller re-authenticates on every call, and receives only enough state to\n * decide whether its own grant work is still valid.\n *\n * @author taek <leekt216@gmail.com>\n */\n\nimport { type RelayClock, relayNow } from \"../clock.js\";\nimport type { RelayCaller } from \"../security/authentication.js\";\nimport type { RelayStore } from \"../store/interface.js\";\nimport { withRelayTransaction } from \"../store/interface.js\";\nimport { type AuthorizationState, readAuthorizationState } from \"./request.js\";\n\nexport interface ResumeAuthorizationInput {\n readonly store: RelayStore;\n readonly clock: RelayClock;\n /** Freshly authenticated `client` caller; only the bound client may resume. */\n readonly caller: RelayCaller;\n readonly requestId: string;\n}\n\nexport function resumeAuthorization(input: ResumeAuthorizationInput): Promise<AuthorizationState> {\n const now = relayNow(input.clock);\n return withRelayTransaction(input.store, (transaction) =>\n readAuthorizationState(\n transaction,\n input.requestId,\n now,\n (request) => request.clientId === input.caller.clientId,\n ),\n );\n}\n","/**\n * Authenticated client pickup of a released authorization code.\n *\n * ```text\n * state and owner reads the request and decision records; writes nothing\n * transitions none — pickup is idempotent\n * terminal follows the decision record\n * retry positively safe? yes: the code stays one-shot at consumption, where the\n * PKCE verifier and the code hash lock decide\n * ```\n *\n * The relay mints the code, so releasing the sealed copy to the authenticated\n * creating client adds no authority: consumption still requires the verifier\n * only that client holds. The request's stored clientId owns who may pick up;\n * any other caller reads absence, never existence.\n *\n * @author taek <leekt216@gmail.com>\n */\nimport { openArtifact } from \"../artifact/encrypt.js\";\nimport { type RelayClock, relayNow } from \"../clock.js\";\nimport { relayFailure } from \"../relay/errors.js\";\nimport type { RelayCaller } from \"../security/authentication.js\";\nimport type { RelayKms } from \"../security/kms.js\";\nimport { type RelayStore, withRelayTransaction } from \"../store/interface.js\";\n\nexport interface FetchAuthorizationCodeInput {\n readonly store: RelayStore;\n readonly clock: RelayClock;\n readonly kms: RelayKms;\n /** Authenticated `client` caller; only the creating client may pick up. */\n readonly caller: RelayCaller;\n readonly requestId: string;\n}\n\nexport type FetchedAuthorizationCode =\n | Readonly<{ outcome: \"pending\" }>\n | Readonly<{ outcome: \"rejected\"; decidedAt: number }>\n | Readonly<{ outcome: \"approved\"; decidedAt: number; code: string; codeExpiresAt: number }>;\n\nexport async function fetchAuthorizationCode(\n input: FetchAuthorizationCodeInput,\n): Promise<FetchedAuthorizationCode> {\n const now = relayNow(input.clock);\n const decided = await withRelayTransaction(input.store, async (transaction) => {\n const request = await transaction.lockAuthorizationRequest(input.requestId);\n if (!request || request.clientId !== input.caller.clientId) {\n return relayFailure(\"relay_not_found\", \"authorization request does not exist\");\n }\n const decision = await transaction.lockAuthorizationDecision(input.requestId);\n if (!decision) {\n if (now >= request.expiresAt) {\n return relayFailure(\"relay_expired\", \"authorization request expired\");\n }\n return null;\n }\n return decision;\n });\n if (decided === null) return Object.freeze({ outcome: \"pending\" });\n if (decided.outcome === \"rejected\" || decided.codeRef === null) {\n return Object.freeze({ outcome: \"rejected\", decidedAt: decided.decidedAt });\n }\n const codeExpiresAt = decided.codeExpiresAt ?? 0;\n if (now >= codeExpiresAt) {\n return relayFailure(\"relay_expired\", \"authorization code expired\");\n }\n // Opened only after every stored fact agreed; the plaintext never persists.\n return Object.freeze({\n outcome: \"approved\",\n decidedAt: decided.decidedAt,\n code: await openArtifact(input.kms, decided.codeRef),\n codeExpiresAt,\n });\n}\n","/**\n * Deployment-owned client/device authentication port.\n *\n * The relay never parses credentials. It hands the request to the deployment,\n * which returns the authenticated bindings or nothing. `clientId` and `subject`\n * come only from here: wire input may never declare either.\n *\n * @author taek <leekt216@gmail.com>\n */\n\nimport { type CaptureContext, captureDenseArray, exactRecord } from \"@oaath/protocol\";\nimport { OaathRelayError, relayFailure } from \"../relay/errors.js\";\nimport { boundedText, canonicalIdentifier, RELAY_LIMITS } from \"../store/records.js\";\n\n/** `client` is the requesting application; `owner` is the approving account owner. */\nexport type RelayCallerRole = \"client\" | \"owner\";\n\nconst MAX_REDIRECT_URIS = 8;\n\nexport interface RelayCaller {\n readonly role: RelayCallerRole;\n readonly clientId: string;\n /** Pairwise user/device subject. */\n readonly subject: string;\n /**\n * Redirect URIs the deployment registered for this client. An authorization\n * code may only be requested for one of them. `owner` callers pass an empty\n * list; they never receive a code at a redirect URI.\n */\n readonly redirectUris: readonly string[];\n}\n\nexport interface RelayAuthentication {\n /**\n * Resolves to a `RelayCaller`-shaped value, or `null`/`undefined` when the\n * caller is not authenticated. May throw `OaathRelayError` to choose a code.\n */\n authenticate(request: Request): Promise<unknown>;\n}\n\nfunction captureCaller(value: unknown): RelayCaller {\n const context: CaptureContext = new WeakSet();\n // A port that breaks its own contract is an internal failure, not a 401.\n const fail = (message: string): never => relayFailure(\"relay_internal\", message);\n const record = exactRecord(\n value,\n [\"role\", \"clientId\", \"subject\", \"redirectUris\"],\n \"authenticated caller\",\n context,\n fail,\n );\n if (record.role !== \"client\" && record.role !== \"owner\") {\n return relayFailure(\"relay_internal\", \"authenticated caller role is unsupported\");\n }\n const redirectUris = captureDenseArray(record.redirectUris, \"caller redirectUris\", context, fail);\n if (redirectUris.length > MAX_REDIRECT_URIS) {\n return relayFailure(\"relay_internal\", \"caller redirectUris is unbounded\");\n }\n return Object.freeze({\n role: record.role,\n clientId: canonicalIdentifier(record.clientId, \"caller clientId\", \"relay_internal\"),\n subject: canonicalIdentifier(record.subject, \"caller subject\", \"relay_internal\"),\n redirectUris: Object.freeze(\n redirectUris.map((uri) =>\n boundedText(uri, RELAY_LIMITS.redirectUri, \"caller redirectUri\", \"relay_internal\"),\n ),\n ),\n });\n}\n\nexport async function authenticateCaller(\n authentication: RelayAuthentication,\n request: Request,\n required: RelayCallerRole | readonly RelayCallerRole[],\n): Promise<RelayCaller> {\n let authenticated: unknown;\n try {\n authenticated = await authentication.authenticate(request);\n } catch (error) {\n // Unreadable authentication is not authentication.\n if (error instanceof OaathRelayError) throw error;\n return relayFailure(\"relay_unauthenticated\", \"authentication port failed\");\n }\n if (authenticated === null || authenticated === undefined) {\n return relayFailure(\"relay_unauthenticated\", \"caller is not authenticated\");\n }\n const caller = captureCaller(authenticated);\n const roles = typeof required === \"string\" ? [required] : required;\n if (!roles.includes(caller.role)) {\n return relayFailure(\"relay_forbidden\", \"caller may not act in the required role\");\n }\n return caller;\n}\n","/**\n * Optional deployment-owned limiter port.\n *\n * There is no default limiter: an unset port means no limiting, and the relay\n * never invents a policy the deployment did not choose. A limiter that fails is\n * treated as `limited`, because an unreadable limiter is not permission.\n *\n * @author taek <leekt216@gmail.com>\n */\n\nimport { relayFailure } from \"../relay/errors.js\";\n\nexport interface RelayRateLimitInput {\n /** Stable route name, never a credential-bearing URL. */\n readonly route: string;\n readonly clientId: string | null;\n}\n\nexport interface RelayRateLimiter {\n /** Resolves to `\"allowed\"` or `\"limited\"`. Anything else is `limited`. */\n check(input: RelayRateLimitInput): Promise<unknown>;\n}\n\nexport async function assertWithinRateLimit(\n limiter: RelayRateLimiter | undefined,\n input: RelayRateLimitInput,\n): Promise<void> {\n if (!limiter) return;\n let verdict: unknown;\n try {\n verdict = await limiter.check(input);\n } catch {\n return relayFailure(\"relay_rate_limited\", \"rate limiter is unreadable\");\n }\n if (verdict !== \"allowed\") {\n return relayFailure(\"relay_rate_limited\", \"rate limiter rejected the call\");\n }\n}\n","/**\n * Fetch-standard relay handler.\n *\n * Every wire input is exact-captured once here and handed to a use case as typed\n * data. Every failure leaves as a structured code projected to a status; no\n * message text, driver output, or internal detail reaches a response body.\n *\n * Endpoints:\n *\n * ```text\n * POST /authorization/requests client create request\n * GET /authorization/requests/{requestId} owner fetch request\n * POST /authorization/requests/{requestId}/decision owner approve or reject\n * GET /authorization/requests/{requestId}/code client released-code pickup\n * POST /authorization/codes/consume client one-time code consume\n * POST /authorization/artifacts/{artifactId}/claim client one-time artifact claim\n * POST /authorization/resume client fresh auth + recovery read\n * GET /bootstrap client URL-only service context\n * POST /invalidations client capability invalidation\n * POST /chains/{chainId}/{port} client chain execution relay,\n * port in reads |\n * observation | bundler |\n * quote | submissions | usage\n * POST /chains/{chainId}/paymaster/{method} client registered paymaster proxy,\n * method in stub-data | data\n * ```\n *\n * EXPERIMENTAL PREVIEW routes for the owner-phone approval surface. Preview\n * means: no stability guarantee and no production qualification. Their wire\n * shapes are pinned field-for-field by the strict Swift decoders in\n * `native/ios/Sources/OwnerPhone/{Projection,Decision}.swift`.\n *\n * ```text\n * GET /native/projections/{operationId} owner consent projection\n * POST /native/decisions/{operationId} owner approve or reject saga\n * ```\n *\n * @author taek <leekt216@gmail.com>\n */\n\nimport {\n type CaptureContext,\n captureDenseArray,\n captureRecord,\n exactCapturedRecord,\n OAATH_SERVICE_BOOTSTRAP_VERSION,\n parseServiceBootstrap,\n type ServiceBootstrap,\n} from \"@oaath/protocol\";\nimport { claimEncryptedArtifact } from \"../artifact/claim.js\";\nimport { consumeAuthorizationCode } from \"../authorization/code.js\";\nimport type { AuthorizationDecisionCommand } from \"../authorization/decision.js\";\nimport { submitAuthorizationDecision } from \"../authorization/decision.js\";\nimport { fetchAuthorizationCode } from \"../authorization/pickup.js\";\nimport {\n type AuthorizationState,\n createAuthorizationRequest,\n fetchAuthorizationRequest,\n} from \"../authorization/request.js\";\nimport { resumeAuthorization } from \"../authorization/resume.js\";\nimport { type RelayClock, relayNow } from \"../clock.js\";\nimport { submitOwnerPhoneDecision } from \"../native/decision.js\";\nimport { projectOwnerPhoneRequest } from \"../native/projection.js\";\nimport {\n authenticateCaller,\n type RelayAuthentication,\n type RelayCaller,\n type RelayCallerRole,\n} from \"../security/authentication.js\";\nimport type { RelayKms } from \"../security/kms.js\";\nimport { assertWithinRateLimit, type RelayRateLimiter } from \"../security/rate-limit.js\";\nimport type { RelaySessionSignerProvider } from \"../session-signer/kms-provider.js\";\nimport { type RelayStore, withRelayTransaction } from \"../store/interface.js\";\nimport {\n boundedText,\n canonicalIdentifier,\n OAATH_CAPABILITY_INVALIDATION_RECORD_VERSION,\n RELAY_LIMITS,\n timestamp,\n} from \"../store/records.js\";\nimport { jsonResponse, relayErrorCode, relayErrorResponse, relayFailure } from \"./errors.js\";\n\nconst DEFAULT_REQUEST_TTL_MS = 300_000;\nconst DEFAULT_CODE_TTL_MS = 60_000;\nconst DEFAULT_MAX_BODY_BYTES = 65_536;\nconst MAX_TTL_MS = 86_400_000;\n/** RFC 6749 ceiling, matching `MAX_AUTHORIZATION_CODE_LIFETIME` in @oaath/protocol. */\nconst MAX_CODE_TTL_MS = 600_000;\nconst MAX_PAYMASTER_REQUEST_TIMEOUT_MS = 30_000;\nconst HASH = /^0x[0-9a-f]{64}$/u;\n\nconst INVALID = \"relay_request_invalid\" as const;\n\n/**\n * One deployment-injected chain execution surface the relay serves to clients.\n * Each port takes exactly one captured request value and answers with the\n * evidence it owns; the relay never interprets the payload beyond exact wire\n * hygiene, so port meaning stays with its SDK owner.\n */\nexport interface RelayChainPort {\n readonly chainId: number;\n readonly reads: (request: unknown) => Promise<unknown>;\n readonly observation: (request: unknown) => Promise<unknown>;\n readonly bundler: (request: unknown) => Promise<unknown>;\n readonly quote: (request: unknown) => Promise<unknown>;\n /** Opens, sends, and settles one submission in one call; never retried here. */\n readonly submission: (request: unknown) => Promise<unknown>;\n /** Finalized per-grant usage evidence, or null when this chain serves none. */\n readonly usage: ((request: unknown) => Promise<unknown>) | null;\n readonly feePayer: Readonly<{ address: `0x${string}`; balance: string }> | null;\n /** Authenticated commitment to one exact ERC-7902 static paymaster, or null. */\n readonly staticPaymasterConfigurationHash: `0x${string}` | null;\n}\n\n/** The identity facts `GET /bootstrap` serves; chains derive from `chains`. */\nexport interface RelayBootstrapConfiguration {\n readonly application: unknown;\n readonly userHandle: string;\n readonly account: unknown;\n readonly ownerValidator: `0x${string}` | null;\n}\n\n/**\n * Remote session-key custody, declared once for the deployment: the mode and\n * provider identity are served through the bootstrap document, and the same\n * provider answers the `/session-signers` routes. For `oaath_hosted` the\n * provider is typically `createKmsSessionSignerProvider`; for\n * `application_backend` it is the deployment's own authenticated port to the\n * integrating application's signer — never a client-supplied endpoint.\n */\nexport interface RelaySessionSignerConfiguration {\n readonly mode: \"application_backend\" | \"oaath_hosted\";\n readonly providerId: string;\n readonly provider: Readonly<RelaySessionSignerProvider>;\n}\n\n/** Authenticated identity and one opaque ERC-7677 params tuple. */\nexport interface RelayPaymasterServiceRequest {\n readonly caller: Readonly<{ clientId: string; subject: string }>;\n readonly params: unknown;\n readonly signal: AbortSignal;\n}\n\n/**\n * One deployment-owned paymaster provider. The relay exposes only these two\n * closed ERC-7677 operations and invokes the selected method once.\n */\nexport interface RelayPaymasterServiceProvider {\n readonly getPaymasterStubData: (\n request: Readonly<RelayPaymasterServiceRequest>,\n ) => Promise<unknown>;\n readonly getPaymasterData: (request: Readonly<RelayPaymasterServiceRequest>) => Promise<unknown>;\n}\n\nexport interface RelayPaymasterServiceConfiguration {\n readonly chainId: number;\n readonly providerId: string;\n /** Hard response deadline; the provider also receives its abort signal. */\n readonly requestTimeoutMs: number;\n readonly provider: Readonly<RelayPaymasterServiceProvider>;\n}\n\nexport interface RelayHandlerOptions {\n readonly store: RelayStore;\n readonly authentication: RelayAuthentication;\n readonly kms: RelayKms;\n readonly clock: RelayClock;\n /** Optional. There is no default limiter. */\n readonly rateLimit?: RelayRateLimiter;\n readonly requestTtlMs?: number;\n readonly codeTtlMs?: number;\n readonly maxBodyBytes?: number;\n /** Optional URL-only bootstrap surface; requires `chains` as well. */\n readonly bootstrap?: Readonly<RelayBootstrapConfiguration>;\n /** Optional chain execution relays; required when `bootstrap` is served. */\n readonly chains?: readonly Readonly<RelayChainPort>[];\n /** Optional remote session-key custody; requires `bootstrap` as well. */\n readonly sessionSigner?: Readonly<RelaySessionSignerConfiguration>;\n /**\n * Optional deployment-owned paymaster services, at most one per chain.\n * Configuration requires both bootstrap and a deployment rate limiter.\n */\n readonly paymasterServices?: readonly Readonly<RelayPaymasterServiceConfiguration>[];\n}\n\nexport type RelayHandler = (request: Request) => Promise<Response>;\n\nconst OPTION_KEYS: readonly string[] = [\n \"store\",\n \"authentication\",\n \"kms\",\n \"clock\",\n \"rateLimit\",\n \"requestTtlMs\",\n \"codeTtlMs\",\n \"maxBodyBytes\",\n \"bootstrap\",\n \"chains\",\n \"sessionSigner\",\n \"paymasterServices\",\n];\n\nconst CHAIN_PORT_NAMES = [\"reads\", \"observation\", \"bundler\", \"quote\", \"submission\"] as const;\ntype ChainPortName = (typeof CHAIN_PORT_NAMES)[number] | \"usage\";\n\n/**\n * The Grant a chain port request acts for, where the port's contract names\n * one: a submission's prepared operation and a usage read both carry it.\n * Reading it here is bounded extraction for the invalidation gate, not\n * interpretation — the port's own owner still captures the payload exactly.\n */\nfunction chainRequestGrantId(name: ChainPortName, request: unknown): string | null {\n try {\n if (name === \"usage\") {\n const grantId = (request as { readonly grantId?: unknown } | null)?.grantId;\n return typeof grantId === \"string\" && grantId.length > 0 ? grantId : null;\n }\n if (name === \"submission\") {\n const prepared = (request as { readonly prepared?: unknown } | null)?.prepared;\n const grantId = (prepared as { readonly grantId?: unknown } | null)?.grantId;\n return typeof grantId === \"string\" && grantId.length > 0 ? grantId : null;\n }\n } catch {\n // A hostile getter reads as absent; the port's exact capture still owns\n // whether such a payload is usable at all.\n }\n return null;\n}\n\n/**\n * Ports may be class instances, so only their required capabilities are checked.\n * Narrowing follows the runtime check.\n */\nfunction requirePort<Port>(value: unknown, methods: readonly string[], label: string): Port {\n if (!value || typeof value !== \"object\") {\n return relayFailure(\"relay_internal\", `${label} must be an object`);\n }\n for (const method of methods) {\n if (typeof (value as Record<string, unknown>)[method] !== \"function\") {\n return relayFailure(\"relay_internal\", `${label} must implement ${method}()`);\n }\n }\n return value as Port;\n}\n\nfunction duration(value: unknown, fallback: number, label: string, maximum = MAX_TTL_MS): number {\n if (value === undefined) return fallback;\n const milliseconds = timestamp(value, label, \"relay_internal\");\n if (milliseconds < 1 || milliseconds > maximum) {\n return relayFailure(\"relay_internal\", `${label} must be a bounded positive duration`);\n }\n return milliseconds;\n}\n\ninterface CapturedOptions {\n readonly store: RelayStore;\n readonly authentication: RelayAuthentication;\n readonly kms: RelayKms;\n readonly clock: RelayClock;\n readonly rateLimit: RelayRateLimiter | undefined;\n readonly requestTtlMs: number;\n readonly codeTtlMs: number;\n readonly maxBodyBytes: number;\n /** The exact parsed document `GET /bootstrap` serves, or null when unserved. */\n readonly bootstrap: Readonly<ServiceBootstrap> | null;\n readonly sessionSigner: Readonly<RelaySessionSignerConfiguration> | null;\n readonly chains: ReadonlyMap<number, Readonly<RelayChainPort>>;\n readonly paymasterServices: ReadonlyMap<number, Readonly<RelayPaymasterServiceConfiguration>>;\n}\n\nfunction captureChainPorts(value: unknown): ReadonlyMap<number, Readonly<RelayChainPort>> {\n if (!Array.isArray(value)) {\n return relayFailure(\"relay_internal\", \"chains must be an array of chain ports\");\n }\n const chains = new Map<number, Readonly<RelayChainPort>>();\n for (const entry of value) {\n const port = requirePort<RelayChainPort>(entry, [...CHAIN_PORT_NAMES], \"chain port\");\n if (\n typeof port.chainId !== \"number\" ||\n !Number.isSafeInteger(port.chainId) ||\n port.chainId < 1\n ) {\n return relayFailure(\"relay_internal\", \"chain port chainId must be a positive integer\");\n }\n if (port.usage !== null && typeof port.usage !== \"function\") {\n return relayFailure(\"relay_internal\", \"chain port usage must be a function or null\");\n }\n if (\n port.staticPaymasterConfigurationHash !== null &&\n (typeof port.staticPaymasterConfigurationHash !== \"string\" ||\n !HASH.test(port.staticPaymasterConfigurationHash))\n ) {\n return relayFailure(\n \"relay_internal\",\n \"chain port static paymaster commitment must be a lowercase hash or null\",\n );\n }\n if (chains.has(port.chainId)) {\n return relayFailure(\"relay_internal\", \"chain ports repeat a chainId\");\n }\n chains.set(port.chainId, port);\n }\n return chains;\n}\n\nfunction capturePaymasterServices(\n value: unknown,\n context: CaptureContext,\n chains: ReadonlyMap<number, Readonly<RelayChainPort>>,\n): ReadonlyMap<number, Readonly<RelayPaymasterServiceConfiguration>> {\n if (value === undefined) return new Map();\n const entries = captureDenseArray(value, \"paymaster services\", context, (message) =>\n relayFailure(\"relay_internal\", message),\n );\n const services = new Map<number, Readonly<RelayPaymasterServiceConfiguration>>();\n for (const entry of entries) {\n const service = exactCapturedRecord(\n captureRecord(entry, \"paymaster service\", context, (message) =>\n relayFailure(\"relay_internal\", message),\n ),\n [\"chainId\", \"providerId\", \"requestTimeoutMs\", \"provider\"],\n \"paymaster service\",\n (message) => relayFailure(\"relay_internal\", message),\n );\n const chainId = service.chainId;\n if (typeof chainId !== \"number\" || !Number.isSafeInteger(chainId) || chainId < 1) {\n relayFailure(\"relay_internal\", \"paymaster service chainId must be a positive integer\");\n }\n if (!chains.has(chainId)) {\n relayFailure(\"relay_internal\", \"paymaster service chain is not configured\");\n }\n if (services.has(chainId)) {\n relayFailure(\"relay_internal\", \"paymaster services repeat a chainId\");\n }\n if (service.requestTimeoutMs === undefined) {\n relayFailure(\"relay_internal\", \"paymaster requestTimeoutMs is required\");\n }\n services.set(\n chainId,\n Object.freeze({\n chainId,\n providerId: canonicalIdentifier(\n service.providerId,\n \"paymaster providerId\",\n \"relay_internal\",\n ),\n requestTimeoutMs: duration(\n service.requestTimeoutMs,\n 0,\n \"paymaster requestTimeoutMs\",\n MAX_PAYMASTER_REQUEST_TIMEOUT_MS,\n ),\n provider: requirePort<RelayPaymasterServiceProvider>(\n service.provider,\n [\"getPaymasterStubData\", \"getPaymasterData\"],\n \"paymaster provider\",\n ),\n }),\n );\n }\n return services;\n}\n\nfunction captureOptions(value: unknown): CapturedOptions {\n const context: CaptureContext = new WeakSet();\n const record = captureRecord(value, \"relay handler options\", context, (message) =>\n relayFailure(\"relay_internal\", message),\n );\n for (const key of Object.keys(record)) {\n if (!OPTION_KEYS.includes(key)) {\n relayFailure(\"relay_internal\", \"relay handler options contain an unknown field\");\n }\n }\n const chains =\n record.chains === undefined\n ? new Map<number, Readonly<RelayChainPort>>()\n : captureChainPorts(record.chains);\n const rateLimit =\n record.rateLimit === undefined\n ? undefined\n : requirePort<RelayRateLimiter>(record.rateLimit, [\"check\"], \"rateLimit\");\n const paymasterServices = capturePaymasterServices(record.paymasterServices, context, chains);\n if (paymasterServices.size > 0) {\n if (record.bootstrap === undefined) {\n relayFailure(\"relay_internal\", \"a paymaster service requires a bootstrap surface\");\n }\n if (rateLimit === undefined) {\n relayFailure(\"relay_internal\", \"a paymaster service requires a rate limiter\");\n }\n }\n let sessionSigner: Readonly<RelaySessionSignerConfiguration> | null = null;\n if (record.sessionSigner !== undefined) {\n if (record.bootstrap === undefined) {\n relayFailure(\"relay_internal\", \"a session signer requires a bootstrap surface\");\n }\n const custody = captureRecord(\n record.sessionSigner,\n \"relay session signer configuration\",\n context,\n (message) => relayFailure(\"relay_internal\", message),\n );\n if (custody.mode !== \"application_backend\" && custody.mode !== \"oaath_hosted\") {\n relayFailure(\"relay_internal\", \"session signer mode is unsupported\");\n }\n if (typeof custody.providerId !== \"string\" || custody.providerId.length < 1) {\n relayFailure(\"relay_internal\", \"session signer providerId is invalid\");\n }\n sessionSigner = Object.freeze({\n mode: custody.mode as \"application_backend\" | \"oaath_hosted\",\n providerId: custody.providerId,\n provider: requirePort<RelaySessionSignerProvider>(\n custody.provider,\n [\"credential\", \"sign\"],\n \"session signer provider\",\n ),\n });\n }\n let bootstrap: Readonly<ServiceBootstrap> | null = null;\n if (record.bootstrap !== undefined) {\n if (chains.size === 0) {\n relayFailure(\"relay_internal\", \"a bootstrap surface requires chain ports\");\n }\n const identity = captureRecord(\n record.bootstrap,\n \"relay bootstrap configuration\",\n context,\n (message) => relayFailure(\"relay_internal\", message),\n );\n // The exact protocol parser owns document meaning; a misconfigured\n // deployment fails at construction, never at a client's request.\n try {\n bootstrap = parseServiceBootstrap({\n version: OAATH_SERVICE_BOOTSTRAP_VERSION,\n application: identity.application,\n userHandle: identity.userHandle,\n account: identity.account,\n ownerValidator: identity.ownerValidator,\n chains: [...chains.values()].map((port) => {\n const paymasterService = paymasterServices.get(port.chainId);\n return {\n chainId: port.chainId,\n usage: port.usage !== null,\n feePayer: port.feePayer,\n paymasterService:\n paymasterService === undefined ? null : { providerId: paymasterService.providerId },\n staticPaymasterConfigurationHash: port.staticPaymasterConfigurationHash,\n };\n }),\n // The one custody declaration serves both the document and the\n // signing routes; they can never disagree.\n sessionSigner:\n sessionSigner === null\n ? { mode: \"frontend\", providerId: null }\n : { mode: sessionSigner.mode, providerId: sessionSigner.providerId },\n });\n } catch {\n relayFailure(\"relay_internal\", \"relay bootstrap configuration is invalid\");\n }\n }\n return Object.freeze({\n store: requirePort<RelayStore>(record.store, [\"begin\", \"close\"], \"store\"),\n authentication: requirePort<RelayAuthentication>(\n record.authentication,\n [\"authenticate\"],\n \"authentication\",\n ),\n kms: requirePort<RelayKms>(record.kms, [\"encrypt\", \"decrypt\"], \"kms\"),\n clock: requirePort<RelayClock>(record.clock, [\"now\"], \"clock\"),\n rateLimit,\n requestTtlMs: duration(record.requestTtlMs, DEFAULT_REQUEST_TTL_MS, \"requestTtlMs\"),\n codeTtlMs: duration(record.codeTtlMs, DEFAULT_CODE_TTL_MS, \"codeTtlMs\", MAX_CODE_TTL_MS),\n maxBodyBytes: duration(record.maxBodyBytes, DEFAULT_MAX_BODY_BYTES, \"maxBodyBytes\"),\n bootstrap,\n sessionSigner,\n chains,\n paymasterServices,\n });\n}\n\nfunction requireMethod(request: Request, expected: \"GET\" | \"POST\"): void {\n if (request.method !== expected) {\n relayFailure(\"relay_method_not_allowed\", \"route does not accept this method\");\n }\n}\n\nasync function bodyRecord(\n request: Request,\n maxBodyBytes: number,\n): Promise<Record<string, unknown>> {\n const contentType = request.headers.get(\"content-type\") ?? \"\";\n if (!contentType.toLowerCase().startsWith(\"application/json\")) {\n relayFailure(INVALID, \"request body must be application/json\");\n }\n let text: string;\n try {\n text = await request.text();\n } catch {\n return relayFailure(INVALID, \"request body is unreadable\");\n }\n if (new TextEncoder().encode(text).byteLength > maxBodyBytes) {\n return relayFailure(INVALID, \"request body exceeds its bound\");\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(text) as unknown;\n } catch {\n return relayFailure(INVALID, \"request body is not JSON\");\n }\n const context: CaptureContext = new WeakSet();\n return captureRecord(parsed, \"request body\", context, (message) =>\n relayFailure(INVALID, message),\n );\n}\n\nfunction exactBody(\n record: Record<string, unknown>,\n keys: readonly string[],\n): Record<string, unknown> {\n return exactCapturedRecord(record, keys, \"request body\", (message) =>\n relayFailure(INVALID, message),\n );\n}\n\nasync function invokePaymasterService(\n service: Readonly<RelayPaymasterServiceConfiguration>,\n method: \"stub-data\" | \"data\",\n caller: Readonly<RelayCaller>,\n params: unknown,\n): Promise<unknown> {\n const controller = new AbortController();\n let timeout: ReturnType<typeof setTimeout> | undefined;\n try {\n const deadline = new Promise<never>((_resolve, reject) => {\n timeout = setTimeout(() => {\n controller.abort();\n reject(new Error(\"paymaster request deadline elapsed\"));\n }, service.requestTimeoutMs);\n });\n const capability =\n method === \"stub-data\"\n ? service.provider.getPaymasterStubData\n : service.provider.getPaymasterData;\n const request: Readonly<RelayPaymasterServiceRequest> = Object.freeze({\n caller: Object.freeze({ clientId: caller.clientId, subject: caller.subject }),\n params,\n signal: controller.signal,\n });\n return await Promise.race([\n Promise.resolve(Reflect.apply(capability, undefined, [request])),\n deadline,\n ]);\n } catch {\n return relayFailure(\"relay_chain_unavailable\", \"paymaster provider did not answer\");\n } finally {\n if (timeout !== undefined) clearTimeout(timeout);\n }\n}\n\nfunction decisionCommand(record: Record<string, unknown>): AuthorizationDecisionCommand {\n if (record.outcome === \"approved\") {\n const exact = exactBody(record, [\"outcome\", \"artifact\"]);\n return Object.freeze({\n outcome: \"approved\",\n artifact: boundedText(exact.artifact, RELAY_LIMITS.artifactPlaintext, \"artifact\", INVALID),\n });\n }\n if (record.outcome === \"rejected\") {\n exactBody(record, [\"outcome\"]);\n return Object.freeze({ outcome: \"rejected\" });\n }\n return relayFailure(INVALID, \"decision outcome is unsupported\");\n}\n\n/**\n * EXPERIMENTAL PREVIEW — the phone decision body: `{command, artifact?}`.\n * `approve` hands over the artifact the client will claim once; `reject`\n * carries nothing else. The saga answers the stored outcome on a replay.\n */\nfunction phoneDecisionCommand(record: Record<string, unknown>): AuthorizationDecisionCommand {\n if (record.command === \"approve\") {\n const exact = exactBody(record, [\"command\", \"artifact\"]);\n return Object.freeze({\n outcome: \"approved\",\n artifact: boundedText(exact.artifact, RELAY_LIMITS.artifactPlaintext, \"artifact\", INVALID),\n });\n }\n if (record.command === \"reject\") {\n exactBody(record, [\"command\"]);\n return Object.freeze({ outcome: \"rejected\" });\n }\n return relayFailure(INVALID, \"decision command is unsupported\");\n}\n\nfunction stateBody(state: AuthorizationState): unknown {\n return {\n requestId: state.requestId,\n clientId: state.clientId,\n redirectUri: state.redirectUri,\n requestedScope: state.requestedScope,\n expiresAt: state.expiresAt,\n expired: state.expired,\n decision: state.decision,\n };\n}\n\nexport function createRelayHandler(options: RelayHandlerOptions): RelayHandler {\n const captured = captureOptions(options);\n\n const authenticate = async (\n request: Request,\n role: RelayCallerRole | readonly RelayCallerRole[],\n route: string,\n ): Promise<RelayCaller> => {\n const caller = await authenticateCaller(captured.authentication, request, role);\n // Limiting happens after authentication so a deployment can key on clientId.\n // The authentication port owns unauthenticated abuse.\n await assertWithinRateLimit(captured.rateLimit, { route, clientId: caller.clientId });\n return caller;\n };\n\n const route = async (request: Request): Promise<Response> => {\n const segments = new URL(request.url).pathname.split(\"/\").filter((part) => part.length > 0);\n const [head, group, third, fourth] = segments;\n\n // EXPERIMENTAL PREVIEW — owner-phone approval routes. Same wire hygiene as\n // every relay route: exact capture, structured codes, no-store responses.\n if (head === \"native\") {\n if (segments.length === 3 && group === \"projections\") {\n requireMethod(request, \"GET\");\n const caller = await authenticate(request, \"owner\", \"native.project\");\n const projection = await projectOwnerPhoneRequest({\n store: captured.store,\n clock: captured.clock,\n caller,\n requestId: canonicalIdentifier(third, \"operationId\", INVALID),\n });\n return jsonResponse(200, projection);\n }\n if (segments.length === 3 && group === \"decisions\") {\n requireMethod(request, \"POST\");\n const caller = await authenticate(request, \"owner\", \"native.decide\");\n const command = phoneDecisionCommand(await bodyRecord(request, captured.maxBodyBytes));\n const decided = await submitOwnerPhoneDecision({\n store: captured.store,\n clock: captured.clock,\n kms: captured.kms,\n caller,\n operationId: canonicalIdentifier(third, \"operationId\", INVALID),\n command,\n codeTtlMs: captured.codeTtlMs,\n });\n return jsonResponse(200, decided);\n }\n return relayFailure(\"relay_not_found\", \"route does not exist\");\n }\n\n if (head === \"bootstrap\" && segments.length === 1) {\n requireMethod(request, \"GET\");\n await authenticate(request, \"client\", \"bootstrap.fetch\");\n if (captured.bootstrap === null) {\n return relayFailure(\"relay_not_found\", \"route does not exist\");\n }\n return jsonResponse(200, captured.bootstrap);\n }\n\n if (head === \"session-signers\") {\n // Remote session-key custody routes, served exactly when the deployment\n // declared it. The caller's authenticated identity — never anything the\n // body claims — names the key: one (clientId, subject, deviceId)\n // identity holds one credential, so a different credential can never\n // sign under an approval that bound this one (the rotation invariant).\n const custody = captured.sessionSigner;\n if (custody === null) return relayFailure(\"relay_not_found\", \"route does not exist\");\n if (segments.length === 1) {\n requireMethod(request, \"POST\");\n const caller = await authenticate(request, \"client\", \"session-signers.credential\");\n const body = exactBody(await bodyRecord(request, captured.maxBodyBytes), [\"deviceId\"]);\n const deviceId = boundedText(body.deviceId, 256, \"session signer deviceId\", INVALID);\n let credential: unknown;\n try {\n credential = await custody.provider.credential({\n clientId: caller.clientId,\n subject: caller.subject,\n deviceId,\n });\n } catch {\n return relayFailure(\"relay_internal\", \"session signer provider did not answer\");\n }\n return jsonResponse(200, { operatorCredential: credential });\n }\n if (segments.length === 2 && group === \"signatures\") {\n requireMethod(request, \"POST\");\n const caller = await authenticate(request, \"client\", \"session-signers.sign\");\n const body = exactBody(await bodyRecord(request, captured.maxBodyBytes), [\n \"deviceId\",\n \"hash\",\n ]);\n const deviceId = boundedText(body.deviceId, 256, \"session signer deviceId\", INVALID);\n // One exact 32-byte hash; the provider signs an identity, never a\n // message it interprets.\n if (typeof body.hash !== \"string\" || !/^0x[0-9a-f]{64}$/u.test(body.hash)) {\n return relayFailure(INVALID, \"session signer hash must be one exact 32-byte hash\");\n }\n let signature: unknown;\n try {\n signature = await custody.provider.sign({\n clientId: caller.clientId,\n subject: caller.subject,\n deviceId,\n hash: body.hash as `0x${string}`,\n });\n } catch {\n return relayFailure(\"relay_internal\", \"session signer provider did not answer\");\n }\n return jsonResponse(200, { signature });\n }\n return relayFailure(\"relay_not_found\", \"route does not exist\");\n }\n\n if (head === \"invalidations\" && segments.length === 1) {\n requireMethod(request, \"POST\");\n const caller = await authenticate(request, \"client\", \"invalidations.create\");\n const body = exactBody(await bodyRecord(request, captured.maxBodyBytes), [\n \"grantId\",\n \"capabilityHash\",\n ]);\n const grantId = canonicalIdentifier(body.grantId, \"grantId\", INVALID);\n const capabilityHash = boundedText(body.capabilityHash, 66, \"capabilityHash\", INVALID);\n if (!/^0x[0-9a-f]{64}$/u.test(capabilityHash)) {\n return relayFailure(INVALID, \"capabilityHash must be a lowercase 32-byte hash\");\n }\n // Durable and enforced: from the committed record on, every chain\n // execution route below refuses this Grant, so the evidence states an\n // enforced fact — this service will no longer act for the capability.\n // Consuming the on-chain install nonce stays the chain-local revocation\n // operation's separate evidence. Replays answer the stored record, so\n // one Grant has exactly one invalidation time.\n const record = await withRelayTransaction(captured.store, async (transaction) => {\n const existing = await transaction.lockCapabilityInvalidation(grantId);\n if (existing) {\n if (existing.clientId !== caller.clientId) {\n // Reported as absence: not an existence oracle for another\n // client's Grant.\n return relayFailure(\"relay_not_found\", \"grant does not exist\");\n }\n return existing;\n }\n const created = Object.freeze({\n version: OAATH_CAPABILITY_INVALIDATION_RECORD_VERSION,\n grantId,\n clientId: caller.clientId,\n capabilityHash,\n invalidatedAt: relayNow(captured.clock),\n });\n if (!(await transaction.insertCapabilityInvalidation(created))) {\n return relayFailure(\"relay_internal\", \"capability invalidation did not commit\");\n }\n return created;\n });\n const digest = await crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(\n `oaath-relay-invalidation:v1:${record.clientId}:${record.grantId}:${record.capabilityHash}:${record.invalidatedAt}`,\n ),\n );\n const evidenceHash = `0x${[...new Uint8Array(digest)]\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\")}`;\n // The evidence is protocol-facing, so it speaks the protocol's seconds\n // domain rather than the relay's millisecond records.\n return jsonResponse(200, {\n evidenceHash,\n invalidatedAt: Math.floor(record.invalidatedAt / 1_000),\n });\n }\n\n if (head === \"chains\" && segments.length === 4 && third === \"paymaster\") {\n requireMethod(request, \"POST\");\n const service = captured.paymasterServices.get(Number(group));\n const method = fourth === \"stub-data\" || fourth === \"data\" ? fourth : null;\n if (service === undefined || method === null) {\n return relayFailure(\"relay_not_found\", \"route does not exist\");\n }\n const caller = await authenticate(request, \"client\", `chains.paymaster.${method}`);\n // The route selects the deployment-owned provider. An application URL\n // is never accepted in this body and therefore can never become a fetch\n // target here.\n const body = exactBody(await bodyRecord(request, captured.maxBodyBytes), [\"params\"]);\n const result = await invokePaymasterService(service, method, caller, body.params);\n return jsonResponse(\n 200,\n result === undefined ? { present: false, result: null } : { present: true, result },\n );\n }\n\n if (head === \"chains\") {\n if (segments.length !== 3) return relayFailure(\"relay_not_found\", \"route does not exist\");\n requireMethod(request, \"POST\");\n const port = captured.chains.get(Number(group));\n const name: ChainPortName | null =\n third === \"submissions\"\n ? \"submission\"\n : third === \"reads\" ||\n third === \"observation\" ||\n third === \"bundler\" ||\n third === \"quote\" ||\n third === \"usage\"\n ? third\n : null;\n if (!port || name === null) {\n return relayFailure(\"relay_not_found\", \"route does not exist\");\n }\n // Submissions also accept the owner role: the owner-signed revocation\n // operation is what removes an installed chain permission, so the\n // owner's console must be able to submit it after the capability died.\n const caller = await authenticate(\n request,\n name === \"submission\" ? [\"client\", \"owner\"] : \"client\",\n `chains.${name}`,\n );\n const body = exactBody(await bodyRecord(request, captured.maxBodyBytes), [\"request\"]);\n const capability = name === \"usage\" ? port.usage : port[name];\n if (capability === null) {\n return relayFailure(\"relay_not_found\", \"route does not exist\");\n }\n // Recorded invalidations are enforced here: a submission or usage read\n // that names an invalidated Grant is refused before its port runs. The\n // ports whose requests carry no Grant identity are chain reads, which\n // grant nothing. This guards the honest capability; the on-chain install\n // nonce is what a hostile holder must still be cut off from, by the\n // chain-local revocation operation.\n //\n // The one pass through the gate is the caller's PROVEN owner role —\n // never a payload claim, which any gated client could spoof to keep\n // spending relay, RPC, and fee-payer budget after invalidation.\n const grantId = caller.role === \"owner\" ? null : chainRequestGrantId(name, body.request);\n if (grantId !== null) {\n const invalidated = await withRelayTransaction(captured.store, (transaction) =>\n transaction.lockCapabilityInvalidation(grantId),\n );\n if (invalidated !== undefined) {\n return relayFailure(\n \"relay_capability_invalidated\",\n \"the Grant's capability is invalidated\",\n );\n }\n }\n let result: unknown;\n try {\n result = await capability(body.request);\n } catch {\n // Port meaning stays with its SDK owner; the relay reports only that\n // this chain surface did not answer. Nothing here retries.\n return relayFailure(\"relay_chain_unavailable\", \"chain port did not answer\");\n }\n // JSON cannot carry `undefined`, and several ports mean it (\"no such\n // fact\"), so the envelope states presence explicitly.\n return jsonResponse(\n 200,\n result === undefined ? { present: false, result: null } : { present: true, result },\n );\n }\n\n if (head !== \"authorization\") {\n relayFailure(\"relay_not_found\", \"route does not exist\");\n }\n\n if (segments.length === 2 && group === \"requests\") {\n requireMethod(request, \"POST\");\n const caller = await authenticate(request, \"client\", \"authorization.create\");\n const body = exactBody(await bodyRecord(request, captured.maxBodyBytes), [\n \"redirectUri\",\n \"codeChallenge\",\n \"requestedScope\",\n ]);\n const created = await createAuthorizationRequest({\n store: captured.store,\n clock: captured.clock,\n caller,\n redirectUri: boundedText(\n body.redirectUri,\n RELAY_LIMITS.redirectUri,\n \"redirectUri\",\n INVALID,\n ),\n codeChallenge: boundedText(\n body.codeChallenge,\n RELAY_LIMITS.codeChallenge,\n \"codeChallenge\",\n INVALID,\n ),\n requestedScope: boundedText(\n body.requestedScope,\n RELAY_LIMITS.requestedScope,\n \"requestedScope\",\n INVALID,\n ),\n requestTtlMs: captured.requestTtlMs,\n });\n return jsonResponse(201, created);\n }\n\n if (segments.length === 3 && group === \"requests\") {\n requireMethod(request, \"GET\");\n const caller = await authenticate(request, \"owner\", \"authorization.fetch\");\n const state = await fetchAuthorizationRequest({\n store: captured.store,\n clock: captured.clock,\n caller,\n requestId: canonicalIdentifier(third, \"requestId\", INVALID),\n });\n return jsonResponse(200, stateBody(state));\n }\n\n if (segments.length === 4 && group === \"requests\" && fourth === \"decision\") {\n requireMethod(request, \"POST\");\n const caller = await authenticate(request, \"owner\", \"authorization.decide\");\n const command = decisionCommand(await bodyRecord(request, captured.maxBodyBytes));\n const decided = await submitAuthorizationDecision({\n store: captured.store,\n clock: captured.clock,\n kms: captured.kms,\n caller,\n requestId: canonicalIdentifier(third, \"requestId\", INVALID),\n command,\n codeTtlMs: captured.codeTtlMs,\n });\n return jsonResponse(200, decided);\n }\n\n if (segments.length === 4 && group === \"requests\" && fourth === \"code\") {\n requireMethod(request, \"GET\");\n const caller = await authenticate(request, \"client\", \"authorization.code\");\n const fetched = await fetchAuthorizationCode({\n store: captured.store,\n clock: captured.clock,\n kms: captured.kms,\n caller,\n requestId: canonicalIdentifier(third, \"requestId\", INVALID),\n });\n return jsonResponse(200, fetched);\n }\n\n if (segments.length === 3 && group === \"codes\" && third === \"consume\") {\n requireMethod(request, \"POST\");\n const caller = await authenticate(request, \"client\", \"authorization.consume\");\n const body = exactBody(await bodyRecord(request, captured.maxBodyBytes), [\n \"code\",\n \"codeVerifier\",\n \"redirectUri\",\n ]);\n const consumed = await consumeAuthorizationCode({\n store: captured.store,\n clock: captured.clock,\n caller,\n code: canonicalIdentifier(body.code, \"code\", INVALID),\n codeVerifier: boundedText(\n body.codeVerifier,\n RELAY_LIMITS.codeVerifier,\n \"codeVerifier\",\n INVALID,\n ),\n redirectUri: boundedText(\n body.redirectUri,\n RELAY_LIMITS.redirectUri,\n \"redirectUri\",\n INVALID,\n ),\n });\n return jsonResponse(200, consumed);\n }\n\n if (segments.length === 4 && group === \"artifacts\" && fourth === \"claim\") {\n requireMethod(request, \"POST\");\n const caller = await authenticate(request, \"client\", \"authorization.claim\");\n const claimed = await claimEncryptedArtifact({\n store: captured.store,\n clock: captured.clock,\n kms: captured.kms,\n caller,\n artifactId: canonicalIdentifier(third, \"artifactId\", INVALID),\n });\n return jsonResponse(200, claimed);\n }\n\n if (segments.length === 2 && group === \"resume\") {\n requireMethod(request, \"POST\");\n const caller = await authenticate(request, \"client\", \"authorization.resume\");\n const body = exactBody(await bodyRecord(request, captured.maxBodyBytes), [\"requestId\"]);\n const state = await resumeAuthorization({\n store: captured.store,\n clock: captured.clock,\n caller,\n requestId: canonicalIdentifier(body.requestId, \"requestId\", INVALID),\n });\n return jsonResponse(200, stateBody(state));\n }\n\n return relayFailure(\"relay_not_found\", \"route does not exist\");\n };\n\n return async (request: Request): Promise<Response> => {\n try {\n return await route(request);\n } catch (error) {\n return relayErrorResponse(relayErrorCode(error));\n }\n };\n}\n","/**\n * Bounded credential and URL redaction for diagnostics only.\n *\n * Nothing here shapes a response or a machine decision. Its only job is to make\n * an adopter's log line safe and finite: no authorization code, verifier, token,\n * artifact, ciphertext, credential-bearing URL, or unbounded provider blob.\n *\n * @author taek <leekt216@gmail.com>\n */\n\nexport const REDACTED = \"[redacted]\";\nconst UNREADABLE_URL = \"[unreadable-url]\";\nconst TRUNCATED = \"[truncated]\";\n\nconst MAX_TEXT = 128;\nconst MAX_DEPTH = 3;\nconst MAX_ENTRIES = 16;\n\n/** Key names whose values are never safe to log, matched after normalization. */\nconst SENSITIVE_KEYS: ReadonlySet<string> = new Set([\n \"apikey\",\n \"artifact\",\n \"authorization\",\n \"bearer\",\n \"ciphertext\",\n \"ciphertextref\",\n \"clientsecret\",\n \"code\",\n \"codechallenge\",\n \"codeverifier\",\n \"cookie\",\n \"credential\",\n \"idtoken\",\n \"key\",\n \"password\",\n \"plaintext\",\n \"privatekey\",\n \"secret\",\n \"session\",\n \"sessionkey\",\n \"setcookie\",\n \"signature\",\n \"token\",\n \"verifier\",\n]);\n\nfunction normalizeKey(key: string): string {\n return key.toLowerCase().replaceAll(/[^a-z0-9]/gu, \"\");\n}\n\nfunction isUrlKey(normalized: string): boolean {\n return normalized.endsWith(\"url\") || normalized.endsWith(\"uri\");\n}\n\nfunction boundText(value: string): string {\n return value.length <= MAX_TEXT ? value : `${value.slice(0, MAX_TEXT)}${TRUNCATED}`;\n}\n\n/** Keeps scheme, host, and path. Drops userinfo, query, and fragment. */\nexport function redactUrl(value: unknown): string {\n if (typeof value !== \"string\") return UNREADABLE_URL;\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return UNREADABLE_URL;\n }\n const port = url.port === \"\" ? \"\" : `:${url.port}`;\n return boundText(`${url.protocol}//${url.hostname}${port}${url.pathname}`);\n}\n\nfunction redactValue(value: unknown, depth: number): unknown {\n if (value === null) return null;\n switch (typeof value) {\n case \"string\":\n return boundText(value);\n case \"number\":\n return Number.isFinite(value) ? value : String(value);\n case \"boolean\":\n return value;\n case \"bigint\":\n return boundText(value.toString());\n case \"object\":\n break;\n default:\n // Functions, symbols, and undefined carry no safe diagnostic value.\n return REDACTED;\n }\n if (depth >= MAX_DEPTH) return REDACTED;\n if (Array.isArray(value)) {\n const items = value.slice(0, MAX_ENTRIES).map((item) => redactValue(item, depth + 1));\n return value.length > MAX_ENTRIES ? [...items, TRUNCATED] : items;\n }\n if (value instanceof Error) {\n // Provider and driver messages routinely embed credentials and payloads.\n return { name: boundText(value.name), message: REDACTED };\n }\n return redactRecord(value as Record<string, unknown>, depth);\n}\n\nfunction redactRecord(value: Record<string, unknown>, depth: number): Record<string, unknown> {\n const redacted: Record<string, unknown> = {};\n let entries = 0;\n for (const key of Object.keys(value)) {\n if (entries >= MAX_ENTRIES) {\n redacted[TRUNCATED] = true;\n break;\n }\n entries += 1;\n const normalized = normalizeKey(key);\n if (SENSITIVE_KEYS.has(normalized)) {\n redacted[key] = REDACTED;\n } else if (isUrlKey(normalized)) {\n redacted[key] = redactUrl(value[key]);\n } else {\n redacted[key] = redactValue(value[key], depth + 1);\n }\n }\n return redacted;\n}\n\n/** Returns a bounded, credential-free projection safe to hand to a logger. */\nexport function redactForLog(value: unknown): unknown {\n return redactValue(value, 0);\n}\n","/**\n * Reference hosted session-signer provider: one KMS-sealed secp256k1 operator\n * key per authenticated `(clientId, subject, deviceId)` identity, signing one\n * exact 32-byte hash at a time.\n *\n * Custody boundary: the private scalar exists in plaintext only inside this\n * process during key generation and signing; at rest it is exactly one\n * KMS-sealed string. No route, log, or return value ever carries key material\n * — `credential` answers the public operator profile and `sign` answers one\n * 65-byte ECDSA signature.\n *\n * Rotation invariant: one identity maps to one credential for this provider's\n * lifetime. There is no rotation path here — a new key requires a new\n * identity, and therefore a newly approved Grant; nothing can silently swap\n * the public key under an existing approval.\n *\n * Like `createMemoryRelayStore`, the in-memory registry makes this a\n * reference implementation, not a production durability claim: a deployment\n * that must survive restarts persists the sealed entries in its own store.\n *\n * @author taek <leekt216@gmail.com>\n */\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport { keccak_256 } from \"@noble/hashes/sha3.js\";\nimport { bytesToHex, hexToBytes } from \"@noble/hashes/utils.js\";\nimport { OAATH_OPERATOR_CREDENTIAL_PROFILE_VERSION } from \"@oaath/protocol\";\nimport type { RelayKms } from \"../security/kms.js\";\n\nconst HASH = /^0x[0-9a-f]{64}$/u;\nconst MAX_IDENTITY_PART = 256;\n\nexport interface SessionSignerIdentity {\n readonly clientId: string;\n readonly subject: string;\n readonly deviceId: string;\n}\n\nexport interface SessionSignerSignRequest extends SessionSignerIdentity {\n /** The exact 32-byte hash to sign; never a message to interpret. */\n readonly hash: `0x${string}`;\n}\n\nexport interface RelaySessionSignerProvider {\n /**\n * The operator credential for one authenticated identity, creating the key\n * on first use. Idempotent: the same identity always answers the same\n * credential.\n */\n readonly credential: (request: Readonly<SessionSignerIdentity>) => Promise<unknown>;\n /** One ECDSA signature over one exact hash, under that identity's key. */\n readonly sign: (request: Readonly<SessionSignerSignRequest>) => Promise<unknown>;\n}\n\nfunction identityKey(request: Readonly<SessionSignerIdentity>): string {\n for (const part of [request.clientId, request.subject, request.deviceId]) {\n if (typeof part !== \"string\" || part.length < 1 || part.length > MAX_IDENTITY_PART) {\n throw new Error(\"session signer identity is invalid\");\n }\n }\n // JSON array form: no separator inside a part can collide two identities.\n return JSON.stringify([request.clientId, request.subject, request.deviceId]);\n}\n\nfunction addressOf(privateKey: Uint8Array): `0x${string}` {\n const publicKey = secp256k1.getPublicKey(privateKey, false);\n return `0x${bytesToHex(keccak_256(publicKey.slice(1)).slice(12))}`;\n}\n\nexport function createKmsSessionSignerProvider(input: {\n readonly kms: RelayKms;\n}): RelaySessionSignerProvider {\n const kms = input.kms;\n /** identity -> KMS-sealed private scalar; the only at-rest key form. */\n const sealed = new Map<string, string>();\n /** Serializes first-use creation so one identity never mints two keys. */\n const creating = new Map<string, Promise<string>>();\n\n async function sealedKeyFor(identity: string): Promise<string> {\n const existing = sealed.get(identity);\n if (existing !== undefined) return existing;\n const pending =\n creating.get(identity) ??\n (async () => {\n const scalar = secp256k1.utils.randomPrivateKey();\n const reference = String(await kms.encrypt(bytesToHex(scalar)));\n scalar.fill(0);\n sealed.set(identity, reference);\n return reference;\n })();\n creating.set(identity, pending);\n pending.finally(() => creating.delete(identity));\n return pending;\n }\n\n return Object.freeze({\n async credential(request: Readonly<SessionSignerIdentity>): Promise<unknown> {\n const identity = identityKey(request);\n const privateKey = hexToBytes(String(await kms.decrypt(await sealedKeyFor(identity))));\n try {\n return Object.freeze({\n version: OAATH_OPERATOR_CREDENTIAL_PROFILE_VERSION,\n kind: \"ecdsa\" as const,\n address: addressOf(privateKey),\n });\n } finally {\n privateKey.fill(0);\n }\n },\n async sign(request: Readonly<SessionSignerSignRequest>): Promise<unknown> {\n const identity = identityKey(request);\n if (typeof request.hash !== \"string\" || !HASH.test(request.hash)) {\n throw new Error(\"session signer hash must be one exact 32-byte hash\");\n }\n // Signing never creates a key: an identity that never fetched its\n // credential holds no approval that could authorize a signature.\n const reference = sealed.get(identity);\n if (reference === undefined) {\n throw new Error(\"session signer identity holds no credential\");\n }\n const privateKey = hexToBytes(String(await kms.decrypt(reference)));\n try {\n const signature = secp256k1.sign(hexToBytes(request.hash.slice(2)), privateKey, {\n lowS: true,\n });\n if (signature.recovery !== 0 && signature.recovery !== 1) {\n throw new Error(\"session signer produced an unusable signature\");\n }\n // 65-byte r ‖ s ‖ v with v in {27, 28}: the exact shape a locally held\n // viem account produces, so the Kernel-side validation is identical.\n return `0x${bytesToHex(signature.toCompactRawBytes())}${(27 + signature.recovery).toString(16)}`;\n } finally {\n privateKey.fill(0);\n }\n },\n });\n}\n","/**\n * In-memory relay store implementing the same transaction contract as\n * PostgreSQL. It is durable only for the life of the process: use it for local\n * development and tests, never for a deployment that must survive a restart.\n *\n * ponytail: one process-wide writer lock stands in for row locks. It is strictly\n * stronger than `SELECT ... FOR UPDATE`, so one-shot semantics are identical;\n * swap in per-row locks only if a single-process relay ever needs throughput.\n *\n * @author taek <leekt216@gmail.com>\n */\n\nimport { relayFailure } from \"../relay/errors.js\";\nimport type { RelayStore, RelayTransaction } from \"./interface.js\";\nimport {\n type AuthorizationCodeRecord,\n type AuthorizationDecisionRecord,\n type AuthorizationRequestRecord,\n type CapabilityInvalidationRecord,\n type EncryptedArtifactRecord,\n parseAuthorizationCodeRecord,\n parseAuthorizationDecisionRecord,\n parseAuthorizationRequestRecord,\n parseCapabilityInvalidationRecord,\n parseEncryptedArtifactRecord,\n} from \"./records.js\";\n\ninterface Tables {\n readonly requests: Map<string, unknown>;\n readonly decisions: Map<string, unknown>;\n readonly codes: Map<string, unknown>;\n readonly artifacts: Map<string, unknown>;\n readonly invalidations: Map<string, unknown>;\n}\n\nfunction emptyTables(): Tables {\n return {\n requests: new Map(),\n decisions: new Map(),\n codes: new Map(),\n artifacts: new Map(),\n invalidations: new Map(),\n };\n}\n\nfunction copyTables(tables: Tables): Tables {\n return {\n requests: new Map(tables.requests),\n decisions: new Map(tables.decisions),\n codes: new Map(tables.codes),\n artifacts: new Map(tables.artifacts),\n invalidations: new Map(tables.invalidations),\n };\n}\n\nfunction insert(table: Map<string, unknown>, key: string, record: unknown): boolean {\n if (table.has(key)) return false;\n table.set(key, record);\n return true;\n}\n\nfunction read<Value>(\n table: Map<string, unknown>,\n key: string,\n parse: (value: unknown) => Value,\n): Value | undefined {\n const stored = table.get(key);\n // Durable reads are re-validated here exactly as the SQL store validates rows.\n return stored === undefined ? undefined : parse(stored);\n}\n\nexport function createMemoryRelayStore(): RelayStore {\n let committed = emptyTables();\n let closed = false;\n let tail: Promise<void> = Promise.resolve();\n\n async function acquire(): Promise<() => void> {\n const prior = tail;\n let release = (): void => {};\n tail = new Promise<void>((resolve) => {\n release = resolve;\n });\n await prior;\n return release;\n }\n\n return {\n async begin(): Promise<RelayTransaction> {\n if (closed) relayFailure(\"relay_store_unavailable\", \"memory relay store is closed\");\n const release = await acquire();\n const staged = copyTables(committed);\n let settled = false;\n\n const open = (): Tables => {\n if (settled) relayFailure(\"relay_internal\", \"relay transaction already settled\");\n return staged;\n };\n const settle = (apply: boolean): void => {\n if (settled) relayFailure(\"relay_internal\", \"relay transaction already settled\");\n settled = true;\n if (apply) committed = staged;\n release();\n };\n\n return {\n async lockAuthorizationRequest(requestId) {\n return read(open().requests, requestId, parseAuthorizationRequestRecord);\n },\n async insertAuthorizationRequest(record: AuthorizationRequestRecord) {\n return insert(open().requests, record.requestId, record);\n },\n async lockAuthorizationDecision(requestId) {\n return read(open().decisions, requestId, parseAuthorizationDecisionRecord);\n },\n async insertAuthorizationDecision(record: AuthorizationDecisionRecord) {\n return insert(open().decisions, record.requestId, record);\n },\n async lockAuthorizationCode(codeHash) {\n return read(open().codes, codeHash, parseAuthorizationCodeRecord);\n },\n async insertAuthorizationCode(record: AuthorizationCodeRecord) {\n return insert(open().codes, record.codeHash, record);\n },\n async consumeAuthorizationCode(codeHash, consumedAt) {\n const codes = open().codes;\n const record = read(codes, codeHash, parseAuthorizationCodeRecord);\n if (!record || record.consumedAt !== null) return false;\n codes.set(codeHash, Object.freeze({ ...record, consumedAt }));\n return true;\n },\n async lockCapabilityInvalidation(grantId) {\n return read(open().invalidations, grantId, parseCapabilityInvalidationRecord);\n },\n async insertCapabilityInvalidation(record: CapabilityInvalidationRecord) {\n return insert(open().invalidations, record.grantId, record);\n },\n async lockEncryptedArtifact(artifactId) {\n return read(open().artifacts, artifactId, parseEncryptedArtifactRecord);\n },\n async insertEncryptedArtifact(record: EncryptedArtifactRecord) {\n return insert(open().artifacts, record.artifactId, record);\n },\n async claimEncryptedArtifact(artifactId, claimedAt) {\n const artifacts = open().artifacts;\n const record = read(artifacts, artifactId, parseEncryptedArtifactRecord);\n if (!record || record.claimedAt !== null) return false;\n artifacts.set(artifactId, Object.freeze({ ...record, claimedAt }));\n return true;\n },\n async commit() {\n settle(true);\n },\n async rollback() {\n if (!settled) settle(false);\n },\n };\n },\n async close(): Promise<void> {\n closed = true;\n committed = emptyTables();\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ //#region src/store/records.d.ts
2
+ declare const OAATH_AUTHORIZATION_REQUEST_RECORD_VERSION: "oaath.authorization-request-record/v1";
3
+ declare const OAATH_AUTHORIZATION_DECISION_RECORD_VERSION: "oaath.authorization-decision-record/v1";
4
+ declare const OAATH_AUTHORIZATION_CODE_RECORD_VERSION: "oaath.authorization-code-record/v1";
5
+ declare const OAATH_ENCRYPTED_ARTIFACT_RECORD_VERSION: "oaath.encrypted-artifact-record/v1";
6
+ declare const OAATH_CAPABILITY_INVALIDATION_RECORD_VERSION: "oaath.capability-invalidation-record/v1";
7
+ interface AuthorizationRequestRecord {
8
+ readonly version: typeof OAATH_AUTHORIZATION_REQUEST_RECORD_VERSION;
9
+ readonly requestId: string;
10
+ /** Client bound by the deployment authentication port, never by wire input. */
11
+ readonly clientId: string;
12
+ /** Pairwise user/device subject bound by the authentication port. */
13
+ readonly subject: string;
14
+ readonly redirectUri: string;
15
+ /** PKCE S256 challenge; the verifier never reaches the store. */
16
+ readonly codeChallenge: string;
17
+ /** Opaque owner-reviewed scope payload. Migrates to @oaath/protocol. */
18
+ readonly requestedScope: string;
19
+ readonly createdAt: number;
20
+ readonly expiresAt: number;
21
+ }
22
+ type AuthorizationDecisionOutcome = "approved" | "rejected";
23
+ /**
24
+ * Terminal decision. Its existence is the single authoritative fact that an
25
+ * authorization request was decided; the request record never mutates.
26
+ */
27
+ interface AuthorizationDecisionRecord {
28
+ readonly version: typeof OAATH_AUTHORIZATION_DECISION_RECORD_VERSION;
29
+ readonly requestId: string;
30
+ readonly outcome: AuthorizationDecisionOutcome;
31
+ readonly decidedAt: number;
32
+ /**
33
+ * KMS-sealed copy of the released code for authenticated client pickup, and
34
+ * its expiry. The relay mints the code itself, so holding a sealed copy adds
35
+ * no new trust; PKCE still guards consumption. Both are null exactly when
36
+ * the outcome is a rejection.
37
+ */
38
+ readonly codeRef: string | null;
39
+ readonly codeExpiresAt: number | null;
40
+ }
41
+ interface AuthorizationCodeRecord {
42
+ readonly version: typeof OAATH_AUTHORIZATION_CODE_RECORD_VERSION;
43
+ /** SHA-256 (base64url) of the released code. The code itself is never stored. */
44
+ readonly codeHash: string;
45
+ readonly requestId: string;
46
+ /** Binding snapshot taken at issue time so consume needs exactly one row lock. */
47
+ readonly clientId: string;
48
+ readonly redirectUri: string;
49
+ readonly codeChallenge: string;
50
+ readonly artifactId: string;
51
+ readonly createdAt: number;
52
+ readonly expiresAt: number;
53
+ /** Set exactly once. A non-null value is terminal. */
54
+ readonly consumedAt: number | null;
55
+ }
56
+ interface EncryptedArtifactRecord {
57
+ readonly version: typeof OAATH_ENCRYPTED_ARTIFACT_RECORD_VERSION;
58
+ readonly artifactId: string;
59
+ readonly requestId: string;
60
+ readonly clientId: string;
61
+ /** Opaque KMS reference. Plaintext never reaches the store. */
62
+ readonly ciphertextRef: string;
63
+ readonly createdAt: number;
64
+ /** Set exactly once. A non-null value is terminal. */
65
+ readonly claimedAt: number | null;
66
+ }
67
+ /**
68
+ * One durable capability invalidation: from the moment this record commits,
69
+ * the relay's chain execution routes refuse every submission and usage read
70
+ * for the Grant, so the recorded evidence states an enforced fact — "this
71
+ * service will no longer act for this capability" — not a bare digest.
72
+ * Consuming the on-chain install nonce is the chain-local revocation
73
+ * operation's job and stays separate evidence.
74
+ */
75
+ interface CapabilityInvalidationRecord {
76
+ readonly version: typeof OAATH_CAPABILITY_INVALIDATION_RECORD_VERSION;
77
+ readonly grantId: string;
78
+ /** The authenticated client that recorded the invalidation. */
79
+ readonly clientId: string;
80
+ readonly capabilityHash: string;
81
+ readonly invalidatedAt: number;
82
+ }
83
+ //#endregion
84
+ //#region src/store/interface.d.ts
85
+ interface RelayTransaction {
86
+ lockAuthorizationRequest(requestId: string): Promise<AuthorizationRequestRecord | undefined>;
87
+ /** Returns false when the identifier already exists. */
88
+ insertAuthorizationRequest(record: AuthorizationRequestRecord): Promise<boolean>;
89
+ lockAuthorizationDecision(requestId: string): Promise<AuthorizationDecisionRecord | undefined>;
90
+ /** Returns false when the request was already decided. */
91
+ insertAuthorizationDecision(record: AuthorizationDecisionRecord): Promise<boolean>;
92
+ lockAuthorizationCode(codeHash: string): Promise<AuthorizationCodeRecord | undefined>;
93
+ insertAuthorizationCode(record: AuthorizationCodeRecord): Promise<boolean>;
94
+ /** Returns true only when this call set `consumed_at`. */
95
+ consumeAuthorizationCode(codeHash: string, consumedAt: number): Promise<boolean>;
96
+ lockCapabilityInvalidation(grantId: string): Promise<CapabilityInvalidationRecord | undefined>;
97
+ /** Returns false when the Grant's capability is already invalidated. */
98
+ insertCapabilityInvalidation(record: CapabilityInvalidationRecord): Promise<boolean>;
99
+ lockEncryptedArtifact(artifactId: string): Promise<EncryptedArtifactRecord | undefined>;
100
+ insertEncryptedArtifact(record: EncryptedArtifactRecord): Promise<boolean>;
101
+ /** Returns true only when this call set `claimed_at`. */
102
+ claimEncryptedArtifact(artifactId: string, claimedAt: number): Promise<boolean>;
103
+ /** Throws `relay_state_ambiguous` when the outcome cannot be proven. */
104
+ commit(): Promise<void>;
105
+ /** Never throws; rollback failure is a suppressed diagnostic. */
106
+ rollback(): Promise<void>;
107
+ }
108
+ interface RelayStore {
109
+ begin(): Promise<RelayTransaction>;
110
+ close(): Promise<void>;
111
+ }
112
+ //#endregion
113
+ export { AuthorizationDecisionRecord as a, OAATH_AUTHORIZATION_CODE_RECORD_VERSION as c, OAATH_ENCRYPTED_ARTIFACT_RECORD_VERSION as d, AuthorizationDecisionOutcome as i, OAATH_AUTHORIZATION_DECISION_RECORD_VERSION as l, RelayTransaction as n, AuthorizationRequestRecord as o, AuthorizationCodeRecord as r, EncryptedArtifactRecord as s, RelayStore as t, OAATH_AUTHORIZATION_REQUEST_RECORD_VERSION as u };
114
+ //# sourceMappingURL=interface-WwvwWs8e.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interface-WwvwWs8e.d.ts","names":[],"sources":["../src/store/records.ts","../src/store/interface.ts"],"mappings":";cAoBa;cAEA;cAEA;cAEA;cAEA;UAgBI;WACN,gBAAgB;WAChB;;WAEA;;WAEA;WACA;;WAEA;;WAEA;WACA;WACA;;KAGC;;;;;UAMK;WACN,gBAAgB;WAChB;WACA,SAAS;WACT;;;;;;;WAOA;WACA;;UAGM;WACN,gBAAgB;;WAEhB;WACA;;WAEA;WACA;WACA;WACA;WACA;WACA;;WAEA;;UAGM;WACN,gBAAgB;WAChB;WACA;WACA;;WAEA;WACA;;WAEA;;;;;;;;;;UAWM;WACN,gBAAgB;WAChB;;WAEA;WACA;WACA;;;;UCtFM;EACf,yBAAyB,oBAAoB,QAAQ;;EAErD,2BAA2B,QAAQ,6BAA6B;EAEhE,0BAA0B,oBAAoB,QAAQ;;EAEtD,4BAA4B,QAAQ,8BAA8B;EAElE,sBAAsB,mBAAmB,QAAQ;EACjD,wBAAwB,QAAQ,0BAA0B;;EAE1D,yBAAyB,kBAAkB,qBAAqB;EAEhE,2BAA2B,kBAAkB,QAAQ;;EAErD,6BAA6B,QAAQ,+BAA+B;EAEpE,sBAAsB,qBAAqB,QAAQ;EACnD,wBAAwB,QAAQ,0BAA0B;;EAE1D,uBAAuB,oBAAoB,oBAAoB;;EAG/D,UAAU;;EAEV,YAAY;;UAGG;EACf,SAAS,QAAQ;EACjB,SAAS"}
@@ -0,0 +1,30 @@
1
+ import { i as RelayClock, n as RelayCaller } from "./authentication-HUYWk5Y2.js";
2
+ import { i as AuthorizationDecisionOutcome, t as RelayStore } from "./interface-WwvwWs8e.js";
3
+ import { a as OwnerPhoneScopeProjection, i as OwnerPhoneRequestProjection, n as OAATH_NATIVE_PROJECTION_VERSION, o as ProjectOwnerPhoneRequestInput, r as OwnerPhonePushProjection, s as projectOwnerPhoneRequest, t as NATIVE_DISPLAY_PAYLOAD_LENGTH } from "./projection-g6k_CCUK.js";
4
+ import { a as RelayKms, r as SubmittedAuthorizationDecision, t as AuthorizationDecisionCommand } from "./decision-dEe9n108.js";
5
+ //#region src/native/decision.d.ts
6
+ interface SubmitOwnerPhoneDecisionInput {
7
+ readonly store: RelayStore;
8
+ readonly clock: RelayClock;
9
+ readonly kms: RelayKms;
10
+ /** Authenticated `owner` caller; only the bound subject may decide. */
11
+ readonly caller: RelayCaller;
12
+ /** `operationId` from `projectOwnerPhoneRequest`. */
13
+ readonly operationId: string;
14
+ readonly command: AuthorizationDecisionCommand;
15
+ readonly codeTtlMs: number;
16
+ }
17
+ interface OwnerPhoneDecision {
18
+ readonly operationId: string;
19
+ /** The stored outcome, which on a replay may differ from the command sent. */
20
+ readonly outcome: AuthorizationDecisionOutcome;
21
+ readonly decidedAt: number;
22
+ /** `decided` performed the transition; `replayed` answered the stored one. */
23
+ readonly settlement: "decided" | "replayed";
24
+ /** One-time release material, on the deciding call only. */
25
+ readonly release: SubmittedAuthorizationDecision | null;
26
+ }
27
+ declare function submitOwnerPhoneDecision(input: SubmitOwnerPhoneDecisionInput): Promise<OwnerPhoneDecision>;
28
+ //#endregion
29
+ export { NATIVE_DISPLAY_PAYLOAD_LENGTH, OAATH_NATIVE_PROJECTION_VERSION, type OwnerPhoneDecision, type OwnerPhonePushProjection, type OwnerPhoneRequestProjection, type OwnerPhoneScopeProjection, type ProjectOwnerPhoneRequestInput, type SubmitOwnerPhoneDecisionInput, projectOwnerPhoneRequest, submitOwnerPhoneDecision };
30
+ //# sourceMappingURL=native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.d.ts","names":[],"sources":["../src/native/decision.ts"],"mappings":";;;;;UA2CiB;WACN,OAAO;WACP,OAAO;WACP,KAAK;;WAEL,QAAQ;;WAER;WACA,SAAS;WACT;;UAGM;WACN;;WAEA,SAAS;WACT;;WAEA;;WAEA,SAAS;;iBAGE,yBACpB,OAAO,gCACN,QAAQ"}
package/dist/native.js ADDED
@@ -0,0 +1,2 @@
1
+ import { i as submitOwnerPhoneDecision, n as OAATH_NATIVE_PROJECTION_VERSION, r as projectOwnerPhoneRequest, t as NATIVE_DISPLAY_PAYLOAD_LENGTH } from "./projection-dGIkE0rI.js";
2
+ export { NATIVE_DISPLAY_PAYLOAD_LENGTH, OAATH_NATIVE_PROJECTION_VERSION, projectOwnerPhoneRequest, submitOwnerPhoneDecision };
@@ -0,0 +1,37 @@
1
+ import { t as RelayStore } from "./interface-WwvwWs8e.js";
2
+ import { Pool } from "pg";
3
+ //#region src/store/postgres/schema.d.ts
4
+ /**
5
+ * The current relay schema. There is no migration runner and no reader for any
6
+ * older schema: an obsolete database is dropped and recreated.
7
+ *
8
+ * Constraints that the database can own are owned by the database — one decision
9
+ * per request, one code and one artifact per request, monotonic timestamps.
10
+ *
11
+ * @author taek <leekt216@gmail.com>
12
+ */
13
+ declare const OAATH_RELAY_POSTGRES_SCHEMA_VERSION: "oaath.relay-postgres-schema/v1";
14
+ declare const OAATH_RELAY_POSTGRES_SCHEMA_STATEMENTS: readonly string[];
15
+ interface RelaySchemaExecutor {
16
+ query(sql: string): Promise<unknown>;
17
+ }
18
+ /**
19
+ * Creates the current schema in the executor's `search_path`. It is not a
20
+ * migration: it fails if the objects already exist.
21
+ */
22
+ declare function createPostgresRelaySchema(executor: RelaySchemaExecutor): Promise<void>;
23
+ //#endregion
24
+ //#region src/store/postgres/store.d.ts
25
+ type PostgresRelayStoreOptions =
26
+ /** The deployment owns the pool: credentials, TLS, limits, and shutdown. */
27
+ Readonly<{
28
+ pool: Pool;
29
+ }> |
30
+ /** The store owns a pool created from this connection string. */
31
+ Readonly<{
32
+ connectionString: string;
33
+ }>;
34
+ declare function createPostgresRelayStore(options: PostgresRelayStoreOptions): RelayStore;
35
+ //#endregion
36
+ export { OAATH_RELAY_POSTGRES_SCHEMA_STATEMENTS, OAATH_RELAY_POSTGRES_SCHEMA_VERSION, type PostgresRelayStoreOptions, type RelaySchemaExecutor, createPostgresRelaySchema, createPostgresRelayStore };
37
+ //# sourceMappingURL=postgres.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.d.ts","names":[],"sources":["../src/store/postgres/schema.ts","../src/store/postgres/store.ts"],"mappings":";;;;;;;;;;;;cAUa;cAIA;UA6DI;EACf,MAAM,cAAc;;;;;;iBAOA,0BAA0B,UAAU,sBAAsB;;;KCxCpE;;AAER;EAAW,MAAM;;;AAEjB;EAAW;;iBA2NC,yBAAyB,SAAS,4BAA4B"}