@oxy.so/contracts 4.16.0 → 4.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.
Files changed (113) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/accountEmail.js +12 -34
  3. package/dist/cjs/accountGraph.js +22 -320
  4. package/dist/cjs/agentKeys.js +11 -13
  5. package/dist/cjs/client/accountEmail.js +48 -0
  6. package/dist/cjs/client/accountGraph.js +323 -0
  7. package/dist/cjs/client/agentKeys.js +77 -0
  8. package/dist/cjs/client/check.js +466 -0
  9. package/dist/cjs/client/deviceBoot.js +22 -0
  10. package/dist/cjs/client/deviceDirectory.js +51 -0
  11. package/dist/cjs/client/deviceSession.js +63 -0
  12. package/dist/cjs/client/externalIdentity.js +19 -0
  13. package/dist/cjs/client/identity.js +45 -0
  14. package/dist/cjs/client/identityLink.js +55 -0
  15. package/dist/cjs/client/identityProof.js +109 -0
  16. package/dist/cjs/client/index.js +190 -0
  17. package/dist/cjs/client/organizations.js +114 -0
  18. package/dist/cjs/client/products.js +153 -0
  19. package/dist/cjs/client/recommendations.js +33 -0
  20. package/dist/cjs/client/reputation.js +41 -0
  21. package/dist/cjs/client/safety.js +15 -0
  22. package/dist/cjs/client/sessionStatus.js +23 -0
  23. package/dist/cjs/client/signIn.js +157 -0
  24. package/dist/cjs/client/userResponse.js +15 -0
  25. package/dist/cjs/client/username.js +173 -0
  26. package/dist/cjs/deviceSession.js +3 -16
  27. package/dist/cjs/identityLink.js +13 -34
  28. package/dist/cjs/identityProof.js +18 -106
  29. package/dist/cjs/organizations.js +21 -41
  30. package/dist/cjs/reputation.js +3 -34
  31. package/dist/cjs/signIn.js +33 -111
  32. package/dist/cjs/username.js +23 -158
  33. package/dist/esm/.tsbuildinfo +1 -1
  34. package/dist/esm/accountEmail.js +4 -32
  35. package/dist/esm/accountGraph.js +4 -309
  36. package/dist/esm/agentKeys.js +4 -10
  37. package/dist/esm/client/accountEmail.js +45 -0
  38. package/dist/esm/client/accountGraph.js +314 -0
  39. package/dist/esm/client/agentKeys.js +74 -0
  40. package/dist/esm/client/check.js +428 -0
  41. package/dist/esm/client/deviceBoot.js +19 -0
  42. package/dist/esm/client/deviceDirectory.js +48 -0
  43. package/dist/esm/client/deviceSession.js +60 -0
  44. package/dist/esm/client/externalIdentity.js +16 -0
  45. package/dist/esm/client/identity.js +42 -0
  46. package/dist/esm/client/identityLink.js +50 -0
  47. package/dist/esm/client/identityProof.js +104 -0
  48. package/dist/esm/client/index.js +37 -0
  49. package/dist/esm/client/organizations.js +111 -0
  50. package/dist/esm/client/products.js +150 -0
  51. package/dist/esm/client/recommendations.js +30 -0
  52. package/dist/esm/client/reputation.js +37 -0
  53. package/dist/esm/client/safety.js +12 -0
  54. package/dist/esm/client/sessionStatus.js +20 -0
  55. package/dist/esm/client/signIn.js +151 -0
  56. package/dist/esm/client/userResponse.js +12 -0
  57. package/dist/esm/client/username.js +167 -0
  58. package/dist/esm/deviceSession.js +1 -15
  59. package/dist/esm/identityLink.js +4 -27
  60. package/dist/esm/identityProof.js +4 -99
  61. package/dist/esm/organizations.js +4 -31
  62. package/dist/esm/reputation.js +1 -32
  63. package/dist/esm/signIn.js +4 -96
  64. package/dist/esm/username.js +4 -148
  65. package/dist/types/.tsbuildinfo +1 -1
  66. package/dist/types/accountEmail.d.ts +2 -34
  67. package/dist/types/accountGraph.d.ts +12 -208
  68. package/dist/types/agency.d.ts +24 -24
  69. package/dist/types/agentKeys.d.ts +8 -6
  70. package/dist/types/client/accountEmail.d.ts +44 -0
  71. package/dist/types/client/accountGraph.d.ts +203 -0
  72. package/dist/types/client/agentKeys.d.ts +113 -0
  73. package/dist/types/client/check.d.ts +184 -0
  74. package/dist/types/client/deviceBoot.d.ts +6 -0
  75. package/dist/types/client/deviceDirectory.d.ts +134 -0
  76. package/dist/types/client/deviceSession.d.ts +91 -0
  77. package/dist/types/client/externalIdentity.d.ts +14 -0
  78. package/dist/types/client/identity.d.ts +8 -0
  79. package/dist/types/client/identityLink.d.ts +21 -0
  80. package/dist/types/client/identityProof.d.ts +73 -0
  81. package/dist/types/client/index.d.ts +37 -0
  82. package/dist/types/client/organizations.d.ts +167 -0
  83. package/dist/types/client/products.d.ts +145 -0
  84. package/dist/types/client/recommendations.d.ts +27 -0
  85. package/dist/types/client/reputation.d.ts +28 -0
  86. package/dist/types/client/safety.d.ts +13 -0
  87. package/dist/types/client/sessionStatus.d.ts +19 -0
  88. package/dist/types/client/signIn.d.ts +107 -0
  89. package/dist/types/client/userResponse.d.ts +7 -0
  90. package/dist/types/client/username.d.ts +126 -0
  91. package/dist/types/deviceDirectory.d.ts +28 -28
  92. package/dist/types/deviceSession.d.ts +1 -12
  93. package/dist/types/externalIdentity.d.ts +11 -11
  94. package/dist/types/identityLink.d.ts +3 -11
  95. package/dist/types/identityProof.d.ts +2 -65
  96. package/dist/types/inference/decisions.d.ts +10 -10
  97. package/dist/types/inference/embeddings.d.ts +16 -16
  98. package/dist/types/inference/errors.d.ts +8 -8
  99. package/dist/types/inference/inbox.d.ts +8 -8
  100. package/dist/types/inference/privateAutoExecution.d.ts +6 -6
  101. package/dist/types/inference/realtime.d.ts +30 -30
  102. package/dist/types/inference/request.d.ts +28 -28
  103. package/dist/types/inference/streamEvents.d.ts +16 -16
  104. package/dist/types/inference/usage.d.ts +4 -4
  105. package/dist/types/oauth.d.ts +2 -2
  106. package/dist/types/organizations.d.ts +8 -10
  107. package/dist/types/products/billing.d.ts +3 -0
  108. package/dist/types/reputation.d.ts +1 -11
  109. package/dist/types/sessionStatus.d.ts +2 -2
  110. package/dist/types/signIn.d.ts +6 -89
  111. package/dist/types/userResponse.d.ts +20 -20
  112. package/dist/types/username.d.ts +1 -96
  113. package/package.json +20 -1
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ /**
3
+ * Product access, plans, checkout and subscription checks, without Zod.
4
+ * Schemas: `../products/*.ts`.
5
+ *
6
+ * Part of `@oxy.so/contracts/client`: never import `zod` here (see `./check.ts`).
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.productSubscriptionCancellationResultCheck = exports.cancelProductSubscriptionCheck = exports.subscriptionCreditGrantsResponseCheck = exports.productSubscriptionsResponseCheck = exports.personalPlanCheckoutResultCheck = exports.personalPlanCheckoutRequestCheck = exports.personalPlanCatalogueCheck = exports.subjectProductAccessCheck = exports.subjectProductAccessQueryCheck = void 0;
10
+ const check_1 = require("./check");
11
+ const identifier = (0, check_1.string)((0, check_1.minLength)(1), (0, check_1.maxLength)(160));
12
+ const displayName = (0, check_1.string)((0, check_1.minLength)(1), (0, check_1.maxLength)(100));
13
+ const count = (0, check_1.number)(check_1.int, check_1.nonnegative, check_1.safe);
14
+ const version = (0, check_1.number)(check_1.int, check_1.positive, check_1.safe);
15
+ const oxyAccountId = (0, check_1.branded)((0, check_1.string)((0, check_1.minLength)(1), (0, check_1.maxLength)(64)));
16
+ const actionKey = (0, check_1.string)((0, check_1.minLength)(8), (0, check_1.maxLength)(160), (0, check_1.pattern)(/^[a-zA-Z0-9_-]+$/));
17
+ const combination = (0, check_1.oneOf)(['maximum', 'sum', 'exclusive']);
18
+ const origin = (0, check_1.oneOf)(['individual', 'bundle']);
19
+ const period = (message) => (0, check_1.refine)((0, check_1.strictObject)({ start: (0, check_1.string)(check_1.datetime), end: (0, check_1.string)(check_1.datetime) }), (value) => Date.parse(value.end) > Date.parse(value.start), message);
20
+ const productBenefit = (0, check_1.discriminatedUnion)('kind', {
21
+ capability: (0, check_1.strictObject)({ kind: (0, check_1.literal)('capability'), productId: identifier, key: identifier }),
22
+ quota: (0, check_1.strictObject)({
23
+ kind: (0, check_1.literal)('quota'),
24
+ productId: identifier,
25
+ key: identifier,
26
+ unit: identifier,
27
+ included: count,
28
+ combination,
29
+ }),
30
+ });
31
+ exports.subjectProductAccessQueryCheck = (0, check_1.exact)()((0, check_1.strictObject)({
32
+ schemaVersion: (0, check_1.literal)(1),
33
+ subjectAccountId: oxyAccountId,
34
+ productId: identifier,
35
+ }));
36
+ exports.subjectProductAccessCheck = (0, check_1.exact)()((0, check_1.strictObject)({
37
+ schemaVersion: (0, check_1.literal)(1),
38
+ subjectAccountId: oxyAccountId,
39
+ productId: identifier,
40
+ evaluatedAt: (0, check_1.string)(check_1.datetime),
41
+ capabilities: (0, check_1.array)((0, check_1.strictObject)({ key: identifier, grantIds: (0, check_1.array)(identifier) })),
42
+ quotas: (0, check_1.array)((0, check_1.strictObject)({
43
+ key: identifier,
44
+ unit: identifier,
45
+ included: count,
46
+ combination,
47
+ grantIds: (0, check_1.array)(identifier),
48
+ })),
49
+ conflicts: (0, check_1.array)((0, check_1.strictObject)({
50
+ key: identifier,
51
+ reason: (0, check_1.oneOf)([
52
+ 'combination_mismatch',
53
+ 'unit_mismatch',
54
+ 'exclusive_overlap',
55
+ 'unsafe_total',
56
+ ]),
57
+ grantIds: (0, check_1.array)(identifier),
58
+ })),
59
+ }));
60
+ exports.personalPlanCatalogueCheck = (0, check_1.exact)()((0, check_1.refine)((0, check_1.strictObject)({
61
+ schemaVersion: (0, check_1.literal)(1),
62
+ state: (0, check_1.oneOf)(['unconfigured', 'configured']),
63
+ purchase: (0, check_1.literal)('unavailable'),
64
+ plans: (0, check_1.array)((0, check_1.strictObject)({
65
+ offerId: identifier,
66
+ offerVersion: version,
67
+ displayName,
68
+ audience: (0, check_1.literal)('personal'),
69
+ kind: (0, check_1.literal)('oxy_one'),
70
+ price: (0, check_1.optional)((0, check_1.strictObject)({
71
+ currency: (0, check_1.string)((0, check_1.pattern)(/^[A-Z]{3}$/)),
72
+ amountMinorUnits: version,
73
+ interval: (0, check_1.literal)('month'),
74
+ trial: (0, check_1.literal)('none'),
75
+ taxTreatment: (0, check_1.literal)('inclusive'),
76
+ merchantTotal: (0, check_1.literal)('final'),
77
+ })),
78
+ benefits: (0, check_1.array)((0, check_1.strictObject)({ displayName, benefit: productBenefit })),
79
+ })),
80
+ }), (value) => (value.state === 'unconfigured') === (value.plans.length === 0), 'Catalogue state must match published plans'));
81
+ exports.personalPlanCheckoutRequestCheck = (0, check_1.exact)()((0, check_1.strictObject)({
82
+ expectedSubjectAccountId: oxyAccountId,
83
+ offerId: identifier,
84
+ offerVersion: version,
85
+ idempotencyKey: actionKey,
86
+ }));
87
+ exports.personalPlanCheckoutResultCheck = (0, check_1.exact)()((0, check_1.discriminatedUnion)('state', {
88
+ unconfigured: (0, check_1.strictObject)({
89
+ state: (0, check_1.literal)('unconfigured'),
90
+ reason: (0, check_1.oneOf)(['provider_unconfigured', 'offer_unconfigured', 'price_unconfigured']),
91
+ }),
92
+ pending: (0, check_1.strictObject)({
93
+ state: (0, check_1.literal)('pending'),
94
+ intentId: identifier,
95
+ checkoutUrl: (0, check_1.optional)((0, check_1.string)(check_1.url, (0, check_1.startsWith)('https://'))),
96
+ }),
97
+ closed: (0, check_1.strictObject)({ state: (0, check_1.literal)('closed'), intentId: identifier }),
98
+ fulfilled: (0, check_1.strictObject)({ state: (0, check_1.literal)('fulfilled'), intentId: identifier }),
99
+ }));
100
+ const billingPeriod = period('Period end must follow start');
101
+ exports.productSubscriptionsResponseCheck = (0, check_1.exact)()((0, check_1.strictObject)({
102
+ subscriptions: (0, check_1.array)((0, check_1.strictObject)({
103
+ sourceId: identifier,
104
+ status: (0, check_1.oneOf)([
105
+ 'active',
106
+ 'trialing',
107
+ 'past_due',
108
+ 'unpaid',
109
+ 'canceled',
110
+ 'paused',
111
+ 'incomplete',
112
+ 'incomplete_expired',
113
+ ]),
114
+ period: billingPeriod,
115
+ cancelAtPeriodEnd: check_1.boolean,
116
+ canCancel: check_1.boolean,
117
+ offers: (0, check_1.array)((0, check_1.strictObject)({
118
+ segmentId: identifier,
119
+ offerId: identifier,
120
+ offerVersion: version,
121
+ displayName,
122
+ origin,
123
+ period: billingPeriod,
124
+ current: check_1.boolean,
125
+ products: (0, check_1.array)((0, check_1.strictObject)({ id: identifier, displayName })),
126
+ })),
127
+ })),
128
+ }));
129
+ exports.subscriptionCreditGrantsResponseCheck = (0, check_1.exact)()((0, check_1.strictObject)({
130
+ grants: (0, check_1.array)((0, check_1.refine)((0, check_1.strictObject)({
131
+ id: identifier,
132
+ invoiceId: identifier,
133
+ origin: (0, check_1.oneOf)([
134
+ 'subscription_payment',
135
+ 'subscription_proration',
136
+ 'subscription_promotional_grant',
137
+ ]),
138
+ period: billingPeriod,
139
+ granted: count,
140
+ consumed: count,
141
+ clawed: count,
142
+ remaining: count,
143
+ promotionId: (0, check_1.nullable)(identifier),
144
+ createdAt: (0, check_1.string)(check_1.datetime),
145
+ }), (value) => BigInt(value.consumed) + BigInt(value.clawed) + BigInt(value.remaining) ===
146
+ BigInt(value.granted), 'Grant conservation differs')),
147
+ }));
148
+ exports.cancelProductSubscriptionCheck = (0, check_1.exact)()((0, check_1.strictObject)({
149
+ sourceId: identifier,
150
+ actionId: (0, check_1.optional)(actionKey),
151
+ expectedSubjectAccountId: (0, check_1.optional)(oxyAccountId),
152
+ }));
153
+ exports.productSubscriptionCancellationResultCheck = (0, check_1.exact)()((0, check_1.union)((0, check_1.strictObject)({ sourceId: identifier, cancelAtPeriodEnd: (0, check_1.literal)(true) }), (0, check_1.strictObject)({ sourceId: identifier, reconciliationPending: (0, check_1.literal)(true) })));
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ /**
3
+ * The recommendation-request check, without Zod. Schemas: `../recommendations.ts`.
4
+ *
5
+ * Part of `@oxy.so/contracts/client`: never import `zod` here (see `./check.ts`).
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.recommendationRequestCheck = void 0;
9
+ const check_1 = require("./check");
10
+ const id = (0, check_1.string)(check_1.trim, (0, check_1.minLength)(1));
11
+ const weight = (0, check_1.optional)((0, check_1.number)((0, check_1.atLeast)(0), (0, check_1.atMost)(10)));
12
+ exports.recommendationRequestCheck = (0, check_1.exact)()((0, check_1.object)({
13
+ clientId: (0, check_1.optional)((0, check_1.string)(check_1.trim, (0, check_1.minLength)(1))),
14
+ limit: (0, check_1.optional)((0, check_1.number)(check_1.int, (0, check_1.atLeast)(1), (0, check_1.atMost)(100))),
15
+ offset: (0, check_1.optional)((0, check_1.number)(check_1.int, (0, check_1.atLeast)(0))),
16
+ excludeTypes: (0, check_1.optional)((0, check_1.array)((0, check_1.oneOf)(['federated', 'agent', 'automated']))),
17
+ excludeIds: (0, check_1.optional)((0, check_1.array)(id, (0, check_1.maxItems)(500))),
18
+ boosts: (0, check_1.optional)((0, check_1.array)((0, check_1.object)({
19
+ userIds: (0, check_1.array)(id, (0, check_1.minItems)(1), (0, check_1.maxItems)(200)),
20
+ weight: (0, check_1.number)((0, check_1.atLeast)(-5), (0, check_1.atMost)(5)),
21
+ reason: (0, check_1.optional)((0, check_1.string)(check_1.trim, (0, check_1.maxLength)(120))),
22
+ }), (0, check_1.maxItems)(50))),
23
+ signalWeights: (0, check_1.optional)((0, check_1.object)({
24
+ graph: weight,
25
+ completeness: weight,
26
+ verified: weight,
27
+ curation: weight,
28
+ interest: weight,
29
+ appBoost: weight,
30
+ repCandidate: weight,
31
+ affinity: weight,
32
+ })),
33
+ }));
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ /**
3
+ * The reputation view guard, without Zod. Schemas: `../reputation.ts`.
4
+ *
5
+ * Part of `@oxy.so/contracts/client`: never import `zod` here (see `./check.ts`).
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.FULL_BALANCE_FIELDS = void 0;
9
+ exports.isFullReputationBalance = isFullReputationBalance;
10
+ /**
11
+ * The fields the full {@link ReputationBalance} carries beyond the public
12
+ * {@link ReputationBalanceSummary} that the API sends ALL-OR-NOTHING. The
13
+ * runtime discriminant between the two views.
14
+ *
15
+ * The V2 blocks (`conduct`, `contribution`, …) are deliberately NOT listed:
16
+ * they are optional on the wire, so requiring them here would make a balance
17
+ * from a server that predates them fail to narrow, hiding the whole private
18
+ * view. Read a V2 block by checking that block.
19
+ */
20
+ exports.FULL_BALANCE_FIELDS = [
21
+ 'positive',
22
+ 'negative',
23
+ 'breakdown',
24
+ 'influence',
25
+ 'reliability',
26
+ 'recalculatedAt',
27
+ 'updatedAt',
28
+ ];
29
+ /**
30
+ * Whether a balance came back as the SUBJECT view, and so carries the
31
+ * breakdown / influence / reliability blocks.
32
+ *
33
+ * Checks every extra field rather than one representative: the point of the
34
+ * guard is that the caller then dereferences those blocks, so a partial payload
35
+ * must not narrow.
36
+ *
37
+ * @param balance - A balance from `getReputationBalance`.
38
+ */
39
+ function isFullReputationBalance(balance) {
40
+ return exports.FULL_BALANCE_FIELDS.every((field) => field in balance);
41
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ /**
3
+ * Profile-access checks, without Zod. Schemas: `../safety.ts`.
4
+ *
5
+ * Part of `@oxy.so/contracts/client`: never import `zod` here (see `./check.ts`).
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.profileAccessDecisionCheck = exports.profileAccessInputCheck = void 0;
9
+ const check_1 = require("./check");
10
+ exports.profileAccessInputCheck = (0, check_1.exact)()((0, check_1.strictObject)({ subjectAccountId: (0, check_1.string)((0, check_1.minLength)(1), (0, check_1.maxLength)(128)) }));
11
+ exports.profileAccessDecisionCheck = (0, check_1.exact)()((0, check_1.strictObject)({
12
+ allowed: check_1.boolean,
13
+ reason: (0, check_1.oneOf)(['public', 'owner', 'private', 'blocked', 'unavailable']),
14
+ policyVersion: (0, check_1.literal)('1'),
15
+ }));
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /**
3
+ * The public-application check, without Zod. Schemas: `../sessionStatus.ts`.
4
+ *
5
+ * Part of `@oxy.so/contracts/client`: never import `zod` here (see `./check.ts`).
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.publicApplicationCheck = void 0;
9
+ const check_1 = require("./check");
10
+ exports.publicApplicationCheck = (0, check_1.exact)()((0, check_1.object)({
11
+ id: (0, check_1.string)(),
12
+ name: (0, check_1.string)(),
13
+ description: (0, check_1.optional)((0, check_1.string)()),
14
+ icon: (0, check_1.optional)((0, check_1.string)()),
15
+ websiteUrl: (0, check_1.optional)((0, check_1.string)()),
16
+ privacyPolicyUrl: (0, check_1.optional)((0, check_1.string)()),
17
+ termsUrl: (0, check_1.optional)((0, check_1.string)()),
18
+ type: (0, check_1.oneOf)(['first_party', 'third_party', 'internal', 'system']),
19
+ isOfficial: check_1.boolean,
20
+ isInternal: check_1.boolean,
21
+ scopes: (0, check_1.array)((0, check_1.string)()),
22
+ developerName: (0, check_1.optional)((0, check_1.string)()),
23
+ }));
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ /**
3
+ * Sign-in constants, guards and response checks, without Zod. Schemas: `../signIn.ts`.
4
+ *
5
+ * Part of `@oxy.so/contracts/client`: never import `zod` here (see `./check.ts`).
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.reauthProofCheck = exports.totpBackupCodesResponseCheck = exports.totpEnrollResponseCheck = exports.signInMethodsCheck = exports.emailSignInChooseAccountCheck = exports.emailSignInPendingCheck = exports.secondFactorRequiredCheck = exports.emailSignInLinkResponseCheck = exports.emailSignInStartResponseCheck = exports.SIGN_IN_ERROR_CODES = exports.REAUTH_ACTIONS = exports.EMAIL_ACCOUNTS_MAX = exports.EMAIL_SIGNIN_CHOICE_TTL_MS = exports.EMAIL_SIGNIN_LONG_CODE_LENGTH = exports.EMAIL_SIGNIN_LONG_CODE_ALPHABET = exports.TOTP_BACKUP_CODE_COUNT = exports.TOTP_PERIOD_SECONDS = exports.TOTP_DIGITS = exports.PASSWORD_MAX_LENGTH = exports.PASSWORD_MIN_LENGTH = exports.SIGNIN_SECOND_FACTOR_MAX_ATTEMPTS = exports.SIGNIN_SECOND_FACTOR_TTL_MS = exports.EMAIL_SIGNIN_LINK_TTL_MS = void 0;
9
+ exports.normalizeEmailSignInCode = normalizeEmailSignInCode;
10
+ exports.isSecondFactorRequired = isSecondFactorRequired;
11
+ exports.isEmailSignInChooseAccount = isEmailSignInChooseAccount;
12
+ const accountEmail_1 = require("./accountEmail");
13
+ const check_1 = require("./check");
14
+ /** How long the link in a sign-in email can be opened. */
15
+ exports.EMAIL_SIGNIN_LINK_TTL_MS = 15 * 60 * 1000;
16
+ /** How long a second-factor challenge can be answered. */
17
+ exports.SIGNIN_SECOND_FACTOR_TTL_MS = 5 * 60 * 1000;
18
+ /** Wrong second-factor codes one challenge accepts. */
19
+ exports.SIGNIN_SECOND_FACTOR_MAX_ATTEMPTS = 5;
20
+ /** Shortest password Oxy accepts when one is set. */
21
+ exports.PASSWORD_MIN_LENGTH = 10;
22
+ /** Longest password Oxy accepts (characters). */
23
+ exports.PASSWORD_MAX_LENGTH = 256;
24
+ /** Digits in an authenticator code. */
25
+ exports.TOTP_DIGITS = 6;
26
+ /** Seconds each authenticator code lasts. */
27
+ exports.TOTP_PERIOD_SECONDS = 30;
28
+ /** Backup codes issued when an authenticator is enabled or they are regenerated. */
29
+ exports.TOTP_BACKUP_CODE_COUNT = 10;
30
+ /**
31
+ * The long sign-in code: ten characters of Crockford base32 without the
32
+ * look-alikes (no 0, O, 1, I, L, U), shown as `XXXXX-XXXXX`. An account whose
33
+ * sign-in codes were guessed at too often today (the per-account ceiling) is
34
+ * sent this instead of 6 digits for the rest of the day, so its owner can still
35
+ * type a code while guessing one is infeasible.
36
+ */
37
+ exports.EMAIL_SIGNIN_LONG_CODE_ALPHABET = '23456789ABCDEFGHJKMNPQRSTVWXYZ';
38
+ exports.EMAIL_SIGNIN_LONG_CODE_LENGTH = 10;
39
+ /**
40
+ * Normalise a typed sign-in code: 6 digits stay as they are; a long code is
41
+ * upper-cased with its dash and spaces removed. Anything else is returned
42
+ * trimmed (and will simply be wrong).
43
+ */
44
+ function normalizeEmailSignInCode(code) {
45
+ const compact = code.trim().replace(/[\s-]/g, '').toUpperCase();
46
+ return compact;
47
+ }
48
+ /**
49
+ * How long, once the email is proven, the person has to choose which of its
50
+ * accounts signs in.
51
+ */
52
+ exports.EMAIL_SIGNIN_CHOICE_TTL_MS = 5 * 60 * 1000;
53
+ /** Most accounts one email can hold; sign-up refuses another past it. */
54
+ exports.EMAIL_ACCOUNTS_MAX = 20;
55
+ /** Narrow a {@link SignInStepResult}. */
56
+ function isSecondFactorRequired(result) {
57
+ return result.secondFactorRequired === true;
58
+ }
59
+ /** Narrow an {@link EmailSignInStepResult}. */
60
+ function isEmailSignInChooseAccount(result) {
61
+ return result.chooseAccount === true;
62
+ }
63
+ /**
64
+ * What a re-verification email code confirms. The code is bound to it: a code
65
+ * asked for one change never authorises another, and the email names it.
66
+ */
67
+ exports.REAUTH_ACTIONS = [
68
+ 'change_password',
69
+ 'totp',
70
+ 'link_commons',
71
+ 'delete_account',
72
+ 'credentials_manage',
73
+ ];
74
+ /**
75
+ * Stable error codes (`error.code` in the API error body). Clients map these
76
+ * through their localization, never the English message.
77
+ */
78
+ exports.SIGN_IN_ERROR_CODES = {
79
+ /** Wrong identifier or password — never says which. */
80
+ invalidCredentials: 'SIGNIN_INVALID_CREDENTIALS',
81
+ /** The request is unknown, expired, spent, or its secret is wrong. */
82
+ requestInvalid: 'SIGNIN_REQUEST_INVALID',
83
+ /** The link is unknown, expired or already used. */
84
+ linkInvalid: 'SIGNIN_LINK_INVALID',
85
+ /** The link was opened in another browser: type the code in the app instead. */
86
+ linkOtherDevice: 'SIGNIN_LINK_OTHER_DEVICE',
87
+ /** The second-factor challenge or its code is wrong, expired or spent. */
88
+ secondFactorInvalid: 'SECOND_FACTOR_INVALID',
89
+ /** Too many failures for this account: wait and try again. */
90
+ locked: 'SIGNIN_LOCKED',
91
+ /** The step needs a fresh proof (`reauth`). */
92
+ reauthRequired: 'REAUTH_REQUIRED',
93
+ /** The fresh proof was wrong. */
94
+ reauthInvalid: 'REAUTH_INVALID',
95
+ /** The account has an authenticator: the proof must carry its code. */
96
+ totpRequired: 'TOTP_REQUIRED',
97
+ /** Enrolling or confirming an authenticator that is already on. */
98
+ totpAlreadyEnabled: 'TOTP_ALREADY_ENABLED',
99
+ /** Disabling, confirming or regenerating codes with no authenticator (or no pending one). */
100
+ totpNotEnabled: 'TOTP_NOT_ENABLED',
101
+ /** The code the authenticator showed at enrolment is wrong. */
102
+ totpCodeInvalid: 'TOTP_CODE_INVALID',
103
+ /** Only official Oxy apps and auth.oxy.so may sign people in here. */
104
+ originNotAllowed: 'SIGNIN_ORIGIN_NOT_ALLOWED',
105
+ /** The username is taken. */
106
+ usernameTaken: 'USERNAME_TAKEN',
107
+ /** The email already holds `EMAIL_ACCOUNTS_MAX` accounts: no sign-up adds another. */
108
+ emailAccountsFull: 'EMAIL_ACCOUNTS_FULL',
109
+ };
110
+ /* -------------------------------------------------------------------------- */
111
+ /* Checks */
112
+ /* -------------------------------------------------------------------------- */
113
+ const expiresAt = (0, check_1.number)(check_1.int, check_1.positive);
114
+ const sixDigits = (0, check_1.string)(check_1.trim, (0, check_1.pattern)(new RegExp(`^\\d{${accountEmail_1.EMAIL_CODE_LENGTH}}$`), `code must be ${accountEmail_1.EMAIL_CODE_LENGTH} digits`));
115
+ const passwordInput = (0, check_1.string)((0, check_1.minLength)(1), (0, check_1.maxLength)(exports.PASSWORD_MAX_LENGTH));
116
+ const secondFactorCode = (0, check_1.string)(check_1.trim, (0, check_1.minLength)(exports.TOTP_DIGITS), (0, check_1.maxLength)(16));
117
+ exports.emailSignInStartResponseCheck = (0, check_1.exact)()((0, check_1.object)({
118
+ requestId: (0, check_1.string)((0, check_1.minLength)(1), (0, check_1.maxLength)(64)),
119
+ requestSecret: accountEmail_1.emailTicketCheck,
120
+ expiresAt,
121
+ retryLater: (0, check_1.optional)((0, check_1.literal)(true)),
122
+ }));
123
+ exports.emailSignInLinkResponseCheck = (0, check_1.exact)()((0, check_1.object)({ approved: (0, check_1.literal)(true) }));
124
+ exports.secondFactorRequiredCheck = (0, check_1.exact)()((0, check_1.object)({ secondFactorRequired: (0, check_1.literal)(true), challengeId: accountEmail_1.emailTicketCheck, expiresAt }));
125
+ exports.emailSignInPendingCheck = (0, check_1.exact)()((0, check_1.object)({ status: (0, check_1.literal)('pending'), expiresAt }));
126
+ const emailSignInAccountOption = (0, check_1.exact)()((0, check_1.object)({
127
+ id: (0, check_1.string)((0, check_1.minLength)(1), (0, check_1.maxLength)(64)),
128
+ username: (0, check_1.optional)((0, check_1.string)((0, check_1.minLength)(1))),
129
+ displayName: (0, check_1.optional)((0, check_1.string)((0, check_1.minLength)(1))),
130
+ avatar: (0, check_1.optional)((0, check_1.string)((0, check_1.minLength)(1))),
131
+ }));
132
+ exports.emailSignInChooseAccountCheck = (0, check_1.exact)()((0, check_1.object)({
133
+ chooseAccount: (0, check_1.literal)(true),
134
+ accounts: (0, check_1.array)(emailSignInAccountOption, (0, check_1.minItems)(2), (0, check_1.maxItems)(exports.EMAIL_ACCOUNTS_MAX)),
135
+ expiresAt,
136
+ }));
137
+ exports.signInMethodsCheck = (0, check_1.exact)()((0, check_1.object)({
138
+ hasEmail: check_1.boolean,
139
+ hasPassword: check_1.boolean,
140
+ totpEnabled: check_1.boolean,
141
+ backupCodesRemaining: (0, check_1.number)(check_1.int, check_1.nonnegative),
142
+ }));
143
+ exports.totpEnrollResponseCheck = (0, check_1.exact)()((0, check_1.object)({
144
+ secret: (0, check_1.string)((0, check_1.pattern)(/^[A-Z2-7]+$/)),
145
+ otpauthUri: (0, check_1.string)((0, check_1.startsWith)('otpauth://totp/')),
146
+ }));
147
+ exports.totpBackupCodesResponseCheck = (0, check_1.exact)()((0, check_1.object)({
148
+ backupCodes: (0, check_1.array)((0, check_1.string)((0, check_1.pattern)(/^[a-z2-9]{5}-[a-z2-9]{5}$/)), (0, check_1.exactItems)(exports.TOTP_BACKUP_CODE_COUNT)),
149
+ }));
150
+ exports.reauthProofCheck = (0, check_1.exact)()((0, check_1.refine)((0, check_1.strictObject)({
151
+ password: (0, check_1.optional)(passwordInput),
152
+ emailCode: (0, check_1.optional)((0, check_1.strictObject)({
153
+ verificationId: (0, check_1.string)(check_1.trim, (0, check_1.minLength)(1), (0, check_1.maxLength)(64)),
154
+ code: sixDigits,
155
+ })),
156
+ totpCode: (0, check_1.optional)(secondFactorCode),
157
+ }), (proof) => proof.password !== undefined || proof.emailCode !== undefined, 'password or emailCode is required'));
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ /**
3
+ * User-response checks, without Zod. Schemas: `../userResponse.ts`.
4
+ *
5
+ * Part of `@oxy.so/contracts/client`: never import `zod` here (see `./check.ts`).
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.userNameCheck = void 0;
9
+ const check_1 = require("./check");
10
+ exports.userNameCheck = (0, check_1.exact)()((0, check_1.looseObject)({
11
+ first: (0, check_1.optional)((0, check_1.string)()),
12
+ last: (0, check_1.optional)((0, check_1.string)()),
13
+ full: (0, check_1.optional)((0, check_1.string)()),
14
+ displayName: (0, check_1.optional)((0, check_1.string)()),
15
+ }));
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ /**
3
+ * The username policy, without Zod. Schemas: `../username.ts`.
4
+ *
5
+ * Part of `@oxy.so/contracts/client`: never import `zod` here (see `./check.ts`).
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.botUsernameCheck = exports.usernameCheck = exports.BOT_USERNAME_INVALID_MESSAGE = exports.BOT_USERNAME_SUFFIX = exports.USERNAME_PATTERN = exports.USERNAME_PATTERN_SOURCE = exports.NUMERIC_USERNAME_MESSAGE = exports.RESERVED_USERNAME_SEGMENTS = exports.RESERVED_USERNAME_MESSAGE = exports.RESERVED_USERNAMES = exports.USERNAME_INVALID_MESSAGE = exports.USERNAME_MAX_LENGTH = exports.USERNAME_MIN_LENGTH = void 0;
9
+ exports.stripDisallowedUsernameCharacters = stripDisallowedUsernameCharacters;
10
+ exports.applyBotUsernameSuffix = applyBotUsernameSuffix;
11
+ exports.usernameCheckForAccountKind = usernameCheckForAccountKind;
12
+ const check_1 = require("./check");
13
+ /** Shortest storable handle. `oxy` sets the floor. */
14
+ exports.USERNAME_MIN_LENGTH = 3;
15
+ /** Longest storable handle, and the `maxLength` an input field should carry. */
16
+ exports.USERNAME_MAX_LENGTH = 30;
17
+ /** The 400 / inline-validation copy for every path that rejects a handle. */
18
+ exports.USERNAME_INVALID_MESSAGE = 'Username must be 3-30 characters, use only letters, numbers, hyphens and underscores, ' +
19
+ 'start and end with a letter or number, and never repeat a separator';
20
+ /**
21
+ * Exact-match handles nobody may newly claim, regardless of account kind.
22
+ *
23
+ * This is NOT a namespace tightening like the bot suffix — it is a list of
24
+ * names withheld from `users_lower_username_key` before anybody asks for
25
+ * them. Compared against the same normalization the unique index applies
26
+ * (`lower(btrim(username))`), so `Admin`, ` ADMIN ` and `admin` are the one
27
+ * name this list means.
28
+ *
29
+ * `oxy`, `mention`, `homiio`, `clarity`, `faircoin`, `astro` and `mercaria`
30
+ * are deliberately NOT here: each already has an `organization`/`project`
31
+ * row, so the unique index already refuses a second one, and `oxy` is the
32
+ * name `USERNAME_MIN_LENGTH` is pinned against in
33
+ * `__tests__/username.test.ts` — listing it would make
34
+ * `usernameSchema.safeParse('oxy')` fail and falsify that comment. A brand
35
+ * with no account of its own yet (measured 2026-09-18: Alia, Allo, TNP,
36
+ * Kaana, Bloom) has no row to protect it, so it is listed until one exists.
37
+ */
38
+ exports.RESERVED_USERNAMES = new Set([
39
+ // Oxy product lines with no account row of their own yet.
40
+ 'alia',
41
+ 'allo',
42
+ 'tnp',
43
+ 'kaana',
44
+ 'bloom',
45
+ // System / role words a signup impersonating staff or Oxy itself would reach for.
46
+ 'admin',
47
+ 'administrator',
48
+ 'root',
49
+ 'superadmin',
50
+ 'super',
51
+ 'superuser',
52
+ 'support',
53
+ 'staff',
54
+ 'moderator',
55
+ 'mod',
56
+ 'security',
57
+ 'system',
58
+ 'official',
59
+ 'help',
60
+ 'noreply',
61
+ 'anonymous',
62
+ 'everyone',
63
+ 'owner',
64
+ ]);
65
+ /** The 400 / inline-validation copy for a handle on {@link RESERVED_USERNAMES}. */
66
+ exports.RESERVED_USERNAME_MESSAGE = 'This username is reserved and cannot be registered';
67
+ /**
68
+ * {@link RESERVED_USERNAMES}, minus `alia`, checked against each `-`/`_`
69
+ * separated SEGMENT of a candidate rather than the whole string — so
70
+ * `official-oxy`, `super-admin` and `team-kaana` are refused the same as the
71
+ * bare words, without banning every word that merely CONTAINS one as a
72
+ * substring (`superman`, `modern`, `grassroot`, `homeowner` all stay legal:
73
+ * none of them separates the reserved word from the rest with `-` or `_`).
74
+ *
75
+ * `alia` is excluded because `alia-` is the live internal-cost-centre
76
+ * namespace: `alia-production-chat` is a minted account and
77
+ * `alia-research` / `alia-voice` / `alia-evaluations` are pinned as legal
78
+ * slugs in `__tests__/username.test.ts` and `internalCostCenterSpecs.test.ts`.
79
+ * Segment-matching `alia` would refuse all four. The bare word `alia` is
80
+ * still refused — {@link RESERVED_USERNAMES} above catches it exactly.
81
+ */
82
+ exports.RESERVED_USERNAME_SEGMENTS = new Set([...exports.RESERVED_USERNAMES].filter((word) => word !== 'alia'));
83
+ /** The 400 / inline-validation copy for a handle that is only digits. */
84
+ exports.NUMERIC_USERNAME_MESSAGE = 'Username cannot be only numbers';
85
+ /**
86
+ * Alphanumeric runs joined by single separators, as a SOURCE string.
87
+ *
88
+ * A string rather than a literal because the OpenAPI docblocks that publish this
89
+ * rule (`POST /auth/register`, `PUT /users/:userId`) must quote it verbatim, and
90
+ * `usernamePolicySingleSource.test.ts` compares them against THIS constant. A
91
+ * published `pattern:` that drifts from the enforced rule is a lie told to every
92
+ * client that generates from the spec, and it is exactly the kind of copy nobody
93
+ * notices going stale.
94
+ *
95
+ * Deliberately NOT re-exported from the package barrel: it exists for the
96
+ * schema below and for that one gate. Anything validating a username uses
97
+ * {@link usernameSchema}, so there is no second way to ask the question.
98
+ *
99
+ * Written as an unambiguous alternation rather than a lookahead: every character
100
+ * belongs to exactly one branch, so matching is linear and there is no
101
+ * backtracking to bound. It also carries no `\p{…}` property escape, which
102
+ * mobile Hermes throws on at runtime — this module is reachable from every React
103
+ * Native consumer.
104
+ */
105
+ exports.USERNAME_PATTERN_SOURCE = '^[A-Za-z0-9]+(?:[-_][A-Za-z0-9]+)*$';
106
+ exports.USERNAME_PATTERN = new RegExp(exports.USERNAME_PATTERN_SOURCE);
107
+ /**
108
+ * Drop the characters the policy forbids, for an input field that filters
109
+ * keystrokes.
110
+ *
111
+ * This is a TYPING aid and nothing else — the result still has to pass
112
+ * {@link usernameSchema}, which is what decides. It does not lower-case (case is
113
+ * preserved, see the header) and it cannot repair a name: a value that is too
114
+ * short, edge-separated or doubly-separated comes back unchanged and fails
115
+ * validation with a message, which is the outcome the coercing rules this
116
+ * replaces used to hide.
117
+ */
118
+ function stripDisallowedUsernameCharacters(input) {
119
+ return input.replace(/[^A-Za-z0-9_-]/g, '');
120
+ }
121
+ /**
122
+ * The label a bot's handle ends in — the ONE exception the policy carries.
123
+ *
124
+ * Lower-case here because it is what a generator appends; the comparison that
125
+ * enforces it folds case, so `MyBot` satisfies it just as `mybot` does.
126
+ *
127
+ * Deliberately NOT re-exported from the package barrel, for the same reason
128
+ * {@link USERNAME_PATTERN_SOURCE} is not: it exists for the schema and the
129
+ * generator aid below. A consumer that wants to SAY the rule uses
130
+ * {@link BOT_USERNAME_INVALID_MESSAGE}, which already quotes it, and one that
131
+ * wants to APPLY it uses {@link applyBotUsernameSuffix} — so there is no second
132
+ * way to spell the check.
133
+ */
134
+ exports.BOT_USERNAME_SUFFIX = 'bot';
135
+ /** The 400 / inline-validation copy for a bot handle that carries no label. */
136
+ exports.BOT_USERNAME_INVALID_MESSAGE = `A bot account's username must end in "${exports.BOT_USERNAME_SUFFIX}"`;
137
+ /**
138
+ * Label a proposed bot handle, so a generator PROPOSES something the server will
139
+ * accept.
140
+ *
141
+ * Alia builds an agent's handle from its display name; without this it would
142
+ * propose `garden-helper` for a bot and be 400ed on submit, which is the same
143
+ * "suggest, then refuse" defect the minimum length already caused once.
144
+ *
145
+ * It appends and never inserts: a separator is the caller's choice, so
146
+ * `garden-helper` becomes `garden-helperbot` while a caller who typed
147
+ * `garden-helper-` gets `garden-helper-bot`. It truncates to leave room rather
148
+ * than overflowing {@link USERNAME_MAX_LENGTH}.
149
+ *
150
+ * Like {@link stripDisallowedUsernameCharacters} it is an aid, not a decision: it
151
+ * cannot repair a handle the base policy refuses, and the result still has to
152
+ * pass {@link botUsernameSchema}.
153
+ */
154
+ function applyBotUsernameSuffix(candidate) {
155
+ const trimmed = candidate.trim();
156
+ if (trimmed.toLowerCase().endsWith(exports.BOT_USERNAME_SUFFIX)) {
157
+ return trimmed;
158
+ }
159
+ return trimmed.slice(0, exports.USERNAME_MAX_LENGTH - exports.BOT_USERNAME_SUFFIX.length) + exports.BOT_USERNAME_SUFFIX;
160
+ }
161
+ /* -------------------------------------------------------------------------- */
162
+ /* Checks */
163
+ /* -------------------------------------------------------------------------- */
164
+ /** The username policy as a check — the twin of `usernameSchema`, same messages. */
165
+ exports.usernameCheck = (0, check_1.refine)((0, check_1.refine)((0, check_1.refine)((0, check_1.string)(check_1.trim, (0, check_1.minLength)(exports.USERNAME_MIN_LENGTH, exports.USERNAME_INVALID_MESSAGE), (0, check_1.maxLength)(exports.USERNAME_MAX_LENGTH, exports.USERNAME_INVALID_MESSAGE), (0, check_1.pattern)(exports.USERNAME_PATTERN, exports.USERNAME_INVALID_MESSAGE)), (username) => !/^[0-9]+$/.test(username), exports.NUMERIC_USERNAME_MESSAGE), (username) => !exports.RESERVED_USERNAMES.has(username.toLowerCase()), exports.RESERVED_USERNAME_MESSAGE), (username) => !username
166
+ .split(/[-_]/)
167
+ .some((segment) => exports.RESERVED_USERNAME_SEGMENTS.has(segment.toLowerCase())), exports.RESERVED_USERNAME_MESSAGE);
168
+ /** A bot's username: the policy plus the `bot` suffix — the twin of `botUsernameSchema`. */
169
+ exports.botUsernameCheck = (0, check_1.refine)(exports.usernameCheck, (username) => username.toLowerCase().endsWith(exports.BOT_USERNAME_SUFFIX), exports.BOT_USERNAME_INVALID_MESSAGE);
170
+ /** The twin of `usernameSchemaForAccountKind`. */
171
+ function usernameCheckForAccountKind(kind) {
172
+ return kind === 'bot' ? exports.botUsernameCheck : exports.usernameCheck;
173
+ }
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deviceJoinResponseSchema = exports.deviceJoinRequestSchema = exports.deviceJoinCodeResponseSchema = exports.deviceJoinCodeRequestSchema = exports.deviceRegisterResponseSchema = exports.deviceProofSchema = exports.deviceBackgroundTokenResponseSchema = exports.deviceBackgroundTokenRequestSchema = exports.deviceBackgroundCredentialResponseSchema = exports.sessionAccountsChangedEventSchema = exports.sessionAccountsChangedReasonSchema = exports.SESSION_ACCOUNTS_CHANGED_EVENT = exports.deviceTokenMintResponseSchema = exports.deviceTokenMintRequestSchema = exports.deviceSessionSyncSchema = exports.activeTokenSchema = exports.deviceSessionStateSchema = exports.sessionAccountSchema = void 0;
3
+ exports.deviceJoinResponseSchema = exports.deviceJoinRequestSchema = exports.deviceJoinCodeResponseSchema = exports.deviceJoinCodeRequestSchema = exports.deviceRegisterResponseSchema = exports.deviceProofSchema = exports.deviceBackgroundTokenResponseSchema = exports.deviceBackgroundTokenRequestSchema = exports.deviceBackgroundCredentialResponseSchema = exports.sessionAccountsChangedEventSchema = exports.sessionAccountsChangedReasonSchema = exports.deviceTokenMintResponseSchema = exports.deviceTokenMintRequestSchema = exports.deviceSessionSyncSchema = exports.activeTokenSchema = exports.deviceSessionStateSchema = exports.sessionAccountSchema = exports.SESSION_ACCOUNTS_CHANGED_EVENT = void 0;
4
4
  const zod_1 = require("zod");
5
+ var deviceSession_1 = require("./client/deviceSession");
6
+ Object.defineProperty(exports, "SESSION_ACCOUNTS_CHANGED_EVENT", { enumerable: true, get: function () { return deviceSession_1.SESSION_ACCOUNTS_CHANGED_EVENT; } });
5
7
  exports.sessionAccountSchema = zod_1.z.object({
6
8
  accountId: zod_1.z.string(),
7
9
  sessionId: zod_1.z.string(),
@@ -61,21 +63,6 @@ exports.deviceTokenMintResponseSchema = zod_1.z.object({
61
63
  nextDeviceSecret: zod_1.z.string(),
62
64
  state: exports.deviceSessionStateSchema,
63
65
  });
64
- /* -------------------------------------------------------------------------- */
65
- /* Instant cross-app session sync (token-free socket signal) */
66
- /* -------------------------------------------------------------------------- */
67
- /**
68
- * Name of the token-free Socket.IO event emitted to room `user:<userId>` on
69
- * every DeviceSession mutation that changes what is signed in for that user.
70
- *
71
- * This is a pure SIGNAL — it carries NO access token, NO deviceSecret and NO
72
- * account bodies. A client that receives it re-fetches its authenticated
73
- * session/account state (`GET /session/device/state`, `GET /accounts`). Unlike
74
- * `session_state` (scoped to `device:<deviceId>`, i.e. a single origin), this
75
- * reaches ALL of a user's connected sockets across their devices/origins so
76
- * every Oxy app reflects an add / switch / signout instantly.
77
- */
78
- exports.SESSION_ACCOUNTS_CHANGED_EVENT = 'session_accounts_changed';
79
66
  /**
80
67
  * Why the signed-in set changed:
81
68
  * - `login` — a brand-new session was minted for the user (QR / cross-app authorize)