@oxyhq/contracts 0.3.0 → 0.5.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,163 @@
1
+ "use strict";
2
+ /**
3
+ * Civic / Commons API contracts (Fase 1 — DNI + crypto-owned reputation).
4
+ *
5
+ * SINGLE SOURCE OF TRUTH for the wire shape of the public "DNI" card a Commons
6
+ * user shows (and others scan): the user's DID, display identity, trust tier,
7
+ * personhood status, verified domains, and credential badges — sealed with an
8
+ * Oxy custodial attestation so a scanner can verify it OFFLINE against the Oxy
9
+ * public key (the same `ES256K-DER-SHA256` scheme as the signed data export).
10
+ *
11
+ * The QR encodes ONLY the DID (`oxydni://card?did=…`) — never trust data — so a
12
+ * card cannot be spoofed by crafting a QR; the scanner resolves the signed card
13
+ * server-side and verifies the Oxy signature. The attestation is computed over
14
+ * the canonical-JSON of the `card` object, so a consumer re-canonicalizes the
15
+ * card it received and verifies `attestation.signature` against
16
+ * `attestation.publicKey` (which MUST be a current verification method of the
17
+ * Oxy DID).
18
+ *
19
+ * Explicit-`interface` exports (PublicCard, SignedPublicCard) follow the same
20
+ * node-resolution rationale as `UserNameResponse` / the identity contracts: a
21
+ * nested `z.infer<>` can degrade to `{}` under a consumer's
22
+ * `moduleResolution: "node"`, so the load-bearing shapes are declared as literal
23
+ * interfaces and the runtime schemas are annotated `z.ZodType<Interface>`.
24
+ *
25
+ * The `attestation` reuses the export-bundle `ExportAttestation` shape from
26
+ * `./identity` (mirrored, not duplicated): `{ issuer, publicKey, alg, signature,
27
+ * signedAt }`. It is `null` ONLY when the Oxy signing key is unconfigured (dev).
28
+ *
29
+ * Platform-agnostic — zod only, no react/react-native/expo, ESM-safe.
30
+ */
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.credentialVerifyResultSchema = exports.credentialListResultSchema = exports.credentialIssueResultSchema = exports.verifiableCredentialResponseSchema = exports.credentialRecordSchema = exports.vouchResultSchema = exports.personhoodStatusResultSchema = exports.personhoodBreakdownSchema = exports.personhoodVouchRecordSchema = exports.validationVoteResultSchema = exports.validationRequestSummarySchema = exports.validationOpenResultSchema = exports.validationOpenRequestSchema = exports.validationVerdictRecordSchema = exports.realLifeAttestationResultSchema = exports.realLifeAttestationRecordSchema = exports.signedPublicCardSchema = exports.publicCardSchema = void 0;
33
+ const zod_1 = require("zod");
34
+ const identity_1 = require("./identity");
35
+ exports.publicCardSchema = zod_1.z.object({
36
+ did: zod_1.z.string(),
37
+ userId: zod_1.z.string(),
38
+ name: zod_1.z.string(),
39
+ username: zod_1.z.string().optional(),
40
+ avatarUrl: zod_1.z.string().optional(),
41
+ trustTier: zod_1.z.enum(['restricted', 'new', 'trusted', 'high_trust', 'verified']),
42
+ personhoodStatus: zod_1.z.enum(['unverified', 'pending', 'verified']),
43
+ verifiedDomains: zod_1.z.array(zod_1.z.string()),
44
+ credentialBadges: zod_1.z.array(zod_1.z.string()),
45
+ issuedAt: zod_1.z.number(),
46
+ });
47
+ exports.signedPublicCardSchema = zod_1.z.object({
48
+ card: exports.publicCardSchema,
49
+ attestation: identity_1.exportAttestationSchema.nullable(),
50
+ });
51
+ exports.realLifeAttestationRecordSchema = zod_1.z.object({
52
+ about: zod_1.z.string(),
53
+ context: zod_1.z.string(),
54
+ nonce: zod_1.z.string(),
55
+ exp: zod_1.z.number(),
56
+ geohash: zod_1.z.string().optional(),
57
+ biometricOk: zod_1.z.boolean().optional(),
58
+ });
59
+ exports.realLifeAttestationResultSchema = zod_1.z.object({
60
+ accepted: zod_1.z.literal(true),
61
+ recordId: zod_1.z.string(),
62
+ subjectUserId: zod_1.z.string(),
63
+ attestorUserId: zod_1.z.string(),
64
+ points: zod_1.z.number(),
65
+ });
66
+ exports.validationVerdictRecordSchema = zod_1.z.object({
67
+ requestId: zod_1.z.string(),
68
+ payloadHash: zod_1.z.string(),
69
+ verdict: zod_1.z.enum(['valid', 'invalid', 'abstain']),
70
+ });
71
+ /** Request body for opening a validation request (`POST /civic/validations`). */
72
+ exports.validationOpenRequestSchema = zod_1.z.object({
73
+ subjectUserId: zod_1.z.string(),
74
+ actionType: zod_1.z.string().min(1),
75
+ sourceActionId: zod_1.z.string().min(1),
76
+ payload: zod_1.z.record(zod_1.z.unknown()),
77
+ highValue: zod_1.z.boolean().optional(),
78
+ });
79
+ exports.validationOpenResultSchema = zod_1.z.object({
80
+ requestId: zod_1.z.string(),
81
+ selectedValidatorCount: zod_1.z.number(),
82
+ expiresAt: zod_1.z.string(),
83
+ });
84
+ exports.validationRequestSummarySchema = zod_1.z.object({
85
+ id: zod_1.z.string(),
86
+ subjectUserId: zod_1.z.string(),
87
+ actionType: zod_1.z.string(),
88
+ payload: zod_1.z.record(zod_1.z.unknown()),
89
+ payloadHash: zod_1.z.string(),
90
+ status: zod_1.z.enum(['pending', 'quorum_met', 'validated', 'rejected', 'expired']),
91
+ highValue: zod_1.z.boolean(),
92
+ expiresAt: zod_1.z.string(),
93
+ });
94
+ exports.validationVoteResultSchema = zod_1.z.object({
95
+ recorded: zod_1.z.literal(true),
96
+ requestId: zod_1.z.string(),
97
+ verdict: zod_1.z.enum(['valid', 'invalid', 'abstain']),
98
+ status: zod_1.z.enum(['pending', 'quorum_met', 'validated', 'rejected', 'expired']),
99
+ });
100
+ exports.personhoodVouchRecordSchema = zod_1.z.object({
101
+ about: zod_1.z.string(),
102
+ context: zod_1.z.string().optional(),
103
+ stake: zod_1.z.number().optional(),
104
+ });
105
+ exports.personhoodBreakdownSchema = zod_1.z.object({
106
+ vouchSignal: zod_1.z.number(),
107
+ realLifeSignal: zod_1.z.number(),
108
+ biometricSignal: zod_1.z.number(),
109
+ evidence: zod_1.z.number(),
110
+ sybilPenalty: zod_1.z.number(),
111
+ seed: zod_1.z.boolean(),
112
+ });
113
+ exports.personhoodStatusResultSchema = zod_1.z.object({
114
+ userId: zod_1.z.string(),
115
+ score: zod_1.z.number(),
116
+ isRealPerson: zod_1.z.boolean(),
117
+ vouchCount: zod_1.z.number(),
118
+ realLifeCount: zod_1.z.number(),
119
+ biometricBound: zod_1.z.boolean(),
120
+ sybilPenalty: zod_1.z.number(),
121
+ breakdown: exports.personhoodBreakdownSchema.nullable(),
122
+ updatedAt: zod_1.z.string().nullable(),
123
+ });
124
+ exports.vouchResultSchema = zod_1.z.object({
125
+ accepted: zod_1.z.literal(true),
126
+ recordId: zod_1.z.string(),
127
+ subjectUserId: zod_1.z.string(),
128
+ voucherUserId: zod_1.z.string(),
129
+ stakeAmount: zod_1.z.number(),
130
+ points: zod_1.z.number(),
131
+ });
132
+ exports.credentialRecordSchema = zod_1.z.object({
133
+ about: zod_1.z.string(),
134
+ types: zod_1.z.array(zod_1.z.string().min(1)).min(1),
135
+ claims: zod_1.z.record(zod_1.z.unknown()),
136
+ expiresAt: zod_1.z.number().optional(),
137
+ });
138
+ exports.verifiableCredentialResponseSchema = zod_1.z.object({
139
+ id: zod_1.z.string(),
140
+ recordId: zod_1.z.string(),
141
+ holderUserId: zod_1.z.string(),
142
+ holderDid: zod_1.z.string(),
143
+ issuerUserId: zod_1.z.string().optional(),
144
+ issuerDid: zod_1.z.string(),
145
+ types: zod_1.z.array(zod_1.z.string()),
146
+ claims: zod_1.z.record(zod_1.z.unknown()),
147
+ status: zod_1.z.enum(['active', 'revoked', 'expired']),
148
+ issuedAt: zod_1.z.number(),
149
+ expiresAt: zod_1.z.number().optional(),
150
+ revokedAt: zod_1.z.number().optional(),
151
+ });
152
+ exports.credentialIssueResultSchema = zod_1.z.object({
153
+ accepted: zod_1.z.literal(true),
154
+ credential: exports.verifiableCredentialResponseSchema,
155
+ });
156
+ exports.credentialListResultSchema = zod_1.z.object({
157
+ credentials: zod_1.z.array(exports.verifiableCredentialResponseSchema),
158
+ });
159
+ exports.credentialVerifyResultSchema = zod_1.z.object({
160
+ valid: zod_1.z.boolean(),
161
+ reason: zod_1.z.string().optional(),
162
+ credential: exports.verifiableCredentialResponseSchema.nullable(),
163
+ });
@@ -62,16 +62,97 @@ exports.didDocumentSchema = zod_1.z.object({
62
62
  alsoKnownAs: zod_1.z.array(zod_1.z.string()),
63
63
  service: zod_1.z.array(exports.didServiceSchema),
64
64
  });
65
- exports.signedRecordEnvelopeSchema = zod_1.z.object({
66
- version: zod_1.z.literal(1),
67
- type: zod_1.z.enum(['identity', 'profile']),
65
+ exports.signedRecordEnvelopeSchema = zod_1.z
66
+ .object({
67
+ version: zod_1.z.union([zod_1.z.literal(1), zod_1.z.literal(2)]),
68
+ type: zod_1.z.enum([
69
+ 'identity',
70
+ 'profile',
71
+ 'reputation_attestation',
72
+ 'real_life_attestation',
73
+ 'validation_verdict',
74
+ 'personhood_vouch',
75
+ 'credential',
76
+ 'node',
77
+ ]),
68
78
  subject: zod_1.z.string(),
69
79
  issuer: zod_1.z.string(),
70
80
  record: zod_1.z.record(zod_1.z.unknown()),
71
81
  issuedAt: zod_1.z.number(),
82
+ seq: zod_1.z.number().int().nonnegative().optional(),
83
+ prev: zod_1.z.string().nullable().optional(),
84
+ collection: zod_1.z.string().min(1).optional(),
85
+ rkey: zod_1.z.string().min(1).optional(),
72
86
  publicKey: zod_1.z.string(),
73
87
  alg: zod_1.z.literal('ES256K-DER-SHA256'),
74
88
  signature: zod_1.z.string(),
89
+ })
90
+ .superRefine((env, ctx) => {
91
+ if (env.version === 2) {
92
+ // v2 REQUIRES the hash-chain fields. `prev` may be `null` at genesis,
93
+ // but the key must be present (it is part of the signed bytes), so we
94
+ // reject only when it is entirely absent.
95
+ if (typeof env.seq !== 'number') {
96
+ ctx.addIssue({
97
+ code: zod_1.z.ZodIssueCode.custom,
98
+ message: 'v2 envelope requires `seq`',
99
+ path: ['seq'],
100
+ });
101
+ }
102
+ if (env.prev === undefined) {
103
+ ctx.addIssue({
104
+ code: zod_1.z.ZodIssueCode.custom,
105
+ message: 'v2 envelope requires `prev` (use `null` at genesis)',
106
+ path: ['prev'],
107
+ });
108
+ }
109
+ if (typeof env.collection !== 'string') {
110
+ ctx.addIssue({
111
+ code: zod_1.z.ZodIssueCode.custom,
112
+ message: 'v2 envelope requires `collection`',
113
+ path: ['collection'],
114
+ });
115
+ }
116
+ if (typeof env.rkey !== 'string') {
117
+ ctx.addIssue({
118
+ code: zod_1.z.ZodIssueCode.custom,
119
+ message: 'v2 envelope requires `rkey`',
120
+ path: ['rkey'],
121
+ });
122
+ }
123
+ }
124
+ else {
125
+ // v1 FORBIDS the v2 chain fields entirely, so a legacy envelope keeps
126
+ // its exact byte shape and cannot smuggle unsigned chain metadata.
127
+ if (env.seq !== undefined) {
128
+ ctx.addIssue({
129
+ code: zod_1.z.ZodIssueCode.custom,
130
+ message: 'v1 envelope must not carry `seq`',
131
+ path: ['seq'],
132
+ });
133
+ }
134
+ if (env.prev !== undefined) {
135
+ ctx.addIssue({
136
+ code: zod_1.z.ZodIssueCode.custom,
137
+ message: 'v1 envelope must not carry `prev`',
138
+ path: ['prev'],
139
+ });
140
+ }
141
+ if (env.collection !== undefined) {
142
+ ctx.addIssue({
143
+ code: zod_1.z.ZodIssueCode.custom,
144
+ message: 'v1 envelope must not carry `collection`',
145
+ path: ['collection'],
146
+ });
147
+ }
148
+ if (env.rkey !== undefined) {
149
+ ctx.addIssue({
150
+ code: zod_1.z.ZodIssueCode.custom,
151
+ message: 'v1 envelope must not carry `rkey`',
152
+ path: ['rkey'],
153
+ });
154
+ }
155
+ }
75
156
  });
76
157
  exports.verifiedDomainSchema = zod_1.z.object({
77
158
  domain: zod_1.z.string(),
package/dist/cjs/index.js CHANGED
@@ -11,7 +11,8 @@
11
11
  * expo, no `require()` in the ESM build.
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
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;
14
+ exports.verifiableCredentialResponseSchema = exports.credentialRecordSchema = exports.vouchResultSchema = exports.personhoodStatusResultSchema = exports.personhoodBreakdownSchema = exports.personhoodVouchRecordSchema = exports.validationVoteResultSchema = exports.validationRequestSummarySchema = exports.validationOpenResultSchema = exports.validationOpenRequestSchema = exports.validationVerdictRecordSchema = exports.realLifeAttestationResultSchema = exports.realLifeAttestationRecordSchema = exports.signedPublicCardSchema = exports.publicCardSchema = 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
+ exports.linkPreviewResponseSchema = exports.linkPreviewBatchResponseSchema = exports.linkPreviewBatchRequestSchema = exports.linkPreviewSchema = exports.credentialVerifyResultSchema = exports.credentialListResultSchema = exports.credentialIssueResultSchema = void 0;
15
16
  var userResponse_1 = require("./userResponse");
16
17
  // Schemas
17
18
  Object.defineProperty(exports, "userNameSchema", { enumerable: true, get: function () { return userResponse_1.userNameSchema; } });
@@ -58,3 +59,30 @@ Object.defineProperty(exports, "authMethodEntrySchema", { enumerable: true, get:
58
59
  Object.defineProperty(exports, "authMethodsResponseSchema", { enumerable: true, get: function () { return identity_1.authMethodsResponseSchema; } });
59
60
  Object.defineProperty(exports, "exportAttestationSchema", { enumerable: true, get: function () { return identity_1.exportAttestationSchema; } });
60
61
  Object.defineProperty(exports, "exportBundleSchema", { enumerable: true, get: function () { return identity_1.exportBundleSchema; } });
62
+ var civic_1 = require("./civic");
63
+ // Schemas
64
+ Object.defineProperty(exports, "publicCardSchema", { enumerable: true, get: function () { return civic_1.publicCardSchema; } });
65
+ Object.defineProperty(exports, "signedPublicCardSchema", { enumerable: true, get: function () { return civic_1.signedPublicCardSchema; } });
66
+ Object.defineProperty(exports, "realLifeAttestationRecordSchema", { enumerable: true, get: function () { return civic_1.realLifeAttestationRecordSchema; } });
67
+ Object.defineProperty(exports, "realLifeAttestationResultSchema", { enumerable: true, get: function () { return civic_1.realLifeAttestationResultSchema; } });
68
+ Object.defineProperty(exports, "validationVerdictRecordSchema", { enumerable: true, get: function () { return civic_1.validationVerdictRecordSchema; } });
69
+ Object.defineProperty(exports, "validationOpenRequestSchema", { enumerable: true, get: function () { return civic_1.validationOpenRequestSchema; } });
70
+ Object.defineProperty(exports, "validationOpenResultSchema", { enumerable: true, get: function () { return civic_1.validationOpenResultSchema; } });
71
+ Object.defineProperty(exports, "validationRequestSummarySchema", { enumerable: true, get: function () { return civic_1.validationRequestSummarySchema; } });
72
+ Object.defineProperty(exports, "validationVoteResultSchema", { enumerable: true, get: function () { return civic_1.validationVoteResultSchema; } });
73
+ Object.defineProperty(exports, "personhoodVouchRecordSchema", { enumerable: true, get: function () { return civic_1.personhoodVouchRecordSchema; } });
74
+ Object.defineProperty(exports, "personhoodBreakdownSchema", { enumerable: true, get: function () { return civic_1.personhoodBreakdownSchema; } });
75
+ Object.defineProperty(exports, "personhoodStatusResultSchema", { enumerable: true, get: function () { return civic_1.personhoodStatusResultSchema; } });
76
+ Object.defineProperty(exports, "vouchResultSchema", { enumerable: true, get: function () { return civic_1.vouchResultSchema; } });
77
+ // Verifiable Credentials (Fase 4 — NEW)
78
+ Object.defineProperty(exports, "credentialRecordSchema", { enumerable: true, get: function () { return civic_1.credentialRecordSchema; } });
79
+ Object.defineProperty(exports, "verifiableCredentialResponseSchema", { enumerable: true, get: function () { return civic_1.verifiableCredentialResponseSchema; } });
80
+ Object.defineProperty(exports, "credentialIssueResultSchema", { enumerable: true, get: function () { return civic_1.credentialIssueResultSchema; } });
81
+ Object.defineProperty(exports, "credentialListResultSchema", { enumerable: true, get: function () { return civic_1.credentialListResultSchema; } });
82
+ Object.defineProperty(exports, "credentialVerifyResultSchema", { enumerable: true, get: function () { return civic_1.credentialVerifyResultSchema; } });
83
+ var links_1 = require("./links");
84
+ // Schemas
85
+ Object.defineProperty(exports, "linkPreviewSchema", { enumerable: true, get: function () { return links_1.linkPreviewSchema; } });
86
+ Object.defineProperty(exports, "linkPreviewBatchRequestSchema", { enumerable: true, get: function () { return links_1.linkPreviewBatchRequestSchema; } });
87
+ Object.defineProperty(exports, "linkPreviewBatchResponseSchema", { enumerable: true, get: function () { return links_1.linkPreviewBatchResponseSchema; } });
88
+ Object.defineProperty(exports, "linkPreviewResponseSchema", { enumerable: true, get: function () { return links_1.linkPreviewResponseSchema; } });
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ /**
3
+ * Link-preview / unfurl API contracts.
4
+ *
5
+ * SINGLE SOURCE OF TRUTH for the wire shape of Oxy's link-preview ("unfurl")
6
+ * resolution surface: the single `GET` lookup and the `POST` batch lookup that
7
+ * every app calls through the SDK so apps stop duplicating their own
8
+ * link-metadata fetching. The API validates its OUTPUT against these schemas;
9
+ * every consumer (`@oxyhq/core`'s link mixin and the apps that call it)
10
+ * validates its INPUT against the same definitions, so producer and consumers
11
+ * cannot drift.
12
+ *
13
+ * Design anchors:
14
+ * - Oxy owns resolution. The `image` (and `favicon`) URLs a preview carries are
15
+ * re-hosted on Oxy media (`cloud.oxy.so/<fileId>`), never raw remote URLs —
16
+ * apps render them directly with no per-app proxy.
17
+ * - Resolution is best-effort and asynchronous. A preview is `'resolved'` once
18
+ * metadata is materialised, `'pending'` while a first-seen URL is being
19
+ * fetched in the background, or `'empty'` when the target yielded no usable
20
+ * metadata. `resolvedAt` (ISO datetime) is present only once `'resolved'`.
21
+ * - The batch response is keyed by the REQUESTED url (the exact string the
22
+ * caller sent), not the canonical/final URL, so a caller can always look its
23
+ * own input back up; the canonical URL lives on `LinkPreview.url`.
24
+ *
25
+ * The `LinkPreview` / `LinkPreviewBatchResponse` exports are declared as explicit
26
+ * `interface`s (with their runtime schemas annotated `z.ZodType<Interface>`),
27
+ * following the same rationale as `UserNameResponse` in `./userResponse`: a
28
+ * `z.infer<>` of a nested-object schema can degrade to `{}` under a consumer's
29
+ * `moduleResolution: "node"` (node10) resolution. A literal interface emits the
30
+ * field types verbatim in the `.d.ts` and survives BOTH `node` and `bundler`
31
+ * resolution. The flat batch-request schema (no nested-object hazard) is inferred
32
+ * via `z.infer<>`.
33
+ *
34
+ * Platform-agnostic — zod only, no react/react-native/expo. ESM-safe (no
35
+ * `require()`).
36
+ */
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.linkPreviewResponseSchema = exports.linkPreviewBatchResponseSchema = exports.linkPreviewBatchRequestSchema = exports.linkPreviewSchema = void 0;
39
+ const zod_1 = require("zod");
40
+ exports.linkPreviewSchema = zod_1.z.object({
41
+ url: zod_1.z.string(),
42
+ status: zod_1.z.enum(['resolved', 'pending', 'empty']),
43
+ title: zod_1.z.string().optional(),
44
+ description: zod_1.z.string().optional(),
45
+ image: zod_1.z.string().optional(),
46
+ siteName: zod_1.z.string().optional(),
47
+ favicon: zod_1.z.string().optional(),
48
+ resolvedAt: zod_1.z.string().optional(),
49
+ });
50
+ /* -------------------------------------------------------------------------- */
51
+ /* Batch request / response */
52
+ /* -------------------------------------------------------------------------- */
53
+ /**
54
+ * Request body for the batch unfurl endpoint. Between 1 and 50 URLs per call;
55
+ * the server resolves each (returning a `'pending'` placeholder for any URL it
56
+ * has not seen before and is fetching in the background).
57
+ */
58
+ exports.linkPreviewBatchRequestSchema = zod_1.z.object({
59
+ urls: zod_1.z.array(zod_1.z.string().max(2048)).min(1).max(50),
60
+ });
61
+ exports.linkPreviewBatchResponseSchema = zod_1.z.object({
62
+ data: zod_1.z.record(zod_1.z.string(), exports.linkPreviewSchema),
63
+ });
64
+ /**
65
+ * Wire shape of the single-URL unfurl lookup (`GET`) — a bare
66
+ * {@link LinkPreview}.
67
+ */
68
+ exports.linkPreviewResponseSchema = exports.linkPreviewSchema;