@oxy.so/contracts 2.2.0 → 4.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 +21 -25
- package/dist/cjs/deviceBoot.js +2 -2
- package/dist/cjs/deviceSession.js +73 -16
- package/dist/cjs/externalIdentity.js +9 -3
- package/dist/cjs/identity.js +1 -3
- package/dist/cjs/identityLink.js +22 -19
- package/dist/cjs/identityProof.js +2 -2
- package/dist/cjs/index.js +59 -28
- 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 +21 -25
- package/dist/esm/deviceBoot.js +2 -2
- package/dist/esm/deviceSession.js +72 -15
- package/dist/esm/externalIdentity.js +8 -2
- package/dist/esm/identity.js +1 -3
- package/dist/esm/identityLink.js +21 -18
- package/dist/esm/identityProof.js +2 -2
- package/dist/esm/index.js +11 -11
- 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 +20 -28
- package/dist/types/accountGraph.d.ts +4 -4
- package/dist/types/deviceBoot.d.ts +2 -2
- package/dist/types/deviceSession.d.ts +127 -15
- package/dist/types/externalIdentity.d.ts +53 -46
- package/dist/types/identity.d.ts +4 -8
- package/dist/types/identityLink.d.ts +54 -118
- package/dist/types/identityProof.d.ts +3 -3
- package/dist/types/index.d.ts +8 -8
- package/dist/types/inference/entitlement.d.ts +2 -2
- package/dist/types/oauth.d.ts +16 -16
- package/dist/types/reputation.d.ts +32 -127
- package/dist/types/signIn.d.ts +717 -0
- package/dist/types/userResponse.d.ts +2 -2
- package/package.json +1 -1
- package/dist/cjs/webauthn.js +0 -114
- package/dist/esm/webauthn.js +0 -111
- package/dist/types/webauthn.d.ts +0 -173
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Email codes and tickets (ADR 0030).
|
|
3
3
|
*
|
|
4
|
-
* A web account is a username
|
|
5
|
-
*
|
|
6
|
-
* ticket the next step spends:
|
|
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
7
|
*
|
|
8
|
-
* - `signup`: the ticket lets `POST /
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* account's recovery email, and the ticket lets them register a new passkey
|
|
12
|
-
* for that account.
|
|
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.
|
|
13
11
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* Commons key has no recovery email: it recovers in Commons.
|
|
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`).
|
|
17
14
|
*/
|
|
18
15
|
import { z } from 'zod';
|
|
19
|
-
|
|
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"];
|
|
20
24
|
export type EmailVerificationPurpose = (typeof EMAIL_VERIFICATION_PURPOSES)[number];
|
|
21
25
|
/** Digits in a code. */
|
|
22
26
|
export declare const EMAIL_CODE_LENGTH = 6;
|
|
@@ -31,7 +35,7 @@ export declare const emailAddressSchema: z.ZodString;
|
|
|
31
35
|
/** An opaque one-use ticket (32 random bytes, base64url). */
|
|
32
36
|
export declare const emailTicketSchema: z.ZodString;
|
|
33
37
|
/** `POST /auth/email/verify/start` */
|
|
34
|
-
export declare const emailVerificationStartRequestSchema: z.
|
|
38
|
+
export declare const emailVerificationStartRequestSchema: z.ZodObject<{
|
|
35
39
|
purpose: z.ZodLiteral<"signup">;
|
|
36
40
|
email: z.ZodString;
|
|
37
41
|
}, "strict", z.ZodTypeAny, {
|
|
@@ -40,17 +44,7 @@ export declare const emailVerificationStartRequestSchema: z.ZodDiscriminatedUnio
|
|
|
40
44
|
}, {
|
|
41
45
|
purpose: "signup";
|
|
42
46
|
email: string;
|
|
43
|
-
}
|
|
44
|
-
purpose: z.ZodLiteral<"recovery">;
|
|
45
|
-
/** The account's username, or its recovery email. */
|
|
46
|
-
identifier: z.ZodString;
|
|
47
|
-
}, "strict", z.ZodTypeAny, {
|
|
48
|
-
purpose: "recovery";
|
|
49
|
-
identifier: string;
|
|
50
|
-
}, {
|
|
51
|
-
purpose: "recovery";
|
|
52
|
-
identifier: string;
|
|
53
|
-
}>]>;
|
|
47
|
+
}>;
|
|
54
48
|
export type EmailVerificationStartRequest = z.infer<typeof emailVerificationStartRequestSchema>;
|
|
55
49
|
export interface EmailVerificationStartResponse {
|
|
56
50
|
/** Names this verification in `confirm`. Returned whether or not a code was sent. */
|
|
@@ -75,8 +69,6 @@ export interface EmailVerificationConfirmResponse {
|
|
|
75
69
|
ticket: string;
|
|
76
70
|
/** Unix milliseconds after which the ticket is refused. */
|
|
77
71
|
expiresAt: number;
|
|
78
|
-
/** Recovery only: the account the ticket recovers. `null` for sign-up. */
|
|
79
|
-
username: string | null;
|
|
80
72
|
}
|
|
81
73
|
export declare const emailVerificationConfirmResponseSchema: z.ZodType<EmailVerificationConfirmResponse>;
|
|
82
74
|
/**
|
|
@@ -90,7 +82,7 @@ export declare const EMAIL_VERIFICATION_ERROR_CODES: {
|
|
|
90
82
|
readonly tooManyAttempts: "EMAIL_CODE_TOO_MANY_ATTEMPTS";
|
|
91
83
|
/** The ticket is unknown, expired, spent, or for another email or purpose. */
|
|
92
84
|
readonly ticketInvalid: "EMAIL_TICKET_INVALID";
|
|
93
|
-
/** A sign-up without a confirmed
|
|
85
|
+
/** A sign-up without a confirmed email. */
|
|
94
86
|
readonly ticketRequired: "EMAIL_TICKET_REQUIRED";
|
|
95
87
|
/** This server cannot send mail. */
|
|
96
88
|
readonly unavailable: "EMAIL_UNAVAILABLE";
|
|
@@ -315,8 +315,8 @@ export declare const createAccountRequestSchema: z.ZodEffects<z.ZodObject<{
|
|
|
315
315
|
*/
|
|
316
316
|
isPrivateAccount: z.ZodOptional<z.ZodBoolean>;
|
|
317
317
|
}, "strip", z.ZodTypeAny, {
|
|
318
|
-
username: string;
|
|
319
318
|
kind: "bot" | "organization" | "project" | "channel";
|
|
319
|
+
username: string;
|
|
320
320
|
parentAccountId?: string | undefined;
|
|
321
321
|
name?: {
|
|
322
322
|
first?: string | undefined;
|
|
@@ -330,8 +330,8 @@ export declare const createAccountRequestSchema: z.ZodEffects<z.ZodObject<{
|
|
|
330
330
|
accountCategories?: ("security" | "news" | "politics" | "business" | "startup" | "finance" | "crypto" | "marketplace" | "retail" | "real_estate" | "agency" | "landlord" | "cooperative" | "architecture" | "technology" | "software" | "ai" | "automation" | "science" | "education" | "books" | "health" | "fitness" | "sports" | "gaming" | "music" | "film" | "podcast" | "art" | "photography" | "comedy" | "food" | "travel" | "fashion" | "home_garden" | "diy" | "automotive" | "animals" | "family" | "nonprofit" | "government" | "community" | "activism" | "environment" | "religion" | "other")[] | undefined;
|
|
331
331
|
isPrivateAccount?: boolean | undefined;
|
|
332
332
|
}, {
|
|
333
|
-
username: string;
|
|
334
333
|
kind: "bot" | "organization" | "project" | "channel";
|
|
334
|
+
username: string;
|
|
335
335
|
parentAccountId?: string | undefined;
|
|
336
336
|
name?: {
|
|
337
337
|
first?: string | undefined;
|
|
@@ -345,8 +345,8 @@ export declare const createAccountRequestSchema: z.ZodEffects<z.ZodObject<{
|
|
|
345
345
|
accountCategories?: ("security" | "news" | "politics" | "business" | "startup" | "finance" | "crypto" | "marketplace" | "retail" | "real_estate" | "agency" | "landlord" | "cooperative" | "architecture" | "technology" | "software" | "ai" | "automation" | "science" | "education" | "books" | "health" | "fitness" | "sports" | "gaming" | "music" | "film" | "podcast" | "art" | "photography" | "comedy" | "food" | "travel" | "fashion" | "home_garden" | "diy" | "automotive" | "animals" | "family" | "nonprofit" | "government" | "community" | "activism" | "environment" | "religion" | "other")[] | undefined;
|
|
346
346
|
isPrivateAccount?: boolean | undefined;
|
|
347
347
|
}>, {
|
|
348
|
-
username: string;
|
|
349
348
|
kind: "bot" | "organization" | "project" | "channel";
|
|
349
|
+
username: string;
|
|
350
350
|
parentAccountId?: string | undefined;
|
|
351
351
|
name?: {
|
|
352
352
|
first?: string | undefined;
|
|
@@ -360,8 +360,8 @@ export declare const createAccountRequestSchema: z.ZodEffects<z.ZodObject<{
|
|
|
360
360
|
accountCategories?: ("security" | "news" | "politics" | "business" | "startup" | "finance" | "crypto" | "marketplace" | "retail" | "real_estate" | "agency" | "landlord" | "cooperative" | "architecture" | "technology" | "software" | "ai" | "automation" | "science" | "education" | "books" | "health" | "fitness" | "sports" | "gaming" | "music" | "film" | "podcast" | "art" | "photography" | "comedy" | "food" | "travel" | "fashion" | "home_garden" | "diy" | "automotive" | "animals" | "family" | "nonprofit" | "government" | "community" | "activism" | "environment" | "religion" | "other")[] | undefined;
|
|
361
361
|
isPrivateAccount?: boolean | undefined;
|
|
362
362
|
}, {
|
|
363
|
-
username: string;
|
|
364
363
|
kind: "bot" | "organization" | "project" | "channel";
|
|
364
|
+
username: string;
|
|
365
365
|
parentAccountId?: string | undefined;
|
|
366
366
|
name?: {
|
|
367
367
|
first?: string | undefined;
|
|
@@ -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
|
|
@@ -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;
|
|
@@ -409,3 +409,115 @@ export declare const deviceBackgroundTokenResponseSchema: z.ZodObject<{
|
|
|
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>;
|