@oxy.so/contracts 1.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.
Files changed (147) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +16 -0
  3. package/dist/cjs/.tsbuildinfo +1 -0
  4. package/dist/cjs/accountGraph.js +489 -0
  5. package/dist/cjs/agency.js +439 -0
  6. package/dist/cjs/browserHub.js +215 -0
  7. package/dist/cjs/civic.js +163 -0
  8. package/dist/cjs/commonsSignIn.js +59 -0
  9. package/dist/cjs/deviceBoot.js +50 -0
  10. package/dist/cjs/deviceDirectory.js +189 -0
  11. package/dist/cjs/devicePairing.js +138 -0
  12. package/dist/cjs/deviceSession.js +164 -0
  13. package/dist/cjs/emailAgentContext.js +32 -0
  14. package/dist/cjs/followGraph.js +28 -0
  15. package/dist/cjs/identity.js +258 -0
  16. package/dist/cjs/inboxPush.js +24 -0
  17. package/dist/cjs/index.js +618 -0
  18. package/dist/cjs/inference/accountBilling.js +334 -0
  19. package/dist/cjs/inference/aliaModelRelease.js +262 -0
  20. package/dist/cjs/inference/attribution.js +106 -0
  21. package/dist/cjs/inference/catalogue.js +487 -0
  22. package/dist/cjs/inference/entitlement.js +217 -0
  23. package/dist/cjs/inference/errors.js +309 -0
  24. package/dist/cjs/inference/identifiers.js +224 -0
  25. package/dist/cjs/inference/inbox.js +105 -0
  26. package/dist/cjs/inference/modelDocumentation.js +433 -0
  27. package/dist/cjs/inference/money.js +188 -0
  28. package/dist/cjs/inference/priceVersion.js +110 -0
  29. package/dist/cjs/inference/providerConnection.js +455 -0
  30. package/dist/cjs/inference/request.js +477 -0
  31. package/dist/cjs/inference/routingPolicy.js +318 -0
  32. package/dist/cjs/inference/streamEvents.js +258 -0
  33. package/dist/cjs/inference/usage.js +329 -0
  34. package/dist/cjs/inference/version.js +105 -0
  35. package/dist/cjs/keyRecovery.js +91 -0
  36. package/dist/cjs/keyRotation.js +75 -0
  37. package/dist/cjs/links.js +68 -0
  38. package/dist/cjs/moderationReputation.js +298 -0
  39. package/dist/cjs/oauth.js +66 -0
  40. package/dist/cjs/oxyRecordTypes.js +71 -0
  41. package/dist/cjs/protocol.js +53 -0
  42. package/dist/cjs/recommendations.js +168 -0
  43. package/dist/cjs/reputation.js +297 -0
  44. package/dist/cjs/sessionStatus.js +121 -0
  45. package/dist/cjs/transparency.js +89 -0
  46. package/dist/cjs/updates.js +252 -0
  47. package/dist/cjs/userInvalidation.js +89 -0
  48. package/dist/cjs/userResponse.js +245 -0
  49. package/dist/cjs/username.js +290 -0
  50. package/dist/cjs/webauthn.js +71 -0
  51. package/dist/esm/.tsbuildinfo +1 -0
  52. package/dist/esm/accountGraph.js +480 -0
  53. package/dist/esm/agency.js +436 -0
  54. package/dist/esm/browserHub.js +212 -0
  55. package/dist/esm/civic.js +160 -0
  56. package/dist/esm/commonsSignIn.js +56 -0
  57. package/dist/esm/deviceBoot.js +47 -0
  58. package/dist/esm/deviceDirectory.js +186 -0
  59. package/dist/esm/devicePairing.js +135 -0
  60. package/dist/esm/deviceSession.js +161 -0
  61. package/dist/esm/emailAgentContext.js +29 -0
  62. package/dist/esm/followGraph.js +27 -0
  63. package/dist/esm/identity.js +255 -0
  64. package/dist/esm/inboxPush.js +21 -0
  65. package/dist/esm/index.js +172 -0
  66. package/dist/esm/inference/accountBilling.js +331 -0
  67. package/dist/esm/inference/aliaModelRelease.js +259 -0
  68. package/dist/esm/inference/attribution.js +103 -0
  69. package/dist/esm/inference/catalogue.js +484 -0
  70. package/dist/esm/inference/entitlement.js +214 -0
  71. package/dist/esm/inference/errors.js +306 -0
  72. package/dist/esm/inference/identifiers.js +221 -0
  73. package/dist/esm/inference/inbox.js +102 -0
  74. package/dist/esm/inference/modelDocumentation.js +430 -0
  75. package/dist/esm/inference/money.js +185 -0
  76. package/dist/esm/inference/priceVersion.js +107 -0
  77. package/dist/esm/inference/providerConnection.js +452 -0
  78. package/dist/esm/inference/request.js +474 -0
  79. package/dist/esm/inference/routingPolicy.js +315 -0
  80. package/dist/esm/inference/streamEvents.js +255 -0
  81. package/dist/esm/inference/usage.js +326 -0
  82. package/dist/esm/inference/version.js +102 -0
  83. package/dist/esm/keyRecovery.js +88 -0
  84. package/dist/esm/keyRotation.js +72 -0
  85. package/dist/esm/links.js +65 -0
  86. package/dist/esm/moderationReputation.js +295 -0
  87. package/dist/esm/oauth.js +63 -0
  88. package/dist/esm/oxyRecordTypes.js +68 -0
  89. package/dist/esm/protocol.js +50 -0
  90. package/dist/esm/recommendations.js +165 -0
  91. package/dist/esm/reputation.js +293 -0
  92. package/dist/esm/sessionStatus.js +118 -0
  93. package/dist/esm/transparency.js +86 -0
  94. package/dist/esm/updates.js +249 -0
  95. package/dist/esm/userInvalidation.js +85 -0
  96. package/dist/esm/userResponse.js +240 -0
  97. package/dist/esm/username.js +283 -0
  98. package/dist/esm/webauthn.js +68 -0
  99. package/dist/types/.tsbuildinfo +1 -0
  100. package/dist/types/accountGraph.d.ts +378 -0
  101. package/dist/types/agency.d.ts +2162 -0
  102. package/dist/types/browserHub.d.ts +856 -0
  103. package/dist/types/civic.d.ts +338 -0
  104. package/dist/types/commonsSignIn.d.ts +58 -0
  105. package/dist/types/deviceBoot.d.ts +74 -0
  106. package/dist/types/deviceDirectory.d.ts +1317 -0
  107. package/dist/types/devicePairing.d.ts +130 -0
  108. package/dist/types/deviceSession.d.ts +411 -0
  109. package/dist/types/emailAgentContext.d.ts +248 -0
  110. package/dist/types/followGraph.d.ts +150 -0
  111. package/dist/types/identity.d.ts +402 -0
  112. package/dist/types/inboxPush.d.ts +30 -0
  113. package/dist/types/index.d.ts +100 -0
  114. package/dist/types/inference/accountBilling.d.ts +738 -0
  115. package/dist/types/inference/aliaModelRelease.d.ts +609 -0
  116. package/dist/types/inference/attribution.d.ts +176 -0
  117. package/dist/types/inference/catalogue.d.ts +1618 -0
  118. package/dist/types/inference/entitlement.d.ts +519 -0
  119. package/dist/types/inference/errors.d.ts +242 -0
  120. package/dist/types/inference/identifiers.d.ts +182 -0
  121. package/dist/types/inference/inbox.d.ts +374 -0
  122. package/dist/types/inference/modelDocumentation.d.ts +1603 -0
  123. package/dist/types/inference/money.d.ts +185 -0
  124. package/dist/types/inference/priceVersion.d.ts +182 -0
  125. package/dist/types/inference/providerConnection.d.ts +968 -0
  126. package/dist/types/inference/request.d.ts +2800 -0
  127. package/dist/types/inference/routingPolicy.d.ts +616 -0
  128. package/dist/types/inference/streamEvents.d.ts +950 -0
  129. package/dist/types/inference/usage.d.ts +1164 -0
  130. package/dist/types/inference/version.d.ts +102 -0
  131. package/dist/types/keyRecovery.d.ts +138 -0
  132. package/dist/types/keyRotation.d.ts +103 -0
  133. package/dist/types/links.d.ts +96 -0
  134. package/dist/types/moderationReputation.d.ts +487 -0
  135. package/dist/types/oauth.d.ts +86 -0
  136. package/dist/types/oxyRecordTypes.d.ts +62 -0
  137. package/dist/types/protocol.d.ts +86 -0
  138. package/dist/types/recommendations.d.ts +542 -0
  139. package/dist/types/reputation.d.ts +457 -0
  140. package/dist/types/sessionStatus.d.ts +231 -0
  141. package/dist/types/transparency.d.ts +392 -0
  142. package/dist/types/updates.d.ts +545 -0
  143. package/dist/types/userInvalidation.d.ts +94 -0
  144. package/dist/types/userResponse.d.ts +1706 -0
  145. package/dist/types/username.d.ts +265 -0
  146. package/dist/types/webauthn.d.ts +77 -0
  147. package/package.json +87 -0
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deviceBackgroundTokenResponseSchema = exports.deviceBackgroundTokenRequestSchema = exports.deviceBackgroundCredentialResponseSchema = exports.sessionAccountsChangedEventSchema = exports.sessionAccountsChangedReasonSchema = exports.SESSION_ACCOUNTS_CHANGED_EVENT = exports.deviceTokenMintResponseSchema = exports.deviceTokenMintRequestSchema = exports.deviceSessionSyncSchema = exports.activeTokenSchema = exports.deviceSessionStateSchema = exports.sessionAccountSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ exports.sessionAccountSchema = zod_1.z.object({
6
+ accountId: zod_1.z.string(),
7
+ sessionId: zod_1.z.string(),
8
+ authuser: zod_1.z.number().int().nonnegative(),
9
+ operatedByUserId: zod_1.z.string().optional(),
10
+ });
11
+ exports.deviceSessionStateSchema = zod_1.z.object({
12
+ deviceId: zod_1.z.string(),
13
+ accounts: zod_1.z.array(exports.sessionAccountSchema),
14
+ activeAccountId: zod_1.z.string().nullable(),
15
+ revision: zod_1.z.number().int().nonnegative(),
16
+ updatedAt: zod_1.z.number(),
17
+ });
18
+ exports.activeTokenSchema = zod_1.z.object({
19
+ accessToken: zod_1.z.string(),
20
+ expiresAt: zod_1.z.string(),
21
+ });
22
+ exports.deviceSessionSyncSchema = zod_1.z.object({
23
+ state: exports.deviceSessionStateSchema,
24
+ activeToken: exports.activeTokenSchema.nullable(),
25
+ });
26
+ /* -------------------------------------------------------------------------- */
27
+ /* Device-secret token mint (phase 2c — zero-cookie transport) */
28
+ /* -------------------------------------------------------------------------- */
29
+ /**
30
+ * Request body for `POST /session/device/token` — the client presents the
31
+ * `deviceId` it stored first-party plus the opaque `deviceSecret`. NO bearer:
32
+ * possession of the secret IS the proof of device ownership. The server matches
33
+ * `sha256(deviceSecret)` against the device's stored `secretHash` (constant-time)
34
+ * and mints a short access token for the device's active account.
35
+ *
36
+ * `accountId` pins the mint to ONE account of that device instead of whichever
37
+ * account is currently active. It exists for identity-bound clients (Commons),
38
+ * whose authenticated user is determined by a local cryptographic key and must
39
+ * never follow an account switch made by another app on the same device. The
40
+ * account must already be a member of the device session; the mint NEVER
41
+ * mutates `activeAccountId`, so pinning is read-only with respect to the device
42
+ * state every other app observes.
43
+ */
44
+ exports.deviceTokenMintRequestSchema = zod_1.z.object({
45
+ deviceId: zod_1.z.string().min(1),
46
+ deviceSecret: zod_1.z.string().min(1),
47
+ accountId: zod_1.z.string().min(1).optional(),
48
+ });
49
+ /**
50
+ * Wire shape of a successful `POST /session/device/token`: the freshly-minted
51
+ * short access token for the active account, its expiry, the device secret the
52
+ * client must persist (`nextDeviceSecret` — on mint this echoes the presented
53
+ * secret unchanged so concurrent refreshes from multiple origins do not race),
54
+ * and the projected device-session state. Sign-in rotates the secret via
55
+ * `issueDeviceSecret`; mint does not.
56
+ */
57
+ exports.deviceTokenMintResponseSchema = zod_1.z.object({
58
+ accessToken: zod_1.z.string(),
59
+ expiresAt: zod_1.z.string(),
60
+ nextDeviceSecret: zod_1.z.string(),
61
+ state: exports.deviceSessionStateSchema,
62
+ });
63
+ /* -------------------------------------------------------------------------- */
64
+ /* Instant cross-app session sync (token-free socket signal) */
65
+ /* -------------------------------------------------------------------------- */
66
+ /**
67
+ * Name of the token-free Socket.IO event emitted to room `user:<userId>` on
68
+ * every DeviceSession mutation that changes what is signed in for that user.
69
+ *
70
+ * This is a pure SIGNAL — it carries NO access token, NO deviceSecret and NO
71
+ * account bodies. A client that receives it re-fetches its authenticated
72
+ * session/account state (`GET /session/device/state`, `GET /accounts`). Unlike
73
+ * `session_state` (scoped to `device:<deviceId>`, i.e. a single origin), this
74
+ * reaches ALL of a user's connected sockets across their devices/origins so
75
+ * every Oxy app reflects an add / switch / signout instantly.
76
+ */
77
+ exports.SESSION_ACCOUNTS_CHANGED_EVENT = 'session_accounts_changed';
78
+ /**
79
+ * Why the signed-in set changed:
80
+ * - `login` — a brand-new session was minted for the user (QR / cross-app authorize)
81
+ * - `add` — an account was registered onto a device set
82
+ * - `switch` — the active account on a device changed
83
+ * - `signout` — one or all accounts were signed out of a device
84
+ * - `revoke` — a dead/revoked account was healed out of a device set
85
+ */
86
+ exports.sessionAccountsChangedReasonSchema = zod_1.z.enum([
87
+ 'login',
88
+ 'add',
89
+ 'switch',
90
+ 'signout',
91
+ 'revoke',
92
+ ]);
93
+ /**
94
+ * Payload of {@link SESSION_ACCOUNTS_CHANGED_EVENT}. `revision` is the mutated
95
+ * DeviceSession revision for device-scoped reasons (`add`/`switch`/`signout`/
96
+ * `revoke`); for `login` (no device mutation at emit time) it is `0`. The
97
+ * payload is deliberately minimal and secret-free — the client refetches.
98
+ */
99
+ exports.sessionAccountsChangedEventSchema = zod_1.z.object({
100
+ userId: zod_1.z.string(),
101
+ revision: zod_1.z.number().int().nonnegative(),
102
+ reason: exports.sessionAccountsChangedReasonSchema,
103
+ });
104
+ /* -------------------------------------------------------------------------- */
105
+ /* Background credential — native background code with no JS runtime */
106
+ /* -------------------------------------------------------------------------- */
107
+ /**
108
+ * Response from `POST /session/device/background-credential` — provisioned by
109
+ * the SDK WHILE THE APP IS RUNNING (bearer required, `deviceId` and account
110
+ * derived server-side from it) and consumed afterwards only by native
111
+ * background code, which has no JS runtime to mint a token for itself.
112
+ *
113
+ * Deliberately a SEPARATE credential from the rotating `deviceSecret`: that one
114
+ * rotates on every mint, so background code presenting it would become a second
115
+ * writer of a value the JS runtime depends on, and background code killed
116
+ * mid-rotation would silently sign the user out on the next cold start. Against
117
+ * this credential background code is the sole writer, and it can never rotate
118
+ * anything JS reads.
119
+ *
120
+ * The raw `secret` is returned exactly once, at provision time — never stored
121
+ * retrievably, never logged, never re-read. A caller that loses it provisions
122
+ * a new one.
123
+ *
124
+ * `expiresAt` is an unvalidated string, like every other expiry in this file:
125
+ * no consumer on the JS path interprets it (native background code parses it
126
+ * itself), and a `.datetime()` here alone would leave one strict field beside
127
+ * two lax ones. If expiry is ever validated it goes on all three at once, with
128
+ * the API's serializers checked against it — the producer is the same server.
129
+ */
130
+ exports.deviceBackgroundCredentialResponseSchema = zod_1.z.object({
131
+ deviceId: zod_1.z.string().min(1),
132
+ secret: zod_1.z.string().min(1),
133
+ accountId: zod_1.z.string().min(1),
134
+ expiresAt: zod_1.z.string(),
135
+ });
136
+ /**
137
+ * Request body for `POST /session/device/background-token` — presented by
138
+ * native background code with NO bearer and NO cookies: possession of the
139
+ * background `secret` IS the proof, as it is for the device-secret mint.
140
+ *
141
+ * Unlike that mint this one NEVER rotates the presented secret (hence no
142
+ * `next…` field to persist in the response), so background code interrupted
143
+ * anywhere between request and response leaves the credential intact and
144
+ * usable on its next run.
145
+ */
146
+ exports.deviceBackgroundTokenRequestSchema = zod_1.z.object({
147
+ deviceId: zod_1.z.string().min(1),
148
+ secret: zod_1.z.string().min(1),
149
+ });
150
+ /**
151
+ * Wire shape of a successful `POST /session/device/background-token`: the short
152
+ * access token, its expiry, and the account the token belongs to — the last so
153
+ * a caller can key cached data per account and drop data belonging to a
154
+ * foreign one.
155
+ *
156
+ * Carries NO device state — no account list, no `activeAccountId`, no
157
+ * `revision`, unlike {@link deviceTokenMintResponseSchema} — deliberately, to
158
+ * cap what a compromised credential record yields.
159
+ */
160
+ exports.deviceBackgroundTokenResponseSchema = zod_1.z.object({
161
+ accessToken: zod_1.z.string(),
162
+ expiresAt: zod_1.z.string(),
163
+ accountId: zod_1.z.string().min(1),
164
+ });
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.emailAgentContextSchema = exports.emailContextMessageSchema = exports.emailContextMailboxSchema = exports.emailContextAddressSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ exports.emailContextAddressSchema = zod_1.z.object({
6
+ name: zod_1.z.string().optional(),
7
+ address: zod_1.z.string().email(),
8
+ }).strict();
9
+ exports.emailContextMailboxSchema = zod_1.z.object({
10
+ mailboxId: zod_1.z.string().min(1),
11
+ name: zod_1.z.string(),
12
+ path: zod_1.z.string(),
13
+ totalMessages: zod_1.z.number().int().nonnegative(),
14
+ unseenMessages: zod_1.z.number().int().nonnegative(),
15
+ }).strict();
16
+ exports.emailContextMessageSchema = zod_1.z.object({
17
+ messageId: zod_1.z.string().min(1),
18
+ mailboxId: zod_1.z.string().min(1),
19
+ from: exports.emailContextAddressSchema,
20
+ subject: zod_1.z.string(),
21
+ receivedAt: zod_1.z.string().datetime(),
22
+ seen: zod_1.z.boolean(),
23
+ answered: zod_1.z.boolean(),
24
+ }).strict();
25
+ exports.emailAgentContextSchema = zod_1.z.object({
26
+ accountId: zod_1.z.string().min(1),
27
+ resourceMailboxId: zod_1.z.string().min(1).nullable(),
28
+ generatedAt: zod_1.z.string().datetime(),
29
+ mailboxes: zod_1.z.array(exports.emailContextMailboxSchema),
30
+ recentUnread: zod_1.z.array(exports.emailContextMessageSchema),
31
+ needsResponse: zod_1.z.array(exports.emailContextMessageSchema),
32
+ }).strict();
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ /**
3
+ * The follow graph wire contract (`/v2/follows`).
4
+ *
5
+ * These types are the boundary between the API that owns the graph and every
6
+ * application that reads it. They live here — not in the API and not in the
7
+ * SDK — because both ends have to agree, and a shape defined on one side is a
8
+ * shape the other side re-declares slightly differently within a release or two.
9
+ *
10
+ * ## Why the state is three fields and not a boolean
11
+ *
12
+ * A user can follow something globally and turn it off in ONE application. That
13
+ * is a state the user themselves created, so the client has to be able to see
14
+ * it and say so — "following, but not shown here" is a sentence a boolean
15
+ * cannot express. `globalState`, `applicationMode` and `effectiveState` are
16
+ * therefore reported separately, and only the last one answers "does this
17
+ * appear in my feed right now".
18
+ *
19
+ * ## Why kinds are strings
20
+ *
21
+ * `FollowTargetKind` is a plain `string`, not a union. Applications register
22
+ * their own kinds at runtime (`mercaria.store`, `syra.artist`), so a union here
23
+ * would mean every new application in the ecosystem needs a release of this
24
+ * package before it can follow anything. The namespace rule is enforced by the
25
+ * database, which is the one place that can enforce it for applications this
26
+ * package has never heard of.
27
+ */
28
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,258 @@
1
+ "use strict";
2
+ /**
3
+ * Self-sovereign identity API contracts.
4
+ *
5
+ * SINGLE SOURCE OF TRUTH for the wire shape of Oxy's AtProto/Bluesky-flavoured
6
+ * identity & portability layer: the W3C DID document the API derives on demand,
7
+ * the signed-record envelope clients sign with their cryptographic key (and the
8
+ * server verifies), the verified-domain badge, the auth-method ↔ DID
9
+ * verification-method mapping, and the signed data-export ("credible exit")
10
+ * bundle. The API validates its OUTPUT against these schemas; every consumer
11
+ * (the Commons vault app, `@oxy.so/core`'s identity mixin) validates its INPUT
12
+ * against the same definitions, so producer and consumers cannot drift.
13
+ *
14
+ * Design anchors (from the identity-layer plan):
15
+ * - DID = `did:web:oxy.so:u:<userId>` — anchored on the stable account id, NOT
16
+ * the keypair. The keypair is a *verification method* that maps 1:1 to the
17
+ * existing `authMethods[]`. Custodial (password-only) users get a DID
18
+ * controlled solely by Oxy (`OXY_DID`); creating a Commons key upgrades them
19
+ * to self-sovereign (`controller = [userDid, OXY_DID]`); fully reversible.
20
+ * - Verification methods use the secp256k1 `EcdsaSecp256k1VerificationKey2019`
21
+ * type with `publicKeyHex` for now (a `Multikey`/`publicKeyMultibase` form may
22
+ * be added later — see the plan's open risks).
23
+ * - Signed records carry an envelope whose signing input is the canonical-JSON
24
+ * of every field EXCEPT `publicKey` and `signature`; `alg` is
25
+ * `ES256K-DER-SHA256` (secp256k1 over the SHA-256 of the canonical bytes,
26
+ * DER-encoded signature) — the same scheme `SignatureService` uses.
27
+ *
28
+ * Explicit-`interface` exports (DidDocument, SignedRecordEnvelope, ExportBundle,
29
+ * VerifiedDomain, AuthMethodsResponse and their sub-parts) follow the same
30
+ * rationale as `UserNameResponse` in `./userResponse`: a `z.infer<>` of a nested
31
+ * object schema can degrade under a consumer's `moduleResolution: "node"`
32
+ * (node10) resolution, so the load-bearing response shapes are declared as
33
+ * literal interfaces and the runtime schemas are annotated `z.ZodType<Interface>`
34
+ * — the emitted `.d.ts` then states the field types verbatim and survives BOTH
35
+ * `node` and `bundler` resolution. Request schemas (no nested-object hazard) are
36
+ * inferred via `z.infer<>`.
37
+ *
38
+ * Platform-agnostic — zod only, no react/react-native/expo. ESM-safe (no
39
+ * `require()`).
40
+ */
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.exportBundleSchema = exports.exportFinancialSectionSchema = exports.exportUsageReservationSchema = exports.exportLedgerEntrySchema = exports.exportUsageReceiptSchema = exports.exportAttestationSchema = exports.authMethodsResponseSchema = exports.authMethodEntrySchema = exports.domainVerificationInstructionsSchema = exports.domainVerificationRequestSchema = exports.verifiedDomainSchema = exports.signedRecordEnvelopeSchema = exports.didDocumentSchema = exports.didServiceSchema = exports.verificationMethodSchema = void 0;
43
+ const zod_1 = require("zod");
44
+ // The option schemas are left UN-annotated so they keep their concrete
45
+ // `ZodObject` type — `z.discriminatedUnion` requires object options and an
46
+ // explicit `z.ZodType<>` annotation would erase the shape it discriminates on.
47
+ // `z.object` already infers each option's type exactly (id/type/controller +
48
+ // the key field), so the union is structurally `VerificationMethod`.
49
+ const secp256k1VerificationMethodSchema = zod_1.z.object({
50
+ id: zod_1.z.string(),
51
+ type: zod_1.z.literal('EcdsaSecp256k1VerificationKey2019'),
52
+ controller: zod_1.z.string(),
53
+ publicKeyHex: zod_1.z.string(),
54
+ });
55
+ const multikeyVerificationMethodSchema = zod_1.z.object({
56
+ id: zod_1.z.string(),
57
+ type: zod_1.z.literal('Multikey'),
58
+ controller: zod_1.z.string(),
59
+ publicKeyMultibase: zod_1.z.string(),
60
+ });
61
+ exports.verificationMethodSchema = zod_1.z.discriminatedUnion('type', [
62
+ secp256k1VerificationMethodSchema,
63
+ multikeyVerificationMethodSchema,
64
+ ]);
65
+ exports.didServiceSchema = zod_1.z.object({
66
+ id: zod_1.z.string(),
67
+ type: zod_1.z.string(),
68
+ serviceEndpoint: zod_1.z.string(),
69
+ });
70
+ exports.didDocumentSchema = zod_1.z.object({
71
+ '@context': zod_1.z.array(zod_1.z.string()),
72
+ id: zod_1.z.string(),
73
+ controller: zod_1.z.array(zod_1.z.string()),
74
+ verificationMethod: zod_1.z.array(exports.verificationMethodSchema),
75
+ authentication: zod_1.z.array(zod_1.z.string()),
76
+ assertionMethod: zod_1.z.array(zod_1.z.string()),
77
+ alsoKnownAs: zod_1.z.array(zod_1.z.string()),
78
+ service: zod_1.z.array(exports.didServiceSchema),
79
+ });
80
+ exports.signedRecordEnvelopeSchema = zod_1.z
81
+ .object({
82
+ version: zod_1.z.union([zod_1.z.literal(1), zod_1.z.literal(2)]),
83
+ // Open, app-defined category (see the `type` doc above). The Oxy STORE
84
+ // re-narrows to `oxySignedRecordTypeSchema`; an app to its own constant.
85
+ type: zod_1.z.string().min(1),
86
+ subject: zod_1.z.string(),
87
+ issuer: zod_1.z.string(),
88
+ record: zod_1.z.record(zod_1.z.unknown()),
89
+ issuedAt: zod_1.z.number(),
90
+ seq: zod_1.z.number().int().nonnegative().optional(),
91
+ prev: zod_1.z.string().nullable().optional(),
92
+ collection: zod_1.z.string().min(1).optional(),
93
+ rkey: zod_1.z.string().min(1).optional(),
94
+ publicKey: zod_1.z.string(),
95
+ alg: zod_1.z.literal('ES256K-DER-SHA256'),
96
+ signature: zod_1.z.string(),
97
+ })
98
+ .superRefine((env, ctx) => {
99
+ if (env.version === 2) {
100
+ // v2 REQUIRES the hash-chain fields. `prev` may be `null` at genesis,
101
+ // but the key must be present (it is part of the signed bytes), so we
102
+ // reject only when it is entirely absent.
103
+ if (typeof env.seq !== 'number') {
104
+ ctx.addIssue({
105
+ code: zod_1.z.ZodIssueCode.custom,
106
+ message: 'v2 envelope requires `seq`',
107
+ path: ['seq'],
108
+ });
109
+ }
110
+ if (env.prev === undefined) {
111
+ ctx.addIssue({
112
+ code: zod_1.z.ZodIssueCode.custom,
113
+ message: 'v2 envelope requires `prev` (use `null` at genesis)',
114
+ path: ['prev'],
115
+ });
116
+ }
117
+ if (typeof env.collection !== 'string') {
118
+ ctx.addIssue({
119
+ code: zod_1.z.ZodIssueCode.custom,
120
+ message: 'v2 envelope requires `collection`',
121
+ path: ['collection'],
122
+ });
123
+ }
124
+ if (typeof env.rkey !== 'string') {
125
+ ctx.addIssue({
126
+ code: zod_1.z.ZodIssueCode.custom,
127
+ message: 'v2 envelope requires `rkey`',
128
+ path: ['rkey'],
129
+ });
130
+ }
131
+ }
132
+ else {
133
+ // v1 FORBIDS the v2 chain fields entirely, so a legacy envelope keeps
134
+ // its exact byte shape and cannot smuggle unsigned chain metadata.
135
+ if (env.seq !== undefined) {
136
+ ctx.addIssue({
137
+ code: zod_1.z.ZodIssueCode.custom,
138
+ message: 'v1 envelope must not carry `seq`',
139
+ path: ['seq'],
140
+ });
141
+ }
142
+ if (env.prev !== undefined) {
143
+ ctx.addIssue({
144
+ code: zod_1.z.ZodIssueCode.custom,
145
+ message: 'v1 envelope must not carry `prev`',
146
+ path: ['prev'],
147
+ });
148
+ }
149
+ if (env.collection !== undefined) {
150
+ ctx.addIssue({
151
+ code: zod_1.z.ZodIssueCode.custom,
152
+ message: 'v1 envelope must not carry `collection`',
153
+ path: ['collection'],
154
+ });
155
+ }
156
+ if (env.rkey !== undefined) {
157
+ ctx.addIssue({
158
+ code: zod_1.z.ZodIssueCode.custom,
159
+ message: 'v1 envelope must not carry `rkey`',
160
+ path: ['rkey'],
161
+ });
162
+ }
163
+ }
164
+ });
165
+ exports.verifiedDomainSchema = zod_1.z.object({
166
+ domain: zod_1.z.string(),
167
+ verifiedAt: zod_1.z.union([zod_1.z.string(), zod_1.z.date()]),
168
+ method: zod_1.z.enum(['dns-txt', 'well-known']),
169
+ });
170
+ /** Request body for `POST /identity/domains` — the domain to start verifying. */
171
+ exports.domainVerificationRequestSchema = zod_1.z.object({
172
+ domain: zod_1.z.string().trim().min(1),
173
+ });
174
+ /**
175
+ * The instructions the API returns when a domain verification is requested. The
176
+ * caller may prove ownership EITHER by publishing the `dns` TXT record OR by
177
+ * serving the `wellKnown` file; either path then satisfies
178
+ * `POST /identity/domains/:domain/verify`.
179
+ */
180
+ exports.domainVerificationInstructionsSchema = zod_1.z.object({
181
+ domain: zod_1.z.string(),
182
+ token: zod_1.z.string(),
183
+ dns: zod_1.z.object({
184
+ name: zod_1.z.string(),
185
+ value: zod_1.z.string(),
186
+ }),
187
+ wellKnown: zod_1.z.object({
188
+ url: zod_1.z.string(),
189
+ body: zod_1.z.string(),
190
+ }),
191
+ });
192
+ exports.authMethodEntrySchema = zod_1.z.object({
193
+ type: zod_1.z.enum(['identity', 'webauthn']),
194
+ linkedAt: zod_1.z.union([zod_1.z.string(), zod_1.z.date()]),
195
+ verificationMethodId: zod_1.z.string().optional(),
196
+ credentialId: zod_1.z.string().optional(),
197
+ name: zod_1.z.string().optional(),
198
+ });
199
+ exports.authMethodsResponseSchema = zod_1.z.object({
200
+ did: zod_1.z.string(),
201
+ methods: zod_1.z.array(exports.authMethodEntrySchema),
202
+ });
203
+ exports.exportAttestationSchema = zod_1.z.object({
204
+ issuer: zod_1.z.string(),
205
+ publicKey: zod_1.z.string(),
206
+ alg: zod_1.z.literal('ES256K-DER-SHA256'),
207
+ signature: zod_1.z.string(),
208
+ signedAt: zod_1.z.number(),
209
+ });
210
+ exports.exportUsageReceiptSchema = zod_1.z.object({
211
+ receiptId: zod_1.z.string(),
212
+ requestId: zod_1.z.string(),
213
+ settledAt: zod_1.z.string(),
214
+ billedAmount: zod_1.z.string(),
215
+ currency: zod_1.z.string(),
216
+ outcome: zod_1.z.string(),
217
+ resolvedModelReference: zod_1.z.string(),
218
+ servingProvider: zod_1.z.string(),
219
+ platformFeeOnly: zod_1.z.boolean(),
220
+ });
221
+ exports.exportLedgerEntrySchema = zod_1.z.object({
222
+ entryId: zod_1.z.string(),
223
+ kind: zod_1.z.string(),
224
+ currency: zod_1.z.string(),
225
+ createdAt: zod_1.z.string(),
226
+ });
227
+ exports.exportUsageReservationSchema = zod_1.z.object({
228
+ reservationId: zod_1.z.string(),
229
+ requestId: zod_1.z.string(),
230
+ status: zod_1.z.string(),
231
+ reservedAmount: zod_1.z.string(),
232
+ currency: zod_1.z.string(),
233
+ createdAt: zod_1.z.string(),
234
+ expiresAt: zod_1.z.string(),
235
+ });
236
+ exports.exportFinancialSectionSchema = zod_1.z.object({
237
+ receipts: zod_1.z.array(exports.exportUsageReceiptSchema),
238
+ ledgerEntries: zod_1.z.array(exports.exportLedgerEntrySchema),
239
+ reservations: zod_1.z.array(exports.exportUsageReservationSchema),
240
+ });
241
+ exports.exportBundleSchema = zod_1.z.object({
242
+ '$schema': zod_1.z.string(),
243
+ exportedAt: zod_1.z.string(),
244
+ did: zod_1.z.string(),
245
+ didDocument: exports.didDocumentSchema,
246
+ profile: zod_1.z.record(zod_1.z.unknown()),
247
+ verifiedDomains: zod_1.z.array(exports.verifiedDomainSchema),
248
+ authMethods: zod_1.z.array(exports.authMethodEntrySchema),
249
+ signedRecords: zod_1.z.array(exports.signedRecordEnvelopeSchema),
250
+ appData: zod_1.z.array(zod_1.z.record(zod_1.z.unknown())),
251
+ social: zod_1.z.object({
252
+ following: zod_1.z.array(zod_1.z.string()),
253
+ followers: zod_1.z.array(zod_1.z.string()),
254
+ }),
255
+ financial: exports.exportFinancialSectionSchema,
256
+ attestation: exports.exportAttestationSchema.nullable(),
257
+ proof: exports.exportAttestationSchema.optional(),
258
+ });
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ /**
3
+ * Canonical contract for Inbox new-mail push notifications.
4
+ *
5
+ * The Android channel id and payload `type` are wire contracts: Android 8+
6
+ * drops a notification whose channel the app has not created, and the client
7
+ * only routes taps it recognises. Two hand-typed copies of either string fail as
8
+ * "the notification never arrived" or "tapping does nothing" — the hardest push
9
+ * symptoms to diagnose.
10
+ *
11
+ * Platform-agnostic — zod only, no react/react-native/expo.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.inboxEmailPushDataSchema = exports.INBOX_EMAIL_PUSH_TYPE = exports.INBOX_EMAIL_PUSH_CHANNEL = void 0;
15
+ const zod_1 = require("zod");
16
+ /** Android notification channel id the new-mail push is sent on. */
17
+ exports.INBOX_EMAIL_PUSH_CHANNEL = 'email';
18
+ /** Runtime type discriminator of the new-mail push payload. */
19
+ exports.INBOX_EMAIL_PUSH_TYPE = 'oxy_inbox_new_message';
20
+ exports.inboxEmailPushDataSchema = zod_1.z.object({
21
+ type: zod_1.z.literal(exports.INBOX_EMAIL_PUSH_TYPE),
22
+ messageId: zod_1.z.string().min(1),
23
+ mailboxId: zod_1.z.string().min(1),
24
+ });