@oxyhq/contracts 0.10.0 → 0.12.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.
@@ -94,6 +94,7 @@ exports.authTokenBundleSchema = zod_1.z.object({
94
94
  refreshToken: zod_1.z.string(),
95
95
  expiresAt: zod_1.z.string(),
96
96
  user: userResponse_1.userResponseSchema,
97
+ deviceSecret: zod_1.z.string().optional(),
97
98
  });
98
99
  // Internal (unexported) arm schemas — PLAIN `z.object` literals (no
99
100
  // `z.ZodType<>` annotation) so `z.discriminatedUnion` can introspect the
@@ -158,6 +159,7 @@ const loginSessionResultSchema = zod_1.z.object({
158
159
  expiresAt: zod_1.z.string(),
159
160
  accessToken: zod_1.z.string().optional(),
160
161
  refreshToken: zod_1.z.string().optional(),
162
+ deviceSecret: zod_1.z.string().optional(),
161
163
  user: zod_1.z.object({
162
164
  id: zod_1.z.string(),
163
165
  username: zod_1.z.string().optional(),
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deviceSessionSyncSchema = exports.activeTokenSchema = exports.deviceSessionStateSchema = exports.sessionAccountSchema = void 0;
3
+ 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(),
@@ -23,3 +23,30 @@ exports.deviceSessionSyncSchema = zod_1.z.object({
23
23
  state: exports.deviceSessionStateSchema,
24
24
  activeToken: exports.activeTokenSchema.nullable(),
25
25
  });
26
+ /* -------------------------------------------------------------------------- */
27
+ /* Device-secret token mint (phase 2c — zero-cookie transport) */
28
+ /* -------------------------------------------------------------------------- */
29
+ /**
30
+ * Request body for `POST /session/device/token` — the client presents the
31
+ * `deviceId` it stored first-party plus the opaque `deviceSecret`. NO bearer:
32
+ * possession of the secret IS the proof of device ownership. The server matches
33
+ * `sha256(deviceSecret)` against the device's stored `secretHash` (constant-time)
34
+ * and mints a short access token for the device's active account.
35
+ */
36
+ exports.deviceTokenMintRequestSchema = zod_1.z.object({
37
+ deviceId: zod_1.z.string().min(1),
38
+ deviceSecret: zod_1.z.string().min(1),
39
+ });
40
+ /**
41
+ * Wire shape of a successful `POST /session/device/token`: the freshly-minted
42
+ * short access token for the active account, its expiry, the NEXT rotating
43
+ * device secret the client must persist (rotation-in-use — the presented secret
44
+ * stays valid for a short grace so multi-tab races don't lock out), and the
45
+ * projected device-session state.
46
+ */
47
+ exports.deviceTokenMintResponseSchema = zod_1.z.object({
48
+ accessToken: zod_1.z.string(),
49
+ expiresAt: zod_1.z.string(),
50
+ nextDeviceSecret: zod_1.z.string(),
51
+ state: exports.deviceSessionStateSchema,
52
+ });
@@ -2,6 +2,16 @@
2
2
  /**
3
3
  * Canonical contract for the FedCM ID-token JWT payload.
4
4
  *
5
+ * DEAD SINCE THE WAVE-2 FEDCM DELETION (found during the comment sweep, not
6
+ * fixed here — this is a published `@oxyhq/contracts` export, so removing it
7
+ * is a breaking change/major-version decision, out of scope for a comment
8
+ * fix): `POST /fedcm/exchange`, `fedcm.service.exchangeIdToken`, and
9
+ * `packages/auth/server/index.ts`'s `mintSessionForClient` — every consumer
10
+ * and producer this file describes — are all deleted. No current code
11
+ * imports `fedcmTokenPayloadSchema` / `FedcmTokenPayload` outside this
12
+ * package. Flag for a follow-up major-version cleanup.
13
+ *
14
+ * Original doc (historical, describes the now-deleted system):
5
15
  * SINGLE SOURCE OF TRUTH for the decoded claims of the HS256 ID token the auth
6
16
  * IdP (`auth.oxy.so`) signs and `POST /fedcm/exchange` consumes. The API decodes
7
17
  * the JWT, verifies its signature, then validates the resulting claim object
package/dist/cjs/index.js CHANGED
@@ -11,16 +11,16 @@
11
11
  * expo, no `require()` in the ESM build.
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.personhoodBreakdownSchema = exports.personhoodVouchRecordSchema = 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.fedcmTokenPayloadSchema = exports.sessionStatusSchema = exports.publicApplicationSchema = exports.applicationTypeSchema = exports.safeParseContract = exports.resolveUserId = exports.deviceSessionsResponseSchema = exports.deviceSessionAccountSchema = exports.currentUserResponseSchema = exports.userProfileUpdateSchema = exports.userResponseSchema = exports.userNameSchema = void 0;
15
- exports.deviceResolveResponseSchema = exports.deviceResolveRequestSchema = exports.loginResultSchema = exports.deviceTokenIssueResponseSchema = exports.tokenRefreshResponseSchema = exports.tokenRefreshRequestSchema = exports.webSessionResultSchema = exports.authTokenBundleSchema = exports.deviceExchangeRequestSchema = exports.deviceBootFragmentSchema = exports.deviceBootReasonSchema = 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 = void 0;
14
+ exports.personhoodBreakdownSchema = exports.personhoodVouchRecordSchema = 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.fedcmTokenPayloadSchema = exports.sessionStatusSchema = exports.publicApplicationSchema = exports.applicationTypeSchema = exports.safeParseContract = exports.resolveUserId = exports.deviceLinkedSessionsResponseSchema = exports.deviceLinkedSessionSchema = exports.currentUserResponseSchema = exports.userProfileUpdateSchema = exports.userResponseSchema = exports.userNameSchema = void 0;
15
+ exports.deviceResolveResponseSchema = exports.deviceResolveRequestSchema = exports.loginResultSchema = exports.deviceTokenIssueResponseSchema = exports.tokenRefreshResponseSchema = exports.tokenRefreshRequestSchema = exports.webSessionResultSchema = exports.authTokenBundleSchema = exports.deviceExchangeRequestSchema = exports.deviceBootFragmentSchema = exports.deviceBootReasonSchema = 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 = void 0;
16
16
  var userResponse_1 = require("./userResponse");
17
17
  // Schemas
18
18
  Object.defineProperty(exports, "userNameSchema", { enumerable: true, get: function () { return userResponse_1.userNameSchema; } });
19
19
  Object.defineProperty(exports, "userResponseSchema", { enumerable: true, get: function () { return userResponse_1.userResponseSchema; } });
20
20
  Object.defineProperty(exports, "userProfileUpdateSchema", { enumerable: true, get: function () { return userResponse_1.userProfileUpdateSchema; } });
21
21
  Object.defineProperty(exports, "currentUserResponseSchema", { enumerable: true, get: function () { return userResponse_1.currentUserResponseSchema; } });
22
- Object.defineProperty(exports, "deviceSessionAccountSchema", { enumerable: true, get: function () { return userResponse_1.deviceSessionAccountSchema; } });
23
- Object.defineProperty(exports, "deviceSessionsResponseSchema", { enumerable: true, get: function () { return userResponse_1.deviceSessionsResponseSchema; } });
22
+ Object.defineProperty(exports, "deviceLinkedSessionSchema", { enumerable: true, get: function () { return userResponse_1.deviceLinkedSessionSchema; } });
23
+ Object.defineProperty(exports, "deviceLinkedSessionsResponseSchema", { enumerable: true, get: function () { return userResponse_1.deviceLinkedSessionsResponseSchema; } });
24
24
  // Helpers
25
25
  Object.defineProperty(exports, "resolveUserId", { enumerable: true, get: function () { return userResponse_1.resolveUserId; } });
26
26
  Object.defineProperty(exports, "safeParseContract", { enumerable: true, get: function () { return userResponse_1.safeParseContract; } });
@@ -99,6 +99,8 @@ Object.defineProperty(exports, "sessionAccountSchema", { enumerable: true, get:
99
99
  Object.defineProperty(exports, "deviceSessionStateSchema", { enumerable: true, get: function () { return deviceSession_1.deviceSessionStateSchema; } });
100
100
  Object.defineProperty(exports, "activeTokenSchema", { enumerable: true, get: function () { return deviceSession_1.activeTokenSchema; } });
101
101
  Object.defineProperty(exports, "deviceSessionSyncSchema", { enumerable: true, get: function () { return deviceSession_1.deviceSessionSyncSchema; } });
102
+ Object.defineProperty(exports, "deviceTokenMintRequestSchema", { enumerable: true, get: function () { return deviceSession_1.deviceTokenMintRequestSchema; } });
103
+ Object.defineProperty(exports, "deviceTokenMintResponseSchema", { enumerable: true, get: function () { return deviceSession_1.deviceTokenMintResponseSchema; } });
102
104
  var deviceBoot_1 = require("./deviceBoot");
103
105
  // Schemas
104
106
  Object.defineProperty(exports, "deviceBootReasonSchema", { enumerable: true, get: function () { return deviceBoot_1.deviceBootReasonSchema; } });
@@ -20,9 +20,10 @@
20
20
  * Faithful to the producers:
21
21
  * - `packages/api/src/utils/serializeApplication.ts` `serializePublicApplication`
22
22
  * — the ONLY shape returned to an unauthenticated consent UI. Optional fields
23
- * (`description`, `icon`, `websiteUrl`, `developerName`) are OMITTED when
24
- * absent (never serialized as `null`), so they are `.optional()` — NOT
25
- * `.nullable()`. `type` is the `Application.type` enum.
23
+ * (`description`, `icon`, `websiteUrl`, `privacyPolicyUrl`, `termsUrl`,
24
+ * `developerName`) are OMITTED when absent (never serialized as `null`), so
25
+ * they are `.optional()` — NOT `.nullable()`. `type` is the `Application.type`
26
+ * enum.
26
27
  * - `packages/api/src/routes/auth.ts` `GET /session/status/:sessionToken` — the
27
28
  * inner object of the API's `{ data: ... }` success envelope. The handler
28
29
  * ALWAYS emits `status`, `authorized` (`status === 'authorized'`),
@@ -55,9 +56,10 @@ exports.applicationTypeSchema = zod_1.z.enum([
55
56
  * `GET /auth/oauth/client/:clientId` (OAuth code flow).
56
57
  *
57
58
  * Optional fields are `.optional()` (NOT `.nullable()`): the serializer OMITS
58
- * `description` / `icon` / `websiteUrl` / `developerName` when the underlying
59
- * value is absent — it never writes `null` for them. `developerName` is only
60
- * attached for non-official apps when a name could be resolved.
59
+ * `description` / `icon` / `websiteUrl` / `privacyPolicyUrl` / `termsUrl` /
60
+ * `developerName` when the underlying value is absent — it never writes `null`
61
+ * for them. `developerName` is only attached for non-official apps when a name
62
+ * could be resolved.
61
63
  */
62
64
  exports.publicApplicationSchema = zod_1.z.object({
63
65
  id: zod_1.z.string(),
@@ -65,6 +67,8 @@ exports.publicApplicationSchema = zod_1.z.object({
65
67
  description: zod_1.z.string().optional(),
66
68
  icon: zod_1.z.string().optional(),
67
69
  websiteUrl: zod_1.z.string().optional(),
70
+ privacyPolicyUrl: zod_1.z.string().optional(),
71
+ termsUrl: zod_1.z.string().optional(),
68
72
  type: exports.applicationTypeSchema,
69
73
  isOfficial: zod_1.z.boolean(),
70
74
  isInternal: zod_1.z.boolean(),
@@ -17,7 +17,8 @@
17
17
  *
18
18
  * Faithful to the producers:
19
19
  * - `packages/api/src/utils/userTransform.ts` `formatUserResponse` — the
20
- * canonical serialization used by `/auth/refresh-all`, device sessions, etc.
20
+ * canonical serialization used by the device-first bootstrap/exchange
21
+ * endpoints (`deviceAuth.ts`), login/signup, device sessions, etc.
21
22
  * Emits `id` (NOT `_id`), forwards `username` verbatim (may be absent), and
22
23
  * emits `name` as the structured `{ first, last, full, displayName }`
23
24
  * subdocument.
@@ -25,14 +26,12 @@
25
26
  * `''`; `full` and `displayName` are Mongoose VIRTUALS. Formatted API
26
27
  * responses compose both fields, while raw-document responses may omit the
27
28
  * virtuals if the query did not materialise them.
28
- * - The `/auth/refresh-all` handler in `packages/api/src/routes/auth.ts`, whose
29
- * per-slot `authuser` is the numeric `oxy_rt_${authuser}` cookie slot.
30
29
  *
31
30
  * Platform-agnostic — zod only, no react/react-native/expo. ESM-safe (no
32
31
  * `require()`).
33
32
  */
34
33
  Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.deviceSessionsResponseSchema = exports.deviceSessionAccountSchema = exports.currentUserResponseSchema = exports.userProfileUpdateSchema = exports.userResponseSchema = exports.userNameSchema = void 0;
34
+ exports.deviceLinkedSessionsResponseSchema = exports.deviceLinkedSessionSchema = exports.currentUserResponseSchema = exports.userProfileUpdateSchema = exports.userResponseSchema = exports.userNameSchema = void 0;
36
35
  exports.resolveUserId = resolveUserId;
37
36
  exports.safeParseContract = safeParseContract;
38
37
  const zod_1 = require("zod");
@@ -151,13 +150,13 @@ exports.currentUserResponseSchema = zod_1.z.object({
151
150
  * session). Backs the multi-account chooser. The embedded user mirrors
152
151
  * `formatUserResponse`; it is nullable on slots that lost their user document.
153
152
  */
154
- exports.deviceSessionAccountSchema = zod_1.z.object({
153
+ exports.deviceLinkedSessionSchema = zod_1.z.object({
155
154
  sessionId: zod_1.z.string(),
156
155
  isCurrent: zod_1.z.boolean().optional(),
157
156
  user: exports.userResponseSchema.nullable().optional(),
158
157
  });
159
158
  /** Wire shape of `GET /session/device/sessions/:sessionId` (an array). */
160
- exports.deviceSessionsResponseSchema = zod_1.z.array(exports.deviceSessionAccountSchema);
159
+ exports.deviceLinkedSessionsResponseSchema = zod_1.z.array(exports.deviceLinkedSessionSchema);
161
160
  /**
162
161
  * Safely parse a value against a contract schema. Returns the parsed (typed)
163
162
  * value, or `null` when validation fails — the same ergonomics the auth app's