@oxy.so/contracts 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/accountEmail.js +79 -0
- package/dist/cjs/deviceBoot.js +2 -2
- package/dist/cjs/deviceSession.js +73 -16
- package/dist/cjs/identity.js +1 -3
- package/dist/cjs/identityLink.js +92 -0
- package/dist/cjs/identityProof.js +6 -29
- package/dist/cjs/index.js +82 -65
- package/dist/cjs/reputation.js +10 -55
- package/dist/cjs/signIn.js +304 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/accountEmail.js +76 -0
- package/dist/esm/deviceBoot.js +2 -2
- package/dist/esm/deviceSession.js +72 -15
- package/dist/esm/identity.js +1 -3
- package/dist/esm/identityLink.js +87 -0
- package/dist/esm/identityProof.js +6 -29
- package/dist/esm/index.js +13 -16
- package/dist/esm/reputation.js +9 -54
- package/dist/esm/signIn.js +299 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/accountEmail.d.ts +90 -0
- package/dist/types/agency.d.ts +2 -2
- package/dist/types/deviceBoot.d.ts +2 -2
- package/dist/types/deviceSession.d.ts +131 -19
- package/dist/types/externalIdentity.d.ts +4 -4
- package/dist/types/identity.d.ts +4 -8
- package/dist/types/identityLink.d.ts +146 -0
- package/dist/types/identityProof.d.ts +15 -42
- package/dist/types/index.d.ts +10 -12
- package/dist/types/inference/accountBilling.d.ts +2 -2
- package/dist/types/inference/embeddings.d.ts +16 -16
- package/dist/types/inference/entitlement.d.ts +2 -2
- package/dist/types/inference/errors.d.ts +8 -8
- package/dist/types/inference/inbox.d.ts +8 -8
- package/dist/types/inference/providerConnection.d.ts +20 -20
- package/dist/types/inference/request.d.ts +16 -16
- package/dist/types/inference/streamEvents.d.ts +20 -20
- package/dist/types/keyRecovery.d.ts +4 -4
- package/dist/types/oauth.d.ts +16 -16
- package/dist/types/reputation.d.ts +32 -127
- package/dist/types/sessionStatus.d.ts +2 -2
- package/dist/types/signIn.d.ts +717 -0
- package/dist/types/userResponse.d.ts +2 -2
- package/package.json +1 -1
- package/dist/cjs/identityMove.js +0 -156
- package/dist/cjs/identityRecovery.js +0 -51
- package/dist/cjs/webIdentityCarrier.js +0 -181
- package/dist/cjs/webauthn.js +0 -85
- package/dist/esm/identityMove.js +0 -148
- package/dist/esm/identityRecovery.js +0 -48
- package/dist/esm/webIdentityCarrier.js +0 -178
- package/dist/esm/webauthn.js +0 -82
- package/dist/types/identityMove.d.ts +0 -185
- package/dist/types/identityRecovery.d.ts +0 -246
- package/dist/types/webIdentityCarrier.d.ts +0 -1130
- package/dist/types/webauthn.d.ts +0 -285
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email codes and tickets (ADR 0030).
|
|
3
|
+
*
|
|
4
|
+
* A web account is a username and an email; a password and an authenticator
|
|
5
|
+
* app are optional and added later. The email is proven by a 6-digit code sent
|
|
6
|
+
* to it, and the proof is a short-lived one-use ticket the next step spends:
|
|
7
|
+
*
|
|
8
|
+
* - `signup`: the ticket lets `POST /auth/signup` create the account with that
|
|
9
|
+
* email. `start` answers the same whether or not the address already has an
|
|
10
|
+
* account, so it never tells anyone which emails have an Oxy account.
|
|
11
|
+
*
|
|
12
|
+
* Signing in by email (`signin`) and re-verifying before a sensitive change
|
|
13
|
+
* (`reauth`) use the same code, through their own routes (`signIn.ts`).
|
|
14
|
+
*/
|
|
15
|
+
import { z } from 'zod';
|
|
16
|
+
/**
|
|
17
|
+
* - `signup`: above.
|
|
18
|
+
* - `signin`: the code (and link) of an email sign-in (`POST /auth/signin/email/start`).
|
|
19
|
+
* - `reauth`: a signed-in person proving it is them before a sensitive step
|
|
20
|
+
* (`POST /users/me/reauth/email`): a password, an authenticator, deleting the
|
|
21
|
+
* account, linking Commons.
|
|
22
|
+
*/
|
|
23
|
+
export declare const EMAIL_VERIFICATION_PURPOSES: readonly ["signup", "signin", "reauth"];
|
|
24
|
+
export type EmailVerificationPurpose = (typeof EMAIL_VERIFICATION_PURPOSES)[number];
|
|
25
|
+
/** Digits in a code. */
|
|
26
|
+
export declare const EMAIL_CODE_LENGTH = 6;
|
|
27
|
+
/** How long a code can be confirmed. */
|
|
28
|
+
export declare const EMAIL_CODE_TTL_MS: number;
|
|
29
|
+
/** Wrong codes before a verification is spent and a new code is needed. */
|
|
30
|
+
export declare const EMAIL_CODE_MAX_ATTEMPTS = 5;
|
|
31
|
+
/** How long a confirmed code's ticket can be spent. */
|
|
32
|
+
export declare const EMAIL_TICKET_TTL_MS: number;
|
|
33
|
+
/** An email address as the API stores it: trimmed and lowercase. */
|
|
34
|
+
export declare const emailAddressSchema: z.ZodString;
|
|
35
|
+
/** An opaque one-use ticket (32 random bytes, base64url). */
|
|
36
|
+
export declare const emailTicketSchema: z.ZodString;
|
|
37
|
+
/** `POST /auth/email/verify/start` */
|
|
38
|
+
export declare const emailVerificationStartRequestSchema: z.ZodObject<{
|
|
39
|
+
purpose: z.ZodLiteral<"signup">;
|
|
40
|
+
email: z.ZodString;
|
|
41
|
+
}, "strict", z.ZodTypeAny, {
|
|
42
|
+
purpose: "signup";
|
|
43
|
+
email: string;
|
|
44
|
+
}, {
|
|
45
|
+
purpose: "signup";
|
|
46
|
+
email: string;
|
|
47
|
+
}>;
|
|
48
|
+
export type EmailVerificationStartRequest = z.infer<typeof emailVerificationStartRequestSchema>;
|
|
49
|
+
export interface EmailVerificationStartResponse {
|
|
50
|
+
/** Names this verification in `confirm`. Returned whether or not a code was sent. */
|
|
51
|
+
verificationId: string;
|
|
52
|
+
/** Unix milliseconds after which the code is refused. */
|
|
53
|
+
expiresAt: number;
|
|
54
|
+
}
|
|
55
|
+
export declare const emailVerificationStartResponseSchema: z.ZodType<EmailVerificationStartResponse>;
|
|
56
|
+
/** `POST /auth/email/verify/confirm` */
|
|
57
|
+
export declare const emailVerificationConfirmRequestSchema: z.ZodObject<{
|
|
58
|
+
verificationId: z.ZodString;
|
|
59
|
+
code: z.ZodString;
|
|
60
|
+
}, "strict", z.ZodTypeAny, {
|
|
61
|
+
code: string;
|
|
62
|
+
verificationId: string;
|
|
63
|
+
}, {
|
|
64
|
+
code: string;
|
|
65
|
+
verificationId: string;
|
|
66
|
+
}>;
|
|
67
|
+
export type EmailVerificationConfirmRequest = z.infer<typeof emailVerificationConfirmRequestSchema>;
|
|
68
|
+
export interface EmailVerificationConfirmResponse {
|
|
69
|
+
ticket: string;
|
|
70
|
+
/** Unix milliseconds after which the ticket is refused. */
|
|
71
|
+
expiresAt: number;
|
|
72
|
+
}
|
|
73
|
+
export declare const emailVerificationConfirmResponseSchema: z.ZodType<EmailVerificationConfirmResponse>;
|
|
74
|
+
/**
|
|
75
|
+
* Stable error codes (`error.code` in the API error body). Clients map these
|
|
76
|
+
* through their localization, never the English message.
|
|
77
|
+
*/
|
|
78
|
+
export declare const EMAIL_VERIFICATION_ERROR_CODES: {
|
|
79
|
+
/** The code is wrong, or its verification expired or was spent. */
|
|
80
|
+
readonly codeInvalid: "EMAIL_CODE_INVALID";
|
|
81
|
+
/** Too many wrong codes: request a new one. */
|
|
82
|
+
readonly tooManyAttempts: "EMAIL_CODE_TOO_MANY_ATTEMPTS";
|
|
83
|
+
/** The ticket is unknown, expired, spent, or for another email or purpose. */
|
|
84
|
+
readonly ticketInvalid: "EMAIL_TICKET_INVALID";
|
|
85
|
+
/** A sign-up without a confirmed email. */
|
|
86
|
+
readonly ticketRequired: "EMAIL_TICKET_REQUIRED";
|
|
87
|
+
/** This server cannot send mail. */
|
|
88
|
+
readonly unavailable: "EMAIL_UNAVAILABLE";
|
|
89
|
+
};
|
|
90
|
+
export type EmailVerificationErrorCode = (typeof EMAIL_VERIFICATION_ERROR_CODES)[keyof typeof EMAIL_VERIFICATION_ERROR_CODES];
|
package/dist/types/agency.d.ts
CHANGED
|
@@ -190,6 +190,7 @@ export declare const delegationGrantSchema: z.ZodObject<{
|
|
|
190
190
|
createdAt: z.ZodString;
|
|
191
191
|
updatedAt: z.ZodString;
|
|
192
192
|
}, "strict", z.ZodTypeAny, {
|
|
193
|
+
expiresAt: string | null;
|
|
193
194
|
ownerAccountId: string;
|
|
194
195
|
id: string;
|
|
195
196
|
actor: {
|
|
@@ -223,11 +224,11 @@ export declare const delegationGrantSchema: z.ZodObject<{
|
|
|
223
224
|
}[];
|
|
224
225
|
maximumAutonomy: "read_only" | "draft" | "execute_on_request" | "autonomous";
|
|
225
226
|
canRedelegate: boolean;
|
|
226
|
-
expiresAt: string | null;
|
|
227
227
|
revokedAt: string | null;
|
|
228
228
|
createdAt: string;
|
|
229
229
|
updatedAt: string;
|
|
230
230
|
}, {
|
|
231
|
+
expiresAt: string | null;
|
|
231
232
|
ownerAccountId: string;
|
|
232
233
|
id: string;
|
|
233
234
|
actor: {
|
|
@@ -251,7 +252,6 @@ export declare const delegationGrantSchema: z.ZodObject<{
|
|
|
251
252
|
capabilityPackages: ("security" | "finance" | "read" | "create" | "publish" | "communicate" | "administer" | "delegate")[];
|
|
252
253
|
capabilities: string[];
|
|
253
254
|
maximumAutonomy: "read_only" | "draft" | "execute_on_request" | "autonomous";
|
|
254
|
-
expiresAt: string | null;
|
|
255
255
|
createdAt: string;
|
|
256
256
|
updatedAt: string;
|
|
257
257
|
toolOverrides?: {
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* SINGLE SOURCE OF TRUTH for the first-party login result (the session arm). The
|
|
5
5
|
* API validates its OUTPUT against this schema; every consumer (`@oxy.so/core`'s
|
|
6
6
|
* auth mixin) validates its INPUT against the same definition, so producer and
|
|
7
|
-
* consumers cannot drift.
|
|
8
|
-
*
|
|
7
|
+
* consumers cannot drift. This is the session arm every sign-in
|
|
8
|
+
* ends in (email code or link, password, authenticator, Commons handoff).
|
|
9
9
|
*
|
|
10
10
|
* The device transport is `deviceId` + `deviceSecret` + `POST /session/device/token`
|
|
11
11
|
* (see `deviceSession.ts`). The legacy cookie/bootstrap/refresh-family lanes were
|
|
@@ -166,9 +166,10 @@ export type DeviceSessionSync = z.infer<typeof deviceSessionSyncSchema>;
|
|
|
166
166
|
/**
|
|
167
167
|
* Request body for `POST /session/device/token` — the client presents the
|
|
168
168
|
* `deviceId` it stored first-party plus the opaque `deviceSecret`. NO bearer:
|
|
169
|
-
* possession of the secret IS the proof of device ownership. The server
|
|
170
|
-
* `sha256(deviceSecret)`
|
|
171
|
-
*
|
|
169
|
+
* possession of the secret IS the proof of device ownership. The server looks
|
|
170
|
+
* `sha256(deviceSecret)` up among the device's holder credentials (one per app
|
|
171
|
+
* or origin that joined the shared DeviceSession) and mints a short access
|
|
172
|
+
* token for the device's active account.
|
|
172
173
|
*
|
|
173
174
|
* `accountId` pins the mint to ONE account of that device instead of whichever
|
|
174
175
|
* account is currently active. It exists for identity-bound clients (Commons),
|
|
@@ -196,8 +197,8 @@ export declare const deviceTokenMintRequestSchema: z.ZodObject<{
|
|
|
196
197
|
* short access token for the active account, its expiry, the device secret the
|
|
197
198
|
* client must persist (`nextDeviceSecret` — on mint this echoes the presented
|
|
198
199
|
* secret unchanged so concurrent refreshes from multiple origins do not race),
|
|
199
|
-
* and the projected device-session state.
|
|
200
|
-
*
|
|
200
|
+
* and the projected device-session state. Nothing rotates: each sign-in issues
|
|
201
|
+
* a NEW holder credential and leaves the others valid.
|
|
201
202
|
*/
|
|
202
203
|
export declare const deviceTokenMintResponseSchema: z.ZodObject<{
|
|
203
204
|
accessToken: z.ZodString;
|
|
@@ -330,12 +331,11 @@ export type SessionAccountsChangedEvent = z.infer<typeof sessionAccountsChangedE
|
|
|
330
331
|
* derived server-side from it) and consumed afterwards only by native
|
|
331
332
|
* background code, which has no JS runtime to mint a token for itself.
|
|
332
333
|
*
|
|
333
|
-
* Deliberately a SEPARATE credential from the
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
* anything JS reads.
|
|
334
|
+
* Deliberately a SEPARATE credential from the holder `deviceSecret`: that one
|
|
335
|
+
* is device-wide and mints for whichever account is active, while this one is
|
|
336
|
+
* bound to ONE account and expires, so a widget worker never holds a
|
|
337
|
+
* credential that reaches every account on the device. Background code is its
|
|
338
|
+
* sole writer and never touches anything JS reads.
|
|
339
339
|
*
|
|
340
340
|
* The raw `secret` is returned exactly once, at provision time — never stored
|
|
341
341
|
* retrievably, never logged, never re-read. A caller that loses it provisions
|
|
@@ -353,13 +353,13 @@ export declare const deviceBackgroundCredentialResponseSchema: z.ZodObject<{
|
|
|
353
353
|
accountId: z.ZodString;
|
|
354
354
|
expiresAt: z.ZodString;
|
|
355
355
|
}, "strip", z.ZodTypeAny, {
|
|
356
|
-
accountId: string;
|
|
357
356
|
expiresAt: string;
|
|
357
|
+
accountId: string;
|
|
358
358
|
deviceId: string;
|
|
359
359
|
secret: string;
|
|
360
360
|
}, {
|
|
361
|
-
accountId: string;
|
|
362
361
|
expiresAt: string;
|
|
362
|
+
accountId: string;
|
|
363
363
|
deviceId: string;
|
|
364
364
|
secret: string;
|
|
365
365
|
}>;
|
|
@@ -368,10 +368,10 @@ export declare const deviceBackgroundCredentialResponseSchema: z.ZodObject<{
|
|
|
368
368
|
* native background code with NO bearer and NO cookies: possession of the
|
|
369
369
|
* background `secret` IS the proof, as it is for the device-secret mint.
|
|
370
370
|
*
|
|
371
|
-
*
|
|
372
|
-
* `next…` field
|
|
373
|
-
*
|
|
374
|
-
*
|
|
371
|
+
* Like that mint this one NEVER rotates the presented secret, and it carries
|
|
372
|
+
* no `next…` field at all, so background code interrupted anywhere between
|
|
373
|
+
* request and response leaves the credential intact and usable on its next
|
|
374
|
+
* run.
|
|
375
375
|
*/
|
|
376
376
|
export declare const deviceBackgroundTokenRequestSchema: z.ZodObject<{
|
|
377
377
|
deviceId: z.ZodString;
|
|
@@ -398,14 +398,126 @@ export declare const deviceBackgroundTokenResponseSchema: z.ZodObject<{
|
|
|
398
398
|
expiresAt: z.ZodString;
|
|
399
399
|
accountId: z.ZodString;
|
|
400
400
|
}, "strip", z.ZodTypeAny, {
|
|
401
|
-
accountId: string;
|
|
402
401
|
expiresAt: string;
|
|
402
|
+
accountId: string;
|
|
403
403
|
accessToken: string;
|
|
404
404
|
}, {
|
|
405
|
-
accountId: string;
|
|
406
405
|
expiresAt: string;
|
|
406
|
+
accountId: string;
|
|
407
407
|
accessToken: string;
|
|
408
408
|
}>;
|
|
409
409
|
export type DeviceBackgroundCredentialResponse = z.infer<typeof deviceBackgroundCredentialResponseSchema>;
|
|
410
410
|
export type DeviceBackgroundTokenRequest = z.infer<typeof deviceBackgroundTokenRequestSchema>;
|
|
411
411
|
export type DeviceBackgroundTokenResponse = z.infer<typeof deviceBackgroundTokenResponseSchema>;
|
|
412
|
+
/**
|
|
413
|
+
* Proof that the caller holds a device: the `deviceId` it stored first-party and
|
|
414
|
+
* one of that device's holder secrets. Sent with `POST /session/device/join-code`
|
|
415
|
+
* and, optionally, with a sign-in (`POST /auth/session/claim`, the email,
|
|
416
|
+
* password and second-factor sign-ins, `POST /auth/signup`), where
|
|
417
|
+
* a valid proof puts the new session on THAT device so every app holding it sees
|
|
418
|
+
* the account. An invalid proof on a sign-in is ignored, never an error.
|
|
419
|
+
*/
|
|
420
|
+
export declare const deviceProofSchema: z.ZodObject<{
|
|
421
|
+
deviceId: z.ZodString;
|
|
422
|
+
deviceSecret: z.ZodString;
|
|
423
|
+
}, "strip", z.ZodTypeAny, {
|
|
424
|
+
deviceId: string;
|
|
425
|
+
deviceSecret: string;
|
|
426
|
+
}, {
|
|
427
|
+
deviceId: string;
|
|
428
|
+
deviceSecret: string;
|
|
429
|
+
}>;
|
|
430
|
+
/**
|
|
431
|
+
* `POST /session/device/register` — auth.oxy.so only. No body. A new, empty
|
|
432
|
+
* DeviceSession with a server-chosen `deviceId` and ONE holder credential for
|
|
433
|
+
* auth.oxy.so. The raw secret is returned exactly once.
|
|
434
|
+
*/
|
|
435
|
+
export declare const deviceRegisterResponseSchema: z.ZodObject<{
|
|
436
|
+
deviceId: z.ZodString;
|
|
437
|
+
deviceSecret: z.ZodString;
|
|
438
|
+
}, "strip", z.ZodTypeAny, {
|
|
439
|
+
deviceId: string;
|
|
440
|
+
deviceSecret: string;
|
|
441
|
+
}, {
|
|
442
|
+
deviceId: string;
|
|
443
|
+
deviceSecret: string;
|
|
444
|
+
}>;
|
|
445
|
+
/**
|
|
446
|
+
* `POST /session/device/join-code` — auth.oxy.so only (the bridge window). Proves
|
|
447
|
+
* auth.oxy.so's device and asks for a one-use code an official app redeems to
|
|
448
|
+
* join it. The code is bound to the application (`clientId`), its exact
|
|
449
|
+
* registered `redirectUri` and the app's PKCE challenge, and lives about a
|
|
450
|
+
* minute.
|
|
451
|
+
*/
|
|
452
|
+
export declare const deviceJoinCodeRequestSchema: z.ZodObject<{
|
|
453
|
+
deviceId: z.ZodString;
|
|
454
|
+
deviceSecret: z.ZodString;
|
|
455
|
+
} & {
|
|
456
|
+
clientId: z.ZodString;
|
|
457
|
+
redirectUri: z.ZodString;
|
|
458
|
+
codeChallenge: z.ZodString;
|
|
459
|
+
codeChallengeMethod: z.ZodLiteral<"S256">;
|
|
460
|
+
}, "strip", z.ZodTypeAny, {
|
|
461
|
+
deviceId: string;
|
|
462
|
+
deviceSecret: string;
|
|
463
|
+
clientId: string;
|
|
464
|
+
redirectUri: string;
|
|
465
|
+
codeChallenge: string;
|
|
466
|
+
codeChallengeMethod: "S256";
|
|
467
|
+
}, {
|
|
468
|
+
deviceId: string;
|
|
469
|
+
deviceSecret: string;
|
|
470
|
+
clientId: string;
|
|
471
|
+
redirectUri: string;
|
|
472
|
+
codeChallenge: string;
|
|
473
|
+
codeChallengeMethod: "S256";
|
|
474
|
+
}>;
|
|
475
|
+
export declare const deviceJoinCodeResponseSchema: z.ZodObject<{
|
|
476
|
+
code: z.ZodString;
|
|
477
|
+
/** Seconds until the code expires. */
|
|
478
|
+
expiresIn: z.ZodNumber;
|
|
479
|
+
}, "strip", z.ZodTypeAny, {
|
|
480
|
+
code: string;
|
|
481
|
+
expiresIn: number;
|
|
482
|
+
}, {
|
|
483
|
+
code: string;
|
|
484
|
+
expiresIn: number;
|
|
485
|
+
}>;
|
|
486
|
+
/**
|
|
487
|
+
* `POST /session/device/join` — called by the app's own origin with the code the
|
|
488
|
+
* bridge window posted to it and the PKCE verifier only the app holds. Returns a
|
|
489
|
+
* NEW holder credential for the browser's device; the app then mints through the
|
|
490
|
+
* ordinary `POST /session/device/token`.
|
|
491
|
+
*/
|
|
492
|
+
export declare const deviceJoinRequestSchema: z.ZodObject<{
|
|
493
|
+
code: z.ZodString;
|
|
494
|
+
codeVerifier: z.ZodString;
|
|
495
|
+
clientId: z.ZodString;
|
|
496
|
+
redirectUri: z.ZodString;
|
|
497
|
+
}, "strip", z.ZodTypeAny, {
|
|
498
|
+
code: string;
|
|
499
|
+
clientId: string;
|
|
500
|
+
redirectUri: string;
|
|
501
|
+
codeVerifier: string;
|
|
502
|
+
}, {
|
|
503
|
+
code: string;
|
|
504
|
+
clientId: string;
|
|
505
|
+
redirectUri: string;
|
|
506
|
+
codeVerifier: string;
|
|
507
|
+
}>;
|
|
508
|
+
export declare const deviceJoinResponseSchema: z.ZodObject<{
|
|
509
|
+
deviceId: z.ZodString;
|
|
510
|
+
deviceSecret: z.ZodString;
|
|
511
|
+
}, "strip", z.ZodTypeAny, {
|
|
512
|
+
deviceId: string;
|
|
513
|
+
deviceSecret: string;
|
|
514
|
+
}, {
|
|
515
|
+
deviceId: string;
|
|
516
|
+
deviceSecret: string;
|
|
517
|
+
}>;
|
|
518
|
+
export type DeviceProof = z.infer<typeof deviceProofSchema>;
|
|
519
|
+
export type DeviceRegisterResponse = z.infer<typeof deviceRegisterResponseSchema>;
|
|
520
|
+
export type DeviceJoinCodeRequest = z.infer<typeof deviceJoinCodeRequestSchema>;
|
|
521
|
+
export type DeviceJoinCodeResponse = z.infer<typeof deviceJoinCodeResponseSchema>;
|
|
522
|
+
export type DeviceJoinRequest = z.infer<typeof deviceJoinRequestSchema>;
|
|
523
|
+
export type DeviceJoinResponse = z.infer<typeof deviceJoinResponseSchema>;
|
|
@@ -253,6 +253,7 @@ export declare const resolveExternalIdentityResponseSchema: z.ZodEffects<z.ZodOb
|
|
|
253
253
|
sourceUserId: string;
|
|
254
254
|
}[];
|
|
255
255
|
redirectedUserIds: string[];
|
|
256
|
+
email?: string | undefined;
|
|
256
257
|
kind?: "bot" | "personal" | "organization" | "project" | "channel" | undefined;
|
|
257
258
|
bio?: string | undefined;
|
|
258
259
|
avatar?: string | null | undefined;
|
|
@@ -263,7 +264,6 @@ export declare const resolveExternalIdentityResponseSchema: z.ZodEffects<z.ZodOb
|
|
|
263
264
|
did?: string | undefined;
|
|
264
265
|
verifiedDomains?: import("./identity").VerifiedDomain[] | undefined;
|
|
265
266
|
_id?: string | undefined;
|
|
266
|
-
email?: string | undefined;
|
|
267
267
|
phone?: string | undefined;
|
|
268
268
|
address?: string | undefined;
|
|
269
269
|
birthday?: string | undefined;
|
|
@@ -307,6 +307,7 @@ export declare const resolveExternalIdentityResponseSchema: z.ZodEffects<z.ZodOb
|
|
|
307
307
|
sourceUserId: string;
|
|
308
308
|
}[];
|
|
309
309
|
redirectedUserIds: string[];
|
|
310
|
+
email?: string | undefined;
|
|
310
311
|
kind?: "bot" | "personal" | "organization" | "project" | "channel" | undefined;
|
|
311
312
|
bio?: string | undefined;
|
|
312
313
|
avatar?: string | null | undefined;
|
|
@@ -317,7 +318,6 @@ export declare const resolveExternalIdentityResponseSchema: z.ZodEffects<z.ZodOb
|
|
|
317
318
|
did?: string | undefined;
|
|
318
319
|
verifiedDomains?: import("./identity").VerifiedDomain[] | undefined;
|
|
319
320
|
_id?: string | undefined;
|
|
320
|
-
email?: string | undefined;
|
|
321
321
|
phone?: string | undefined;
|
|
322
322
|
address?: string | undefined;
|
|
323
323
|
birthday?: string | undefined;
|
|
@@ -361,6 +361,7 @@ export declare const resolveExternalIdentityResponseSchema: z.ZodEffects<z.ZodOb
|
|
|
361
361
|
sourceUserId: string;
|
|
362
362
|
}[];
|
|
363
363
|
redirectedUserIds: string[];
|
|
364
|
+
email?: string | undefined;
|
|
364
365
|
kind?: "bot" | "personal" | "organization" | "project" | "channel" | undefined;
|
|
365
366
|
bio?: string | undefined;
|
|
366
367
|
avatar?: string | null | undefined;
|
|
@@ -371,7 +372,6 @@ export declare const resolveExternalIdentityResponseSchema: z.ZodEffects<z.ZodOb
|
|
|
371
372
|
did?: string | undefined;
|
|
372
373
|
verifiedDomains?: import("./identity").VerifiedDomain[] | undefined;
|
|
373
374
|
_id?: string | undefined;
|
|
374
|
-
email?: string | undefined;
|
|
375
375
|
phone?: string | undefined;
|
|
376
376
|
address?: string | undefined;
|
|
377
377
|
birthday?: string | undefined;
|
|
@@ -415,6 +415,7 @@ export declare const resolveExternalIdentityResponseSchema: z.ZodEffects<z.ZodOb
|
|
|
415
415
|
sourceUserId: string;
|
|
416
416
|
}[];
|
|
417
417
|
redirectedUserIds: string[];
|
|
418
|
+
email?: string | undefined;
|
|
418
419
|
kind?: "bot" | "personal" | "organization" | "project" | "channel" | undefined;
|
|
419
420
|
bio?: string | undefined;
|
|
420
421
|
avatar?: string | null | undefined;
|
|
@@ -425,7 +426,6 @@ export declare const resolveExternalIdentityResponseSchema: z.ZodEffects<z.ZodOb
|
|
|
425
426
|
did?: string | undefined;
|
|
426
427
|
verifiedDomains?: import("./identity").VerifiedDomain[] | undefined;
|
|
427
428
|
_id?: string | undefined;
|
|
428
|
-
email?: string | undefined;
|
|
429
429
|
phone?: string | undefined;
|
|
430
430
|
address?: string | undefined;
|
|
431
431
|
birthday?: string | undefined;
|
package/dist/types/identity.d.ts
CHANGED
|
@@ -315,18 +315,14 @@ export type DomainVerificationInstructions = z.infer<typeof domainVerificationIn
|
|
|
315
315
|
/**
|
|
316
316
|
* One linked authentication method. Mirrors a `User.authMethods[]` entry.
|
|
317
317
|
* `verificationMethodId` is present for `identity` methods (a key), linking the
|
|
318
|
-
* auth method to its DID verification-method fragment.
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
* verification method, so it carries no `verificationMethodId` (a passkey-only
|
|
322
|
-
* account stays custodial).
|
|
318
|
+
* auth method to its DID verification-method fragment. A key is the only
|
|
319
|
+
* linked method: an email, a password and an authenticator are sign-in
|
|
320
|
+
* factors of the account, not DID verification methods.
|
|
323
321
|
*/
|
|
324
322
|
export interface AuthMethodEntry {
|
|
325
|
-
type: 'identity'
|
|
323
|
+
type: 'identity';
|
|
326
324
|
linkedAt: string | Date;
|
|
327
325
|
verificationMethodId?: string;
|
|
328
|
-
credentialId?: string;
|
|
329
|
-
name?: string;
|
|
330
326
|
}
|
|
331
327
|
export declare const authMethodEntrySchema: z.ZodType<AuthMethodEntry>;
|
|
332
328
|
/**
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linking Commons to an account without a key (ADR 0029 D3) — the two-device
|
|
3
|
+
* relay.
|
|
4
|
+
*
|
|
5
|
+
* An account without a key links a Commons root once, and becomes
|
|
6
|
+
* self-custodied: its email is deleted and its phrase in Commons is how it gets
|
|
7
|
+
* back in. The authority is the same as `POST /auth/link` (ADR 0024 D8): a root
|
|
8
|
+
* proof (`link_identity`) by the key Commons holds over a one-use challenge,
|
|
9
|
+
* and the account's own confirmation — a code just sent to its email (plus its
|
|
10
|
+
* authenticator code when it has one). Only the transport is new, because the
|
|
11
|
+
* two factors live on two devices:
|
|
12
|
+
*
|
|
13
|
+
* 1. The signed-in account (the "Link Commons" panel of `@oxy.so/services`)
|
|
14
|
+
* opens a link request → `{ linkId, challenge }`, shown as a QR
|
|
15
|
+
* (`oxycommons://link?id=…&c=…`).
|
|
16
|
+
* 2. Commons scans it, reads the request (the account's id and username),
|
|
17
|
+
* signs the root proof over the challenge and posts it with its key.
|
|
18
|
+
* 3. Both screens show the same 6-digit code, derived from the link id and
|
|
19
|
+
* that key (`deriveIdentityLinkCode` in `@oxy.so/core`); the person checks
|
|
20
|
+
* they match, so a photographed QR cannot slip another key in.
|
|
21
|
+
* 4. The panel completes with the email code: the account gains the root,
|
|
22
|
+
* loses the email, and Commons signs in with it.
|
|
23
|
+
*
|
|
24
|
+
* The server stores only the challenge's hash; the challenge travels in the QR.
|
|
25
|
+
*/
|
|
26
|
+
import { z } from 'zod';
|
|
27
|
+
export declare const IDENTITY_LINK_STATUSES: readonly ["pending", "signed", "completed", "cancelled"];
|
|
28
|
+
export type IdentityLinkStatus = (typeof IDENTITY_LINK_STATUSES)[number];
|
|
29
|
+
/** The scheme and host Commons routes a link QR to. */
|
|
30
|
+
export declare const IDENTITY_LINK_QR_PREFIX = "oxycommons://link";
|
|
31
|
+
export declare const identityLinkIdSchema: z.ZodString;
|
|
32
|
+
/** The QR auth.oxy.so shows: the request's id and the challenge Commons signs. */
|
|
33
|
+
export declare function buildIdentityLinkQrPayload(linkId: string, challenge: string): string;
|
|
34
|
+
/** The request a scanned code names, or `null` for anything that is not a link QR. */
|
|
35
|
+
export declare function parseIdentityLinkQrPayload(raw: string): {
|
|
36
|
+
linkId: string;
|
|
37
|
+
challenge: string;
|
|
38
|
+
} | null;
|
|
39
|
+
/** `POST /identity/link` */
|
|
40
|
+
export interface IdentityLinkCreateResponse {
|
|
41
|
+
linkId: string;
|
|
42
|
+
/** The one-use `link_identity` proof challenge, hex. */
|
|
43
|
+
challenge: string;
|
|
44
|
+
/** Unix milliseconds. */
|
|
45
|
+
expiresAt: number;
|
|
46
|
+
qrPayload: string;
|
|
47
|
+
}
|
|
48
|
+
export declare const identityLinkCreateResponseSchema: z.ZodType<IdentityLinkCreateResponse>;
|
|
49
|
+
/** `GET /identity/link/:linkId` — what both devices poll. */
|
|
50
|
+
export interface IdentityLinkState {
|
|
51
|
+
status: IdentityLinkStatus;
|
|
52
|
+
/** The account being linked: the proof's subject and actor. */
|
|
53
|
+
userId: string;
|
|
54
|
+
username: string | null;
|
|
55
|
+
/** The key Commons signed with, once it has. */
|
|
56
|
+
publicKey: string | null;
|
|
57
|
+
audience: string;
|
|
58
|
+
expiresAt: number;
|
|
59
|
+
}
|
|
60
|
+
export declare const identityLinkStateSchema: z.ZodType<IdentityLinkState>;
|
|
61
|
+
/** `POST /identity/link/:linkId/proof` — from Commons, no bearer. */
|
|
62
|
+
export declare const identityLinkProofRequestSchema: z.ZodObject<{
|
|
63
|
+
publicKey: z.ZodString;
|
|
64
|
+
proof: z.ZodObject<{
|
|
65
|
+
v: z.ZodLiteral<2>;
|
|
66
|
+
challenge: z.ZodString;
|
|
67
|
+
expiresAt: z.ZodNumber;
|
|
68
|
+
signature: z.ZodString;
|
|
69
|
+
}, "strip", z.ZodTypeAny, {
|
|
70
|
+
expiresAt: number;
|
|
71
|
+
signature: string;
|
|
72
|
+
v: 2;
|
|
73
|
+
challenge: string;
|
|
74
|
+
}, {
|
|
75
|
+
expiresAt: number;
|
|
76
|
+
signature: string;
|
|
77
|
+
v: 2;
|
|
78
|
+
challenge: string;
|
|
79
|
+
}>;
|
|
80
|
+
}, "strict", z.ZodTypeAny, {
|
|
81
|
+
publicKey: string;
|
|
82
|
+
proof: {
|
|
83
|
+
expiresAt: number;
|
|
84
|
+
signature: string;
|
|
85
|
+
v: 2;
|
|
86
|
+
challenge: string;
|
|
87
|
+
};
|
|
88
|
+
}, {
|
|
89
|
+
publicKey: string;
|
|
90
|
+
proof: {
|
|
91
|
+
expiresAt: number;
|
|
92
|
+
signature: string;
|
|
93
|
+
v: 2;
|
|
94
|
+
challenge: string;
|
|
95
|
+
};
|
|
96
|
+
}>;
|
|
97
|
+
export type IdentityLinkProofRequest = z.infer<typeof identityLinkProofRequestSchema>;
|
|
98
|
+
/**
|
|
99
|
+
* `POST /identity/link/:linkId/complete` — the account's own confirmation: a
|
|
100
|
+
* code just sent to its email for this link (`reauth`, plus its authenticator
|
|
101
|
+
* code when it has one).
|
|
102
|
+
*/
|
|
103
|
+
export declare const identityLinkCompleteRequestSchema: z.ZodObject<{
|
|
104
|
+
reauth: z.ZodObject<{
|
|
105
|
+
emailCode: z.ZodObject<{
|
|
106
|
+
verificationId: z.ZodString;
|
|
107
|
+
code: z.ZodString;
|
|
108
|
+
}, "strict", z.ZodTypeAny, {
|
|
109
|
+
code: string;
|
|
110
|
+
verificationId: string;
|
|
111
|
+
}, {
|
|
112
|
+
code: string;
|
|
113
|
+
verificationId: string;
|
|
114
|
+
}>;
|
|
115
|
+
totpCode: z.ZodOptional<z.ZodString>;
|
|
116
|
+
}, "strict", z.ZodTypeAny, {
|
|
117
|
+
emailCode: {
|
|
118
|
+
code: string;
|
|
119
|
+
verificationId: string;
|
|
120
|
+
};
|
|
121
|
+
totpCode?: string | undefined;
|
|
122
|
+
}, {
|
|
123
|
+
emailCode: {
|
|
124
|
+
code: string;
|
|
125
|
+
verificationId: string;
|
|
126
|
+
};
|
|
127
|
+
totpCode?: string | undefined;
|
|
128
|
+
}>;
|
|
129
|
+
}, "strict", z.ZodTypeAny, {
|
|
130
|
+
reauth: {
|
|
131
|
+
emailCode: {
|
|
132
|
+
code: string;
|
|
133
|
+
verificationId: string;
|
|
134
|
+
};
|
|
135
|
+
totpCode?: string | undefined;
|
|
136
|
+
};
|
|
137
|
+
}, {
|
|
138
|
+
reauth: {
|
|
139
|
+
emailCode: {
|
|
140
|
+
code: string;
|
|
141
|
+
verificationId: string;
|
|
142
|
+
};
|
|
143
|
+
totpCode?: string | undefined;
|
|
144
|
+
};
|
|
145
|
+
}>;
|
|
146
|
+
export type IdentityLinkCompleteRequest = z.infer<typeof identityLinkCompleteRequestSchema>;
|
|
@@ -27,26 +27,12 @@ export declare const IDENTITY_PROOF_CHALLENGE_TTL_MS: number;
|
|
|
27
27
|
* action and spent only by a proof for that action.
|
|
28
28
|
*/
|
|
29
29
|
export declare const IDENTITY_PROOF_ACTIONS: {
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
readonly phraseConfirmed: "web_envelope_phrase_confirmed";
|
|
36
|
-
/** Record that the recovery material re-derived the root. */
|
|
37
|
-
readonly recoveryVerified: "web_envelope_recovery_verified";
|
|
38
|
-
/** Remove the web holder. */
|
|
39
|
-
readonly delete: "web_envelope_delete";
|
|
40
|
-
/** Link a keyless account's first root without a web envelope (`POST /auth/link`). */
|
|
30
|
+
/**
|
|
31
|
+
* Link Commons' root to an account that has none (`POST /auth/link`).
|
|
32
|
+
* The account becomes self-custodied and its email is deleted
|
|
33
|
+
* (ADR 0029 D3).
|
|
34
|
+
*/
|
|
41
35
|
readonly link: "link_identity";
|
|
42
|
-
/** Create a personal account together with its root (passkey sign-up). */
|
|
43
|
-
readonly enroll: "enroll_identity";
|
|
44
|
-
/** Prove the root to start signed-out recovery. */
|
|
45
|
-
readonly recoverStart: "recover_account_start";
|
|
46
|
-
/** Bind the new passkey and envelope when completing signed-out recovery. */
|
|
47
|
-
readonly recoverComplete: "recover_account_complete";
|
|
48
|
-
/** Seal the root for the Commons device that joined a move (payload: move id + sealed bytes). */
|
|
49
|
-
readonly moveSeal: "identity_move_seal";
|
|
50
36
|
};
|
|
51
37
|
export type IdentityProofAction = (typeof IDENTITY_PROOF_ACTIONS)[keyof typeof IDENTITY_PROOF_ACTIONS];
|
|
52
38
|
export declare const IDENTITY_PROOF_ACTION_VALUES: [IdentityProofAction, ...IdentityProofAction[]];
|
|
@@ -64,7 +50,7 @@ export interface IdentityProofClaims {
|
|
|
64
50
|
rootPublicKey: string;
|
|
65
51
|
/** SHA-256 hex of `canonicalJson(payload)`, or `null` when the operation has no payload. */
|
|
66
52
|
payloadDigest: string | null;
|
|
67
|
-
/** The
|
|
53
|
+
/** The revision the operation expects to replace, or `null` when it replaces nothing. */
|
|
68
54
|
expectedRevision: number | null;
|
|
69
55
|
audience: string;
|
|
70
56
|
/** The one-use server challenge. */
|
|
@@ -103,11 +89,11 @@ export declare const identityProofSchema: z.ZodObject<{
|
|
|
103
89
|
export type IdentityProof = z.infer<typeof identityProofSchema>;
|
|
104
90
|
/** `POST /identity/proof-challenge` */
|
|
105
91
|
export declare const identityProofChallengeRequestSchema: z.ZodObject<{
|
|
106
|
-
action: z.ZodEnum<[
|
|
92
|
+
action: z.ZodEnum<["link_identity", ..."link_identity"[]]>;
|
|
107
93
|
}, "strip", z.ZodTypeAny, {
|
|
108
|
-
action:
|
|
94
|
+
action: "link_identity";
|
|
109
95
|
}, {
|
|
110
|
-
action:
|
|
96
|
+
action: "link_identity";
|
|
111
97
|
}>;
|
|
112
98
|
export type IdentityProofChallengeRequest = z.infer<typeof identityProofChallengeRequestSchema>;
|
|
113
99
|
export interface IdentityProofChallengeResponse {
|
|
@@ -123,34 +109,21 @@ export declare const identityProofChallengeResponseSchema: z.ZodType<IdentityPro
|
|
|
123
109
|
*/
|
|
124
110
|
export declare const IDENTITY_ERROR_CODES: {
|
|
125
111
|
readonly proofInvalid: "IDENTITY_PROOF_INVALID";
|
|
126
|
-
readonly revisionConflict: "IDENTITY_ENVELOPE_REVISION_CONFLICT";
|
|
127
112
|
readonly rootAlreadyLinked: "IDENTITY_ROOT_ALREADY_LINKED";
|
|
128
113
|
readonly rootLinkedElsewhere: "IDENTITY_ROOT_LINKED_ELSEWHERE";
|
|
129
|
-
readonly noRoot: "IDENTITY_NO_ROOT";
|
|
130
114
|
readonly freshFactorRequired: "IDENTITY_FRESH_FACTOR_REQUIRED";
|
|
131
|
-
readonly lastWebHolder: "IDENTITY_LAST_WEB_HOLDER";
|
|
132
|
-
readonly enrollmentRequired: "IDENTITY_ENROLLMENT_REQUIRED";
|
|
133
|
-
readonly enrollmentInvalid: "IDENTITY_ENROLLMENT_INVALID";
|
|
134
115
|
readonly notPersonal: "IDENTITY_NOT_PERSONAL_ACCOUNT";
|
|
135
|
-
readonly recoveryFailed: "IDENTITY_RECOVERY_FAILED";
|
|
136
116
|
};
|
|
137
117
|
export type IdentityErrorCode = (typeof IDENTITY_ERROR_CODES)[keyof typeof IDENTITY_ERROR_CODES];
|
|
138
118
|
/**
|
|
139
|
-
* `GET /identity/root-status` —
|
|
140
|
-
*
|
|
141
|
-
*
|
|
119
|
+
* `GET /identity/root-status` — how the signed-in account is kept (ADR 0029 D3),
|
|
120
|
+
* for Accounts and the account menu to recommend linking Commons. Read with a
|
|
121
|
+
* bearer from any first-party origin.
|
|
142
122
|
*/
|
|
143
123
|
export interface IdentityRootStatus {
|
|
144
|
-
/** Whether
|
|
124
|
+
/** Whether Commons' root is linked: the account is self-custodied. */
|
|
145
125
|
rootLinked: boolean;
|
|
146
|
-
/**
|
|
147
|
-
|
|
148
|
-
passkeys: number;
|
|
149
|
-
verifiedPasskeys: number;
|
|
150
|
-
} | null;
|
|
151
|
-
/** Whether the root has recovery words (a raw-key root does not). `null` when unknown (no web holder). */
|
|
152
|
-
hasPhrase: boolean | null;
|
|
153
|
-
phraseConfirmedAt: string | null;
|
|
154
|
-
recoveryVerifiedAt: string | null;
|
|
126
|
+
/** The email of an account without a key; `null` once Commons is linked. */
|
|
127
|
+
recoveryEmail: string | null;
|
|
155
128
|
}
|
|
156
129
|
export declare const identityRootStatusSchema: z.ZodType<IdentityRootStatus>;
|