@oxyhq/contracts 0.12.0 → 0.13.1

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,27 +1,15 @@
1
1
  /**
2
- * Device-first bootstrap & token contracts (auth centralization, wave 1).
2
+ * First-party login result contract.
3
3
  *
4
- * SINGLE SOURCE OF TRUTH for the wire shape of the new device-first session
5
- * bootstrap: the top-level `#oxy_boot=…` fragment the API hands back from
6
- * `GET /auth/device/bootstrap`, the token bundle a boot code / web-session
7
- * fast-path exchanges into, the persisted-refresh rotation, the native
8
- * device-token issuance, the IdP chooser's device-resolve, and the first-party
9
- * password login result (2FA arm vs. session arm). The API validates its OUTPUT
10
- * against these schemas; every consumer (`@oxyhq/core`'s device-boot mixin, the
11
- * SDK cold boot, the IdP chooser) validates its INPUT against the same
12
- * definitions, so producer and consumers cannot drift.
4
+ * SINGLE SOURCE OF TRUTH for the first-party password login result (2FA arm vs.
5
+ * session arm). The API validates its OUTPUT against this schema; every consumer
6
+ * (`@oxyhq/core`'s auth mixin) validates its INPUT against the same definition,
7
+ * so producer and consumers cannot drift.
13
8
  *
14
- * Design anchors (from the auth-centralization plan):
15
- * - The bootstrap fragment carries NO tokens and NO deviceId — only a
16
- * `state` echo (CSRF), a `reason`, a short-lived single-use `code`, and an
17
- * opaque `deviceToken`. Tokens are obtained by exchanging the `code` at
18
- * `POST /auth/device/exchange` (origin-bound GETDEL burn).
19
- * - Refresh is ONE rotating, single-use family shared by web and native.
20
- * - `loginResult` mirrors what `POST /auth/login` returns today
21
- * (`buildSessionAuthResponse` in the API's `session.controller.ts`): either a
22
- * 2FA challenge (`{ twoFactorRequired: true, loginToken }`) or a session
23
- * payload. The session arm matches `SessionAuthResponse` EXACTLY, plus an
24
- * optional `refreshToken` the new server adds for the persisted-refresh lane.
9
+ * The device transport is `deviceId` + `deviceSecret` + `POST /session/device/token`
10
+ * (see `deviceSession.ts`). The legacy cookie/bootstrap/refresh-family lanes were
11
+ * removed in the zero-cookie cutover — nothing here carries a refresh token or a
12
+ * boot fragment.
25
13
  *
26
14
  * Nested-object response shapes are declared as explicit `interface`s with the
27
15
  * runtime schema annotated `z.ZodType<Interface>` — the same rationale as
@@ -34,172 +22,22 @@
34
22
  * `require()`).
35
23
  */
36
24
  import { z } from 'zod';
37
- import { type UserResponse } from './userResponse';
38
- /**
39
- * Why the bootstrap hop resolved the way it did.
40
- * - `session` — the device cookie resolved an active session; a `code` is
41
- * present to exchange for tokens.
42
- * - `no_session` — the device is known but has no active session; no `code`.
43
- * - `new_device` — first contact; the cookie was just planted, no session yet.
44
- */
45
- export declare const deviceBootReasonSchema: z.ZodEnum<["session", "no_session", "new_device"]>;
46
- export type DeviceBootReason = z.infer<typeof deviceBootReasonSchema>;
47
- export declare const deviceBootFragmentSchema: z.ZodDiscriminatedUnion<"reason", [z.ZodObject<{
48
- reason: z.ZodLiteral<"session">;
49
- code: z.ZodString;
50
- v: z.ZodLiteral<1>;
51
- state: z.ZodString;
52
- deviceToken: z.ZodString;
53
- }, "strip", z.ZodTypeAny, {
54
- code: string;
55
- reason: "session";
56
- v: 1;
57
- state: string;
58
- deviceToken: string;
59
- }, {
60
- code: string;
61
- reason: "session";
62
- v: 1;
63
- state: string;
64
- deviceToken: string;
65
- }>, z.ZodObject<{
66
- reason: z.ZodLiteral<"no_session">;
67
- v: z.ZodLiteral<1>;
68
- state: z.ZodString;
69
- deviceToken: z.ZodString;
70
- }, "strip", z.ZodTypeAny, {
71
- reason: "no_session";
72
- v: 1;
73
- state: string;
74
- deviceToken: string;
75
- }, {
76
- reason: "no_session";
77
- v: 1;
78
- state: string;
79
- deviceToken: string;
80
- }>, z.ZodObject<{
81
- reason: z.ZodLiteral<"new_device">;
82
- v: z.ZodLiteral<1>;
83
- state: z.ZodString;
84
- deviceToken: z.ZodString;
85
- }, "strip", z.ZodTypeAny, {
86
- reason: "new_device";
87
- v: 1;
88
- state: string;
89
- deviceToken: string;
90
- }, {
91
- reason: "new_device";
92
- v: 1;
93
- state: string;
94
- deviceToken: string;
95
- }>]>;
96
- export type DeviceBootFragment = z.infer<typeof deviceBootFragmentSchema>;
97
- /** Request body for `POST /auth/device/exchange` — the single-use boot code. */
98
- export declare const deviceExchangeRequestSchema: z.ZodObject<{
99
- code: z.ZodString;
100
- }, "strip", z.ZodTypeAny, {
101
- code: string;
102
- }, {
103
- code: string;
104
- }>;
105
- export type DeviceExchangeRequest = z.infer<typeof deviceExchangeRequestSchema>;
106
- /**
107
- * The token bundle returned by `POST /auth/device/exchange` and
108
- * `POST /auth/device/web-session` — the freshly-minted access token, its
109
- * rotating refresh-family head, the owning `sessionId`, and the full canonical
110
- * user object. `expiresAt` is an ISO string.
111
- */
112
- export interface AuthTokenBundle {
113
- sessionId: string;
114
- accessToken: string;
115
- refreshToken: string;
116
- expiresAt: string;
117
- user: UserResponse;
118
- /**
119
- * The device secret (phase 2c — zero-cookie transport). Present ONLY when
120
- * the bundle is minted for a device that carries a `DeviceSession` doc; the
121
- * client persists it first-party and later mints access tokens via
122
- * `POST /session/device/token`. Optional and additive: cookie-lane bundles
123
- * for a device with no doc omit it, so existing consumers are unaffected.
124
- */
125
- deviceSecret?: string;
25
+ /** One anomalous signal the server flagged on a sign-in (new device, location, …). */
26
+ export interface SecurityAlertAnomaly {
27
+ type: string;
28
+ reason: string;
29
+ details?: string;
126
30
  }
127
- export declare const authTokenBundleSchema: z.ZodType<AuthTokenBundle>;
128
31
  /**
129
- * The `*.oxy.so` same-site fast path returns a `reason`-discriminated result:
130
- * a full session (the device cookie resolved an active session) OR a
131
- * signed-out arm (the device is known / was just planted). BOTH arms carry the
132
- * rotated opaque `deviceToken` to persist — the deviceToken is device-level
133
- * attribution, not session-level, so it is refreshed even when signed out.
134
- *
135
- * IMPORTANT: the success arm nests the token bundle under `session` — it is
136
- * NOT a bare {@link AuthTokenBundle}. That distinction is load-bearing for the
137
- * consumer (`@oxyhq/core`'s cold boot uses `result.session` and persists the
138
- * `deviceToken` from the SAME envelope).
139
- */
140
- /**
141
- * Success arm: an active session resolved from the same-site device cookie.
142
- */
143
- export interface WebSessionSession {
144
- reason: 'session';
145
- session: AuthTokenBundle;
146
- deviceToken: string;
147
- }
148
- /**
149
- * Signed-out arm: the device is known (or freshly planted) but has no active
150
- * session. Carries only the rotated `deviceToken`.
32
+ * The "New sign-in detected" payload the API attaches to a successful
33
+ * `POST /auth/login` when anomaly detection fires (`session.controller.ts`).
34
+ * The IdP renders `message` and gates the flow on user acknowledgement before
35
+ * continuing to the OAuth authorize step.
151
36
  */
152
- export interface WebSessionNoSession {
153
- reason: 'no_session' | 'new_device';
154
- deviceToken: string;
37
+ export interface SecurityAlert {
38
+ message: string;
39
+ anomalies: SecurityAlertAnomaly[];
155
40
  }
156
- /** The `reason`-discriminated outcome of `POST /auth/device/web-session`. */
157
- export type WebSessionResult = WebSessionSession | WebSessionNoSession;
158
- export declare const webSessionResultSchema: z.ZodType<WebSessionResult>;
159
- /** Request body for `POST /auth/refresh-token` — the current refresh token. */
160
- export declare const tokenRefreshRequestSchema: z.ZodObject<{
161
- refreshToken: z.ZodString;
162
- }, "strip", z.ZodTypeAny, {
163
- refreshToken: string;
164
- }, {
165
- refreshToken: string;
166
- }>;
167
- export type TokenRefreshRequest = z.infer<typeof tokenRefreshRequestSchema>;
168
- /**
169
- * Wire shape of `POST /auth/refresh-token`: the rotated (single-use) family —
170
- * a new access token, the next refresh token, the new access-token expiry, and
171
- * the owning session id. `expiresAt` is an ISO string.
172
- */
173
- export declare const tokenRefreshResponseSchema: z.ZodObject<{
174
- accessToken: z.ZodString;
175
- refreshToken: z.ZodString;
176
- expiresAt: z.ZodString;
177
- sessionId: z.ZodString;
178
- }, "strip", z.ZodTypeAny, {
179
- expiresAt: string;
180
- sessionId: string;
181
- accessToken: string;
182
- refreshToken: string;
183
- }, {
184
- expiresAt: string;
185
- sessionId: string;
186
- accessToken: string;
187
- refreshToken: string;
188
- }>;
189
- export type TokenRefreshResponse = z.infer<typeof tokenRefreshResponseSchema>;
190
- /**
191
- * Wire shape of `POST /auth/device/token` — issues (or rotates) the opaque
192
- * device token for the native channel. The deviceId is taken from the bearer
193
- * JWT claims server-side; only the token comes back.
194
- */
195
- export declare const deviceTokenIssueResponseSchema: z.ZodObject<{
196
- deviceToken: z.ZodString;
197
- }, "strip", z.ZodTypeAny, {
198
- deviceToken: string;
199
- }, {
200
- deviceToken: string;
201
- }>;
202
- export type DeviceTokenIssueResponse = z.infer<typeof deviceTokenIssueResponseSchema>;
203
41
  /**
204
42
  * `POST /auth/login` when the account has 2FA enabled: a short-lived login
205
43
  * token to be presented at the 2FA challenge, and no session yet.
@@ -210,8 +48,7 @@ export interface LoginTwoFactorRequired {
210
48
  }
211
49
  /**
212
50
  * `POST /auth/login` when authentication completed in one step. Matches the
213
- * API's `SessionAuthResponse` EXACTLY (`buildSessionAuthResponse`), plus the
214
- * optional `refreshToken` the persisted-refresh lane adds. `user` is the
51
+ * API's `SessionAuthResponse` EXACTLY (`buildSessionAuthResponse`). `user` is the
215
52
  * truncated session-user shape the login endpoint emits (NOT the full
216
53
  * `userResponseSchema`).
217
54
  */
@@ -220,14 +57,20 @@ export interface LoginSessionResult {
220
57
  deviceId: string;
221
58
  expiresAt: string;
222
59
  accessToken?: string;
223
- refreshToken?: string;
224
60
  /**
225
- * The device secret (phase 2c — zero-cookie transport). Present ONLY when
226
- * the sign-in resolved a device binding; the client persists it first-party
227
- * and later mints access tokens via `POST /session/device/token`. Optional
228
- * and additivewired identically to `refreshToken`.
61
+ * The device secret (zero-cookie transport). Emitted on every successful
62
+ * sign-in; the client persists it first-party alongside `deviceId` and later
63
+ * mints access tokens via `POST /session/device/token`. Optional only because
64
+ * a best-effort mint can fail it is the sole restore credential.
229
65
  */
230
66
  deviceSecret?: string;
67
+ /**
68
+ * Present only when the server's anomaly detection flagged this sign-in.
69
+ * The IdP shows a "New sign-in detected" acknowledgement before proceeding.
70
+ * The session is already established regardless — this is an interstitial,
71
+ * not a gate on the credential check.
72
+ */
73
+ securityAlert?: SecurityAlert;
231
74
  user: {
232
75
  id: string;
233
76
  username?: string;
@@ -237,33 +80,3 @@ export interface LoginSessionResult {
237
80
  /** The discriminated outcome of `POST /auth/login`. */
238
81
  export type LoginResult = LoginTwoFactorRequired | LoginSessionResult;
239
82
  export declare const loginResultSchema: z.ZodType<LoginResult>;
240
- /**
241
- * Request body for `POST /auth/device/resolve` (X-Oxy-Internal, called by the
242
- * IdP chooser) — the device key the chooser read from the first-party
243
- * `oxy_device` cookie.
244
- */
245
- export declare const deviceResolveRequestSchema: z.ZodObject<{
246
- deviceKey: z.ZodString;
247
- }, "strip", z.ZodTypeAny, {
248
- deviceKey: string;
249
- }, {
250
- deviceKey: string;
251
- }>;
252
- export type DeviceResolveRequest = z.infer<typeof deviceResolveRequestSchema>;
253
- /** One account resolved for the IdP chooser from a device's session set. */
254
- export interface DeviceResolveAccount {
255
- user: UserResponse;
256
- sessionId: string;
257
- accessToken: string;
258
- expiresAt: string;
259
- }
260
- /**
261
- * Wire shape of `POST /auth/device/resolve` — the device's active account id
262
- * (or `null` when signed out of all) plus every account signed in on the
263
- * device. Replaces the IdP's legacy cookie-based chooser feed.
264
- */
265
- export interface DeviceResolveResponse {
266
- activeAccountId: string | null;
267
- accounts: DeviceResolveAccount[];
268
- }
269
- export declare const deviceResolveResponseSchema: z.ZodType<DeviceResolveResponse>;
@@ -39,24 +39,24 @@ export declare const deviceSessionStateSchema: z.ZodObject<{
39
39
  }, "strip", z.ZodTypeAny, {
40
40
  updatedAt: number;
41
41
  deviceId: string;
42
- activeAccountId: string | null;
43
42
  accounts: {
44
43
  sessionId: string;
45
44
  accountId: string;
46
45
  authuser: number;
47
46
  operatedByUserId?: string | undefined;
48
47
  }[];
48
+ activeAccountId: string | null;
49
49
  revision: number;
50
50
  }, {
51
51
  updatedAt: number;
52
52
  deviceId: string;
53
- activeAccountId: string | null;
54
53
  accounts: {
55
54
  sessionId: string;
56
55
  accountId: string;
57
56
  authuser: number;
58
57
  operatedByUserId?: string | undefined;
59
58
  }[];
59
+ activeAccountId: string | null;
60
60
  revision: number;
61
61
  }>;
62
62
  export declare const activeTokenSchema: z.ZodObject<{
@@ -94,24 +94,24 @@ export declare const deviceSessionSyncSchema: z.ZodObject<{
94
94
  }, "strip", z.ZodTypeAny, {
95
95
  updatedAt: number;
96
96
  deviceId: string;
97
- activeAccountId: string | null;
98
97
  accounts: {
99
98
  sessionId: string;
100
99
  accountId: string;
101
100
  authuser: number;
102
101
  operatedByUserId?: string | undefined;
103
102
  }[];
103
+ activeAccountId: string | null;
104
104
  revision: number;
105
105
  }, {
106
106
  updatedAt: number;
107
107
  deviceId: string;
108
- activeAccountId: string | null;
109
108
  accounts: {
110
109
  sessionId: string;
111
110
  accountId: string;
112
111
  authuser: number;
113
112
  operatedByUserId?: string | undefined;
114
113
  }[];
114
+ activeAccountId: string | null;
115
115
  revision: number;
116
116
  }>;
117
117
  activeToken: z.ZodNullable<z.ZodObject<{
@@ -128,13 +128,13 @@ export declare const deviceSessionSyncSchema: z.ZodObject<{
128
128
  state: {
129
129
  updatedAt: number;
130
130
  deviceId: string;
131
- activeAccountId: string | null;
132
131
  accounts: {
133
132
  sessionId: string;
134
133
  accountId: string;
135
134
  authuser: number;
136
135
  operatedByUserId?: string | undefined;
137
136
  }[];
137
+ activeAccountId: string | null;
138
138
  revision: number;
139
139
  };
140
140
  activeToken: {
@@ -145,13 +145,13 @@ export declare const deviceSessionSyncSchema: z.ZodObject<{
145
145
  state: {
146
146
  updatedAt: number;
147
147
  deviceId: string;
148
- activeAccountId: string | null;
149
148
  accounts: {
150
149
  sessionId: string;
151
150
  accountId: string;
152
151
  authuser: number;
153
152
  operatedByUserId?: string | undefined;
154
153
  }[];
154
+ activeAccountId: string | null;
155
155
  revision: number;
156
156
  };
157
157
  activeToken: {
@@ -174,11 +174,11 @@ export declare const deviceTokenMintRequestSchema: z.ZodObject<{
174
174
  deviceId: z.ZodString;
175
175
  deviceSecret: z.ZodString;
176
176
  }, "strip", z.ZodTypeAny, {
177
- deviceSecret: string;
178
177
  deviceId: string;
179
- }, {
180
178
  deviceSecret: string;
179
+ }, {
181
180
  deviceId: string;
181
+ deviceSecret: string;
182
182
  }>;
183
183
  /**
184
184
  * Wire shape of a successful `POST /session/device/token`: the freshly-minted
@@ -215,58 +215,103 @@ export declare const deviceTokenMintResponseSchema: z.ZodObject<{
215
215
  }, "strip", z.ZodTypeAny, {
216
216
  updatedAt: number;
217
217
  deviceId: string;
218
- activeAccountId: string | null;
219
218
  accounts: {
220
219
  sessionId: string;
221
220
  accountId: string;
222
221
  authuser: number;
223
222
  operatedByUserId?: string | undefined;
224
223
  }[];
224
+ activeAccountId: string | null;
225
225
  revision: number;
226
226
  }, {
227
227
  updatedAt: number;
228
228
  deviceId: string;
229
- activeAccountId: string | null;
230
229
  accounts: {
231
230
  sessionId: string;
232
231
  accountId: string;
233
232
  authuser: number;
234
233
  operatedByUserId?: string | undefined;
235
234
  }[];
235
+ activeAccountId: string | null;
236
236
  revision: number;
237
237
  }>;
238
238
  }, "strip", z.ZodTypeAny, {
239
239
  expiresAt: string;
240
+ accessToken: string;
240
241
  state: {
241
242
  updatedAt: number;
242
243
  deviceId: string;
243
- activeAccountId: string | null;
244
244
  accounts: {
245
245
  sessionId: string;
246
246
  accountId: string;
247
247
  authuser: number;
248
248
  operatedByUserId?: string | undefined;
249
249
  }[];
250
+ activeAccountId: string | null;
250
251
  revision: number;
251
252
  };
252
- accessToken: string;
253
253
  nextDeviceSecret: string;
254
254
  }, {
255
255
  expiresAt: string;
256
+ accessToken: string;
256
257
  state: {
257
258
  updatedAt: number;
258
259
  deviceId: string;
259
- activeAccountId: string | null;
260
260
  accounts: {
261
261
  sessionId: string;
262
262
  accountId: string;
263
263
  authuser: number;
264
264
  operatedByUserId?: string | undefined;
265
265
  }[];
266
+ activeAccountId: string | null;
266
267
  revision: number;
267
268
  };
268
- accessToken: string;
269
269
  nextDeviceSecret: string;
270
270
  }>;
271
271
  export type DeviceTokenMintRequest = z.infer<typeof deviceTokenMintRequestSchema>;
272
272
  export type DeviceTokenMintResponse = z.infer<typeof deviceTokenMintResponseSchema>;
273
+ /** Request body for `POST /session/device/hub-ticket`. */
274
+ export declare const deviceHubTicketIssueRequestSchema: z.ZodObject<{
275
+ returnOrigin: z.ZodString;
276
+ }, "strip", z.ZodTypeAny, {
277
+ returnOrigin: string;
278
+ }, {
279
+ returnOrigin: string;
280
+ }>;
281
+ /** Response from `POST /session/device/hub-ticket`. */
282
+ export declare const deviceHubTicketIssueResponseSchema: z.ZodObject<{
283
+ ticket: z.ZodString;
284
+ expiresIn: z.ZodNumber;
285
+ }, "strip", z.ZodTypeAny, {
286
+ ticket: string;
287
+ expiresIn: number;
288
+ }, {
289
+ ticket: string;
290
+ expiresIn: number;
291
+ }>;
292
+ /** Request body for `POST /session/device/redeem-ticket`. */
293
+ export declare const deviceHubTicketRedeemRequestSchema: z.ZodObject<{
294
+ ticket: z.ZodString;
295
+ returnOrigin: z.ZodString;
296
+ }, "strip", z.ZodTypeAny, {
297
+ returnOrigin: string;
298
+ ticket: string;
299
+ }, {
300
+ returnOrigin: string;
301
+ ticket: string;
302
+ }>;
303
+ /** Response from `POST /session/device/redeem-ticket`. */
304
+ export declare const deviceHubTicketRedeemResponseSchema: z.ZodObject<{
305
+ deviceId: z.ZodString;
306
+ deviceSecret: z.ZodString;
307
+ }, "strip", z.ZodTypeAny, {
308
+ deviceId: string;
309
+ deviceSecret: string;
310
+ }, {
311
+ deviceId: string;
312
+ deviceSecret: string;
313
+ }>;
314
+ export type DeviceHubTicketIssueRequest = z.infer<typeof deviceHubTicketIssueRequestSchema>;
315
+ export type DeviceHubTicketIssueResponse = z.infer<typeof deviceHubTicketIssueResponseSchema>;
316
+ export type DeviceHubTicketRedeemRequest = z.infer<typeof deviceHubTicketRedeemRequestSchema>;
317
+ export type DeviceHubTicketRedeemResponse = z.infer<typeof deviceHubTicketRedeemResponseSchema>;
@@ -2,7 +2,7 @@
2
2
  * @oxyhq/contracts — single source of truth for API request/response contracts.
3
3
  *
4
4
  * Zod schemas plus their inferred types, shared by the backend (`@oxyhq/api`)
5
- * and the client SDKs (`@oxyhq/core`, `@oxyhq/auth`, `@oxyhq/services`). The
5
+ * and the client SDKs (`@oxyhq/core`, `@oxyhq/services`). The
6
6
  * producer validates its output and every consumer validates its input against
7
7
  * exactly the same definitions, so the wire shape cannot drift.
8
8
  *
@@ -13,8 +13,6 @@ export { userNameSchema, userResponseSchema, userProfileUpdateSchema, currentUse
13
13
  export type { UserNameResponse, UserResponse, UserProfileUpdate, CurrentUserResponseContract, DeviceLinkedSessionResponse, DeviceLinkedSessionsResponseContract, } from './userResponse';
14
14
  export { applicationTypeSchema, publicApplicationSchema, sessionStatusSchema, } from './sessionStatus';
15
15
  export type { ApplicationTypeContract, PublicApplicationResponse, SessionStatusResponse, } from './sessionStatus';
16
- export { fedcmTokenPayloadSchema, } from './fedcmToken';
17
- export type { FedcmTokenPayload, } from './fedcmToken';
18
16
  export { recommendationExcludeTypeSchema, recommendationBoostSchema, recommendationSignalWeightsSchema, recommendationRequestSchema, recommendationCountSchema, recommendationItemSchema, recommendationResponseSchema, appEndorsementInputSchema, appInterestInputSchema, appUserSignalIngestSchema, appAffinityEventTypeSchema, appAffinityEventSchema, appAffinityEventsIngestSchema, } from './recommendations';
19
17
  export type { RecommendationExcludeType, RecommendationBoost, RecommendationSignalWeights, RecommendationRequest, RecommendationCount, RecommendationItem, RecommendationResponse, AppEndorsementInput, AppInterestInput, AppUserSignalIngest, AppAffinityEventType, AppAffinityEvent, AppAffinityEventsIngest, } from './recommendations';
20
18
  export { verificationMethodSchema, didServiceSchema, didDocumentSchema, signedRecordEnvelopeSchema, verifiedDomainSchema, domainVerificationRequestSchema, domainVerificationInstructionsSchema, authMethodEntrySchema, authMethodsResponseSchema, exportAttestationSchema, exportBundleSchema, } from './identity';
@@ -27,7 +25,7 @@ export { publicCardSchema, signedPublicCardSchema, realLifeAttestationRecordSche
27
25
  export type { CardTrustTier, PersonhoodStatus, PublicCard, SignedPublicCard, RealLifeAttestationRecord, RealLifeAttestationResult, ValidationVerdict, ValidationRequestStatus, ValidationVerdictRecord, ValidationOpenRequest, ValidationOpenResult, ValidationRequestSummary, ValidationVoteResult, PersonhoodVouchRecord, PersonhoodBreakdown, PersonhoodStatusResult, VouchResult, CredentialStatus, CredentialRecord, VerifiableCredentialResponse, CredentialIssueResult, CredentialListResult, CredentialVerifyResult, } from './civic';
28
26
  export { linkPreviewSchema, linkPreviewBatchRequestSchema, linkPreviewBatchResponseSchema, linkPreviewResponseSchema, } from './links';
29
27
  export type { LinkPreviewStatus, LinkPreview, LinkPreviewBatchRequest, LinkPreviewBatchResponse, } from './links';
30
- export { sessionAccountSchema, deviceSessionStateSchema, activeTokenSchema, deviceSessionSyncSchema, deviceTokenMintRequestSchema, deviceTokenMintResponseSchema, } from './deviceSession';
31
- export type { SessionAccount, DeviceSessionState, ActiveToken, DeviceSessionSync, DeviceTokenMintRequest, DeviceTokenMintResponse, } from './deviceSession';
32
- export { deviceBootReasonSchema, deviceBootFragmentSchema, deviceExchangeRequestSchema, authTokenBundleSchema, webSessionResultSchema, tokenRefreshRequestSchema, tokenRefreshResponseSchema, deviceTokenIssueResponseSchema, loginResultSchema, deviceResolveRequestSchema, deviceResolveResponseSchema, } from './deviceBoot';
33
- export type { DeviceBootReason, DeviceBootFragment, DeviceExchangeRequest, AuthTokenBundle, WebSessionResult, WebSessionSession, WebSessionNoSession, TokenRefreshRequest, TokenRefreshResponse, DeviceTokenIssueResponse, LoginTwoFactorRequired, LoginSessionResult, LoginResult, DeviceResolveRequest, DeviceResolveAccount, DeviceResolveResponse, } from './deviceBoot';
28
+ export { sessionAccountSchema, deviceSessionStateSchema, activeTokenSchema, deviceSessionSyncSchema, deviceTokenMintRequestSchema, deviceTokenMintResponseSchema, deviceHubTicketIssueRequestSchema, deviceHubTicketIssueResponseSchema, deviceHubTicketRedeemRequestSchema, deviceHubTicketRedeemResponseSchema, } from './deviceSession';
29
+ export type { SessionAccount, DeviceSessionState, ActiveToken, DeviceSessionSync, DeviceTokenMintRequest, DeviceTokenMintResponse, DeviceHubTicketIssueRequest, DeviceHubTicketIssueResponse, DeviceHubTicketRedeemRequest, DeviceHubTicketRedeemResponse, } from './deviceSession';
30
+ export { loginResultSchema, } from './deviceBoot';
31
+ export type { LoginTwoFactorRequired, LoginSessionResult, LoginResult, SecurityAlert, SecurityAlertAnomaly, } from './deviceBoot';
@@ -11,13 +11,12 @@
11
11
  *
12
12
  * This package (`@oxyhq/contracts`) is the dedicated, zero-dependency home for
13
13
  * these contracts so the backend (`@oxyhq/api`) and the client SDKs
14
- * (`@oxyhq/core`, `@oxyhq/auth`, `@oxyhq/services`) can all depend on it without
14
+ * (`@oxyhq/core`, `@oxyhq/services`) can all depend on it without
15
15
  * the backend having to depend on a client SDK to obtain its schemas.
16
16
  *
17
17
  * Faithful to the producers:
18
18
  * - `packages/api/src/utils/userTransform.ts` `formatUserResponse` — the
19
- * canonical serialization used by the device-first bootstrap/exchange
20
- * endpoints (`deviceAuth.ts`), login/signup, device sessions, etc.
19
+ * canonical serialization used by login/signup, device sessions, etc.
21
20
  * Emits `id` (NOT `_id`), forwards `username` verbatim (may be absent), and
22
21
  * emits `name` as the structured `{ first, last, full, displayName }`
23
22
  * subdocument.
@@ -417,12 +416,12 @@ export declare const currentUserResponseSchema: z.ZodObject<{
417
416
  verifiedDomains?: import("./identity").VerifiedDomain[] | undefined;
418
417
  verified?: boolean | undefined;
419
418
  username?: string | undefined;
419
+ avatar?: string | null | undefined;
420
420
  _id?: string | undefined;
421
421
  email?: string | undefined;
422
422
  phone?: string | undefined;
423
423
  address?: string | undefined;
424
424
  birthday?: string | undefined;
425
- avatar?: string | null | undefined;
426
425
  color?: string | null | undefined;
427
426
  language?: string | undefined;
428
427
  } & {
@@ -437,12 +436,12 @@ export declare const currentUserResponseSchema: z.ZodObject<{
437
436
  verifiedDomains?: import("./identity").VerifiedDomain[] | undefined;
438
437
  verified?: boolean | undefined;
439
438
  username?: string | undefined;
439
+ avatar?: string | null | undefined;
440
440
  _id?: string | undefined;
441
441
  email?: string | undefined;
442
442
  phone?: string | undefined;
443
443
  address?: string | undefined;
444
444
  birthday?: string | undefined;
445
- avatar?: string | null | undefined;
446
445
  color?: string | null | undefined;
447
446
  language?: string | undefined;
448
447
  } & {
@@ -549,7 +548,6 @@ export declare const deviceLinkedSessionSchema: z.ZodObject<{
549
548
  }, z.ZodTypeAny, "passthrough">>>>;
550
549
  }, "strip", z.ZodTypeAny, {
551
550
  sessionId: string;
552
- isCurrent?: boolean | undefined;
553
551
  user?: z.objectOutputType<{
554
552
  /** MongoDB ObjectId as a string. Present on `formatUserResponse` output. */
555
553
  id: z.ZodOptional<z.ZodString>;
@@ -580,9 +578,9 @@ export declare const deviceLinkedSessionSchema: z.ZodObject<{
580
578
  */
581
579
  verifiedDomains: z.ZodOptional<z.ZodArray<z.ZodType<import("./identity").VerifiedDomain, z.ZodTypeDef, import("./identity").VerifiedDomain>, "many">>;
582
580
  }, z.ZodTypeAny, "passthrough"> | null | undefined;
581
+ isCurrent?: boolean | undefined;
583
582
  }, {
584
583
  sessionId: string;
585
- isCurrent?: boolean | undefined;
586
584
  user?: z.objectInputType<{
587
585
  /** MongoDB ObjectId as a string. Present on `formatUserResponse` output. */
588
586
  id: z.ZodOptional<z.ZodString>;
@@ -613,6 +611,7 @@ export declare const deviceLinkedSessionSchema: z.ZodObject<{
613
611
  */
614
612
  verifiedDomains: z.ZodOptional<z.ZodArray<z.ZodType<import("./identity").VerifiedDomain, z.ZodTypeDef, import("./identity").VerifiedDomain>, "many">>;
615
613
  }, z.ZodTypeAny, "passthrough"> | null | undefined;
614
+ isCurrent?: boolean | undefined;
616
615
  }>;
617
616
  export type DeviceLinkedSessionResponse = z.infer<typeof deviceLinkedSessionSchema>;
618
617
  /** Wire shape of `GET /session/device/sessions/:sessionId` (an array). */
@@ -709,7 +708,6 @@ export declare const deviceLinkedSessionsResponseSchema: z.ZodArray<z.ZodObject<
709
708
  }, z.ZodTypeAny, "passthrough">>>>;
710
709
  }, "strip", z.ZodTypeAny, {
711
710
  sessionId: string;
712
- isCurrent?: boolean | undefined;
713
711
  user?: z.objectOutputType<{
714
712
  /** MongoDB ObjectId as a string. Present on `formatUserResponse` output. */
715
713
  id: z.ZodOptional<z.ZodString>;
@@ -740,9 +738,9 @@ export declare const deviceLinkedSessionsResponseSchema: z.ZodArray<z.ZodObject<
740
738
  */
741
739
  verifiedDomains: z.ZodOptional<z.ZodArray<z.ZodType<import("./identity").VerifiedDomain, z.ZodTypeDef, import("./identity").VerifiedDomain>, "many">>;
742
740
  }, z.ZodTypeAny, "passthrough"> | null | undefined;
741
+ isCurrent?: boolean | undefined;
743
742
  }, {
744
743
  sessionId: string;
745
- isCurrent?: boolean | undefined;
746
744
  user?: z.objectInputType<{
747
745
  /** MongoDB ObjectId as a string. Present on `formatUserResponse` output. */
748
746
  id: z.ZodOptional<z.ZodString>;
@@ -773,6 +771,7 @@ export declare const deviceLinkedSessionsResponseSchema: z.ZodArray<z.ZodObject<
773
771
  */
774
772
  verifiedDomains: z.ZodOptional<z.ZodArray<z.ZodType<import("./identity").VerifiedDomain, z.ZodTypeDef, import("./identity").VerifiedDomain>, "many">>;
775
773
  }, z.ZodTypeAny, "passthrough"> | null | undefined;
774
+ isCurrent?: boolean | undefined;
776
775
  }>, "many">;
777
776
  export type DeviceLinkedSessionsResponseContract = z.infer<typeof deviceLinkedSessionsResponseSchema>;
778
777
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxyhq/contracts",
3
- "version": "0.12.0",
3
+ "version": "0.13.1",
4
4
  "description": "OxyHQ API contracts — single source of truth for request/response Zod schemas and inferred types, shared by the backend and the client SDKs",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",