@oxyhq/contracts 0.2.1 → 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.
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Self-sovereign identity API contracts.
3
+ *
4
+ * SINGLE SOURCE OF TRUTH for the wire shape of Oxy's AtProto/Bluesky-flavoured
5
+ * identity & portability layer: the W3C DID document the API derives on demand,
6
+ * the signed-record envelope clients sign with their cryptographic key (and the
7
+ * server verifies), the verified-domain badge, the auth-method ↔ DID
8
+ * verification-method mapping, and the signed data-export ("credible exit")
9
+ * bundle. The API validates its OUTPUT against these schemas; every consumer
10
+ * (the Commons vault app, `@oxyhq/core`'s identity mixin) validates its INPUT
11
+ * against the same definitions, so producer and consumers cannot drift.
12
+ *
13
+ * Design anchors (from the identity-layer plan):
14
+ * - DID = `did:web:oxy.so:u:<userId>` — anchored on the stable account id, NOT
15
+ * the keypair. The keypair is a *verification method* that maps 1:1 to the
16
+ * existing `authMethods[]`. Custodial (password-only) users get a DID
17
+ * controlled solely by Oxy (`OXY_DID`); creating a Commons key upgrades them
18
+ * to self-sovereign (`controller = [userDid, OXY_DID]`); fully reversible.
19
+ * - Verification methods use the secp256k1 `EcdsaSecp256k1VerificationKey2019`
20
+ * type with `publicKeyHex` for now (a `Multikey`/`publicKeyMultibase` form may
21
+ * be added later — see the plan's open risks).
22
+ * - Signed records carry an envelope whose signing input is the canonical-JSON
23
+ * of every field EXCEPT `publicKey` and `signature`; `alg` is
24
+ * `ES256K-DER-SHA256` (secp256k1 over the SHA-256 of the canonical bytes,
25
+ * DER-encoded signature) — the same scheme `SignatureService` uses.
26
+ *
27
+ * Explicit-`interface` exports (DidDocument, SignedRecordEnvelope, ExportBundle,
28
+ * VerifiedDomain, AuthMethodsResponse and their sub-parts) follow the same
29
+ * rationale as `UserNameResponse` in `./userResponse`: a `z.infer<>` of a nested
30
+ * object schema can degrade under a consumer's `moduleResolution: "node"`
31
+ * (node10) resolution, so the load-bearing response shapes are declared as
32
+ * literal interfaces and the runtime schemas are annotated `z.ZodType<Interface>`
33
+ * — the emitted `.d.ts` then states the field types verbatim and survives BOTH
34
+ * `node` and `bundler` resolution. Request schemas (no nested-object hazard) are
35
+ * inferred via `z.infer<>`.
36
+ *
37
+ * Platform-agnostic — zod only, no react/react-native/expo. ESM-safe (no
38
+ * `require()`).
39
+ */
40
+ import { z } from 'zod';
41
+ /**
42
+ * A single DID verification method. Mirrors the secp256k1 key entries the API
43
+ * derives from `User.publicKey` + each `authMethods[]` of type `identity`.
44
+ * `id` is a fragment reference within the DID document (e.g.
45
+ * `did:web:oxy.so:u:<id>#key-1`); `controller` is the controlling DID;
46
+ * `publicKeyHex` is the uncompressed/compressed secp256k1 public key in hex.
47
+ */
48
+ export interface VerificationMethod {
49
+ id: string;
50
+ type: 'EcdsaSecp256k1VerificationKey2019';
51
+ controller: string;
52
+ publicKeyHex: string;
53
+ }
54
+ export declare const verificationMethodSchema: z.ZodType<VerificationMethod>;
55
+ /**
56
+ * A DID service entry (the `service[]` array). Oxy publishes its API root and
57
+ * profile endpoints here so a resolver can discover where to fetch the user's
58
+ * data. `serviceEndpoint` is a URL string.
59
+ */
60
+ export interface DidService {
61
+ id: string;
62
+ type: string;
63
+ serviceEndpoint: string;
64
+ }
65
+ export declare const didServiceSchema: z.ZodType<DidService>;
66
+ /**
67
+ * A W3C DID document derived on demand by the API (no stored document).
68
+ *
69
+ * - `controller` is `[userDid, OXY_DID]` for a self-sovereign account (it holds
70
+ * at least one `identity` verification method) or `[OXY_DID]` for a custodial
71
+ * (password-only) account.
72
+ * - `verificationMethod[]` is composed from the account's secp256k1 keys.
73
+ * - `authentication` / `assertionMethod` reference verification-method ids.
74
+ * - `alsoKnownAs[]` carries the account's other identifiers (`acct:` handle,
75
+ * profile URL, any verified-domain URLs).
76
+ */
77
+ export interface DidDocument {
78
+ '@context': string[];
79
+ id: string;
80
+ controller: string[];
81
+ verificationMethod: VerificationMethod[];
82
+ authentication: string[];
83
+ assertionMethod: string[];
84
+ alsoKnownAs: string[];
85
+ service: DidService[];
86
+ }
87
+ export declare const didDocumentSchema: z.ZodType<DidDocument>;
88
+ /**
89
+ * A signed record envelope. `record` is the arbitrary payload; the signing
90
+ * input is the canonical-JSON of every envelope field EXCEPT `publicKey` and
91
+ * `signature`. `subject` and `issuer` are DIDs (the subject the record is about
92
+ * and the signer's DID — equal for self-issued records, `OXY_DID` for a
93
+ * custodial provenance attestation). `issuedAt` is epoch milliseconds.
94
+ */
95
+ export interface SignedRecordEnvelope {
96
+ version: 1;
97
+ type: 'identity' | 'profile';
98
+ subject: string;
99
+ issuer: string;
100
+ record: Record<string, unknown>;
101
+ issuedAt: number;
102
+ publicKey: string;
103
+ alg: 'ES256K-DER-SHA256';
104
+ signature: string;
105
+ }
106
+ export declare const signedRecordEnvelopeSchema: z.ZodType<SignedRecordEnvelope>;
107
+ /**
108
+ * A proven domain ownership badge. `method` records how ownership was proven —
109
+ * a DNS-TXT record (`_oxy-identity.<domain>`) or a `/.well-known/oxy-domain`
110
+ * HTTP file. `verifiedAt` is a string on the wire (ISO timestamp) but accepts a
111
+ * `Date` so the API can validate its own pre-serialization model objects.
112
+ */
113
+ export interface VerifiedDomain {
114
+ domain: string;
115
+ verifiedAt: string | Date;
116
+ method: 'dns-txt' | 'well-known';
117
+ }
118
+ export declare const verifiedDomainSchema: z.ZodType<VerifiedDomain>;
119
+ /** Request body for `POST /identity/domains` — the domain to start verifying. */
120
+ export declare const domainVerificationRequestSchema: z.ZodObject<{
121
+ domain: z.ZodString;
122
+ }, "strip", z.ZodTypeAny, {
123
+ domain: string;
124
+ }, {
125
+ domain: string;
126
+ }>;
127
+ export type DomainVerificationRequest = z.infer<typeof domainVerificationRequestSchema>;
128
+ /**
129
+ * The instructions the API returns when a domain verification is requested. The
130
+ * caller may prove ownership EITHER by publishing the `dns` TXT record OR by
131
+ * serving the `wellKnown` file; either path then satisfies
132
+ * `POST /identity/domains/:domain/verify`.
133
+ */
134
+ export declare const domainVerificationInstructionsSchema: z.ZodObject<{
135
+ domain: z.ZodString;
136
+ token: z.ZodString;
137
+ dns: z.ZodObject<{
138
+ name: z.ZodString;
139
+ value: z.ZodString;
140
+ }, "strip", z.ZodTypeAny, {
141
+ value: string;
142
+ name: string;
143
+ }, {
144
+ value: string;
145
+ name: string;
146
+ }>;
147
+ wellKnown: z.ZodObject<{
148
+ url: z.ZodString;
149
+ body: z.ZodString;
150
+ }, "strip", z.ZodTypeAny, {
151
+ url: string;
152
+ body: string;
153
+ }, {
154
+ url: string;
155
+ body: string;
156
+ }>;
157
+ }, "strip", z.ZodTypeAny, {
158
+ domain: string;
159
+ token: string;
160
+ dns: {
161
+ value: string;
162
+ name: string;
163
+ };
164
+ wellKnown: {
165
+ url: string;
166
+ body: string;
167
+ };
168
+ }, {
169
+ domain: string;
170
+ token: string;
171
+ dns: {
172
+ value: string;
173
+ name: string;
174
+ };
175
+ wellKnown: {
176
+ url: string;
177
+ body: string;
178
+ };
179
+ }>;
180
+ export type DomainVerificationInstructions = z.infer<typeof domainVerificationInstructionsSchema>;
181
+ /**
182
+ * One linked authentication method. Mirrors a `User.authMethods[]` entry.
183
+ * `verificationMethodId` is present for `identity` methods (a key) and absent
184
+ * for `password`/social methods, linking the auth method to its DID
185
+ * verification-method fragment.
186
+ */
187
+ export interface AuthMethodEntry {
188
+ type: 'identity' | 'password' | 'google' | 'apple' | 'github';
189
+ linkedAt: string | Date;
190
+ verificationMethodId?: string;
191
+ }
192
+ export declare const authMethodEntrySchema: z.ZodType<AuthMethodEntry>;
193
+ /**
194
+ * Wire shape of `GET /auth/methods` — the account's DID plus every linked
195
+ * authentication method.
196
+ */
197
+ export interface AuthMethodsResponse {
198
+ did: string;
199
+ methods: AuthMethodEntry[];
200
+ }
201
+ export declare const authMethodsResponseSchema: z.ZodType<AuthMethodsResponse>;
202
+ /**
203
+ * A cryptographic attestation over the canonical-JSON of an export bundle.
204
+ * Reused for both the mandatory Oxy provenance `attestation` (signed with the
205
+ * Oxy custodial key) and the optional client `proof` (signed with the user's
206
+ * own key when they hold one). `signedAt` is epoch milliseconds.
207
+ */
208
+ export interface ExportAttestation {
209
+ issuer: string;
210
+ publicKey: string;
211
+ alg: 'ES256K-DER-SHA256';
212
+ signature: string;
213
+ signedAt: number;
214
+ }
215
+ export declare const exportAttestationSchema: z.ZodType<ExportAttestation>;
216
+ /**
217
+ * The signed, open-format data-export bundle from `GET /users/me/export`. A
218
+ * portable snapshot of the account: its DID document, profile, verified
219
+ * domains, auth methods (no secrets), published signed records, per-app data,
220
+ * and social graph.
221
+ *
222
+ * `attestation` is the Oxy custodial provenance signature. It is `null` only
223
+ * when the Oxy custodial signing key (`OXY_PRIVATE_KEY`) is unset (dev /
224
+ * pre-prod); in production it is always present. Carries an optional client
225
+ * `proof` when the user signed the bundle with their own key.
226
+ */
227
+ export interface ExportBundle {
228
+ '$schema': string;
229
+ exportedAt: string;
230
+ did: string;
231
+ didDocument: DidDocument;
232
+ profile: Record<string, unknown>;
233
+ verifiedDomains: VerifiedDomain[];
234
+ authMethods: AuthMethodEntry[];
235
+ signedRecords: SignedRecordEnvelope[];
236
+ appData: Record<string, unknown>[];
237
+ social: {
238
+ following: string[];
239
+ followers: string[];
240
+ };
241
+ attestation: ExportAttestation | null;
242
+ proof?: ExportAttestation;
243
+ }
244
+ export declare const exportBundleSchema: z.ZodType<ExportBundle>;
@@ -17,3 +17,5 @@ export { fedcmTokenPayloadSchema, } from './fedcmToken';
17
17
  export type { FedcmTokenPayload, } from './fedcmToken';
18
18
  export { recommendationExcludeTypeSchema, recommendationBoostSchema, recommendationSignalWeightsSchema, recommendationRequestSchema, recommendationCountSchema, recommendationItemSchema, recommendationResponseSchema, appEndorsementInputSchema, appInterestInputSchema, appUserSignalIngestSchema, } from './recommendations';
19
19
  export type { RecommendationExcludeType, RecommendationBoost, RecommendationSignalWeights, RecommendationRequest, RecommendationCount, RecommendationItem, RecommendationResponse, AppEndorsementInput, AppInterestInput, AppUserSignalIngest, } from './recommendations';
20
+ export { verificationMethodSchema, didServiceSchema, didDocumentSchema, signedRecordEnvelopeSchema, verifiedDomainSchema, domainVerificationRequestSchema, domainVerificationInstructionsSchema, authMethodEntrySchema, authMethodsResponseSchema, exportAttestationSchema, exportBundleSchema, } from './identity';
21
+ export type { VerificationMethod, DidService, DidDocument, SignedRecordEnvelope, VerifiedDomain, DomainVerificationRequest, DomainVerificationInstructions, AuthMethodEntry, AuthMethodsResponse, ExportAttestation, ExportBundle, } from './identity';
@@ -164,11 +164,11 @@ export declare const recommendationCountSchema: z.ZodObject<{
164
164
  followers: z.ZodNumber;
165
165
  following: z.ZodNumber;
166
166
  }, "strip", z.ZodTypeAny, {
167
- followers: number;
168
167
  following: number;
169
- }, {
170
168
  followers: number;
169
+ }, {
171
170
  following: number;
171
+ followers: number;
172
172
  }>;
173
173
  export type RecommendationCount = z.infer<typeof recommendationCountSchema>;
174
174
  /**
@@ -197,11 +197,11 @@ export declare const recommendationItemSchema: z.ZodObject<{
197
197
  followers: z.ZodNumber;
198
198
  following: z.ZodNumber;
199
199
  }, "strip", z.ZodTypeAny, {
200
- followers: number;
201
200
  following: number;
202
- }, {
203
201
  followers: number;
202
+ }, {
204
203
  following: number;
204
+ followers: number;
205
205
  }>;
206
206
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
207
207
  id: z.ZodString;
@@ -222,11 +222,11 @@ export declare const recommendationItemSchema: z.ZodObject<{
222
222
  followers: z.ZodNumber;
223
223
  following: z.ZodNumber;
224
224
  }, "strip", z.ZodTypeAny, {
225
- followers: number;
226
225
  following: number;
227
- }, {
228
226
  followers: number;
227
+ }, {
229
228
  following: number;
229
+ followers: number;
230
230
  }>;
231
231
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
232
232
  id: z.ZodString;
@@ -247,11 +247,11 @@ export declare const recommendationItemSchema: z.ZodObject<{
247
247
  followers: z.ZodNumber;
248
248
  following: z.ZodNumber;
249
249
  }, "strip", z.ZodTypeAny, {
250
- followers: number;
251
250
  following: number;
252
- }, {
253
251
  followers: number;
252
+ }, {
254
253
  following: number;
254
+ followers: number;
255
255
  }>;
256
256
  }, z.ZodTypeAny, "passthrough">>;
257
257
  export type RecommendationItem = z.infer<typeof recommendationItemSchema>;
@@ -275,11 +275,11 @@ export declare const recommendationResponseSchema: z.ZodArray<z.ZodObject<{
275
275
  followers: z.ZodNumber;
276
276
  following: z.ZodNumber;
277
277
  }, "strip", z.ZodTypeAny, {
278
- followers: number;
279
278
  following: number;
280
- }, {
281
279
  followers: number;
280
+ }, {
282
281
  following: number;
282
+ followers: number;
283
283
  }>;
284
284
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
285
285
  id: z.ZodString;
@@ -300,11 +300,11 @@ export declare const recommendationResponseSchema: z.ZodArray<z.ZodObject<{
300
300
  followers: z.ZodNumber;
301
301
  following: z.ZodNumber;
302
302
  }, "strip", z.ZodTypeAny, {
303
- followers: number;
304
303
  following: number;
305
- }, {
306
304
  followers: number;
305
+ }, {
307
306
  following: number;
307
+ followers: number;
308
308
  }>;
309
309
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
310
310
  id: z.ZodString;
@@ -325,11 +325,11 @@ export declare const recommendationResponseSchema: z.ZodArray<z.ZodObject<{
325
325
  followers: z.ZodNumber;
326
326
  following: z.ZodNumber;
327
327
  }, "strip", z.ZodTypeAny, {
328
- followers: number;
329
328
  following: number;
330
- }, {
331
329
  followers: number;
330
+ }, {
332
331
  following: number;
332
+ followers: number;
333
333
  }>;
334
334
  }, z.ZodTypeAny, "passthrough">>, "many">;
335
335
  export type RecommendationResponse = z.infer<typeof recommendationResponseSchema>;