@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,135 @@
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, `@oxyhq/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.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
+ exports.verificationMethodSchema = zod_1.z.object({
45
+ id: zod_1.z.string(),
46
+ type: zod_1.z.literal('EcdsaSecp256k1VerificationKey2019'),
47
+ controller: zod_1.z.string(),
48
+ publicKeyHex: zod_1.z.string(),
49
+ });
50
+ exports.didServiceSchema = zod_1.z.object({
51
+ id: zod_1.z.string(),
52
+ type: zod_1.z.string(),
53
+ serviceEndpoint: zod_1.z.string(),
54
+ });
55
+ exports.didDocumentSchema = zod_1.z.object({
56
+ '@context': zod_1.z.array(zod_1.z.string()),
57
+ id: zod_1.z.string(),
58
+ controller: zod_1.z.array(zod_1.z.string()),
59
+ verificationMethod: zod_1.z.array(exports.verificationMethodSchema),
60
+ authentication: zod_1.z.array(zod_1.z.string()),
61
+ assertionMethod: zod_1.z.array(zod_1.z.string()),
62
+ alsoKnownAs: zod_1.z.array(zod_1.z.string()),
63
+ service: zod_1.z.array(exports.didServiceSchema),
64
+ });
65
+ exports.signedRecordEnvelopeSchema = zod_1.z.object({
66
+ version: zod_1.z.literal(1),
67
+ type: zod_1.z.enum(['identity', 'profile']),
68
+ subject: zod_1.z.string(),
69
+ issuer: zod_1.z.string(),
70
+ record: zod_1.z.record(zod_1.z.unknown()),
71
+ issuedAt: zod_1.z.number(),
72
+ publicKey: zod_1.z.string(),
73
+ alg: zod_1.z.literal('ES256K-DER-SHA256'),
74
+ signature: zod_1.z.string(),
75
+ });
76
+ exports.verifiedDomainSchema = zod_1.z.object({
77
+ domain: zod_1.z.string(),
78
+ verifiedAt: zod_1.z.union([zod_1.z.string(), zod_1.z.date()]),
79
+ method: zod_1.z.enum(['dns-txt', 'well-known']),
80
+ });
81
+ /** Request body for `POST /identity/domains` — the domain to start verifying. */
82
+ exports.domainVerificationRequestSchema = zod_1.z.object({
83
+ domain: zod_1.z.string().trim().min(1),
84
+ });
85
+ /**
86
+ * The instructions the API returns when a domain verification is requested. The
87
+ * caller may prove ownership EITHER by publishing the `dns` TXT record OR by
88
+ * serving the `wellKnown` file; either path then satisfies
89
+ * `POST /identity/domains/:domain/verify`.
90
+ */
91
+ exports.domainVerificationInstructionsSchema = zod_1.z.object({
92
+ domain: zod_1.z.string(),
93
+ token: zod_1.z.string(),
94
+ dns: zod_1.z.object({
95
+ name: zod_1.z.string(),
96
+ value: zod_1.z.string(),
97
+ }),
98
+ wellKnown: zod_1.z.object({
99
+ url: zod_1.z.string(),
100
+ body: zod_1.z.string(),
101
+ }),
102
+ });
103
+ exports.authMethodEntrySchema = zod_1.z.object({
104
+ type: zod_1.z.enum(['identity', 'password', 'google', 'apple', 'github']),
105
+ linkedAt: zod_1.z.union([zod_1.z.string(), zod_1.z.date()]),
106
+ verificationMethodId: zod_1.z.string().optional(),
107
+ });
108
+ exports.authMethodsResponseSchema = zod_1.z.object({
109
+ did: zod_1.z.string(),
110
+ methods: zod_1.z.array(exports.authMethodEntrySchema),
111
+ });
112
+ exports.exportAttestationSchema = zod_1.z.object({
113
+ issuer: zod_1.z.string(),
114
+ publicKey: zod_1.z.string(),
115
+ alg: zod_1.z.literal('ES256K-DER-SHA256'),
116
+ signature: zod_1.z.string(),
117
+ signedAt: zod_1.z.number(),
118
+ });
119
+ exports.exportBundleSchema = zod_1.z.object({
120
+ '$schema': zod_1.z.string(),
121
+ exportedAt: zod_1.z.string(),
122
+ did: zod_1.z.string(),
123
+ didDocument: exports.didDocumentSchema,
124
+ profile: zod_1.z.record(zod_1.z.unknown()),
125
+ verifiedDomains: zod_1.z.array(exports.verifiedDomainSchema),
126
+ authMethods: zod_1.z.array(exports.authMethodEntrySchema),
127
+ signedRecords: zod_1.z.array(exports.signedRecordEnvelopeSchema),
128
+ appData: zod_1.z.array(zod_1.z.record(zod_1.z.unknown())),
129
+ social: zod_1.z.object({
130
+ following: zod_1.z.array(zod_1.z.string()),
131
+ followers: zod_1.z.array(zod_1.z.string()),
132
+ }),
133
+ attestation: exports.exportAttestationSchema.nullable(),
134
+ proof: exports.exportAttestationSchema.optional(),
135
+ });
package/dist/cjs/index.js CHANGED
@@ -11,7 +11,7 @@
11
11
  * expo, no `require()` in the ESM build.
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.appUserSignalIngestSchema = exports.appInterestInputSchema = exports.appEndorsementInputSchema = exports.recommendationResponseSchema = exports.recommendationItemSchema = exports.recommendationCountSchema = exports.recommendationRequestSchema = exports.recommendationSignalWeightsSchema = exports.recommendationBoostSchema = exports.recommendationExcludeTypeSchema = exports.fedcmTokenPayloadSchema = exports.sessionStatusSchema = exports.publicApplicationSchema = exports.applicationTypeSchema = exports.safeParseContract = exports.resolveUserId = exports.deviceSessionsResponseSchema = exports.deviceSessionAccountSchema = exports.currentUserResponseSchema = exports.refreshAllResponseSchema = exports.refreshAllAccountSchema = exports.userProfileUpdateSchema = exports.userResponseSchema = exports.userNameSchema = void 0;
14
+ exports.exportBundleSchema = exports.exportAttestationSchema = exports.authMethodsResponseSchema = exports.authMethodEntrySchema = exports.domainVerificationInstructionsSchema = exports.domainVerificationRequestSchema = exports.verifiedDomainSchema = exports.signedRecordEnvelopeSchema = exports.didDocumentSchema = exports.didServiceSchema = exports.verificationMethodSchema = exports.appUserSignalIngestSchema = exports.appInterestInputSchema = exports.appEndorsementInputSchema = exports.recommendationResponseSchema = exports.recommendationItemSchema = exports.recommendationCountSchema = exports.recommendationRequestSchema = exports.recommendationSignalWeightsSchema = exports.recommendationBoostSchema = exports.recommendationExcludeTypeSchema = exports.fedcmTokenPayloadSchema = exports.sessionStatusSchema = exports.publicApplicationSchema = exports.applicationTypeSchema = exports.safeParseContract = exports.resolveUserId = exports.deviceSessionsResponseSchema = exports.deviceSessionAccountSchema = exports.currentUserResponseSchema = exports.refreshAllResponseSchema = exports.refreshAllAccountSchema = exports.userProfileUpdateSchema = exports.userResponseSchema = exports.userNameSchema = void 0;
15
15
  var userResponse_1 = require("./userResponse");
16
16
  // Schemas
17
17
  Object.defineProperty(exports, "userNameSchema", { enumerable: true, get: function () { return userResponse_1.userNameSchema; } });
@@ -45,3 +45,16 @@ Object.defineProperty(exports, "recommendationResponseSchema", { enumerable: tru
45
45
  Object.defineProperty(exports, "appEndorsementInputSchema", { enumerable: true, get: function () { return recommendations_1.appEndorsementInputSchema; } });
46
46
  Object.defineProperty(exports, "appInterestInputSchema", { enumerable: true, get: function () { return recommendations_1.appInterestInputSchema; } });
47
47
  Object.defineProperty(exports, "appUserSignalIngestSchema", { enumerable: true, get: function () { return recommendations_1.appUserSignalIngestSchema; } });
48
+ var identity_1 = require("./identity");
49
+ // Schemas
50
+ Object.defineProperty(exports, "verificationMethodSchema", { enumerable: true, get: function () { return identity_1.verificationMethodSchema; } });
51
+ Object.defineProperty(exports, "didServiceSchema", { enumerable: true, get: function () { return identity_1.didServiceSchema; } });
52
+ Object.defineProperty(exports, "didDocumentSchema", { enumerable: true, get: function () { return identity_1.didDocumentSchema; } });
53
+ Object.defineProperty(exports, "signedRecordEnvelopeSchema", { enumerable: true, get: function () { return identity_1.signedRecordEnvelopeSchema; } });
54
+ Object.defineProperty(exports, "verifiedDomainSchema", { enumerable: true, get: function () { return identity_1.verifiedDomainSchema; } });
55
+ Object.defineProperty(exports, "domainVerificationRequestSchema", { enumerable: true, get: function () { return identity_1.domainVerificationRequestSchema; } });
56
+ Object.defineProperty(exports, "domainVerificationInstructionsSchema", { enumerable: true, get: function () { return identity_1.domainVerificationInstructionsSchema; } });
57
+ Object.defineProperty(exports, "authMethodEntrySchema", { enumerable: true, get: function () { return identity_1.authMethodEntrySchema; } });
58
+ Object.defineProperty(exports, "authMethodsResponseSchema", { enumerable: true, get: function () { return identity_1.authMethodsResponseSchema; } });
59
+ Object.defineProperty(exports, "exportAttestationSchema", { enumerable: true, get: function () { return identity_1.exportAttestationSchema; } });
60
+ Object.defineProperty(exports, "exportBundleSchema", { enumerable: true, get: function () { return identity_1.exportBundleSchema; } });
@@ -36,6 +36,7 @@ exports.deviceSessionsResponseSchema = exports.deviceSessionAccountSchema = expo
36
36
  exports.resolveUserId = resolveUserId;
37
37
  exports.safeParseContract = safeParseContract;
38
38
  const zod_1 = require("zod");
39
+ const identity_1 = require("./identity");
39
40
  exports.userNameSchema = zod_1.z
40
41
  .object({
41
42
  first: zod_1.z.string().optional(),
@@ -68,6 +69,9 @@ exports.userResponseSchema = zod_1.z
68
69
  publicKey: zod_1.z.string().optional(),
69
70
  username: zod_1.z.string().optional(),
70
71
  email: zod_1.z.string().optional(),
72
+ phone: zod_1.z.string().optional(),
73
+ address: zod_1.z.string().optional(),
74
+ birthday: zod_1.z.string().optional(),
71
75
  /** Avatar file id (string) or null. */
72
76
  avatar: zod_1.z.string().nullable().optional(),
73
77
  /** Named Bloom color preset (e.g. `"blue"`) or null. */
@@ -75,6 +79,17 @@ exports.userResponseSchema = zod_1.z
75
79
  name: exports.userNameSchema,
76
80
  verified: zod_1.z.boolean().optional(),
77
81
  language: zod_1.z.string().optional(),
82
+ /**
83
+ * The account's self-sovereign identifier
84
+ * (`did:web:<FEDERATION_DOMAIN>:u:<userId>`). Surfaced as a `User`
85
+ * virtual; present on formatted DTOs once the identity layer is live.
86
+ */
87
+ did: zod_1.z.string().optional(),
88
+ /**
89
+ * Proven domain-ownership badges. Each is a {@link verifiedDomainSchema}
90
+ * entry; present only when the account has verified at least one domain.
91
+ */
92
+ verifiedDomains: zod_1.z.array(identity_1.verifiedDomainSchema).optional(),
78
93
  })
79
94
  .passthrough();
80
95
  exports.userProfileUpdateSchema = zod_1.z
@@ -91,6 +106,9 @@ exports.userProfileUpdateSchema = zod_1.z
91
106
  color: zod_1.z.string().nullable().optional(),
92
107
  bio: zod_1.z.string().optional(),
93
108
  description: zod_1.z.string().optional(),
109
+ phone: zod_1.z.string().optional(),
110
+ address: zod_1.z.string().optional(),
111
+ birthday: zod_1.z.string().optional(),
94
112
  location: zod_1.z.string().optional(),
95
113
  locations: zod_1.z.array(zod_1.z.unknown()).optional(),
96
114
  links: zod_1.z.array(zod_1.z.string()).optional(),