@oxyhq/contracts 0.14.0 → 0.14.2

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.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deviceHubTicketRedeemResponseSchema = exports.deviceHubTicketRedeemRequestSchema = exports.deviceHubTicketIssueResponseSchema = exports.deviceHubTicketIssueRequestSchema = exports.deviceTokenMintResponseSchema = exports.deviceTokenMintRequestSchema = exports.deviceSessionSyncSchema = exports.activeTokenSchema = exports.deviceSessionStateSchema = exports.sessionAccountSchema = void 0;
3
+ 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 = void 0;
4
4
  const zod_1 = require("zod");
5
5
  exports.sessionAccountSchema = zod_1.z.object({
6
6
  accountId: zod_1.z.string(),
@@ -72,3 +72,44 @@ exports.deviceHubTicketRedeemResponseSchema = zod_1.z.object({
72
72
  deviceId: zod_1.z.string().min(1),
73
73
  deviceSecret: zod_1.z.string().min(1),
74
74
  });
75
+ /* -------------------------------------------------------------------------- */
76
+ /* Instant cross-app session sync (token-free socket signal) */
77
+ /* -------------------------------------------------------------------------- */
78
+ /**
79
+ * Name of the token-free Socket.IO event emitted to room `user:<userId>` on
80
+ * every DeviceSession mutation that changes what is signed in for that user.
81
+ *
82
+ * This is a pure SIGNAL — it carries NO access token, NO deviceSecret and NO
83
+ * account bodies. A client that receives it re-fetches its authenticated
84
+ * session/account state (`GET /session/device/state`, `GET /accounts`). Unlike
85
+ * `session_state` (scoped to `device:<deviceId>`, i.e. a single origin), this
86
+ * reaches ALL of a user's connected sockets across their devices/origins so
87
+ * every Oxy app reflects an add / switch / signout instantly.
88
+ */
89
+ exports.SESSION_ACCOUNTS_CHANGED_EVENT = 'session_accounts_changed';
90
+ /**
91
+ * Why the signed-in set changed:
92
+ * - `login` — a brand-new session was minted for the user (QR / cross-app authorize)
93
+ * - `add` — an account was registered onto a device set
94
+ * - `switch` — the active account on a device changed
95
+ * - `signout` — one or all accounts were signed out of a device
96
+ * - `revoke` — a dead/revoked account was healed out of a device set
97
+ */
98
+ exports.sessionAccountsChangedReasonSchema = zod_1.z.enum([
99
+ 'login',
100
+ 'add',
101
+ 'switch',
102
+ 'signout',
103
+ 'revoke',
104
+ ]);
105
+ /**
106
+ * Payload of {@link SESSION_ACCOUNTS_CHANGED_EVENT}. `revision` is the mutated
107
+ * DeviceSession revision for device-scoped reasons (`add`/`switch`/`signout`/
108
+ * `revoke`); for `login` (no device mutation at emit time) it is `0`. The
109
+ * payload is deliberately minimal and secret-free — the client refetches.
110
+ */
111
+ exports.sessionAccountsChangedEventSchema = zod_1.z.object({
112
+ userId: zod_1.z.string(),
113
+ revision: zod_1.z.number().int().nonnegative(),
114
+ reason: exports.sessionAccountsChangedReasonSchema,
115
+ });
@@ -190,9 +190,11 @@ exports.domainVerificationInstructionsSchema = zod_1.z.object({
190
190
  }),
191
191
  });
192
192
  exports.authMethodEntrySchema = zod_1.z.object({
193
- type: zod_1.z.enum(['identity', 'password', 'google', 'apple', 'github']),
193
+ type: zod_1.z.enum(['identity', 'password', 'google', 'apple', 'github', 'webauthn']),
194
194
  linkedAt: zod_1.z.union([zod_1.z.string(), zod_1.z.date()]),
195
195
  verificationMethodId: zod_1.z.string().optional(),
196
+ credentialId: zod_1.z.string().optional(),
197
+ name: zod_1.z.string().optional(),
196
198
  });
197
199
  exports.authMethodsResponseSchema = zod_1.z.object({
198
200
  did: zod_1.z.string(),
package/dist/cjs/index.js CHANGED
@@ -12,7 +12,8 @@
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
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.loginResultSchema = 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;
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;
16
17
  var accountGraph_1 = require("./accountGraph");
17
18
  Object.defineProperty(exports, "ORGANIZATION_CATEGORIES", { enumerable: true, get: function () { return accountGraph_1.ORGANIZATION_CATEGORIES; } });
18
19
  Object.defineProperty(exports, "organizationCategorySchema", { enumerable: true, get: function () { return accountGraph_1.organizationCategorySchema; } });
@@ -106,6 +107,47 @@ Object.defineProperty(exports, "deviceHubTicketIssueRequestSchema", { enumerable
106
107
  Object.defineProperty(exports, "deviceHubTicketIssueResponseSchema", { enumerable: true, get: function () { return deviceSession_1.deviceHubTicketIssueResponseSchema; } });
107
108
  Object.defineProperty(exports, "deviceHubTicketRedeemRequestSchema", { enumerable: true, get: function () { return deviceSession_1.deviceHubTicketRedeemRequestSchema; } });
108
109
  Object.defineProperty(exports, "deviceHubTicketRedeemResponseSchema", { enumerable: true, get: function () { return deviceSession_1.deviceHubTicketRedeemResponseSchema; } });
110
+ Object.defineProperty(exports, "SESSION_ACCOUNTS_CHANGED_EVENT", { enumerable: true, get: function () { return deviceSession_1.SESSION_ACCOUNTS_CHANGED_EVENT; } });
111
+ Object.defineProperty(exports, "sessionAccountsChangedReasonSchema", { enumerable: true, get: function () { return deviceSession_1.sessionAccountsChangedReasonSchema; } });
112
+ Object.defineProperty(exports, "sessionAccountsChangedEventSchema", { enumerable: true, get: function () { return deviceSession_1.sessionAccountsChangedEventSchema; } });
109
113
  var deviceBoot_1 = require("./deviceBoot");
110
114
  // Schemas
111
115
  Object.defineProperty(exports, "loginResultSchema", { enumerable: true, get: function () { return deviceBoot_1.loginResultSchema; } });
116
+ var updates_1 = require("./updates");
117
+ // Shared primitives
118
+ Object.defineProperty(exports, "updatePlatformSchema", { enumerable: true, get: function () { return updates_1.updatePlatformSchema; } });
119
+ Object.defineProperty(exports, "updateStatusSchema", { enumerable: true, get: function () { return updates_1.updateStatusSchema; } });
120
+ Object.defineProperty(exports, "updateAssetStatusSchema", { enumerable: true, get: function () { return updates_1.updateAssetStatusSchema; } });
121
+ Object.defineProperty(exports, "sha256HexSchema", { enumerable: true, get: function () { return updates_1.sha256HexSchema; } });
122
+ Object.defineProperty(exports, "channelNameSchema", { enumerable: true, get: function () { return updates_1.channelNameSchema; } });
123
+ Object.defineProperty(exports, "runtimeVersionSchema", { enumerable: true, get: function () { return updates_1.runtimeVersionSchema; } });
124
+ Object.defineProperty(exports, "rolloutPercentSchema", { enumerable: true, get: function () { return updates_1.rolloutPercentSchema; } });
125
+ // Assets: init + complete
126
+ Object.defineProperty(exports, "assetInitItemSchema", { enumerable: true, get: function () { return updates_1.assetInitItemSchema; } });
127
+ Object.defineProperty(exports, "assetInitRequestSchema", { enumerable: true, get: function () { return updates_1.assetInitRequestSchema; } });
128
+ Object.defineProperty(exports, "assetUploadTicketSchema", { enumerable: true, get: function () { return updates_1.assetUploadTicketSchema; } });
129
+ Object.defineProperty(exports, "assetInitResponseSchema", { enumerable: true, get: function () { return updates_1.assetInitResponseSchema; } });
130
+ Object.defineProperty(exports, "assetCompleteRequestSchema", { enumerable: true, get: function () { return updates_1.assetCompleteRequestSchema; } });
131
+ Object.defineProperty(exports, "assetCompleteResultItemSchema", { enumerable: true, get: function () { return updates_1.assetCompleteResultItemSchema; } });
132
+ Object.defineProperty(exports, "assetCompleteResponseSchema", { enumerable: true, get: function () { return updates_1.assetCompleteResponseSchema; } });
133
+ // Create update
134
+ Object.defineProperty(exports, "updateAssetRefSchema", { enumerable: true, get: function () { return updates_1.updateAssetRefSchema; } });
135
+ Object.defineProperty(exports, "createUpdateRequestSchema", { enumerable: true, get: function () { return updates_1.createUpdateRequestSchema; } });
136
+ // Read models
137
+ Object.defineProperty(exports, "updateSchema", { enumerable: true, get: function () { return updates_1.updateSchema; } });
138
+ Object.defineProperty(exports, "createUpdateResponseSchema", { enumerable: true, get: function () { return updates_1.createUpdateResponseSchema; } });
139
+ Object.defineProperty(exports, "rollbackToEmbeddedEntrySchema", { enumerable: true, get: function () { return updates_1.rollbackToEmbeddedEntrySchema; } });
140
+ Object.defineProperty(exports, "channelSchema", { enumerable: true, get: function () { return updates_1.channelSchema; } });
141
+ Object.defineProperty(exports, "channelListResponseSchema", { enumerable: true, get: function () { return updates_1.channelListResponseSchema; } });
142
+ Object.defineProperty(exports, "updateListResponseSchema", { enumerable: true, get: function () { return updates_1.updateListResponseSchema; } });
143
+ // Rollback / promote / rollout
144
+ Object.defineProperty(exports, "rollbackRequestSchema", { enumerable: true, get: function () { return updates_1.rollbackRequestSchema; } });
145
+ Object.defineProperty(exports, "rollbackToEmbeddedRequestSchema", { enumerable: true, get: function () { return updates_1.rollbackToEmbeddedRequestSchema; } });
146
+ Object.defineProperty(exports, "promoteRequestSchema", { enumerable: true, get: function () { return updates_1.promoteRequestSchema; } });
147
+ Object.defineProperty(exports, "updateRolloutPatchSchema", { enumerable: true, get: function () { return updates_1.updateRolloutPatchSchema; } });
148
+ var webauthn_1 = require("./webauthn");
149
+ // Schemas
150
+ Object.defineProperty(exports, "webauthnRegisterOptionsRequestSchema", { enumerable: true, get: function () { return webauthn_1.webauthnRegisterOptionsRequestSchema; } });
151
+ Object.defineProperty(exports, "webauthnLoginOptionsRequestSchema", { enumerable: true, get: function () { return webauthn_1.webauthnLoginOptionsRequestSchema; } });
152
+ Object.defineProperty(exports, "webauthnRegisterVerifyRequestSchema", { enumerable: true, get: function () { return webauthn_1.webauthnRegisterVerifyRequestSchema; } });
153
+ Object.defineProperty(exports, "webauthnLoginVerifyRequestSchema", { enumerable: true, get: function () { return webauthn_1.webauthnLoginVerifyRequestSchema; } });
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ /**
3
+ * Oxy Updates (self-hosted expo-updates protocol) — publish/admin API contracts.
4
+ *
5
+ * SINGLE SOURCE OF TRUTH for the wire shape of the AUTHENTICATED publish/admin
6
+ * surface that the `oxy-ship` CLI and the console Updates tab call. The PUBLIC
7
+ * manifest endpoint (`GET /updates/v1/apps/:clientId/manifest`) speaks the
8
+ * expo-updates v1 protocol verbatim (multipart/mixed, signed) and is therefore
9
+ * NOT modelled here — its shape is dictated by the Expo spec, not by us.
10
+ *
11
+ * The API validates its OUTPUT against these schemas; every consumer (the ship
12
+ * CLI, the console hook) validates its INPUT against the same definitions, so
13
+ * producer and consumers cannot drift.
14
+ *
15
+ * Domain model (mirrors the Mongoose models in `@oxyhq/api`):
16
+ * - A `channel` (e.g. `production`, `preview`, `pr-123`) is a named release
17
+ * track for one application.
18
+ * - An `update` is one published bundle for a single `(channel, runtimeVersion,
19
+ * platform)`. Its `updateId` is a UUIDv4 (the client parses it as a UUID).
20
+ * The HEAD of a track is the newest `published` update for that tuple.
21
+ * - An `asset` is content-addressed by its `sha256`; assets are shared across
22
+ * updates and applications (an unchanged JS bundle is uploaded once).
23
+ *
24
+ * Platform-agnostic — zod only, no react/react-native/expo. ESM-safe (no
25
+ * `require()`).
26
+ */
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.updateRolloutPatchSchema = exports.promoteRequestSchema = exports.rollbackToEmbeddedRequestSchema = 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 = void 0;
29
+ const zod_1 = require("zod");
30
+ /* -------------------------------------------------------------------------- */
31
+ /* Shared primitives */
32
+ /* -------------------------------------------------------------------------- */
33
+ /** The two platforms the expo-updates protocol addresses. */
34
+ exports.updatePlatformSchema = zod_1.z.enum(['ios', 'android']);
35
+ /** Lifecycle of a single published update row. */
36
+ exports.updateStatusSchema = zod_1.z.enum(['published', 'superseded', 'rolled_back']);
37
+ /** Upload lifecycle of a content-addressed asset. */
38
+ exports.updateAssetStatusSchema = zod_1.z.enum(['pending', 'uploaded']);
39
+ /** Lowercase-hex SHA-256 content hash (64 hex chars). */
40
+ exports.sha256HexSchema = zod_1.z
41
+ .string()
42
+ .regex(/^[a-f0-9]{64}$/, 'sha256 must be 64 lowercase hex characters');
43
+ /**
44
+ * A channel name. Constrained to a URL/path-safe slug so it can appear in the
45
+ * `expo-channel-name` header and be used CI-friendly for `pr-<n>` tracks. No
46
+ * colon (BullMQ/id safety) and no slash (path safety).
47
+ */
48
+ exports.channelNameSchema = zod_1.z
49
+ .string()
50
+ .min(1)
51
+ .max(100)
52
+ .regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/, 'channel name must be a URL-safe slug');
53
+ /** A runtime version string (expo-updates `runtimeVersion`, e.g. an appVersion). */
54
+ exports.runtimeVersionSchema = zod_1.z.string().min(1).max(255);
55
+ /** A rollout percentage: 0 rolls out to nobody, 100 to everybody. */
56
+ exports.rolloutPercentSchema = zod_1.z.number().int().min(0).max(100);
57
+ /* -------------------------------------------------------------------------- */
58
+ /* Assets: init + complete */
59
+ /* -------------------------------------------------------------------------- */
60
+ /**
61
+ * One asset the client intends to upload as part of an update. `sha256` is the
62
+ * content hash (dedup key); `contentType` and `size` describe the object the
63
+ * server will accept at the presigned URL.
64
+ */
65
+ exports.assetInitItemSchema = zod_1.z.object({
66
+ sha256: exports.sha256HexSchema,
67
+ contentType: zod_1.z.string().min(1).max(255),
68
+ size: zod_1.z.number().int().positive(),
69
+ });
70
+ /**
71
+ * `POST /updates/v1/assets/init` request. Declares the full asset set of an
72
+ * update; the server replies with a presigned PUT for every asset it does NOT
73
+ * already hold (content-addressed dedup — unchanged assets are never re-uploaded).
74
+ */
75
+ exports.assetInitRequestSchema = zod_1.z.object({
76
+ applicationId: zod_1.z.string().min(1),
77
+ assets: zod_1.z.array(exports.assetInitItemSchema).min(1).max(2000),
78
+ });
79
+ /** One presigned upload the client must PUT its bytes to before completing. */
80
+ exports.assetUploadTicketSchema = zod_1.z.object({
81
+ sha256: exports.sha256HexSchema,
82
+ /** Presigned S3 PUT URL. The client PUTs the exact bytes here. */
83
+ uploadUrl: zod_1.z.string(),
84
+ /** The S3 key the object will live at (`public/updates/assets/<sha256>`). */
85
+ storageKey: zod_1.z.string(),
86
+ /** The Content-Type the presigned URL was signed for; echo it on the PUT. */
87
+ contentType: zod_1.z.string(),
88
+ /**
89
+ * The Cache-Control the presigned URL was signed for; the client MUST send it
90
+ * verbatim on the PUT so the SigV4 signature matches and the stored object
91
+ * carries the long immutable cache header (assets are content-addressed).
92
+ */
93
+ cacheControl: zod_1.z.string(),
94
+ });
95
+ /**
96
+ * `POST /updates/v1/assets/init` response. `missing` holds a presigned upload
97
+ * for each asset the server does not yet have; `existing` lists the sha256s it
98
+ * already holds (the client skips those).
99
+ */
100
+ exports.assetInitResponseSchema = zod_1.z.object({
101
+ missing: zod_1.z.array(exports.assetUploadTicketSchema),
102
+ existing: zod_1.z.array(exports.sha256HexSchema),
103
+ });
104
+ /**
105
+ * `POST /updates/v1/assets/complete` request. Sent after the client has PUT
106
+ * every `missing` asset. The server HEADs each object and flips it to
107
+ * `uploaded`; an object that is absent or size-mismatched is rejected.
108
+ */
109
+ exports.assetCompleteRequestSchema = zod_1.z.object({
110
+ applicationId: zod_1.z.string().min(1),
111
+ sha256s: zod_1.z.array(exports.sha256HexSchema).min(1).max(2000),
112
+ });
113
+ /** Per-asset verification outcome from `assets/complete`. */
114
+ exports.assetCompleteResultItemSchema = zod_1.z.object({
115
+ sha256: exports.sha256HexSchema,
116
+ status: exports.updateAssetStatusSchema,
117
+ size: zod_1.z.number().int().nonnegative(),
118
+ });
119
+ exports.assetCompleteResponseSchema = zod_1.z.object({
120
+ assets: zod_1.z.array(exports.assetCompleteResultItemSchema),
121
+ });
122
+ /* -------------------------------------------------------------------------- */
123
+ /* Create update */
124
+ /* -------------------------------------------------------------------------- */
125
+ /**
126
+ * A single asset reference inside a create-update request. `key` is the
127
+ * expo-export asset key (the md5-basename the client uses to look the asset up
128
+ * and skip embedded ones); `fileExtension` is the suggested on-disk extension.
129
+ */
130
+ exports.updateAssetRefSchema = zod_1.z.object({
131
+ sha256: exports.sha256HexSchema,
132
+ /** expo-export asset key (md5 basename) — how app code references the asset. */
133
+ key: zod_1.z.string().min(1),
134
+ contentType: zod_1.z.string().min(1),
135
+ /** Suggested file extension including the leading dot (e.g. `.js`, `.png`). */
136
+ fileExtension: zod_1.z.string().optional(),
137
+ });
138
+ /**
139
+ * `POST /updates/v1/updates` request. Publishes one bundle for one platform to a
140
+ * channel (the channel is created on demand — CI-friendly for `pr-<n>`). All
141
+ * referenced assets MUST already be `uploaded` (via init/complete). `extra`
142
+ * MUST carry `expoClient` so `Constants.expoConfig` works after an OTA update.
143
+ */
144
+ exports.createUpdateRequestSchema = zod_1.z.object({
145
+ applicationId: zod_1.z.string().min(1),
146
+ channel: exports.channelNameSchema,
147
+ runtimeVersion: exports.runtimeVersionSchema,
148
+ platform: exports.updatePlatformSchema,
149
+ /** The launch (entry-point) asset — its `fileExtension` is ignored by clients. */
150
+ launchAsset: exports.updateAssetRefSchema,
151
+ assets: zod_1.z.array(exports.updateAssetRefSchema),
152
+ /**
153
+ * Opaque `extra` blob embedded verbatim in the signed manifest. MUST contain
154
+ * `expoClient` (the public expo config) so `Constants.expoConfig` resolves
155
+ * after an OTA update; MAY carry other third-party config.
156
+ */
157
+ extra: zod_1.z
158
+ .object({ expoClient: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()) })
159
+ .catchall(zod_1.z.unknown()),
160
+ /** String→string metadata dict; filtered client-side via manifest filters. */
161
+ metadata: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).optional(),
162
+ /** Initial rollout percentage (default 100 — full rollout). */
163
+ rolloutPercent: exports.rolloutPercentSchema.optional(),
164
+ /** Git commit the bundle was built from (audit / console display). */
165
+ gitCommit: zod_1.z.string().max(100).optional(),
166
+ /** Git branch the bundle was built from (audit / console display). */
167
+ gitBranch: zod_1.z.string().max(200).optional(),
168
+ /** Human-readable publish message (console display). */
169
+ message: zod_1.z.string().max(500).optional(),
170
+ });
171
+ exports.updateSchema = zod_1.z.object({
172
+ id: zod_1.z.string(),
173
+ applicationId: zod_1.z.string(),
174
+ channel: zod_1.z.string(),
175
+ runtimeVersion: zod_1.z.string(),
176
+ platform: exports.updatePlatformSchema,
177
+ status: exports.updateStatusSchema,
178
+ rolloutPercent: exports.rolloutPercentSchema,
179
+ launchAssetSha256: exports.sha256HexSchema,
180
+ assetSha256s: zod_1.z.array(exports.sha256HexSchema),
181
+ gitCommit: zod_1.z.string().optional(),
182
+ gitBranch: zod_1.z.string().optional(),
183
+ message: zod_1.z.string().optional(),
184
+ promotedFromUpdateId: zod_1.z.string().optional(),
185
+ createdAt: zod_1.z.string(),
186
+ updatedAt: zod_1.z.string(),
187
+ });
188
+ exports.createUpdateResponseSchema = zod_1.z.object({
189
+ update: exports.updateSchema,
190
+ });
191
+ exports.rollbackToEmbeddedEntrySchema = zod_1.z.object({
192
+ runtimeVersion: zod_1.z.string(),
193
+ platform: exports.updatePlatformSchema,
194
+ commitTime: zod_1.z.string(),
195
+ });
196
+ exports.channelSchema = zod_1.z.object({
197
+ id: zod_1.z.string(),
198
+ applicationId: zod_1.z.string(),
199
+ name: zod_1.z.string(),
200
+ rollbacksToEmbedded: zod_1.z.array(exports.rollbackToEmbeddedEntrySchema),
201
+ createdAt: zod_1.z.string(),
202
+ updatedAt: zod_1.z.string(),
203
+ });
204
+ exports.channelListResponseSchema = zod_1.z.object({
205
+ channels: zod_1.z.array(exports.channelSchema),
206
+ });
207
+ exports.updateListResponseSchema = zod_1.z.object({
208
+ updates: zod_1.z.array(exports.updateSchema),
209
+ });
210
+ /* -------------------------------------------------------------------------- */
211
+ /* Rollback / rollback-to-embedded / promote / rollout */
212
+ /* -------------------------------------------------------------------------- */
213
+ /**
214
+ * `POST /updates/v1/channels/:channel/rollback` request. Marks the current head
215
+ * for `(runtimeVersion, platform)` `rolled_back` so the previous published
216
+ * update (if any) becomes head again. Nothing is deleted.
217
+ */
218
+ exports.rollbackRequestSchema = zod_1.z.object({
219
+ applicationId: zod_1.z.string().min(1),
220
+ runtimeVersion: exports.runtimeVersionSchema,
221
+ platform: exports.updatePlatformSchema,
222
+ });
223
+ /**
224
+ * `POST /updates/v1/channels/:channel/rollback-to-embedded` request. Records a
225
+ * `rollBackToEmbedded` directive so clients on this `(runtimeVersion, platform)`
226
+ * fall back to the update embedded in their binary.
227
+ */
228
+ exports.rollbackToEmbeddedRequestSchema = zod_1.z.object({
229
+ applicationId: zod_1.z.string().min(1),
230
+ runtimeVersion: exports.runtimeVersionSchema,
231
+ platform: exports.updatePlatformSchema,
232
+ });
233
+ /**
234
+ * `POST /updates/v1/channels/:channel/promote` request. Promotes an existing
235
+ * update (by `updateId`) into the target channel by creating a NEW update (new
236
+ * UUID) pointing at the SAME assets. `toChannel` defaults to the path channel.
237
+ */
238
+ exports.promoteRequestSchema = zod_1.z.object({
239
+ applicationId: zod_1.z.string().min(1),
240
+ updateId: zod_1.z.string().min(1),
241
+ /** Target channel to promote into. Defaults to the path `:channel`. */
242
+ toChannel: exports.channelNameSchema.optional(),
243
+ /** Rollout percentage for the promoted update (default 100). */
244
+ rolloutPercent: exports.rolloutPercentSchema.optional(),
245
+ });
246
+ /** `PATCH /updates/v1/updates/:updateId` request — adjust a rollout in place. */
247
+ exports.updateRolloutPatchSchema = zod_1.z.object({
248
+ applicationId: zod_1.z.string().min(1),
249
+ rolloutPercent: exports.rolloutPercentSchema,
250
+ });
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ /**
3
+ * WebAuthn / passkey ceremony contracts (Fase B/b1).
4
+ *
5
+ * These schemas describe ONLY the outer Oxy envelope that wraps a WebAuthn
6
+ * ceremony request — the username the client is registering/authenticating as,
7
+ * plus the device-session options every first-party sign-in accepts. The browser
8
+ * `RegistrationResponseJSON` / `AuthenticationResponseJSON` payloads are NOT
9
+ * mirrored here: they are validated by `@simplewebauthn/server` inside the route
10
+ * (`verifyRegistrationResponse` / `verifyAuthenticationResponse`), which is the
11
+ * single source of truth for their structure. Re-encoding them in Zod would just
12
+ * create a second, drift-prone definition of a shape we do not own.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.webauthnLoginVerifyRequestSchema = exports.webauthnRegisterVerifyRequestSchema = exports.webauthnLoginOptionsRequestSchema = exports.webauthnRegisterOptionsRequestSchema = void 0;
16
+ const zod_1 = require("zod");
17
+ /**
18
+ * Device-session options shared by every first-party sign-in body
19
+ * (`deviceName`/`deviceFingerprint`/`deviceId`). Mirrors what
20
+ * `sessionCreateOptionsFromBody` reads in the API so a WebAuthn login/verify can
21
+ * name and pin its resulting session exactly like `/auth/login` or `/auth/verify`.
22
+ */
23
+ const deviceSessionEnvelope = {
24
+ deviceName: zod_1.z.string().trim().min(1).max(120).optional(),
25
+ deviceFingerprint: zod_1.z.string().trim().min(1).max(256).optional(),
26
+ deviceId: zod_1.z.string().trim().min(1).max(256).optional(),
27
+ };
28
+ /**
29
+ * `POST /webauthn/register/options` — request registration options. With a bearer
30
+ * token the caller links a passkey to their signed-in account and `username` is
31
+ * ignored; without one it is a prospective signup and `username` is the desired
32
+ * (not-yet-created) handle.
33
+ */
34
+ exports.webauthnRegisterOptionsRequestSchema = zod_1.z.object({
35
+ username: zod_1.z.string().trim().min(1).max(60).optional(),
36
+ });
37
+ /**
38
+ * `POST /webauthn/login/options` — request authentication options. When
39
+ * `username` is present the server scopes `allowCredentials` to that user's
40
+ * passkeys (username-first); when omitted it returns an empty allow-list for the
41
+ * usernameless / discoverable-credential flow (the default).
42
+ */
43
+ exports.webauthnLoginOptionsRequestSchema = zod_1.z.object({
44
+ username: zod_1.z.string().trim().min(1).max(60).optional(),
45
+ });
46
+ /**
47
+ * `POST /webauthn/register/verify` — the outer envelope. The browser
48
+ * `RegistrationResponseJSON` travels alongside these fields under `response` and
49
+ * is validated by `@simplewebauthn/server`, not here. `username` is required only
50
+ * for the prospective-signup branch (no bearer); the linking branch ignores it.
51
+ */
52
+ exports.webauthnRegisterVerifyRequestSchema = zod_1.z.object({
53
+ username: zod_1.z.string().trim().min(1).max(60).optional(),
54
+ ...deviceSessionEnvelope,
55
+ });
56
+ /**
57
+ * `POST /webauthn/login/verify` — the outer envelope. The browser
58
+ * `AuthenticationResponseJSON` travels alongside these fields under `response`
59
+ * and is validated by `@simplewebauthn/server`, not here.
60
+ */
61
+ exports.webauthnLoginVerifyRequestSchema = zod_1.z.object({
62
+ ...deviceSessionEnvelope,
63
+ });