@oxyhq/contracts 0.15.0 → 0.17.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/index.js CHANGED
@@ -11,9 +11,9 @@
11
11
  * expo, no `require()` in the ESM build.
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.validationVoteResultSchema = exports.validationRequestSummarySchema = exports.validationOpenResultSchema = exports.validationOpenRequestSchema = exports.validationVerdictRecordSchema = exports.realLifeAttestationResultSchema = exports.realLifeAttestationRecordSchema = exports.signedPublicCardSchema = exports.publicCardSchema = exports.logPageResponseSchema = exports.chainHeadResponseSchema = exports.oxySignedRecordTypeSchema = exports.exportBundleSchema = exports.exportAttestationSchema = exports.authMethodsResponseSchema = exports.authMethodEntrySchema = exports.domainVerificationInstructionsSchema = exports.domainVerificationRequestSchema = exports.verifiedDomainSchema = exports.signedRecordEnvelopeSchema = exports.didDocumentSchema = exports.didServiceSchema = exports.verificationMethodSchema = exports.appAffinityEventsIngestSchema = exports.appAffinityEventSchema = exports.appAffinityEventTypeSchema = exports.appUserSignalIngestSchema = exports.appInterestInputSchema = exports.appEndorsementInputSchema = exports.recommendationResponseSchema = exports.recommendationItemSchema = exports.recommendationCountSchema = exports.recommendationRequestSchema = exports.recommendationSignalWeightsSchema = exports.recommendationBoostSchema = exports.recommendationExcludeTypeSchema = exports.sessionStatusSchema = exports.publicApplicationSchema = exports.applicationTypeSchema = exports.safeParseContract = exports.resolveUserId = exports.deviceLinkedSessionsResponseSchema = exports.deviceLinkedSessionSchema = exports.currentUserResponseSchema = exports.userProfileUpdateSchema = exports.userResponseSchema = exports.userNameSchema = exports.createAccountRequestSchema = exports.organizationCategorySchema = exports.ORGANIZATION_CATEGORIES = void 0;
15
- exports.rollbackRequestSchema = exports.updateListResponseSchema = exports.channelListResponseSchema = exports.channelSchema = exports.rollbackToEmbeddedEntrySchema = exports.createUpdateResponseSchema = exports.updateSchema = exports.createUpdateRequestSchema = exports.updateAssetRefSchema = exports.assetCompleteResponseSchema = exports.assetCompleteResultItemSchema = exports.assetCompleteRequestSchema = exports.assetInitResponseSchema = exports.assetUploadTicketSchema = exports.assetInitRequestSchema = exports.assetInitItemSchema = exports.rolloutPercentSchema = exports.runtimeVersionSchema = exports.channelNameSchema = exports.sha256HexSchema = exports.updateAssetStatusSchema = exports.updateStatusSchema = exports.updatePlatformSchema = exports.loginResultSchema = exports.sessionAccountsChangedEventSchema = exports.sessionAccountsChangedReasonSchema = exports.SESSION_ACCOUNTS_CHANGED_EVENT = exports.deviceHubTicketRedeemResponseSchema = exports.deviceHubTicketRedeemRequestSchema = exports.deviceHubTicketIssueResponseSchema = exports.deviceHubTicketIssueRequestSchema = exports.deviceTokenMintResponseSchema = exports.deviceTokenMintRequestSchema = exports.deviceSessionSyncSchema = exports.activeTokenSchema = exports.deviceSessionStateSchema = exports.sessionAccountSchema = exports.linkPreviewResponseSchema = exports.linkPreviewBatchResponseSchema = exports.linkPreviewBatchRequestSchema = exports.linkPreviewSchema = exports.credentialVerifyResultSchema = exports.credentialListResultSchema = exports.credentialIssueResultSchema = exports.verifiableCredentialResponseSchema = exports.credentialRecordSchema = exports.vouchResultSchema = exports.personhoodStatusResultSchema = exports.personhoodBreakdownSchema = exports.personhoodVouchRecordSchema = void 0;
16
- exports.webauthnLoginVerifyRequestSchema = exports.webauthnRegisterVerifyRequestSchema = exports.webauthnLoginOptionsRequestSchema = exports.webauthnRegisterOptionsRequestSchema = exports.updateRolloutPatchSchema = exports.promoteRequestSchema = exports.rollbackToEmbeddedRequestSchema = void 0;
14
+ exports.validationOpenResultSchema = exports.validationOpenRequestSchema = exports.validationVerdictRecordSchema = exports.realLifeAttestationResultSchema = exports.realLifeAttestationRecordSchema = exports.signedPublicCardSchema = exports.publicCardSchema = exports.logPageResponseSchema = exports.chainHeadResponseSchema = exports.oxySignedRecordTypeSchema = exports.exportBundleSchema = exports.exportAttestationSchema = exports.authMethodsResponseSchema = exports.authMethodEntrySchema = exports.domainVerificationInstructionsSchema = exports.domainVerificationRequestSchema = exports.verifiedDomainSchema = exports.signedRecordEnvelopeSchema = exports.didDocumentSchema = exports.didServiceSchema = exports.verificationMethodSchema = exports.appAffinityEventsIngestSchema = exports.appAffinityEventSchema = exports.appAffinityEventTypeSchema = exports.appUserSignalIngestSchema = exports.appInterestInputSchema = exports.appEndorsementInputSchema = exports.recommendationResponseSchema = exports.recommendationItemSchema = exports.recommendationCountSchema = exports.recommendationRequestSchema = exports.recommendationSignalWeightsSchema = exports.recommendationBoostSchema = exports.recommendationExcludeTypeSchema = exports.sessionStatusSchema = exports.publicApplicationSchema = exports.applicationTypeSchema = exports.safeParseContract = exports.resolveUserId = exports.deviceLinkedSessionsResponseSchema = exports.deviceLinkedSessionSchema = exports.currentUserResponseSchema = exports.userProfileUpdateSchema = exports.userResponseSchema = exports.themePreferenceSchema = exports.userRelationshipSchema = exports.userNameSchema = exports.createAccountRequestSchema = exports.organizationCategorySchema = exports.ORGANIZATION_CATEGORIES = void 0;
15
+ exports.assetCompleteResponseSchema = exports.assetCompleteResultItemSchema = exports.assetCompleteRequestSchema = exports.assetInitResponseSchema = exports.assetUploadTicketSchema = exports.assetInitRequestSchema = exports.assetInitItemSchema = exports.rolloutPercentSchema = exports.runtimeVersionSchema = exports.channelNameSchema = exports.sha256HexSchema = exports.updateAssetStatusSchema = exports.updateStatusSchema = exports.updatePlatformSchema = exports.backupStatusResponseSchema = exports.backupUploadRequestSchema = exports.encryptedBackupEnvelopeSchema = exports.backupLookupIdSchema = exports.rotateKeyCompleteResponseSchema = exports.rotateKeyCompleteRequestSchema = exports.rotateKeyChallengeResponseSchema = exports.loginResultSchema = exports.sessionAccountsChangedEventSchema = exports.sessionAccountsChangedReasonSchema = exports.SESSION_ACCOUNTS_CHANGED_EVENT = exports.deviceHubTicketRedeemResponseSchema = exports.deviceHubTicketRedeemRequestSchema = exports.deviceHubTicketIssueResponseSchema = exports.deviceHubTicketIssueRequestSchema = exports.deviceTokenMintResponseSchema = exports.deviceTokenMintRequestSchema = exports.deviceSessionSyncSchema = exports.activeTokenSchema = exports.deviceSessionStateSchema = exports.sessionAccountSchema = exports.linkPreviewResponseSchema = exports.linkPreviewBatchResponseSchema = exports.linkPreviewBatchRequestSchema = exports.linkPreviewSchema = exports.credentialVerifyResultSchema = exports.credentialListResultSchema = exports.credentialIssueResultSchema = exports.verifiableCredentialResponseSchema = exports.credentialRecordSchema = exports.vouchResultSchema = exports.personhoodStatusResultSchema = exports.personhoodBreakdownSchema = exports.personhoodVouchRecordSchema = exports.validationVoteResultSchema = exports.validationRequestSummarySchema = void 0;
16
+ exports.webauthnLoginVerifyRequestSchema = exports.webauthnRegisterVerifyRequestSchema = exports.webauthnLoginOptionsRequestSchema = exports.webauthnRegisterOptionsRequestSchema = exports.updateRolloutPatchSchema = exports.promoteRequestSchema = exports.rollbackToEmbeddedRequestSchema = exports.rollbackRequestSchema = exports.updateListResponseSchema = exports.channelListResponseSchema = exports.channelSchema = exports.rollbackToEmbeddedEntrySchema = exports.createUpdateResponseSchema = exports.updateSchema = exports.createUpdateRequestSchema = exports.updateAssetRefSchema = void 0;
17
17
  var accountGraph_1 = require("./accountGraph");
18
18
  Object.defineProperty(exports, "ORGANIZATION_CATEGORIES", { enumerable: true, get: function () { return accountGraph_1.ORGANIZATION_CATEGORIES; } });
19
19
  Object.defineProperty(exports, "organizationCategorySchema", { enumerable: true, get: function () { return accountGraph_1.organizationCategorySchema; } });
@@ -21,6 +21,8 @@ Object.defineProperty(exports, "createAccountRequestSchema", { enumerable: true,
21
21
  var userResponse_1 = require("./userResponse");
22
22
  // Schemas
23
23
  Object.defineProperty(exports, "userNameSchema", { enumerable: true, get: function () { return userResponse_1.userNameSchema; } });
24
+ Object.defineProperty(exports, "userRelationshipSchema", { enumerable: true, get: function () { return userResponse_1.userRelationshipSchema; } });
25
+ Object.defineProperty(exports, "themePreferenceSchema", { enumerable: true, get: function () { return userResponse_1.themePreferenceSchema; } });
24
26
  Object.defineProperty(exports, "userResponseSchema", { enumerable: true, get: function () { return userResponse_1.userResponseSchema; } });
25
27
  Object.defineProperty(exports, "userProfileUpdateSchema", { enumerable: true, get: function () { return userResponse_1.userProfileUpdateSchema; } });
26
28
  Object.defineProperty(exports, "currentUserResponseSchema", { enumerable: true, get: function () { return userResponse_1.currentUserResponseSchema; } });
@@ -113,6 +115,17 @@ Object.defineProperty(exports, "sessionAccountsChangedEventSchema", { enumerable
113
115
  var deviceBoot_1 = require("./deviceBoot");
114
116
  // Schemas
115
117
  Object.defineProperty(exports, "loginResultSchema", { enumerable: true, get: function () { return deviceBoot_1.loginResultSchema; } });
118
+ var keyRotation_1 = require("./keyRotation");
119
+ // Schemas
120
+ Object.defineProperty(exports, "rotateKeyChallengeResponseSchema", { enumerable: true, get: function () { return keyRotation_1.rotateKeyChallengeResponseSchema; } });
121
+ Object.defineProperty(exports, "rotateKeyCompleteRequestSchema", { enumerable: true, get: function () { return keyRotation_1.rotateKeyCompleteRequestSchema; } });
122
+ Object.defineProperty(exports, "rotateKeyCompleteResponseSchema", { enumerable: true, get: function () { return keyRotation_1.rotateKeyCompleteResponseSchema; } });
123
+ var keyRecovery_1 = require("./keyRecovery");
124
+ // Schemas — encrypted off-device identity backup (b3 Feature 1)
125
+ Object.defineProperty(exports, "backupLookupIdSchema", { enumerable: true, get: function () { return keyRecovery_1.backupLookupIdSchema; } });
126
+ Object.defineProperty(exports, "encryptedBackupEnvelopeSchema", { enumerable: true, get: function () { return keyRecovery_1.encryptedBackupEnvelopeSchema; } });
127
+ Object.defineProperty(exports, "backupUploadRequestSchema", { enumerable: true, get: function () { return keyRecovery_1.backupUploadRequestSchema; } });
128
+ Object.defineProperty(exports, "backupStatusResponseSchema", { enumerable: true, get: function () { return keyRecovery_1.backupStatusResponseSchema; } });
116
129
  var updates_1 = require("./updates");
117
130
  // Shared primitives
118
131
  Object.defineProperty(exports, "updatePlatformSchema", { enumerable: true, get: function () { return updates_1.updatePlatformSchema; } });
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.backupStatusResponseSchema = exports.backupUploadRequestSchema = exports.encryptedBackupEnvelopeSchema = exports.backupLookupIdSchema = void 0;
4
+ /**
5
+ * Encrypted off-device identity backup contract (b3 Feature 1).
6
+ *
7
+ * SINGLE SOURCE OF TRUTH for the "encrypted identity backup" flow, where a
8
+ * client stores an encrypted copy of its self-custody identity key off-device so
9
+ * a lost/wiped device can be recovered from the recovery phrase ALONE — without
10
+ * the platform ever seeing the phrase, the derived encryption key, or the
11
+ * plaintext private key.
12
+ *
13
+ * Zero-knowledge design (mirrors the zero-cookie `DeviceSession.secretHash`
14
+ * pattern): the client derives, from the FULL 64-byte BIP-39 seed, both an
15
+ * encryption key (`backupKey`) and a locator (`lookupId`) via HKDF with
16
+ * domain-separated `info` labels. It uploads ONLY the XChaCha20-Poly1305
17
+ * ciphertext plus the raw `lookupId`; the server stores the ciphertext and
18
+ * `sha256(lookupId)` (never the raw `lookupId`). Restoration re-derives both
19
+ * from the phrase, fetches the envelope by `lookupId`, and decrypts locally.
20
+ *
21
+ * The server can neither locate a backup (it lacks the seed to compute the
22
+ * lookup id) nor decrypt one (it lacks the seed to compute the backup key) — a
23
+ * DB dump yields only opaque ciphertext keyed by an un-invertible hash.
24
+ *
25
+ * The producer (`@oxyhq/api`) validates its request/response against these
26
+ * schemas; the consumer (`@oxyhq/core` identity-backup mixin) validates its
27
+ * input against the same definitions, so the wire shape cannot drift.
28
+ *
29
+ * All shapes here are FLAT (no nested objects), so `z.infer<>` is safe under a
30
+ * consumer's node10 `moduleResolution`. Platform-agnostic — zod only, ESM-safe
31
+ * (no `require()`).
32
+ */
33
+ const zod_1 = require("zod");
34
+ /** 256-bit backup locator (32 bytes), lowercase/uppercase hex. */
35
+ exports.backupLookupIdSchema = zod_1.z
36
+ .string()
37
+ .trim()
38
+ .regex(/^[0-9a-fA-F]{64}$/, 'lookupId must be 64 hex characters');
39
+ /**
40
+ * The stored, self-describing encrypted backup as it lives at rest and travels
41
+ * on the public restore endpoint. Contains NO secret and NO locator: the
42
+ * `lookupId` is uploaded separately (see {@link backupUploadRequestSchema}) and
43
+ * only its hash is ever persisted.
44
+ *
45
+ * - `version` — envelope/KDF version, so a future scheme migration is
46
+ * distinguishable at rest.
47
+ * - `algorithm` — the AEAD used. Pinned literal so a mismatched decryptor
48
+ * fails loudly rather than silently.
49
+ * - `kdfInfo` — the HKDF `info` label used to derive the encryption key
50
+ * (domain-separation tag; documents exactly which context produced the key).
51
+ * - `nonce` — the 24-byte XChaCha20-Poly1305 nonce, hex.
52
+ * - `ciphertext` — the encrypted `{privateKey, publicKey, createdAt}` payload
53
+ * with the appended Poly1305 tag, hex.
54
+ * - `publicKeyHint` — a short, non-sensitive prefix of the backed-up identity's
55
+ * public key, so the owner can recognise WHICH identity a backup belongs to
56
+ * without exposing the full key. Bound into the AEAD associated data.
57
+ * - `createdAt` — ISO-8601 creation timestamp.
58
+ */
59
+ exports.encryptedBackupEnvelopeSchema = zod_1.z.object({
60
+ version: zod_1.z.number().int().positive(),
61
+ algorithm: zod_1.z.literal('xchacha20poly1305'),
62
+ kdfInfo: zod_1.z.string().min(1),
63
+ nonce: zod_1.z.string().trim().min(1),
64
+ ciphertext: zod_1.z.string().trim().min(1),
65
+ publicKeyHint: zod_1.z.string().trim().min(1),
66
+ createdAt: zod_1.z.string().trim().min(1),
67
+ });
68
+ /**
69
+ * Request body of `POST /identity/backup` — the envelope PLUS the raw
70
+ * `lookupId`. The server sha256-hashes `lookupId` before storing it (it never
71
+ * persists the raw value), and upserts by the authenticated user id so a
72
+ * re-upload REPLACES the prior backup rather than accumulating duplicates.
73
+ */
74
+ exports.backupUploadRequestSchema = exports.encryptedBackupEnvelopeSchema.extend({
75
+ /**
76
+ * The raw 256-bit backup locator (hex), derived client-side from the seed
77
+ * with a domain-separated HKDF `info`. The server stores ONLY its sha256; a
78
+ * DB dump therefore cannot recompute a locator to enumerate backups.
79
+ */
80
+ lookupId: exports.backupLookupIdSchema,
81
+ });
82
+ /**
83
+ * Response of `GET /identity/backup/status` (and the write/delete acks): whether
84
+ * the authenticated user has a stored backup, plus the non-sensitive hint +
85
+ * timestamp when one exists. Carries no ciphertext and no locator.
86
+ */
87
+ exports.backupStatusResponseSchema = zod_1.z.object({
88
+ exists: zod_1.z.boolean(),
89
+ publicKeyHint: zod_1.z.string().optional(),
90
+ createdAt: zod_1.z.string().optional(),
91
+ });
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.rotateKeyCompleteResponseSchema = exports.rotateKeyCompleteRequestSchema = exports.rotateKeyChallengeResponseSchema = void 0;
4
+ /**
5
+ * Key-rotation contract (b3 Feature 3 — key rotation + last-credential replacement).
6
+ *
7
+ * SINGLE SOURCE OF TRUTH for the atomic key-rotation flow:
8
+ * - `POST /auth/rotate/challenge` — mint a single-use `rotate_key` challenge.
9
+ * - `POST /auth/rotate/complete` — prove control of the CURRENT (old) key and
10
+ * atomically swap in the new one.
11
+ *
12
+ * Rotation is an atomic REPLACE of the single identity key, never a
13
+ * remove-then-add, so it never passes through a zero-auth-method state and is
14
+ * independent of the unlink guards. Because the client proves possession of the
15
+ * current key (from SecureStore OR a recovery-phrase re-derivation), the LAST
16
+ * remaining credential can be replaced — the server only cares that the
17
+ * signature validates against the current `publicKey`.
18
+ *
19
+ * The API validates its output against these schemas; `@oxyhq/core`'s identity
20
+ * mixin validates its input against the same definitions, so producer and
21
+ * consumer cannot drift.
22
+ *
23
+ * All shapes here are FLAT (no nested objects), so `z.infer<>` is safe under a
24
+ * consumer's node10 `moduleResolution` — no interface-pinning needed.
25
+ *
26
+ * Platform-agnostic — zod only, ESM-safe (no `require()`).
27
+ */
28
+ const zod_1 = require("zod");
29
+ /**
30
+ * Response of `POST /auth/rotate/challenge`: the single-use `rotate_key`
31
+ * challenge the client must sign with its CURRENT key, plus its expiry.
32
+ */
33
+ exports.rotateKeyChallengeResponseSchema = zod_1.z.object({
34
+ challenge: zod_1.z.string(),
35
+ /** ISO-8601 expiry timestamp. */
36
+ expiresAt: zod_1.z.string(),
37
+ });
38
+ /**
39
+ * Request body of `POST /auth/rotate/complete`.
40
+ *
41
+ * Two proofs are required:
42
+ * - `signature` — the CURRENT (old) key signs
43
+ * `JSON.stringify({ action: 'rotate_key', userId, oldPublicKey, newPublicKey,
44
+ * challenge, timestamp })` (proves control of the key being replaced).
45
+ * - `newKeyProof` — the NEW key signs
46
+ * `JSON.stringify({ action: 'rotate_key_new', userId, newPublicKey, challenge,
47
+ * timestamp })` (proof-of-possession of the key being rotated IN; prevents an
48
+ * attacker rotating their account to a re-encoding of someone else's key they
49
+ * do not control).
50
+ *
51
+ * The request carries ONLY `newPublicKey` — `oldPublicKey` and `userId` are
52
+ * derived server-side from the authenticated user document (never
53
+ * client-supplied), so a caller cannot prove control of key X while rotating
54
+ * key Y.
55
+ */
56
+ exports.rotateKeyCompleteRequestSchema = zod_1.z.object({
57
+ newPublicKey: zod_1.z.string().trim().min(1),
58
+ challenge: zod_1.z.string().trim().min(1),
59
+ signature: zod_1.z.string().trim().min(1),
60
+ /** Proof-of-possession: the NEW key signs the rotate_key_new payload. */
61
+ newKeyProof: zod_1.z.string().trim().min(1),
62
+ timestamp: zod_1.z.number(),
63
+ /**
64
+ * When true, all OTHER active sessions for the account are revoked after a
65
+ * successful rotation (the rotating device stays signed in). Use it when the
66
+ * old key is presumed compromised.
67
+ */
68
+ signOutEverywhere: zod_1.z.boolean().optional(),
69
+ });
70
+ /** Response of `POST /auth/rotate/complete`: the account's new (rotated) public key. */
71
+ exports.rotateKeyCompleteResponseSchema = zod_1.z.object({
72
+ success: zod_1.z.boolean(),
73
+ publicKey: zod_1.z.string(),
74
+ message: zod_1.z.string(),
75
+ });
@@ -30,7 +30,7 @@
30
30
  * `require()`).
31
31
  */
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.deviceLinkedSessionsResponseSchema = exports.deviceLinkedSessionSchema = exports.currentUserResponseSchema = exports.userProfileUpdateSchema = exports.userResponseSchema = exports.userNameSchema = void 0;
33
+ exports.deviceLinkedSessionsResponseSchema = exports.deviceLinkedSessionSchema = exports.currentUserResponseSchema = exports.userProfileUpdateSchema = exports.userResponseSchema = exports.themePreferenceSchema = exports.userRelationshipSchema = exports.userNameSchema = void 0;
34
34
  exports.resolveUserId = resolveUserId;
35
35
  exports.safeParseContract = safeParseContract;
36
36
  const zod_1 = require("zod");
@@ -44,6 +44,14 @@ exports.userNameSchema = zod_1.z
44
44
  displayName: zod_1.z.string().optional(),
45
45
  })
46
46
  .passthrough();
47
+ exports.userRelationshipSchema = zod_1.z.object({
48
+ isFollowing: zod_1.z.boolean(),
49
+ followsYou: zod_1.z.boolean(),
50
+ });
51
+ exports.themePreferenceSchema = zod_1.z.object({
52
+ mode: zod_1.z.enum(['light', 'dark', 'system']),
53
+ colorPreset: zod_1.z.string(),
54
+ });
47
55
  /**
48
56
  * The canonical user object emitted by `formatUserResponse`.
49
57
  *
@@ -102,6 +110,19 @@ exports.userResponseSchema = zod_1.z
102
110
  * Absent on personal, project, and bot accounts.
103
111
  */
104
112
  organizationCategory: accountGraph_1.organizationCategorySchema.optional(),
113
+ /**
114
+ * The authenticated viewer's relationship to this profile. Present ONLY
115
+ * on single-profile fetches (`GET /profiles/username/:username`,
116
+ * `GET /users/:userId`) when the request is authenticated; OMITTED for
117
+ * anonymous requests and for the bulk `POST /users/by-ids` fan-out.
118
+ */
119
+ relationship: exports.userRelationshipSchema.optional(),
120
+ /**
121
+ * Portable theme preference. Rides the self/session payload (cold boot),
122
+ * so it is present on the current-user DTO (`GET /users/me`,
123
+ * `GET /session/user/:sessionId`) and absent until the user sets it.
124
+ */
125
+ themePreference: exports.themePreferenceSchema.optional(),
105
126
  })
106
127
  .passthrough();
107
128
  exports.userProfileUpdateSchema = zod_1.z
@@ -142,6 +163,11 @@ exports.userProfileUpdateSchema = zod_1.z
142
163
  notificationPreferences: zod_1.z.record(zod_1.z.unknown()).optional(),
143
164
  userPreferences: zod_1.z.record(zod_1.z.unknown()).optional(),
144
165
  privacySettings: zod_1.z.record(zod_1.z.unknown()).optional(),
166
+ /**
167
+ * Portable theme preference. Written through the same `PUT /users/me`
168
+ * settings-update path as `languages`/`userPreferences`.
169
+ */
170
+ themePreference: exports.themePreferenceSchema.optional(),
145
171
  })
146
172
  .passthrough();
147
173
  /**