@oxy.so/contracts 4.17.0 → 4.21.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 (50) hide show
  1. package/dist/cjs/accountAccess.js +72 -0
  2. package/dist/cjs/agency.js +112 -1
  3. package/dist/cjs/applicationRoles.js +211 -0
  4. package/dist/cjs/client/check.js +9 -0
  5. package/dist/cjs/client/index.js +22 -1
  6. package/dist/cjs/client/safety.js +183 -2
  7. package/dist/cjs/client/signIn.js +2 -0
  8. package/dist/cjs/index.js +13 -3
  9. package/dist/cjs/safety.js +430 -1
  10. package/dist/cjs/serviceToken.js +14 -0
  11. package/dist/esm/accountAccess.js +69 -0
  12. package/dist/esm/agency.js +111 -0
  13. package/dist/esm/applicationRoles.js +207 -0
  14. package/dist/esm/client/check.js +8 -0
  15. package/dist/esm/client/index.js +1 -1
  16. package/dist/esm/client/safety.js +183 -2
  17. package/dist/esm/client/signIn.js +2 -0
  18. package/dist/esm/index.js +4 -1
  19. package/dist/esm/safety.js +423 -0
  20. package/dist/esm/serviceToken.js +11 -0
  21. package/dist/types/accountAccess.d.ts +128 -0
  22. package/dist/types/accountEmail.d.ts +2 -2
  23. package/dist/types/agency.d.ts +327 -2
  24. package/dist/types/agentKeys.d.ts +6 -6
  25. package/dist/types/applicationRoles.d.ts +438 -0
  26. package/dist/types/client/agentKeys.d.ts +2 -2
  27. package/dist/types/client/check.d.ts +3 -0
  28. package/dist/types/client/deviceSession.d.ts +1 -1
  29. package/dist/types/client/index.d.ts +1 -1
  30. package/dist/types/client/safety.d.ts +204 -4
  31. package/dist/types/client/signIn.d.ts +1 -1
  32. package/dist/types/deviceSession.d.ts +4 -4
  33. package/dist/types/email/messages.d.ts +2 -2
  34. package/dist/types/externalIdentity.d.ts +4 -4
  35. package/dist/types/index.d.ts +5 -2
  36. package/dist/types/inference/accountBilling.d.ts +2 -2
  37. package/dist/types/inference/catalogue.d.ts +22 -22
  38. package/dist/types/inference/providerConnection.d.ts +4 -4
  39. package/dist/types/inference/realtime.d.ts +74 -74
  40. package/dist/types/inference/request.d.ts +60 -60
  41. package/dist/types/inference/usage.d.ts +4 -4
  42. package/dist/types/products/access.d.ts +4 -4
  43. package/dist/types/safety.d.ts +2374 -2
  44. package/dist/types/serviceToken.d.ts +11 -0
  45. package/dist/types/signIn.d.ts +5 -5
  46. package/dist/types/userResponse.d.ts +2 -2
  47. package/package.json +5 -20
  48. package/dist/cjs/.tsbuildinfo +0 -1
  49. package/dist/esm/.tsbuildinfo +0 -1
  50. package/dist/types/.tsbuildinfo +0 -1
@@ -1,4 +1,12 @@
1
1
  import { z } from 'zod';
2
+ import { accountActorChainSchema } from './accountSubject.js';
3
+ // The Zod-free half of this contract lives in `./client/` (`@oxy.so/contracts/client`);
4
+ // its vocabularies are re-exported here so the root entry is unchanged.
5
+ import { PURCHASE_APPROVAL_STATUSES, SAFETY_POLICY_VERSION, SUPERVISED_ACTIONS, SUPERVISION_CONSENT_VERSION, SUPERVISION_INVITATION_STATUSES, SUPERVISION_STATUSES, } from './client/safety.js';
6
+ import { ORGANIZATION_TYPES } from './organizations.js';
7
+ import { reauthProofSchema } from './signIn.js';
8
+ import { userResponseSchema } from './userResponse.js';
9
+ export { PURCHASE_APPROVAL_STATUSES, SAFETY_POLICY_VERSION, SUPERVISED_ACTIONS, SUPERVISION_CONSENT_VERSION, SUPERVISION_INVITATION_STATUSES, SUPERVISION_STATUSES, };
2
10
  /** The requester is authenticated by the bearer; applications cannot submit viewer IDs. */
3
11
  export const profileAccessInputSchema = z
4
12
  .object({ subjectAccountId: z.string().min(1).max(128) })
@@ -10,3 +18,418 @@ export const profileAccessDecisionSchema = z
10
18
  policyVersion: z.literal('1'),
11
19
  })
12
20
  .strict();
21
+ export const SAFETY_DECISION_REASONS = [
22
+ 'allowed',
23
+ 'owner',
24
+ 'public',
25
+ 'private',
26
+ 'blocked',
27
+ 'unavailable',
28
+ 'unsupported_consumer',
29
+ 'contact_not_approved',
30
+ 'mature_content',
31
+ 'unrated_content',
32
+ 'approval_required',
33
+ ];
34
+ const accountId = z.string().min(1).max(128);
35
+ const resourceId = z.string().trim().min(1).max(256);
36
+ const uniqueIds = (max, min = 1) => z
37
+ .array(accountId)
38
+ .min(min)
39
+ .max(max)
40
+ .refine((ids) => new Set(ids).size === ids.length, 'Account IDs must be unique');
41
+ export const safetyDecisionSchema = z
42
+ .object({
43
+ allowed: z.boolean(),
44
+ reason: z.enum(SAFETY_DECISION_REASONS),
45
+ policyVersion: z.literal(SAFETY_POLICY_VERSION),
46
+ })
47
+ .strict();
48
+ export const profileAccessBatchInputSchema = z
49
+ .object({ subjectAccountIds: uniqueIds(100) })
50
+ .strict();
51
+ export const profileAccessBatchResponseSchema = z
52
+ .object({
53
+ items: z
54
+ .array(z
55
+ .object({
56
+ subjectAccountId: accountId,
57
+ decision: safetyDecisionSchema,
58
+ })
59
+ .strict())
60
+ .max(100),
61
+ })
62
+ .strict();
63
+ export const MESSAGE_ACCESS_MAX_RESOURCES = 100;
64
+ export const MESSAGE_ACCESS_MAX_PARTICIPANTS = 1024;
65
+ export const MESSAGE_ACCESS_MAX_SUPERVISED_PARTICIPANTS = 256;
66
+ export const MESSAGE_ACCESS_MAX_PARTICIPANT_SLOTS = 4096;
67
+ /** Leaves room for the original requester proof in a 512 KiB request. */
68
+ export const MESSAGE_ACCESS_MAX_INPUT_BYTES = 448 * 1024;
69
+ export const messageAccessInputSchema = z
70
+ .object({ participantAccountIds: uniqueIds(MESSAGE_ACCESS_MAX_PARTICIPANTS), resourceId })
71
+ .strict();
72
+ export const contactAccessInputSchema = z.object({ targetAccountIds: uniqueIds(1000) }).strict();
73
+ export const contactAccessResponseSchema = z
74
+ .object({
75
+ items: z
76
+ .array(z
77
+ .object({
78
+ targetAccountId: accountId,
79
+ decision: safetyDecisionSchema,
80
+ })
81
+ .strict())
82
+ .max(1000),
83
+ })
84
+ .strict();
85
+ export const CONTENT_CLASSIFICATIONS = ['general', 'mature', 'unrated'];
86
+ export const contentAccessInputSchema = z
87
+ .object({
88
+ resourceId,
89
+ classification: z.enum(CONTENT_CLASSIFICATIONS),
90
+ authorAccountId: accountId.optional(),
91
+ audience: z.enum(['public', 'private', 'followers']).optional(),
92
+ applicationAudienceAllowed: z.boolean().optional(),
93
+ applicationResourceGrant: z.boolean().optional(),
94
+ operation: z.enum(['read', 'manage_own']).optional(),
95
+ })
96
+ .strict()
97
+ .refine((item) => !item.audience ||
98
+ item.audience === 'public' ||
99
+ (!!item.authorAccountId && item.applicationAudienceAllowed !== undefined), 'Nonpublic content requires its authoritative author and application audience decision')
100
+ .refine((item) => item.operation !== 'manage_own' || !!item.authorAccountId, 'Own management requires its authoritative author');
101
+ export const publicationPolicySchema = z
102
+ .object({
103
+ publicationAllowed: z.boolean(),
104
+ requiredAudience: z.literal('private').nullable(),
105
+ collaborationAllowed: z.boolean(),
106
+ federationAllowed: z.boolean(),
107
+ policyVersion: z.literal(SAFETY_POLICY_VERSION),
108
+ })
109
+ .strict();
110
+ export const publicationPoliciesInputSchema = z
111
+ .object({
112
+ authorAccountIds: z
113
+ .array(accountId)
114
+ .min(1)
115
+ .max(100)
116
+ .refine((ids) => new Set(ids).size === ids.length, 'Author IDs must be unique'),
117
+ })
118
+ .strict();
119
+ export const publicationPoliciesResponseSchema = z
120
+ .object({
121
+ items: z
122
+ .array(z.object({ authorAccountId: accountId, policy: publicationPolicySchema }).strict())
123
+ .max(100),
124
+ })
125
+ .strict();
126
+ export const contentAccessBatchInputSchema = z
127
+ .object({
128
+ items: z
129
+ .array(contentAccessInputSchema)
130
+ .min(1)
131
+ .max(100)
132
+ .refine((items) => new Set(items.map((item) => item.resourceId)).size === items.length, 'Resource IDs must be unique'),
133
+ })
134
+ .strict();
135
+ export const contentAccessBatchResponseSchema = z
136
+ .object({
137
+ items: z
138
+ .array(z
139
+ .object({
140
+ resourceId,
141
+ decision: safetyDecisionSchema,
142
+ })
143
+ .strict())
144
+ .max(100),
145
+ })
146
+ .strict();
147
+ /** A reviewed background consumer may decide delivery, but never authenticate as the sender. */
148
+ export const deliveryAccessInputSchema = messageAccessInputSchema
149
+ .extend({ senderAccountId: accountId })
150
+ .strict();
151
+ /** Count repeated participants across resources too: this bounds both graph and pair evaluations. */
152
+ const messageBatch = (schema) => z
153
+ .object({ items: z.array(schema).min(1).max(MESSAGE_ACCESS_MAX_RESOURCES) })
154
+ .strict()
155
+ .refine((value) => new Set(value.items.map((item) => item.resourceId)).size === value.items.length, 'Resource IDs must be unique')
156
+ .refine((value) => value.items.reduce((total, item) => total + item.participantAccountIds.length, 0) <=
157
+ MESSAGE_ACCESS_MAX_PARTICIPANT_SLOTS, 'Participant budget exceeded')
158
+ .refine((value) => new TextEncoder().encode(JSON.stringify(value)).byteLength <=
159
+ MESSAGE_ACCESS_MAX_INPUT_BYTES, 'Message batch byte budget exceeded');
160
+ export const messageAccessBatchInputSchema = messageBatch(messageAccessInputSchema);
161
+ export const deliveryAccessBatchInputSchema = messageBatch(deliveryAccessInputSchema);
162
+ export const messageAccessBatchResponseSchema = contentAccessBatchResponseSchema;
163
+ /** Live socket-recipient proof; a request ID correlates the result and never identifies an account. */
164
+ export const messagingSessionsInputSchema = z
165
+ .object({
166
+ items: z
167
+ .array(z
168
+ .object({
169
+ requestId: resourceId,
170
+ accessToken: z.string().min(1).max(16384),
171
+ })
172
+ .strict())
173
+ .min(1)
174
+ .max(100),
175
+ })
176
+ .strict()
177
+ .refine((value) => new Set(value.items.map((item) => item.requestId)).size === value.items.length, 'Request IDs must be unique')
178
+ .refine((value) => new TextEncoder().encode(JSON.stringify(value)).byteLength <= MESSAGE_ACCESS_MAX_INPUT_BYTES, 'Session proof byte budget exceeded');
179
+ export const messagingSessionsResponseSchema = z
180
+ .object({
181
+ items: z
182
+ .array(z.discriminatedUnion('allowed', [
183
+ z.object({ requestId: resourceId, allowed: z.literal(true), accountId }).strict(),
184
+ z.object({ requestId: resourceId, allowed: z.literal(false) }).strict(),
185
+ ]))
186
+ .max(100),
187
+ })
188
+ .strict();
189
+ export const safetyRequesterSchema = z.union([
190
+ z.object({ accessToken: z.string().min(1).max(16384).nullable() }).strict(),
191
+ z.object({ connectionToken: z.string().min(1).max(16384) }).strict(),
192
+ ]);
193
+ export const supervisionSchema = z
194
+ .object({
195
+ childAccountId: accountId,
196
+ guardianAccountId: accountId.nullable(),
197
+ status: z.enum(SUPERVISION_STATUSES),
198
+ policyVersion: z.literal(SAFETY_POLICY_VERSION),
199
+ consentVersion: z.literal(SUPERVISION_CONSENT_VERSION),
200
+ createdAt: z.string().datetime(),
201
+ })
202
+ .strict();
203
+ export const supervisionInvitationSchema = z
204
+ .object({
205
+ id: accountId,
206
+ childAccountId: accountId,
207
+ guardianAccountId: accountId,
208
+ status: z.enum(SUPERVISION_INVITATION_STATUSES),
209
+ expiresAt: z.string().datetime(),
210
+ consentVersion: z.literal(SUPERVISION_CONSENT_VERSION),
211
+ createdAt: z.string().datetime(),
212
+ })
213
+ .strict();
214
+ export const supervisionContactSchema = z
215
+ .object({
216
+ childAccountId: accountId,
217
+ contactAccountId: accountId,
218
+ approvedAt: z.string().datetime(),
219
+ })
220
+ .strict();
221
+ export const supervisionStateSchema = z
222
+ .object({
223
+ self: supervisionSchema.nullable(),
224
+ children: z.array(supervisionSchema).max(100),
225
+ invitations: z.array(supervisionInvitationSchema).max(100),
226
+ })
227
+ .strict();
228
+ export const supervisionContactsResponseSchema = z
229
+ .object({ items: z.array(supervisionContactSchema).max(1000) })
230
+ .strict();
231
+ const fingerprint = z.string().regex(/^[a-f0-9]{64}$/);
232
+ const minorUnits = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
233
+ export const purchaseApprovalLineSchema = z
234
+ .object({
235
+ itemReference: resourceId,
236
+ title: z.string().trim().min(1).max(300),
237
+ optionsText: z.string().trim().max(300),
238
+ merchantAccountId: accountId,
239
+ quantity: z.number().int().min(1).max(1000000),
240
+ unitAmountMinor: minorUnits,
241
+ lineAmountMinor: minorUnits,
242
+ })
243
+ .strict();
244
+ const purchaseEffectsObject = z
245
+ .object({
246
+ operationId: resourceId,
247
+ resourceId,
248
+ cartFingerprint: fingerprint,
249
+ summary: z.string().trim().min(1).max(300),
250
+ merchantAccountIds: z
251
+ .array(accountId)
252
+ .min(1)
253
+ .max(100)
254
+ .refine((ids) => new Set(ids).size === ids.length, 'Merchant accounts must be unique')
255
+ .transform((ids) => [...ids].sort()),
256
+ lineItems: z.array(purchaseApprovalLineSchema).min(1).max(200),
257
+ shippingMinor: minorUnits,
258
+ taxMinor: minorUnits,
259
+ discountMinor: minorUnits,
260
+ roundingAdjustmentMinor: z
261
+ .number()
262
+ .int()
263
+ .min(-Number.MAX_SAFE_INTEGER)
264
+ .max(Number.MAX_SAFE_INTEGER),
265
+ paymentFingerprint: fingerprint,
266
+ amountMinor: minorUnits,
267
+ currency: z.string().regex(/^[A-Z]{3}$/),
268
+ expiresAt: z.string().datetime(),
269
+ })
270
+ .strict();
271
+ function validatePurchaseEvidence(value, ctx) {
272
+ const merchants = new Set(value.merchantAccountIds);
273
+ const references = new Set();
274
+ for (const line of value.lineItems) {
275
+ const key = `${line.merchantAccountId}:${line.itemReference}`;
276
+ if (!merchants.has(line.merchantAccountId) || references.has(key))
277
+ ctx.addIssue({
278
+ code: z.ZodIssueCode.custom,
279
+ message: 'Purchase lines must name an included merchant and unique item reference',
280
+ });
281
+ references.add(key);
282
+ }
283
+ if (merchants.size !== new Set(value.lineItems.map((line) => line.merchantAccountId)).size)
284
+ ctx.addIssue({
285
+ code: z.ZodIssueCode.custom,
286
+ message: 'Every merchant must have an approval line',
287
+ });
288
+ const total = value.lineItems.reduce((sum, line) => sum + BigInt(line.lineAmountMinor), 0n) +
289
+ BigInt(value.shippingMinor) +
290
+ BigInt(value.taxMinor) -
291
+ BigInt(value.discountMinor) +
292
+ BigInt(value.roundingAdjustmentMinor);
293
+ if (total < 0n || total > BigInt(Number.MAX_SAFE_INTEGER) || total !== BigInt(value.amountMinor))
294
+ ctx.addIssue({
295
+ code: z.ZodIssueCode.custom,
296
+ message: 'Approval evidence must equal the exact payment total',
297
+ });
298
+ if (Math.abs(value.roundingAdjustmentMinor) >
299
+ value.lineItems.length + 3 * value.merchantAccountIds.length)
300
+ ctx.addIssue({
301
+ code: z.ZodIssueCode.custom,
302
+ message: 'Rounding adjustment exceeds the bounded conversion stages',
303
+ });
304
+ }
305
+ export const purchaseEffectsSchema = purchaseEffectsObject.superRefine(validatePurchaseEvidence);
306
+ const purchaseApprovalFields = {
307
+ id: accountId,
308
+ childAccountId: accountId,
309
+ applicationId: accountId,
310
+ status: z.enum(PURCHASE_APPROVAL_STATUSES),
311
+ createdAt: z.string().datetime(),
312
+ receiptReference: z.string().max(512).nullable(),
313
+ };
314
+ export const purchaseApprovalSchema = purchaseEffectsObject
315
+ .extend(purchaseApprovalFields)
316
+ .strict()
317
+ .superRefine(validatePurchaseEvidence);
318
+ export const purchaseApprovalSummarySchema = purchaseEffectsObject
319
+ .omit({ lineItems: true })
320
+ .extend(purchaseApprovalFields)
321
+ .strict();
322
+ export const purchaseApprovalListSchema = z
323
+ .object({
324
+ items: z.array(purchaseApprovalSummarySchema).max(100),
325
+ nextCursor: z.string().nullable(),
326
+ })
327
+ .strict();
328
+ export const reservePurchaseSchema = purchaseEffectsObject
329
+ .extend({ approvalId: accountId })
330
+ .strict()
331
+ .superRefine(validatePurchaseEvidence);
332
+ export const confirmPurchaseSchema = z
333
+ .object({
334
+ approvalId: accountId,
335
+ operationId: resourceId,
336
+ receiptReference: z.string().trim().min(1).max(512),
337
+ })
338
+ .strict();
339
+ export const cancelPurchaseSchema = confirmPurchaseSchema.omit({ receiptReference: true });
340
+ export const SAFETY_ERROR_CODES = [
341
+ 'bad_request',
342
+ 'validation_failed',
343
+ 'unauthorized',
344
+ 'forbidden',
345
+ 'not_found',
346
+ 'conflict',
347
+ 'reauth_required',
348
+ 'limit_reached',
349
+ 'service_unavailable',
350
+ 'rate_limited',
351
+ ];
352
+ export const safetyErrorSchema = z
353
+ .object({ error: z.object({ code: z.enum(SAFETY_ERROR_CODES), message: z.string() }).strict() })
354
+ .strict();
355
+ export const supervisionInviteInputSchema = z
356
+ .object({
357
+ guardianAccountId: accountId,
358
+ consentVersion: z.literal(SUPERVISION_CONSENT_VERSION),
359
+ reauth: reauthProofSchema,
360
+ })
361
+ .strict();
362
+ export const supervisionAcceptInputSchema = z
363
+ .object({ consentVersion: z.literal(SUPERVISION_CONSENT_VERSION), reauth: reauthProofSchema })
364
+ .strict();
365
+ export const supervisionContactInputSchema = z
366
+ .object({ childAccountId: accountId, contactAccountId: accountId, reauth: reauthProofSchema })
367
+ .strict();
368
+ export const supervisionReviewInputSchema = z
369
+ .object({
370
+ childAccountId: accountId,
371
+ action: z.enum(['end', 'transfer']),
372
+ guardianAccountId: accountId.optional(),
373
+ evidenceReference: z.string().trim().min(1).max(2048),
374
+ reauth: reauthProofSchema,
375
+ })
376
+ .strict();
377
+ export const purchaseReviewInputSchema = z
378
+ .object({ decision: z.enum(['approved', 'rejected']), reauth: reauthProofSchema })
379
+ .strict();
380
+ export const safetySessionInputSchema = z
381
+ .object({
382
+ sessionId: accountId,
383
+ accessToken: z.string().min(1).max(16384),
384
+ action: z.enum(SUPERVISED_ACTIONS),
385
+ })
386
+ .strict();
387
+ export const safetySessionValidationSchema = z
388
+ .object({
389
+ valid: z.literal(true),
390
+ sessionId: accountId,
391
+ expiresAt: z.string().datetime(),
392
+ lastActivity: z.string().datetime(),
393
+ user: userResponseSchema,
394
+ actor: accountActorChainSchema,
395
+ })
396
+ .strict();
397
+ /** Minimal identity for the authenticated account's supervision management, never profile details. */
398
+ export const safetyPersonSchema = z
399
+ .object({ accountId, username: z.string().nullable(), displayName: z.string().nullable() })
400
+ .strict();
401
+ export const safetyPeopleInputSchema = z.union([
402
+ z.object({ query: z.string().trim().min(2).max(100) }).strict(),
403
+ z.object({ accountIds: uniqueIds(100) }).strict(),
404
+ ]);
405
+ export const safetyPeopleResponseSchema = z
406
+ .object({ items: z.array(safetyPersonSchema).max(100) })
407
+ .strict();
408
+ /** Existing public employer identity only; never directory content or management authority. */
409
+ export const safetyOrganizationIdentitySchema = z
410
+ .object({
411
+ accountId,
412
+ username: z.string().nullable(),
413
+ name: z.string(),
414
+ organizationType: z.enum(ORGANIZATION_TYPES),
415
+ })
416
+ .strict();
417
+ export const safetyOrganizationsInputSchema = z.union([
418
+ z
419
+ .object({
420
+ query: z.string().trim().min(1).max(100),
421
+ limit: z.number().int().min(1).max(20).optional(),
422
+ })
423
+ .strict(),
424
+ z.object({ ids: uniqueIds(100) }).strict(),
425
+ ]);
426
+ export const safetyOrganizationsResponseSchema = z
427
+ .object({
428
+ items: z
429
+ .array(z
430
+ .object({ requestedAccountId: accountId, organization: safetyOrganizationIdentitySchema })
431
+ .strict())
432
+ .max(100),
433
+ missingIds: z.array(accountId).max(100),
434
+ })
435
+ .strict();
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod';
2
+ /** Omitted means the existing grant; an explicit set only narrows that authority. */
3
+ export const serviceTokenScopesSchema = z
4
+ .array(z.string().trim().min(1).max(128))
5
+ .min(1)
6
+ .max(100)
7
+ .refine((scopes) => new Set(scopes).size === scopes.length, 'Requested scopes must be unique')
8
+ .transform((scopes) => [...scopes].sort());
9
+ export const serviceTokenOptionsSchema = z
10
+ .object({ scopes: serviceTokenScopesSchema.optional() })
11
+ .strict();
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Wire contract for `GET /internal/accounts/:accountId/access/:userId`: Oxy
3
+ * answers a trusted first-party service's question "may this person act FOR
4
+ * that account, and with what?" with no session of that person in the request.
5
+ *
6
+ * It exists for the account Oxy never lets anybody act AS: a `channel`
7
+ * ({@link isDelegatedActAsEligibleKind} refuses it). An app publishes to a
8
+ * channel with ITS OWN credential, on behalf of a member Oxy vouches for here,
9
+ * so nobody holds a bearer that speaks as the channel. A long-running import
10
+ * (Oxy Move) has only a service token and `X-Oxy-User-Id`, which the
11
+ * user-facing `GET /accounts/:id/members` refuses; this is its answer.
12
+ *
13
+ * Needs a service token whose application is platform-trusted AND holds the
14
+ * privileged {@link ACCOUNTS_MEMBERSHIP_READ_SCOPE}. The answer is always 200:
15
+ * `access` is `null` for no active membership, an archived account, an unknown
16
+ * account and an unclaimed directory account alike. Callers must treat every
17
+ * other status as a refusal (fail closed), and must not cache the answer longer
18
+ * than the action it authorizes.
19
+ *
20
+ * Platform-agnostic — zod only.
21
+ */
22
+ import { z } from 'zod';
23
+ /**
24
+ * The scope the endpoint requires.
25
+ *
26
+ * Privileged (staff-granted). Channel membership is sensitive because a channel
27
+ * is anonymous: its members are the people behind a voice that is published
28
+ * without their names, and "is this person a member of that channel" is
29
+ * exactly the fact the channel exists to withhold.
30
+ */
31
+ export declare const ACCOUNTS_MEMBERSHIP_READ_SCOPE: "accounts:membership:read";
32
+ /**
33
+ * Where the access comes from.
34
+ *
35
+ * - `self` — the person IS the account (a personal account asked about itself).
36
+ * - `direct` — an active membership row on the account.
37
+ * - `inherited` — an active, cascading membership on an ancestor account.
38
+ */
39
+ export declare const ACCOUNT_ACCESS_SOURCES: readonly ["self", "direct", "inherited"];
40
+ export type AccountAccessSource = (typeof ACCOUNT_ACCESS_SOURCES)[number];
41
+ export declare const accountAccessSourceSchema: z.ZodEnum<["self", "direct", "inherited"]>;
42
+ /**
43
+ * One person's EFFECTIVE access over one account.
44
+ *
45
+ * `role` and `permissions` are strings rather than closed enums on purpose: the
46
+ * role and permission vocabularies are the API's, they grow, and a consumer
47
+ * pinned to an older contracts release must keep reading new ones. Gate on
48
+ * `permissions` (the role's baseline adjusted by per-member grants and
49
+ * revokes), never on `role`.
50
+ */
51
+ export declare const accountAccessGrantSchema: z.ZodObject<{
52
+ role: z.ZodString;
53
+ permissions: z.ZodArray<z.ZodString, "many">;
54
+ /** Only an active membership grants access, so this is the one value. */
55
+ status: z.ZodLiteral<"active">;
56
+ source: z.ZodEnum<["self", "direct", "inherited"]>;
57
+ }, "strip", z.ZodTypeAny, {
58
+ status: "active";
59
+ role: string;
60
+ permissions: string[];
61
+ source: "self" | "direct" | "inherited";
62
+ }, {
63
+ status: "active";
64
+ role: string;
65
+ permissions: string[];
66
+ source: "self" | "direct" | "inherited";
67
+ }>;
68
+ export type AccountAccessGrant = z.infer<typeof accountAccessGrantSchema>;
69
+ export declare const accountAccessVerdictSchema: z.ZodEffects<z.ZodObject<{
70
+ accountId: z.ZodString;
71
+ /** `null` when no such account exists. */
72
+ kind: z.ZodNullable<z.ZodEnum<["personal", "organization", "project", "bot", "channel"]>>;
73
+ /** `null` means: this person may not act for this account. */
74
+ access: z.ZodNullable<z.ZodObject<{
75
+ role: z.ZodString;
76
+ permissions: z.ZodArray<z.ZodString, "many">;
77
+ /** Only an active membership grants access, so this is the one value. */
78
+ status: z.ZodLiteral<"active">;
79
+ source: z.ZodEnum<["self", "direct", "inherited"]>;
80
+ }, "strip", z.ZodTypeAny, {
81
+ status: "active";
82
+ role: string;
83
+ permissions: string[];
84
+ source: "self" | "direct" | "inherited";
85
+ }, {
86
+ status: "active";
87
+ role: string;
88
+ permissions: string[];
89
+ source: "self" | "direct" | "inherited";
90
+ }>>;
91
+ }, "strip", z.ZodTypeAny, {
92
+ kind: "organization" | "personal" | "project" | "bot" | "channel" | null;
93
+ accountId: string;
94
+ access: {
95
+ status: "active";
96
+ role: string;
97
+ permissions: string[];
98
+ source: "self" | "direct" | "inherited";
99
+ } | null;
100
+ }, {
101
+ kind: "organization" | "personal" | "project" | "bot" | "channel" | null;
102
+ accountId: string;
103
+ access: {
104
+ status: "active";
105
+ role: string;
106
+ permissions: string[];
107
+ source: "self" | "direct" | "inherited";
108
+ } | null;
109
+ }>, {
110
+ kind: "organization" | "personal" | "project" | "bot" | "channel" | null;
111
+ accountId: string;
112
+ access: {
113
+ status: "active";
114
+ role: string;
115
+ permissions: string[];
116
+ source: "self" | "direct" | "inherited";
117
+ } | null;
118
+ }, {
119
+ kind: "organization" | "personal" | "project" | "bot" | "channel" | null;
120
+ accountId: string;
121
+ access: {
122
+ status: "active";
123
+ role: string;
124
+ permissions: string[];
125
+ source: "self" | "direct" | "inherited";
126
+ } | null;
127
+ }>;
128
+ export type AccountAccessVerdict = z.infer<typeof accountAccessVerdictSchema>;
@@ -24,11 +24,11 @@ export declare const emailVerificationStartRequestSchema: z.ZodObject<{
24
24
  purpose: z.ZodLiteral<"signup">;
25
25
  email: z.ZodString;
26
26
  }, "strict", z.ZodTypeAny, {
27
- purpose: "signup";
28
27
  email: string;
29
- }, {
30
28
  purpose: "signup";
29
+ }, {
31
30
  email: string;
31
+ purpose: "signup";
32
32
  }>;
33
33
  export type EmailVerificationStartRequest = z.infer<typeof emailVerificationStartRequestSchema>;
34
34
  export interface EmailVerificationStartResponse {