@oaath/server 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +239 -5
  2. package/dist/apns.d.ts +2 -2
  3. package/dist/apns.js +2 -2
  4. package/dist/{challenge-AGTmUfj2.js → challenge-DmpGSogj.js} +2 -2
  5. package/dist/{challenge-AGTmUfj2.js.map → challenge-DmpGSogj.js.map} +1 -1
  6. package/dist/inbox-B80EUVht.js +249 -0
  7. package/dist/inbox-B80EUVht.js.map +1 -0
  8. package/dist/index.d.ts +9 -255
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +631 -48
  11. package/dist/index.js.map +1 -1
  12. package/dist/interface-DHpwP0wr.d.ts +245 -0
  13. package/dist/interface-DHpwP0wr.d.ts.map +1 -0
  14. package/dist/kernel.d.ts +42 -0
  15. package/dist/kernel.d.ts.map +1 -0
  16. package/dist/kernel.js +80 -0
  17. package/dist/kernel.js.map +1 -0
  18. package/dist/kms-BWkywdJM.d.ts +18 -0
  19. package/dist/kms-BWkywdJM.d.ts.map +1 -0
  20. package/dist/native.d.ts +3 -30
  21. package/dist/native.js +115 -2
  22. package/dist/native.js.map +1 -0
  23. package/dist/postgres.d.ts +38 -3
  24. package/dist/postgres.d.ts.map +1 -1
  25. package/dist/postgres.js +301 -14
  26. package/dist/postgres.js.map +1 -1
  27. package/dist/projection-B7IB9irs.d.ts +228 -0
  28. package/dist/projection-B7IB9irs.d.ts.map +1 -0
  29. package/dist/{records-Bgr-9PUh.js → records-BQNDxbPg.js} +32 -8
  30. package/dist/records-BQNDxbPg.js.map +1 -0
  31. package/dist/records-BUvqmp0D.js +70 -0
  32. package/dist/records-BUvqmp0D.js.map +1 -0
  33. package/dist/service-Cf4f-9KP.js +706 -0
  34. package/dist/service-Cf4f-9KP.js.map +1 -0
  35. package/dist/service-J51bOVe6.d.ts +483 -0
  36. package/dist/service-J51bOVe6.d.ts.map +1 -0
  37. package/package.json +39 -8
  38. package/LICENSE +0 -201
  39. package/dist/authentication-HUYWk5Y2.d.ts +0 -46
  40. package/dist/authentication-HUYWk5Y2.d.ts.map +0 -1
  41. package/dist/decision-dEe9n108.d.ts +0 -53
  42. package/dist/decision-dEe9n108.d.ts.map +0 -1
  43. package/dist/interface-WwvwWs8e.d.ts +0 -114
  44. package/dist/interface-WwvwWs8e.d.ts.map +0 -1
  45. package/dist/native.d.ts.map +0 -1
  46. package/dist/projection-dGIkE0rI.js +0 -516
  47. package/dist/projection-dGIkE0rI.js.map +0 -1
  48. package/dist/projection-g6k_CCUK.d.ts +0 -136
  49. package/dist/projection-g6k_CCUK.d.ts.map +0 -1
  50. package/dist/records-Bgr-9PUh.js.map +0 -1
@@ -0,0 +1,483 @@
1
+ import { b as RelayClock, i as AuthorizationDecisionOutcome, o as AuthorizationOwnerRoute, t as RelayStore } from "./interface-DHpwP0wr.js";
2
+ import { c as OwnerPhoneRevocationDecision, d as OwnerPhonePermissionApprovals, m as RelayCaller, n as OwnerPhonePushProjection, p as RelayAuthentication, r as OwnerPhoneRequestProjection } from "./projection-B7IB9irs.js";
3
+ import { t as RelayKms } from "./kms-BWkywdJM.js";
4
+ import { PermissionRequest, ServiceAccount, ServiceBootstrap } from "@oaath/protocol";
5
+ //#region src/authorization/decision.d.ts
6
+ type AuthorizationDecisionCommand =
7
+ /** The owner supplies a request-bound approval artifact; the client claims it once. */
8
+ Readonly<{
9
+ outcome: "approved";
10
+ artifact: string;
11
+ }> | Readonly<{
12
+ outcome: "rejected";
13
+ }>;
14
+ interface SubmitAuthorizationDecisionInput {
15
+ readonly store: RelayStore;
16
+ readonly clock: RelayClock;
17
+ readonly kms: RelayKms;
18
+ /** Authenticated `owner` caller; only the bound subject may decide. */
19
+ readonly caller: RelayCaller;
20
+ readonly requestId: string;
21
+ readonly command: AuthorizationDecisionCommand;
22
+ readonly codeTtlMs: number;
23
+ }
24
+ type SubmittedAuthorizationDecision = Readonly<{
25
+ outcome: "approved";
26
+ decidedAt: number;
27
+ /** Released exactly once, here. Only its SHA-256 is stored. */
28
+ code: string;
29
+ artifactId: string;
30
+ redirectUri: string;
31
+ codeExpiresAt: number;
32
+ }> | Readonly<{
33
+ outcome: "rejected";
34
+ decidedAt: number;
35
+ }>;
36
+ declare function submitAuthorizationDecision(input: SubmitAuthorizationDecisionInput): Promise<SubmittedAuthorizationDecision>;
37
+ //#endregion
38
+ //#region src/authorization/request.d.ts
39
+ /** Resolves once at creation; existing requests never follow later routing changes. */
40
+ interface RelayOwnerRouting {
41
+ resolveOwner(caller: Readonly<RelayCaller>, request: Readonly<{
42
+ requestId: string;
43
+ requestedScope: string;
44
+ }>): Promise<Readonly<AuthorizationOwnerRoute> | null>;
45
+ }
46
+ interface CreateAuthorizationRequestInput {
47
+ readonly store: RelayStore;
48
+ readonly clock: RelayClock;
49
+ /** Authenticated `client` caller; it owns `clientId` and `subject`. */
50
+ readonly caller: RelayCaller;
51
+ readonly ownerRouting: RelayOwnerRouting;
52
+ readonly redirectUri: string;
53
+ readonly codeChallenge: string;
54
+ readonly requestedScope: string;
55
+ readonly requestTtlMs: number;
56
+ }
57
+ interface CreatedAuthorizationRequest {
58
+ /** Non-secret comparison code shown by the approving phone. */
59
+ readonly matchCode: string;
60
+ readonly requestId: string;
61
+ readonly expiresAt: number;
62
+ }
63
+ interface AuthorizationState {
64
+ readonly requestId: string;
65
+ readonly clientId: string;
66
+ readonly redirectUri: string;
67
+ readonly requestedScope: string;
68
+ readonly expiresAt: number;
69
+ readonly expired: boolean;
70
+ readonly decision: Readonly<{
71
+ outcome: AuthorizationDecisionOutcome;
72
+ decidedAt: number;
73
+ }> | null;
74
+ }
75
+ declare function createAuthorizationRequest(input: CreateAuthorizationRequestInput): Promise<CreatedAuthorizationRequest>;
76
+ interface FetchAuthorizationRequestInput {
77
+ readonly store: RelayStore;
78
+ readonly clock: RelayClock;
79
+ /** Authenticated `owner` caller; only the bound subject may read the request. */
80
+ readonly caller: RelayCaller;
81
+ readonly requestId: string;
82
+ }
83
+ /** Read for the approving owner. */
84
+ declare function fetchAuthorizationRequest(input: FetchAuthorizationRequestInput): Promise<AuthorizationState>;
85
+ //#endregion
86
+ //#region src/directory/records.d.ts
87
+ declare const OAATH_SERVICE_DIRECTORY_VERSION: "oaath.service-directory/v1";
88
+ interface DirectoryWorkspace {
89
+ readonly workspaceId: string;
90
+ readonly kind: "personal" | "team";
91
+ }
92
+ interface DirectoryApplication {
93
+ readonly clientId: string;
94
+ readonly applicationId: string;
95
+ readonly applicationName: string;
96
+ }
97
+ /** Membership names the authenticated application/user pair, not owner authority. */
98
+ interface DirectoryMembership {
99
+ readonly workspaceId: string;
100
+ readonly clientId: string;
101
+ readonly subject: string;
102
+ }
103
+ /** Enrollment identity used to route owner work; private key material is never stored here. */
104
+ interface DirectoryOwnerDevice {
105
+ readonly workspaceId: string;
106
+ readonly ownerDeviceId: string;
107
+ readonly subject: string;
108
+ }
109
+ interface DirectoryAccount extends ServiceAccount {
110
+ readonly workspaceId: string;
111
+ readonly accountId: string;
112
+ readonly ownerDeviceId: string;
113
+ readonly chainIds: readonly number[];
114
+ }
115
+ /** A preference; current membership is checked again whenever it is resolved. */
116
+ interface DirectorySelection extends DirectoryMembership {
117
+ readonly accountId: string;
118
+ }
119
+ interface ServiceDirectoryDocument {
120
+ readonly version: typeof OAATH_SERVICE_DIRECTORY_VERSION;
121
+ readonly workspaces: readonly Readonly<DirectoryWorkspace>[];
122
+ readonly applications: readonly Readonly<DirectoryApplication>[];
123
+ readonly memberships: readonly Readonly<DirectoryMembership>[];
124
+ readonly ownerDevices: readonly Readonly<DirectoryOwnerDevice>[];
125
+ readonly accounts: readonly Readonly<DirectoryAccount>[];
126
+ readonly selections: readonly Readonly<DirectorySelection>[];
127
+ }
128
+ //#endregion
129
+ //#region src/native/authentication.d.ts
130
+ declare const OAATH_OWNER_DEVICE_CREDENTIAL_VERSION: "oaath.owner-device-credential/v1";
131
+ type OwnerDeviceReference = Pick<DirectoryOwnerDevice, "workspaceId" | "ownerDeviceId">;
132
+ /** Authentication binding captured at issuance; contains no bearer or owner key. */
133
+ interface OwnerDeviceCredentialRecord extends DirectoryOwnerDevice {
134
+ readonly version: typeof OAATH_OWNER_DEVICE_CREDENTIAL_VERSION;
135
+ readonly credentialHash: string;
136
+ readonly revoked: boolean;
137
+ }
138
+ interface OwnerDeviceCredentialStore {
139
+ /** Null means absent. Unreadable or unavailable storage must throw. */
140
+ read(credentialHash: string): Promise<unknown>;
141
+ /** Insert an immutable binding once. Never replace a revoked record. */
142
+ insert(record: Readonly<OwnerDeviceCredentialRecord>): Promise<boolean>;
143
+ /** Atomically revoke all credentials already issued for this device. Idempotent. */
144
+ revoke(device: Readonly<OwnerDeviceReference>): Promise<void>;
145
+ }
146
+ interface OwnerDeviceAuthentication extends RelayAuthentication {
147
+ authenticate(request: Request): Promise<Readonly<RelayCaller> | null>;
148
+ /**
149
+ * Deployment administration only, after authenticated pairing/enrollment.
150
+ * Returns a fresh 32-byte base64url bearer after its hash is stored. A lost
151
+ * write response throws; nothing is returned and no write is retried.
152
+ */
153
+ issue(device: Readonly<OwnerDeviceReference>): Promise<string>;
154
+ /** Revokes relay access only. Does not uninstall permissions or delete keys/accounts. */
155
+ revoke(device: Readonly<OwnerDeviceReference>): Promise<void>;
156
+ }
157
+ /**
158
+ * One active -> revoked transition per credential hash, separate from account
159
+ * authority. Directory identity is checked at issuance and authentication;
160
+ * an issued credential can never be retargeted to a changed owner subject.
161
+ * No cache, operation lane, retries or owned connections. Recreated instances
162
+ * read the same stores. The deployment owns pool shutdown and pairing delivery.
163
+ * Explicit later issuance creates a new credential; it cannot revive an old one.
164
+ */
165
+ declare function createOwnerDeviceAuthentication(options: {
166
+ readonly store: OwnerDeviceCredentialStore;
167
+ readonly directory: Pick<ServiceDirectory, "read">;
168
+ }): Readonly<OwnerDeviceAuthentication>;
169
+ /** Ephemeral deployment adapter; the authentication service owns no local cache. */
170
+ declare function createMemoryOwnerDeviceCredentialStore(): OwnerDeviceCredentialStore;
171
+ //#endregion
172
+ //#region src/native/decision.d.ts
173
+ interface SubmitOwnerPhoneDecisionInput {
174
+ readonly store: RelayStore;
175
+ readonly clock: RelayClock;
176
+ readonly kms: RelayKms;
177
+ /** Authenticated `owner` caller; only the bound subject may decide. */
178
+ readonly caller: RelayCaller;
179
+ /** `operationId` from `projectOwnerPhoneRequest`. */
180
+ readonly operationId: string;
181
+ readonly command: AuthorizationDecisionCommand;
182
+ readonly codeTtlMs: number;
183
+ readonly permissionApprovals?: OwnerPhonePermissionApprovals;
184
+ }
185
+ interface OwnerPhoneDecision {
186
+ readonly operationId: string;
187
+ /** The stored outcome, which on a replay may differ from the command sent. */
188
+ readonly outcome: AuthorizationDecisionOutcome;
189
+ readonly decidedAt: number;
190
+ /** `decided` performed the transition; `replayed` answered the stored one. */
191
+ readonly settlement: "decided" | "replayed";
192
+ /** One-time release material, on the deciding call only. */
193
+ readonly release: SubmittedAuthorizationDecision | null;
194
+ }
195
+ declare function submitOwnerPhoneDecision(input: SubmitOwnerPhoneDecisionInput): Promise<OwnerPhoneDecision>;
196
+ //#endregion
197
+ //#region src/native/display.d.ts
198
+ /** Bounded base64url match code length. 48 bits is plenty to compare by eye. */
199
+ declare const NATIVE_DISPLAY_PAYLOAD_LENGTH = 8;
200
+ //#endregion
201
+ //#region src/native/inbox.d.ts
202
+ declare const OAATH_NATIVE_INBOX_VERSION: "oaath.native-inbox/v1";
203
+ interface OwnerPhoneInbox {
204
+ readonly version: typeof OAATH_NATIVE_INBOX_VERSION;
205
+ readonly requests: readonly Readonly<OwnerPhonePushProjection>[];
206
+ }
207
+ /** The store owns transaction resources; this read prepares, signs and submits nothing. */
208
+ declare function listOwnerPhoneRequests(input: {
209
+ readonly store: RelayStore;
210
+ readonly clock: RelayClock;
211
+ readonly caller: RelayCaller;
212
+ }): Promise<Readonly<OwnerPhoneInbox>>;
213
+ //#endregion
214
+ //#region src/revocation/service.d.ts
215
+ interface RequestOwnerPhoneRevocationInput {
216
+ readonly store: RelayStore;
217
+ readonly clock: RelayClock;
218
+ readonly kms: RelayKms;
219
+ readonly directory: Pick<ServiceDirectory, "resolveRevocationOwner">;
220
+ /** Deployment-authenticated original application/member. */
221
+ readonly caller: RelayCaller;
222
+ readonly grantId: string;
223
+ readonly chainId: number;
224
+ readonly requestTtlMs: number;
225
+ /**
226
+ * Deployment uses prepareKernelPermissionRevocation to verify the retained Kernel
227
+ * capability, read target-chain state, and choose effect/root nonce/gas.
228
+ * Receives the retained approval plaintext; never log or expose it to clients.
229
+ * Preparation must not reserve a nonce or execution lane; concurrent
230
+ * preparations may lose admission.
231
+ * Returns the SDK signingRequest only. Must not sign or submit an operation.
232
+ */
233
+ readonly prepare: (input: Readonly<{
234
+ request: Readonly<PermissionRequest>;
235
+ artifact: string;
236
+ chainId: number;
237
+ }>) => Promise<unknown>;
238
+ }
239
+ interface OwnerPhoneRevocationStatus {
240
+ readonly grantId: string;
241
+ readonly chainId: number;
242
+ readonly operationId: string;
243
+ /** Relay timestamp in milliseconds. */
244
+ readonly expiresAt: number;
245
+ /** Custody status only, never submission or grant revocation completion. */
246
+ readonly status: "pending" | "approved" | "rejected" | "expired";
247
+ }
248
+ type ClientRevocationInput = Pick<RequestOwnerPhoneRevocationInput, "store" | "clock" | "caller" | "grantId" | "chainId">;
249
+ /** Authenticated metadata lookup. It never prepares, opens KMS custody or submits. */
250
+ declare function fetchClientPhoneRevocation(input: ClientRevocationInput): Promise<Readonly<OwnerPhoneRevocationStatus>>;
251
+ /**
252
+ * Returns the current grant/chain request before touching preparation or KMS.
253
+ * Only positively expired, undecided custody may be replaced. Approved custody
254
+ * remains immutable even after expiry: operation evidence owns any replacement.
255
+ * Pure preparation runs outside the transaction; final admission locks the
256
+ * original grant again so concurrent callers share the winner's exact request.
257
+ */
258
+ declare function requestOwnerPhoneRevocation(input: RequestOwnerPhoneRevocationInput): Promise<Readonly<OwnerPhoneRevocationStatus & {
259
+ created: boolean;
260
+ }>>;
261
+ interface OwnerRevocationInput {
262
+ readonly store: RelayStore;
263
+ readonly clock: RelayClock;
264
+ readonly caller: RelayCaller;
265
+ readonly operationId: string;
266
+ }
267
+ declare function fetchOwnerPhoneRevocation(input: OwnerRevocationInput): Promise<OwnerPhoneRequestProjection>;
268
+ declare function submitOwnerPhoneRevocationDecision(input: OwnerRevocationInput & {
269
+ readonly kms: RelayKms;
270
+ readonly command: AuthorizationDecisionCommand;
271
+ }): Promise<OwnerPhoneRevocationDecision>;
272
+ //#endregion
273
+ //#region src/security/rate-limit.d.ts
274
+ /**
275
+ * Optional deployment-owned limiter port.
276
+ *
277
+ * There is no default limiter: an unset port means no limiting, and the relay
278
+ * never invents a policy the deployment did not choose. A limiter that fails is
279
+ * treated as `limited`, because an unreadable limiter is not permission.
280
+ *
281
+ * @author taek <leekt216@gmail.com>
282
+ */
283
+ interface RelayRateLimitInput {
284
+ /** Stable route name, never a credential-bearing URL. */
285
+ readonly route: string;
286
+ readonly clientId: string | null;
287
+ }
288
+ interface RelayRateLimiter {
289
+ /** Resolves to `"allowed"` or `"limited"`. Anything else is `limited`. */
290
+ check(input: RelayRateLimitInput): Promise<unknown>;
291
+ }
292
+ //#endregion
293
+ //#region src/session-signer/kms-provider.d.ts
294
+ interface SessionSignerIdentity {
295
+ readonly clientId: string;
296
+ readonly subject: string;
297
+ readonly deviceId: string;
298
+ }
299
+ interface SessionSignerSignRequest extends SessionSignerIdentity {
300
+ /** The exact 32-byte hash to sign; never a message to interpret. */
301
+ readonly hash: `0x${string}`;
302
+ }
303
+ interface RelaySessionSignerProvider {
304
+ /**
305
+ * The operator credential for one authenticated identity, creating the key
306
+ * on first use. Idempotent: the same identity always answers the same
307
+ * credential.
308
+ */
309
+ readonly credential: (request: Readonly<SessionSignerIdentity>) => Promise<unknown>;
310
+ /** One ECDSA signature over one exact hash, under that identity's key. */
311
+ readonly sign: (request: Readonly<SessionSignerSignRequest>) => Promise<unknown>;
312
+ }
313
+ declare function createKmsSessionSignerProvider(input: {
314
+ readonly kms: RelayKms;
315
+ }): RelaySessionSignerProvider;
316
+ //#endregion
317
+ //#region src/relay/handler.d.ts
318
+ /**
319
+ * One deployment-injected chain execution surface the relay serves to clients.
320
+ * Each port takes exactly one captured request value and answers with the
321
+ * evidence it owns; the relay never interprets the payload beyond exact wire
322
+ * hygiene, so port meaning stays with its SDK owner.
323
+ */
324
+ interface RelayChainPort {
325
+ readonly gas?: Readonly<{
326
+ enableVerificationGasFloor: bigint;
327
+ }>;
328
+ readonly chainId: number;
329
+ readonly reads: (request: unknown) => Promise<unknown>;
330
+ readonly observation: (request: unknown) => Promise<unknown>;
331
+ readonly bundler: (request: unknown) => Promise<unknown>;
332
+ readonly quote: (request: unknown) => Promise<unknown>;
333
+ /** Opens, sends, and settles one submission in one call; never retried here. */
334
+ readonly submission: (request: unknown) => Promise<unknown>;
335
+ /** Finalized per-grant usage evidence, or null when this chain serves none. */
336
+ readonly usage: ((request: unknown) => Promise<unknown>) | null;
337
+ readonly feePayer: Readonly<{
338
+ address: `0x${string}`;
339
+ balance: string;
340
+ }> | null;
341
+ /** Authenticated commitment to one exact ERC-7902 static paymaster, or null. */
342
+ readonly staticPaymasterConfigurationHash: `0x${string}` | null;
343
+ }
344
+ /** Selection resolved from the deployment's membership and account records. */
345
+ interface RelayBootstrapSelection {
346
+ readonly application: Readonly<Pick<ServiceBootstrap["application"], "applicationId" | "applicationName">>;
347
+ readonly context: ServiceBootstrap["context"];
348
+ readonly account: ServiceBootstrap["account"];
349
+ readonly ownerValidator: `0x${string}` | null;
350
+ readonly chainIds: readonly number[];
351
+ }
352
+ /** Called for each authenticated bootstrap request; null means no assigned account. */
353
+ interface RelayBootstrapConfiguration {
354
+ readonly resolve: (caller: Readonly<RelayCaller>) => Promise<Readonly<RelayBootstrapSelection> | null>;
355
+ }
356
+ /**
357
+ * Remote session-key custody, declared once for the deployment: the mode and
358
+ * provider identity are served through the bootstrap document, and the same
359
+ * provider answers the `/session-signers` routes. For `oaath_hosted` the
360
+ * provider is typically `createKmsSessionSignerProvider`; for
361
+ * `application_backend` it is the deployment's own authenticated port to the
362
+ * integrating application's signer — never a client-supplied endpoint.
363
+ */
364
+ interface RelaySessionSignerConfiguration {
365
+ readonly mode: "application_backend" | "oaath_hosted";
366
+ readonly providerId: string;
367
+ readonly provider: Readonly<RelaySessionSignerProvider>;
368
+ }
369
+ /** Authenticated identity and one opaque ERC-7677 params tuple. */
370
+ interface RelayPaymasterServiceRequest {
371
+ readonly caller: Readonly<{
372
+ clientId: string;
373
+ subject: string;
374
+ }>;
375
+ readonly params: unknown;
376
+ readonly signal: AbortSignal;
377
+ }
378
+ /**
379
+ * One deployment-owned paymaster provider. The relay exposes only these two
380
+ * closed ERC-7677 operations and invokes the selected method once.
381
+ */
382
+ interface RelayPaymasterServiceProvider {
383
+ readonly getPaymasterStubData: (request: Readonly<RelayPaymasterServiceRequest>) => Promise<unknown>;
384
+ readonly getPaymasterData: (request: Readonly<RelayPaymasterServiceRequest>) => Promise<unknown>;
385
+ }
386
+ interface RelayPaymasterServiceConfiguration {
387
+ readonly chainId: number;
388
+ readonly providerId: string;
389
+ /** Hard response deadline; the provider also receives its abort signal. */
390
+ readonly requestTimeoutMs: number;
391
+ readonly provider: Readonly<RelayPaymasterServiceProvider>;
392
+ }
393
+ interface RelayHandlerOptions {
394
+ /** Enables application-initiated phone revocation; preparation never signs or submits. */
395
+ readonly revocations?: Readonly<Pick<RequestOwnerPhoneRevocationInput, "directory" | "prepare">>;
396
+ /** Enables canonical permission approval through the owner phone. */
397
+ readonly permissionApprovals?: OwnerPhonePermissionApprovals;
398
+ readonly store: RelayStore;
399
+ readonly authentication: RelayAuthentication;
400
+ /** Required. Resolves an approving device independently of the requesting member. */
401
+ readonly ownerRouting: RelayOwnerRouting;
402
+ readonly kms: RelayKms;
403
+ readonly clock: RelayClock;
404
+ /** Optional. There is no default limiter. */
405
+ readonly rateLimit?: RelayRateLimiter;
406
+ readonly requestTtlMs?: number;
407
+ readonly codeTtlMs?: number;
408
+ readonly maxBodyBytes?: number;
409
+ /** Optional URL-only bootstrap surface; requires `chains` as well. */
410
+ readonly bootstrap?: Readonly<RelayBootstrapConfiguration>;
411
+ /** Optional chain execution relays; required when `bootstrap` is served. */
412
+ readonly chains?: readonly Readonly<RelayChainPort>[];
413
+ /** Optional remote session-key custody; requires `bootstrap` as well. */
414
+ readonly sessionSigner?: Readonly<RelaySessionSignerConfiguration>;
415
+ /**
416
+ * Optional deployment-owned paymaster services, at most one per chain.
417
+ * Configuration requires both bootstrap and a deployment rate limiter.
418
+ */
419
+ readonly paymasterServices?: readonly Readonly<RelayPaymasterServiceConfiguration>[];
420
+ }
421
+ type RelayHandler = (request: Request) => Promise<Response>;
422
+ declare function createRelayHandler(options: RelayHandlerOptions): RelayHandler;
423
+ //#endregion
424
+ //#region src/directory/service.d.ts
425
+ interface ServiceDirectorySnapshot {
426
+ readonly revision: number;
427
+ readonly directory: Readonly<ServiceDirectoryDocument>;
428
+ }
429
+ /** One atomic row. A failed/ambiguous write is never automatically retried. */
430
+ interface ServiceDirectoryStore {
431
+ read(): Promise<unknown>;
432
+ /** Null expects absence; otherwise replace exactly this revision and advance it by one. */
433
+ compareAndSwap(expectedRevision: number | null, directory: Readonly<ServiceDirectoryDocument>): Promise<boolean>;
434
+ }
435
+ /** Deployment-authenticated pairing result; contains public identity only. */
436
+ interface EnrollOwnerDeviceInput {
437
+ readonly expectedRevision: number;
438
+ readonly device: Readonly<DirectoryOwnerDevice>;
439
+ readonly accounts: readonly Readonly<DirectoryAccount>[];
440
+ }
441
+ interface ServiceDirectory extends RelayBootstrapConfiguration, RelayOwnerRouting {
442
+ read(): Promise<Readonly<ServiceDirectorySnapshot> | null>;
443
+ /** Admission for the original permission context, restricted to its configured chains. */
444
+ resolveRevocationOwner(caller: Readonly<RelayCaller>, input: Readonly<{
445
+ requestId: string;
446
+ requestedScope: string;
447
+ chainId: number;
448
+ }>): Promise<Readonly<AuthorizationOwnerRoute> | null>;
449
+ /** Deployment administration capability, never an unauthenticated HTTP endpoint. */
450
+ replace(input: {
451
+ readonly expectedRevision: number | null;
452
+ readonly directory: unknown;
453
+ }): Promise<boolean>;
454
+ /**
455
+ * Atomically enroll a new P-256 phone and its Kernel accounts in one workspace.
456
+ * The deployment authenticates pairing and assigns the owner subject first.
457
+ * No membership, authentication credential, or onchain operation is created.
458
+ * False means the expected revision lost; read before a fresh admin decision.
459
+ */
460
+ enrollOwnerDevice(input: Readonly<EnrollOwnerDeviceInput>): Promise<boolean>;
461
+ /** False means a concurrent directory write won; read current state before choosing again. */
462
+ selectAccount(caller: Readonly<RelayCaller>, selection: {
463
+ readonly workspaceId: string;
464
+ readonly accountId: string;
465
+ }): Promise<boolean>;
466
+ }
467
+ /**
468
+ * Owns membership/account selection and atomic phone enrollment over one
469
+ * versioned directory document. Enrollment moves absent device/accounts to
470
+ * jointly registered identities; it cannot overwrite them. Its single CAS is
471
+ * the persisted evidence and cleanup owner: a lost response causes no retry,
472
+ * and a recreated reader sees the whole enrollment or none of it.
473
+ * Writes use compare-and-swap; bootstrap/admission reads never reserve resources.
474
+ * A reload reads durable state afresh. Member removal blocks new admission but
475
+ * does not revoke grants or delete operation evidence. The deployment owns store
476
+ * resources and cleanup; this service owns no connections and retries no writes.
477
+ */
478
+ declare function createServiceDirectory(store: ServiceDirectoryStore): Readonly<ServiceDirectory>;
479
+ /** Ephemeral deployment/test store; the service captures every read and write boundary. */
480
+ declare function createMemoryServiceDirectoryStore(): ServiceDirectoryStore;
481
+ //#endregion
482
+ export { FetchAuthorizationRequestInput as $, listOwnerPhoneRequests as A, createMemoryOwnerDeviceCredentialStore as B, RequestOwnerPhoneRevocationInput as C, submitOwnerPhoneRevocationDecision as D, requestOwnerPhoneRevocation as E, OAATH_OWNER_DEVICE_CREDENTIAL_VERSION as F, DirectoryOwnerDevice as G, DirectoryAccount as H, OwnerDeviceAuthentication as I, OAATH_SERVICE_DIRECTORY_VERSION as J, DirectorySelection as K, OwnerDeviceCredentialRecord as L, OwnerPhoneDecision as M, SubmitOwnerPhoneDecisionInput as N, OAATH_NATIVE_INBOX_VERSION as O, submitOwnerPhoneDecision as P, CreatedAuthorizationRequest as Q, OwnerDeviceCredentialStore as R, OwnerPhoneRevocationStatus as S, fetchOwnerPhoneRevocation as T, DirectoryApplication as U, createOwnerDeviceAuthentication as V, DirectoryMembership as W, AuthorizationState as X, ServiceDirectoryDocument as Y, CreateAuthorizationRequestInput as Z, SessionSignerIdentity as _, createMemoryServiceDirectoryStore as a, SubmittedAuthorizationDecision as at, RelayRateLimitInput as b, RelayBootstrapSelection as c, RelayPaymasterServiceConfiguration as d, RelayOwnerRouting as et, RelayPaymasterServiceProvider as f, RelaySessionSignerProvider as g, createRelayHandler as h, ServiceDirectoryStore as i, SubmitAuthorizationDecisionInput as it, NATIVE_DISPLAY_PAYLOAD_LENGTH as j, OwnerPhoneInbox as k, RelayHandler as l, RelaySessionSignerConfiguration as m, ServiceDirectory as n, fetchAuthorizationRequest as nt, createServiceDirectory as o, submitAuthorizationDecision as ot, RelayPaymasterServiceRequest as p, DirectoryWorkspace as q, ServiceDirectorySnapshot as r, AuthorizationDecisionCommand as rt, RelayBootstrapConfiguration as s, EnrollOwnerDeviceInput as t, createAuthorizationRequest as tt, RelayHandlerOptions as u, SessionSignerSignRequest as v, fetchClientPhoneRevocation as w, RelayRateLimiter as x, createKmsSessionSignerProvider as y, OwnerDeviceReference as z };
483
+ //# sourceMappingURL=service-J51bOVe6.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-J51bOVe6.d.ts","names":[],"sources":["../src/authorization/decision.ts","../src/authorization/request.ts","../src/directory/records.ts","../src/native/authentication.ts","../src/native/decision.ts","../src/native/display.ts","../src/native/inbox.ts","../src/revocation/service.ts","../src/security/rate-limit.ts","../src/session-signer/kms-provider.ts","../src/relay/handler.ts","../src/directory/service.ts"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oaath/server",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "OAAth deployable relay and PostgreSQL boundary.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -23,40 +23,71 @@
23
23
  "types": "./dist/index.d.ts",
24
24
  "exports": {
25
25
  ".": {
26
+ "oaath-source": {
27
+ "types": "./src/index.ts",
28
+ "default": "./src/index.ts"
29
+ },
26
30
  "types": "./dist/index.d.ts",
27
31
  "default": "./dist/index.js"
28
32
  },
29
33
  "./postgres": {
34
+ "oaath-source": {
35
+ "types": "./src/postgres.ts",
36
+ "node": "./src/postgres.ts"
37
+ },
30
38
  "types": "./dist/postgres.d.ts",
31
39
  "node": "./dist/postgres.js"
32
40
  },
33
41
  "./native": {
42
+ "oaath-source": {
43
+ "types": "./src/native.ts",
44
+ "default": "./src/native.ts"
45
+ },
34
46
  "types": "./dist/native.d.ts",
35
47
  "default": "./dist/native.js"
36
48
  },
37
49
  "./apns": {
50
+ "oaath-source": {
51
+ "types": "./src/apns.ts",
52
+ "node": "./src/apns.ts"
53
+ },
38
54
  "types": "./dist/apns.d.ts",
39
55
  "node": "./dist/apns.js"
56
+ },
57
+ "./kernel": {
58
+ "oaath-source": {
59
+ "types": "./src/kernel.ts",
60
+ "default": "./src/kernel.ts"
61
+ },
62
+ "types": "./dist/kernel.d.ts",
63
+ "default": "./dist/kernel.js"
40
64
  }
41
65
  },
42
66
  "files": [
43
67
  "dist",
44
68
  "README.md"
45
69
  ],
70
+ "scripts": {
71
+ "build": "tsdown",
72
+ "prepack": "bun run build",
73
+ "typecheck": "tsc --noEmit",
74
+ "test": "vitest run",
75
+ "test:postgres": "OAATH_REQUIRE_POSTGRES=1 vitest run test/postgres.test.ts test/restart.test.ts test/service-directory-postgres.test.ts test/revocation-service.test.ts test/revocation-executor.test.ts test/native-inbox.test.ts test/owner-device-authentication-postgres.test.ts",
76
+ "release:publish": "bun publish --access public --tolerate-republish",
77
+ "release:check": "bun pm pack --dry-run"
78
+ },
46
79
  "dependencies": {
47
80
  "@noble/curves": "1.9.1",
48
81
  "@noble/hashes": "2.2.0",
82
+ "@oaath/protocol": "0.3.0",
49
83
  "pg": "8.22.0",
50
- "@oaath/protocol": "0.1.0"
84
+ "@oaath/sdk": "0.3.0"
51
85
  },
52
86
  "devDependencies": {
53
87
  "@types/node": "22.13.0",
54
88
  "@types/pg": "8.20.3"
55
89
  },
56
- "scripts": {
57
- "build": "tsdown",
58
- "typecheck": "tsc --noEmit",
59
- "test": "vitest run",
60
- "test:postgres": "OAATH_REQUIRE_POSTGRES=1 vitest run test/postgres.test.ts test/restart.test.ts"
90
+ "publishConfig": {
91
+ "access": "public"
61
92
  }
62
- }
93
+ }