@oxy.so/contracts 4.16.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.
- package/dist/cjs/accountAccess.js +72 -0
- package/dist/cjs/accountEmail.js +12 -34
- package/dist/cjs/accountGraph.js +22 -320
- package/dist/cjs/agency.js +112 -1
- package/dist/cjs/agentKeys.js +11 -13
- package/dist/cjs/applicationRoles.js +211 -0
- package/dist/cjs/client/accountEmail.js +48 -0
- package/dist/cjs/client/accountGraph.js +323 -0
- package/dist/cjs/client/agentKeys.js +77 -0
- package/dist/cjs/client/check.js +475 -0
- package/dist/cjs/client/deviceBoot.js +22 -0
- package/dist/cjs/client/deviceDirectory.js +51 -0
- package/dist/cjs/client/deviceSession.js +63 -0
- package/dist/cjs/client/externalIdentity.js +19 -0
- package/dist/cjs/client/identity.js +45 -0
- package/dist/cjs/client/identityLink.js +55 -0
- package/dist/cjs/client/identityProof.js +109 -0
- package/dist/cjs/client/index.js +211 -0
- package/dist/cjs/client/organizations.js +114 -0
- package/dist/cjs/client/products.js +153 -0
- package/dist/cjs/client/recommendations.js +33 -0
- package/dist/cjs/client/reputation.js +41 -0
- package/dist/cjs/client/safety.js +196 -0
- package/dist/cjs/client/sessionStatus.js +23 -0
- package/dist/cjs/client/signIn.js +159 -0
- package/dist/cjs/client/userResponse.js +15 -0
- package/dist/cjs/client/username.js +173 -0
- package/dist/cjs/deviceSession.js +3 -16
- package/dist/cjs/identityLink.js +13 -34
- package/dist/cjs/identityProof.js +18 -106
- package/dist/cjs/index.js +13 -3
- package/dist/cjs/organizations.js +21 -41
- package/dist/cjs/reputation.js +3 -34
- package/dist/cjs/safety.js +430 -1
- package/dist/cjs/serviceToken.js +14 -0
- package/dist/cjs/signIn.js +33 -111
- package/dist/cjs/username.js +23 -158
- package/dist/esm/accountAccess.js +69 -0
- package/dist/esm/accountEmail.js +4 -32
- package/dist/esm/accountGraph.js +4 -309
- package/dist/esm/agency.js +111 -0
- package/dist/esm/agentKeys.js +4 -10
- package/dist/esm/applicationRoles.js +207 -0
- package/dist/esm/client/accountEmail.js +45 -0
- package/dist/esm/client/accountGraph.js +314 -0
- package/dist/esm/client/agentKeys.js +74 -0
- package/dist/esm/client/check.js +436 -0
- package/dist/esm/client/deviceBoot.js +19 -0
- package/dist/esm/client/deviceDirectory.js +48 -0
- package/dist/esm/client/deviceSession.js +60 -0
- package/dist/esm/client/externalIdentity.js +16 -0
- package/dist/esm/client/identity.js +42 -0
- package/dist/esm/client/identityLink.js +50 -0
- package/dist/esm/client/identityProof.js +104 -0
- package/dist/esm/client/index.js +37 -0
- package/dist/esm/client/organizations.js +111 -0
- package/dist/esm/client/products.js +150 -0
- package/dist/esm/client/recommendations.js +30 -0
- package/dist/esm/client/reputation.js +37 -0
- package/dist/esm/client/safety.js +193 -0
- package/dist/esm/client/sessionStatus.js +20 -0
- package/dist/esm/client/signIn.js +153 -0
- package/dist/esm/client/userResponse.js +12 -0
- package/dist/esm/client/username.js +167 -0
- package/dist/esm/deviceSession.js +1 -15
- package/dist/esm/identityLink.js +4 -27
- package/dist/esm/identityProof.js +4 -99
- package/dist/esm/index.js +4 -1
- package/dist/esm/organizations.js +4 -31
- package/dist/esm/reputation.js +1 -32
- package/dist/esm/safety.js +423 -0
- package/dist/esm/serviceToken.js +11 -0
- package/dist/esm/signIn.js +4 -96
- package/dist/esm/username.js +4 -148
- package/dist/types/accountAccess.d.ts +128 -0
- package/dist/types/accountEmail.d.ts +4 -36
- package/dist/types/accountGraph.d.ts +12 -208
- package/dist/types/agency.d.ts +351 -26
- package/dist/types/agentKeys.d.ts +14 -12
- package/dist/types/applicationRoles.d.ts +438 -0
- package/dist/types/client/accountEmail.d.ts +44 -0
- package/dist/types/client/accountGraph.d.ts +203 -0
- package/dist/types/client/agentKeys.d.ts +113 -0
- package/dist/types/client/check.d.ts +187 -0
- package/dist/types/client/deviceBoot.d.ts +6 -0
- package/dist/types/client/deviceDirectory.d.ts +134 -0
- package/dist/types/client/deviceSession.d.ts +91 -0
- package/dist/types/client/externalIdentity.d.ts +14 -0
- package/dist/types/client/identity.d.ts +8 -0
- package/dist/types/client/identityLink.d.ts +21 -0
- package/dist/types/client/identityProof.d.ts +73 -0
- package/dist/types/client/index.d.ts +37 -0
- package/dist/types/client/organizations.d.ts +167 -0
- package/dist/types/client/products.d.ts +145 -0
- package/dist/types/client/recommendations.d.ts +27 -0
- package/dist/types/client/reputation.d.ts +28 -0
- package/dist/types/client/safety.d.ts +213 -0
- package/dist/types/client/sessionStatus.d.ts +19 -0
- package/dist/types/client/signIn.d.ts +107 -0
- package/dist/types/client/userResponse.d.ts +7 -0
- package/dist/types/client/username.d.ts +126 -0
- package/dist/types/deviceDirectory.d.ts +28 -28
- package/dist/types/deviceSession.d.ts +5 -16
- package/dist/types/email/messages.d.ts +2 -2
- package/dist/types/externalIdentity.d.ts +15 -15
- package/dist/types/identityLink.d.ts +3 -11
- package/dist/types/identityProof.d.ts +2 -65
- package/dist/types/index.d.ts +5 -2
- package/dist/types/inference/accountBilling.d.ts +2 -2
- package/dist/types/inference/catalogue.d.ts +22 -22
- package/dist/types/inference/decisions.d.ts +10 -10
- package/dist/types/inference/embeddings.d.ts +16 -16
- package/dist/types/inference/errors.d.ts +8 -8
- package/dist/types/inference/inbox.d.ts +8 -8
- package/dist/types/inference/privateAutoExecution.d.ts +6 -6
- package/dist/types/inference/providerConnection.d.ts +4 -4
- package/dist/types/inference/realtime.d.ts +92 -92
- package/dist/types/inference/request.d.ts +48 -48
- package/dist/types/inference/streamEvents.d.ts +16 -16
- package/dist/types/inference/usage.d.ts +4 -4
- package/dist/types/oauth.d.ts +2 -2
- package/dist/types/organizations.d.ts +8 -10
- package/dist/types/products/access.d.ts +4 -4
- package/dist/types/products/billing.d.ts +3 -0
- package/dist/types/reputation.d.ts +1 -11
- package/dist/types/safety.d.ts +2374 -2
- package/dist/types/serviceToken.d.ts +11 -0
- package/dist/types/sessionStatus.d.ts +2 -2
- package/dist/types/signIn.d.ts +11 -94
- package/dist/types/userResponse.d.ts +22 -22
- package/dist/types/username.d.ts +1 -96
- package/package.json +24 -20
- package/dist/cjs/.tsbuildinfo +0 -1
- package/dist/esm/.tsbuildinfo +0 -1
- package/dist/types/.tsbuildinfo +0 -1
package/dist/cjs/agency.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.normalizedAppEventSchema = exports.catalogRegistrationSchema = exports.appCapabilityCatalogSchema = exports.catalogEventSchema = exports.catalogToolSchema = exports.auditEventSchema = exports.auditResultSchema = exports.policyDecisionSchema = exports.invocationPrincipalSchema = exports.capabilityTicketClaimsSchema = exports.automationDefinitionSchema = exports.automationDataFlowSchema = exports.automationActorSelectionSchema = exports.automationTriggerSchema = exports.delegationGrantSchema = exports.capabilityTicketRequestSchema = exports.capabilityCoordinatorSchema = exports.executionAuthorizationRefSchema = exports.capabilityCatalogBindingSchema = exports.grantLimitSchema = exports.toolGrantOverrideSchema = exports.resourceRefSchema = exports.foregroundExecutionAuthorizationInputSchema = exports.executionActorRefSchema = exports.actorRefSchema = exports.capabilityPackageSchema = exports.CAPABILITY_PACKAGES = exports.autonomyLevelSchema = exports.AUTONOMY_LEVELS = void 0;
|
|
3
|
+
exports.normalizedAppEventSchema = exports.catalogRegistrationSchema = exports.appCapabilityCatalogSchema = exports.CATALOG_INTERNAL_TRANSPORTS = exports.catalogFeatureSchema = exports.catalogEventSchema = exports.catalogToolSchema = exports.auditEventSchema = exports.auditResultSchema = exports.policyDecisionSchema = exports.invocationPrincipalSchema = exports.capabilityTicketClaimsSchema = exports.automationDefinitionSchema = exports.automationDataFlowSchema = exports.automationActorSelectionSchema = exports.automationTriggerSchema = exports.agentRequesterCeilingSchema = exports.agentRequesterCeilingWriteSchema = exports.AGENT_REQUESTER_CEILING_AUTONOMY = exports.delegationGrantSchema = exports.capabilityTicketRequestSchema = exports.capabilityCoordinatorSchema = exports.executionAuthorizationRefSchema = exports.capabilityCatalogBindingSchema = exports.grantLimitSchema = exports.toolGrantOverrideSchema = exports.resourceRefSchema = exports.foregroundExecutionAuthorizationInputSchema = exports.executionActorRefSchema = exports.actorRefSchema = exports.capabilityPackageSchema = exports.CAPABILITY_PACKAGES = exports.autonomyLevelSchema = exports.AUTONOMY_LEVELS = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const capabilityInvocation_1 = require("./capabilityInvocation");
|
|
6
6
|
const nonEmptyStringSchema = zod_1.z.string().trim().min(1);
|
|
@@ -143,6 +143,35 @@ exports.delegationGrantSchema = zod_1.z
|
|
|
143
143
|
updatedAt: zod_1.z.string().datetime(),
|
|
144
144
|
})
|
|
145
145
|
.strict();
|
|
146
|
+
/**
|
|
147
|
+
* The two levels an owner publishes for whoever uses their agent (ADR 0042):
|
|
148
|
+
* "Ver" and "Ver y actuar". A ceiling never says `draft` or `execute_on_request`:
|
|
149
|
+
* an agent is either allowed to act on its own or not at all, and nothing ever
|
|
150
|
+
* asks the person for approval.
|
|
151
|
+
*/
|
|
152
|
+
exports.AGENT_REQUESTER_CEILING_AUTONOMY = ['read_only', 'autonomous'];
|
|
153
|
+
/** What an agent may do in one app for whoever uses it; written by an operator of the bot. */
|
|
154
|
+
exports.agentRequesterCeilingWriteSchema = zod_1.z
|
|
155
|
+
.object({
|
|
156
|
+
capabilityPackages: zod_1.z.array(exports.capabilityPackageSchema),
|
|
157
|
+
capabilities: zod_1.z.array(identifierSchema).default([]),
|
|
158
|
+
toolOverrides: zod_1.z.array(exports.toolGrantOverrideSchema).default([]),
|
|
159
|
+
limits: zod_1.z.array(exports.grantLimitSchema).default([]),
|
|
160
|
+
maximumAutonomy: zod_1.z.enum(exports.AGENT_REQUESTER_CEILING_AUTONOMY),
|
|
161
|
+
})
|
|
162
|
+
.strict();
|
|
163
|
+
exports.agentRequesterCeilingSchema = exports.agentRequesterCeilingWriteSchema
|
|
164
|
+
.extend({
|
|
165
|
+
id: identifierSchema,
|
|
166
|
+
agentAccountId: identifierSchema,
|
|
167
|
+
appId: identifierSchema,
|
|
168
|
+
catalog: exports.capabilityCatalogBindingSchema,
|
|
169
|
+
version: zod_1.z.number().int().positive(),
|
|
170
|
+
revokedAt: zod_1.z.string().datetime().nullable(),
|
|
171
|
+
createdAt: zod_1.z.string().datetime(),
|
|
172
|
+
updatedAt: zod_1.z.string().datetime(),
|
|
173
|
+
})
|
|
174
|
+
.strict();
|
|
146
175
|
exports.automationTriggerSchema = zod_1.z.discriminatedUnion('type', [
|
|
147
176
|
zod_1.z.object({ type: zod_1.z.literal('manual') }).strict(),
|
|
148
177
|
zod_1.z
|
|
@@ -204,6 +233,8 @@ exports.capabilityTicketClaimsSchema = zod_1.z
|
|
|
204
233
|
/** Signed only for callers that explicitly requested a pinned catalogue. */
|
|
205
234
|
catalog: exports.capabilityCatalogBindingSchema.optional(),
|
|
206
235
|
grantId: identifierSchema.optional(),
|
|
236
|
+
/** The owner's published ceiling that bounds an agent acting for a non-owner (ADR 0042). */
|
|
237
|
+
ceilingId: identifierSchema.optional(),
|
|
207
238
|
requesterAccountId: identifierSchema,
|
|
208
239
|
ownerAccountId: identifierSchema,
|
|
209
240
|
actor: exports.executionActorRefSchema,
|
|
@@ -242,6 +273,24 @@ exports.capabilityTicketClaimsSchema = zod_1.z
|
|
|
242
273
|
message: 'requester actors require their exact principal and direct read-only authority without standing grants',
|
|
243
274
|
});
|
|
244
275
|
}
|
|
276
|
+
if (claims.ceilingId !== undefined) {
|
|
277
|
+
if (claims.grantId !== undefined) {
|
|
278
|
+
context.addIssue({
|
|
279
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
280
|
+
path: ['ceilingId'],
|
|
281
|
+
message: 'a ticket is bounded by either a grant or a ceiling, never both',
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
if (claims.actor.type !== 'agent' ||
|
|
285
|
+
claims.ownerAccountId !== claims.requesterAccountId ||
|
|
286
|
+
claims.resource.resourceId !== claims.resource.effectiveAccountId) {
|
|
287
|
+
context.addIssue({
|
|
288
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
289
|
+
path: ['ceilingId'],
|
|
290
|
+
message: "a ceiling bounds an agent acting on the requester's own authority at an account root",
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
}
|
|
245
294
|
if (claims.exp <= claims.iat) {
|
|
246
295
|
context.addIssue({
|
|
247
296
|
code: zod_1.z.ZodIssueCode.custom,
|
|
@@ -303,6 +352,7 @@ exports.policyDecisionSchema = zod_1.z
|
|
|
303
352
|
reason: identifierSchema,
|
|
304
353
|
effectiveAutonomy: exports.autonomyLevelSchema.optional(),
|
|
305
354
|
grantId: identifierSchema.optional(),
|
|
355
|
+
ceilingId: identifierSchema.optional(),
|
|
306
356
|
})
|
|
307
357
|
.strict();
|
|
308
358
|
exports.auditResultSchema = zod_1.z
|
|
@@ -512,6 +562,24 @@ exports.catalogEventSchema = zod_1.z
|
|
|
512
562
|
resourceTypes: zod_1.z.array(identifierSchema).min(1),
|
|
513
563
|
})
|
|
514
564
|
.strict();
|
|
565
|
+
/**
|
|
566
|
+
* A feature an agent may gate on (Alia ADR 0020 §6): the app answers whether the
|
|
567
|
+
* person may use it (`checkTool`) and, when using it costs something, spends it
|
|
568
|
+
* (`consumeTool`). Both are internal tools of the same catalogue.
|
|
569
|
+
*/
|
|
570
|
+
exports.catalogFeatureSchema = zod_1.z
|
|
571
|
+
.object({
|
|
572
|
+
key: zod_1.z
|
|
573
|
+
.string()
|
|
574
|
+
.regex(/^[a-z][a-z0-9_-]*(?:\.[a-z][a-z0-9_-]*)*$/, 'feature keys are dot-separated slugs')
|
|
575
|
+
.max(128),
|
|
576
|
+
description: nonEmptyStringSchema,
|
|
577
|
+
checkTool: identifierSchema,
|
|
578
|
+
consumeTool: identifierSchema.optional(),
|
|
579
|
+
})
|
|
580
|
+
.strict();
|
|
581
|
+
/** How a coordinator reaches the catalogue's internal tools. */
|
|
582
|
+
exports.CATALOG_INTERNAL_TRANSPORTS = ['http', 'mcp'];
|
|
515
583
|
exports.appCapabilityCatalogSchema = zod_1.z
|
|
516
584
|
.object({
|
|
517
585
|
schemaVersion: zod_1.z.literal('1'),
|
|
@@ -567,11 +635,54 @@ exports.appCapabilityCatalogSchema = zod_1.z
|
|
|
567
635
|
})
|
|
568
636
|
.strict()
|
|
569
637
|
.optional(),
|
|
638
|
+
/**
|
|
639
|
+
* `mcp`: internal tools are served at `<internalBaseUrl>/_oxy/mcp`. Absent or
|
|
640
|
+
* `http`: each tool's `invocation` path on `internalBaseUrl`.
|
|
641
|
+
*/
|
|
642
|
+
internalTransport: zod_1.z.enum(exports.CATALOG_INTERNAL_TRANSPORTS).optional(),
|
|
643
|
+
features: zod_1.z.array(exports.catalogFeatureSchema).optional(),
|
|
570
644
|
tools: zod_1.z.array(exports.catalogToolSchema),
|
|
571
645
|
events: zod_1.z.array(exports.catalogEventSchema),
|
|
572
646
|
})
|
|
573
647
|
.strict()
|
|
574
648
|
.superRefine((catalog, context) => {
|
|
649
|
+
const toolsByName = new Map(catalog.tools.map((tool) => [tool.name, tool]));
|
|
650
|
+
const featureKeys = new Set();
|
|
651
|
+
for (const [index, feature] of (catalog.features ?? []).entries()) {
|
|
652
|
+
if (featureKeys.has(feature.key)) {
|
|
653
|
+
context.addIssue({
|
|
654
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
655
|
+
message: `Duplicate feature key: ${feature.key}`,
|
|
656
|
+
path: ['features', index, 'key'],
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
featureKeys.add(feature.key);
|
|
660
|
+
const check = toolsByName.get(feature.checkTool);
|
|
661
|
+
if (!check ||
|
|
662
|
+
check.effect !== 'read' ||
|
|
663
|
+
check.exposure.length !== 1 ||
|
|
664
|
+
check.exposure[0] !== 'internal') {
|
|
665
|
+
context.addIssue({
|
|
666
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
667
|
+
message: 'checkTool must name an internal-only read tool of this catalogue',
|
|
668
|
+
path: ['features', index, 'checkTool'],
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
if (feature.consumeTool !== undefined) {
|
|
672
|
+
const consume = toolsByName.get(feature.consumeTool);
|
|
673
|
+
if (!consume ||
|
|
674
|
+
consume.effect === 'read' ||
|
|
675
|
+
consume.idempotency !== 'required' ||
|
|
676
|
+
consume.exposure.length !== 1 ||
|
|
677
|
+
consume.exposure[0] !== 'internal') {
|
|
678
|
+
context.addIssue({
|
|
679
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
680
|
+
message: 'consumeTool must name an internal-only effectful tool that requires idempotency keys',
|
|
681
|
+
path: ['features', index, 'consumeTool'],
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
575
686
|
const names = new Set();
|
|
576
687
|
for (const [index, tool] of catalog.tools.entries()) {
|
|
577
688
|
if (names.has(tool.name)) {
|
package/dist/cjs/agentKeys.js
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.agentKeyListResponseSchema = exports.
|
|
3
|
+
exports.agentKeyListResponseSchema = exports.agentKeyOperationResultSchema = exports.agentKeyOperationChallengeSchema = exports.executeAgentKeyOperationSchema = exports.agentKeyOperationProofSchema = exports.agentKeyOperationSchema = exports.agentVerifyRequestSchema = exports.agentChallengeRequestSchema = exports.agentSignatureSchema = exports.agentProofClaimsSchema = exports.ACCOUNT_AUTH_METHODS = exports.AGENT_PROOF_ACTIONS = exports.AGENT_PROOF_TTL_MS = exports.AGENT_PROOF_AUDIENCE = void 0;
|
|
4
4
|
exports.buildAgentProofMessage = buildAgentProofMessage;
|
|
5
5
|
/** Autonomous runtime proof. No private key crosses this contract. */
|
|
6
6
|
const zod_1 = require("zod");
|
|
7
7
|
const signIn_1 = require("./signIn");
|
|
8
8
|
const identityProof_1 = require("./identityProof");
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
];
|
|
9
|
+
// The Zod-free half of this contract lives in `./client/` (`@oxy.so/contracts/client`);
|
|
10
|
+
// it is re-exported here so the root entry is unchanged.
|
|
11
|
+
const agentKeys_1 = require("./client/agentKeys");
|
|
12
|
+
var agentKeys_2 = require("./client/agentKeys");
|
|
13
|
+
Object.defineProperty(exports, "AGENT_PROOF_AUDIENCE", { enumerable: true, get: function () { return agentKeys_2.AGENT_PROOF_AUDIENCE; } });
|
|
14
|
+
Object.defineProperty(exports, "AGENT_PROOF_TTL_MS", { enumerable: true, get: function () { return agentKeys_2.AGENT_PROOF_TTL_MS; } });
|
|
15
|
+
Object.defineProperty(exports, "AGENT_PROOF_ACTIONS", { enumerable: true, get: function () { return agentKeys_2.AGENT_PROOF_ACTIONS; } });
|
|
16
|
+
Object.defineProperty(exports, "ACCOUNT_AUTH_METHODS", { enumerable: true, get: function () { return agentKeys_2.ACCOUNT_AUTH_METHODS; } });
|
|
18
17
|
exports.agentProofClaimsSchema = zod_1.z
|
|
19
18
|
.object({
|
|
20
19
|
version: zod_1.z.literal(1),
|
|
21
|
-
audience: zod_1.z.literal(
|
|
22
|
-
action: zod_1.z.enum(
|
|
20
|
+
audience: zod_1.z.literal(agentKeys_1.AGENT_PROOF_AUDIENCE),
|
|
21
|
+
action: zod_1.z.enum(agentKeys_1.AGENT_PROOF_ACTIONS),
|
|
23
22
|
accountId: zod_1.z.string().min(1),
|
|
24
23
|
actorId: zod_1.z.string().min(1),
|
|
25
24
|
authMethodId: zod_1.z.string().nullable(),
|
|
@@ -101,7 +100,6 @@ exports.agentKeyOperationResultSchema = zod_1.z
|
|
|
101
100
|
revokedMethodIds: zod_1.z.array(zod_1.z.string()),
|
|
102
101
|
})
|
|
103
102
|
.strict();
|
|
104
|
-
exports.ACCOUNT_AUTH_METHODS = ['identity', 'agent_key'];
|
|
105
103
|
/** Public credential inventory. Never includes a proof, bearer or private key. */
|
|
106
104
|
exports.agentKeyListResponseSchema = zod_1.z
|
|
107
105
|
.object({
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Application roles — the wire contract for permissions an APPLICATION declares
|
|
4
|
+
* about its own users, and for the grants that give them to Oxy users.
|
|
5
|
+
*
|
|
6
|
+
* Oxy decides who holds an app's operator powers (who may run Mercaria's
|
|
7
|
+
* payments desk, moderate GoWay, administer Homiio), so no app keeps an
|
|
8
|
+
* allow-list of Oxy user ids in its environment. The app declares a closed
|
|
9
|
+
* vocabulary of keys, its owners grant them to people, and the app's backend
|
|
10
|
+
* asks Oxy which of them the human behind a request holds
|
|
11
|
+
* (`GET /applications/:appId/roles/me`, read through `@oxy.so/core/server`).
|
|
12
|
+
*
|
|
13
|
+
* ## Why an application key can never collide with an Oxy permission
|
|
14
|
+
*
|
|
15
|
+
* Every permission Oxy itself checks (`app:update`, `apps:create`,
|
|
16
|
+
* `credentials:rotate`, every scope) is spelled with a COLON. An application key
|
|
17
|
+
* is dot-separated lowercase segments and cannot contain one, so the two
|
|
18
|
+
* vocabularies are disjoint by syntax, not by convention. They are also stored
|
|
19
|
+
* apart (scoped to one application id) and no Oxy gate ever reads an
|
|
20
|
+
* application key. A key means something only to the application that declared
|
|
21
|
+
* it.
|
|
22
|
+
*
|
|
23
|
+
* The pattern is exported as a SOURCE string because the API renders the same
|
|
24
|
+
* text into a Postgres CHECK; JavaScript's `RegExp` and Postgres' ARE agree on
|
|
25
|
+
* everything it uses (anchors, classes, a capturing group, a bounded repeat).
|
|
26
|
+
*
|
|
27
|
+
* Platform-agnostic — zod only, no react/react-native/expo.
|
|
28
|
+
*/
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.applicationRolesMeSchema = exports.listApplicationRoleGrantsQuerySchema = exports.revokeApplicationRoleGrantRequestSchema = exports.createApplicationRoleGrantRequestSchema = exports.applicationRoleGrantListSchema = exports.applicationRoleGrantSchema = exports.declareApplicationPermissionsResponseSchema = exports.applicationPermissionListSchema = exports.applicationPermissionSchema = exports.declareApplicationPermissionsRequestSchema = exports.applicationPermissionDeclarationSchema = exports.applicationPermissionKeySchema = exports.APPLICATION_ROLE_ERROR_CODES = exports.APPLICATION_ROLE_GRANTS_PAGE_MAX = exports.APPLICATION_ROLE_GRANTS_PAGE_DEFAULT = exports.APPLICATION_ROLE_REASON_MAX_LENGTH = exports.APPLICATION_PERMISSIONS_MAX_DECLARED = exports.APPLICATION_PERMISSION_DESCRIPTION_MAX_LENGTH = exports.APPLICATION_PERMISSION_KEY_MAX_LENGTH = exports.APPLICATION_PERMISSION_KEY_PATTERN = exports.APPLICATION_PERMISSION_KEY_PATTERN_SOURCE = void 0;
|
|
31
|
+
exports.isApplicationPermissionKey = isApplicationPermissionKey;
|
|
32
|
+
const zod_1 = require("zod");
|
|
33
|
+
/**
|
|
34
|
+
* Two to four dot-separated segments, each a lowercase letter followed by
|
|
35
|
+
* lowercase letters, digits or underscores: `payments.operate`,
|
|
36
|
+
* `catalog.review.publish`. At least two segments so a key always names an
|
|
37
|
+
* area and an action; never a colon (see the header).
|
|
38
|
+
*/
|
|
39
|
+
exports.APPLICATION_PERMISSION_KEY_PATTERN_SOURCE = '^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*){1,3}$';
|
|
40
|
+
exports.APPLICATION_PERMISSION_KEY_PATTERN = new RegExp(exports.APPLICATION_PERMISSION_KEY_PATTERN_SOURCE);
|
|
41
|
+
exports.APPLICATION_PERMISSION_KEY_MAX_LENGTH = 64;
|
|
42
|
+
exports.APPLICATION_PERMISSION_DESCRIPTION_MAX_LENGTH = 280;
|
|
43
|
+
/** How many live keys one application may declare. Operator powers are few. */
|
|
44
|
+
exports.APPLICATION_PERMISSIONS_MAX_DECLARED = 64;
|
|
45
|
+
exports.APPLICATION_ROLE_REASON_MAX_LENGTH = 500;
|
|
46
|
+
exports.APPLICATION_ROLE_GRANTS_PAGE_DEFAULT = 50;
|
|
47
|
+
exports.APPLICATION_ROLE_GRANTS_PAGE_MAX = 200;
|
|
48
|
+
/**
|
|
49
|
+
* The `error` codes the application-roles routes answer beyond the generic
|
|
50
|
+
* ones (`BAD_REQUEST`, `UNAUTHORIZED`, `FORBIDDEN`, `NOT_FOUND`). Renaming one
|
|
51
|
+
* is a breaking change.
|
|
52
|
+
*/
|
|
53
|
+
exports.APPLICATION_ROLE_ERROR_CODES = {
|
|
54
|
+
/** 403: a grant naming yourself on an application you do not own outright. */
|
|
55
|
+
selfGrantForbidden: 'SELF_GRANT_FORBIDDEN',
|
|
56
|
+
/** 422: the key is not a live declared permission of this application. */
|
|
57
|
+
unknownPermission: 'UNKNOWN_PERMISSION',
|
|
58
|
+
/** 422: the grantee is not a person (an organization, project, bot or channel). */
|
|
59
|
+
granteeNotAPerson: 'GRANTEE_NOT_A_PERSON',
|
|
60
|
+
/** 409: the grantee already holds the key; `details.grantId` names the live grant. */
|
|
61
|
+
alreadyGranted: 'ALREADY_GRANTED',
|
|
62
|
+
/** 409: the grant was already revoked. */
|
|
63
|
+
alreadyRevoked: 'ALREADY_REVOKED',
|
|
64
|
+
/** 403: the bearer's session belongs to a DIFFERENT application. */
|
|
65
|
+
sessionApplicationMismatch: 'SESSION_APPLICATION_MISMATCH',
|
|
66
|
+
};
|
|
67
|
+
/** Whether `value` is a well-formed application permission key. */
|
|
68
|
+
function isApplicationPermissionKey(value) {
|
|
69
|
+
return (typeof value === 'string' &&
|
|
70
|
+
value.length <= exports.APPLICATION_PERMISSION_KEY_MAX_LENGTH &&
|
|
71
|
+
exports.APPLICATION_PERMISSION_KEY_PATTERN.test(value));
|
|
72
|
+
}
|
|
73
|
+
exports.applicationPermissionKeySchema = zod_1.z
|
|
74
|
+
.string()
|
|
75
|
+
.max(exports.APPLICATION_PERMISSION_KEY_MAX_LENGTH)
|
|
76
|
+
.regex(exports.APPLICATION_PERMISSION_KEY_PATTERN, 'A permission key is 2-4 dot-separated lowercase segments, e.g. payments.operate');
|
|
77
|
+
/** Plain text: no control characters other than a newline or a tab. */
|
|
78
|
+
function plainText(max) {
|
|
79
|
+
return zod_1.z
|
|
80
|
+
.string()
|
|
81
|
+
.trim()
|
|
82
|
+
.min(1)
|
|
83
|
+
.max(max)
|
|
84
|
+
.refine((value) => Array.from(value).every((character) => {
|
|
85
|
+
const code = character.charCodeAt(0);
|
|
86
|
+
return (code >= 32 && code !== 127) || character === '\n' || character === '\t';
|
|
87
|
+
}), 'Must be plain text');
|
|
88
|
+
}
|
|
89
|
+
const id = zod_1.z.string().min(1).max(128);
|
|
90
|
+
const isoTimestamp = zod_1.z.string().min(1);
|
|
91
|
+
const reasonSchema = plainText(exports.APPLICATION_ROLE_REASON_MAX_LENGTH);
|
|
92
|
+
/** One key as the application's owners declare it. */
|
|
93
|
+
exports.applicationPermissionDeclarationSchema = zod_1.z
|
|
94
|
+
.object({
|
|
95
|
+
key: exports.applicationPermissionKeySchema,
|
|
96
|
+
description: plainText(exports.APPLICATION_PERMISSION_DESCRIPTION_MAX_LENGTH),
|
|
97
|
+
})
|
|
98
|
+
.strict();
|
|
99
|
+
/**
|
|
100
|
+
* `PUT /applications/:appId/roles/permissions` — the WHOLE vocabulary.
|
|
101
|
+
*
|
|
102
|
+
* Declarative: a key present here and not live is added, a live key absent
|
|
103
|
+
* here is retired (and every grant of it revoked), a live key present here
|
|
104
|
+
* keeps its identity and takes the new description. Sending the same body twice
|
|
105
|
+
* changes nothing.
|
|
106
|
+
*/
|
|
107
|
+
exports.declareApplicationPermissionsRequestSchema = zod_1.z
|
|
108
|
+
.object({
|
|
109
|
+
permissions: zod_1.z
|
|
110
|
+
.array(exports.applicationPermissionDeclarationSchema)
|
|
111
|
+
.max(exports.APPLICATION_PERMISSIONS_MAX_DECLARED),
|
|
112
|
+
})
|
|
113
|
+
.strict()
|
|
114
|
+
.superRefine((value, ctx) => {
|
|
115
|
+
const seen = new Set();
|
|
116
|
+
value.permissions.forEach((permission, index) => {
|
|
117
|
+
if (seen.has(permission.key)) {
|
|
118
|
+
ctx.addIssue({
|
|
119
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
120
|
+
path: ['permissions', index, 'key'],
|
|
121
|
+
message: `Duplicate permission key ${permission.key}`,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
seen.add(permission.key);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
/** A declared key. Retired keys are history: they confer nothing. */
|
|
128
|
+
exports.applicationPermissionSchema = zod_1.z.object({
|
|
129
|
+
key: exports.applicationPermissionKeySchema,
|
|
130
|
+
description: zod_1.z.string(),
|
|
131
|
+
declaredAt: isoTimestamp,
|
|
132
|
+
declaredByUserId: id.nullable(),
|
|
133
|
+
retiredAt: isoTimestamp.nullable(),
|
|
134
|
+
retiredByUserId: id.nullable(),
|
|
135
|
+
});
|
|
136
|
+
exports.applicationPermissionListSchema = zod_1.z.object({
|
|
137
|
+
items: zod_1.z.array(exports.applicationPermissionSchema),
|
|
138
|
+
});
|
|
139
|
+
exports.declareApplicationPermissionsResponseSchema = exports.applicationPermissionListSchema.extend({
|
|
140
|
+
/** Keys that became live with this declaration. */
|
|
141
|
+
added: zod_1.z.array(exports.applicationPermissionKeySchema),
|
|
142
|
+
/** Keys this declaration retired. */
|
|
143
|
+
retired: zod_1.z.array(exports.applicationPermissionKeySchema),
|
|
144
|
+
/** Live keys whose description changed. */
|
|
145
|
+
described: zod_1.z.array(exports.applicationPermissionKeySchema),
|
|
146
|
+
/** Live grants revoked because their key was retired. */
|
|
147
|
+
revokedGrants: zod_1.z.number().int().nonnegative(),
|
|
148
|
+
});
|
|
149
|
+
/** One grant of one key to one Oxy user. Revocation is a stamp, never a delete. */
|
|
150
|
+
exports.applicationRoleGrantSchema = zod_1.z.object({
|
|
151
|
+
id,
|
|
152
|
+
applicationId: id,
|
|
153
|
+
permission: exports.applicationPermissionKeySchema,
|
|
154
|
+
userId: id,
|
|
155
|
+
/** The grantee's handle, for display. */
|
|
156
|
+
username: zod_1.z.string().nullable(),
|
|
157
|
+
/** The HUMAN who granted it; null once that account was erased. */
|
|
158
|
+
grantedByUserId: id.nullable(),
|
|
159
|
+
grantedAt: isoTimestamp,
|
|
160
|
+
grantReason: zod_1.z.string().nullable(),
|
|
161
|
+
revokedAt: isoTimestamp.nullable(),
|
|
162
|
+
revokedByUserId: id.nullable(),
|
|
163
|
+
revokeReason: zod_1.z.string().nullable(),
|
|
164
|
+
});
|
|
165
|
+
exports.applicationRoleGrantListSchema = zod_1.z.object({
|
|
166
|
+
items: zod_1.z.array(exports.applicationRoleGrantSchema),
|
|
167
|
+
nextCursor: zod_1.z.string().nullable(),
|
|
168
|
+
});
|
|
169
|
+
/** `POST /applications/:appId/roles/grants` — name the grantee by id OR handle. */
|
|
170
|
+
exports.createApplicationRoleGrantRequestSchema = zod_1.z
|
|
171
|
+
.object({
|
|
172
|
+
userId: id.optional(),
|
|
173
|
+
username: zod_1.z.string().trim().min(1).max(64).optional(),
|
|
174
|
+
permission: exports.applicationPermissionKeySchema,
|
|
175
|
+
reason: reasonSchema.optional(),
|
|
176
|
+
})
|
|
177
|
+
.strict()
|
|
178
|
+
.refine((value) => (value.userId === undefined) !== (value.username === undefined), {
|
|
179
|
+
message: 'Name the grantee with exactly one of userId or username',
|
|
180
|
+
path: ['userId'],
|
|
181
|
+
});
|
|
182
|
+
/** `POST /applications/:appId/roles/grants/:grantId/revoke`. */
|
|
183
|
+
exports.revokeApplicationRoleGrantRequestSchema = zod_1.z
|
|
184
|
+
.object({
|
|
185
|
+
reason: reasonSchema.optional(),
|
|
186
|
+
})
|
|
187
|
+
.strict();
|
|
188
|
+
/** `GET /applications/:appId/roles/grants` query. */
|
|
189
|
+
exports.listApplicationRoleGrantsQuerySchema = zod_1.z
|
|
190
|
+
.object({
|
|
191
|
+
permission: exports.applicationPermissionKeySchema.optional(),
|
|
192
|
+
userId: id.optional(),
|
|
193
|
+
includeRevoked: zod_1.z
|
|
194
|
+
.enum(['true', 'false'])
|
|
195
|
+
.transform((value) => value === 'true')
|
|
196
|
+
.optional(),
|
|
197
|
+
limit: zod_1.z.coerce.number().int().min(1).max(exports.APPLICATION_ROLE_GRANTS_PAGE_MAX).optional(),
|
|
198
|
+
cursor: zod_1.z.string().min(1).max(512).optional(),
|
|
199
|
+
})
|
|
200
|
+
.strict();
|
|
201
|
+
/**
|
|
202
|
+
* `GET /applications/:appId/roles/me` — the keys the HUMAN behind the bearer
|
|
203
|
+
* holds for this application, in no particular order. `userId` is that human
|
|
204
|
+
* (the operator), which is NOT the account the session speaks as when a person
|
|
205
|
+
* is acting as an organization.
|
|
206
|
+
*/
|
|
207
|
+
exports.applicationRolesMeSchema = zod_1.z.object({
|
|
208
|
+
applicationId: id,
|
|
209
|
+
userId: id,
|
|
210
|
+
permissions: zod_1.z.array(exports.applicationPermissionKeySchema),
|
|
211
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Account-email constants and response checks, without Zod. Schemas: `../accountEmail.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.emailVerificationConfirmResponseCheck = exports.emailVerificationStartResponseCheck = exports.emailTicketCheck = exports.emailAddressCheck = exports.EMAIL_VERIFICATION_ERROR_CODES = exports.EMAIL_TICKET_TTL_MS = exports.EMAIL_CODE_MAX_ATTEMPTS = exports.EMAIL_CODE_TTL_MS = exports.EMAIL_CODE_LENGTH = exports.EMAIL_VERIFICATION_PURPOSES = void 0;
|
|
9
|
+
const check_1 = require("./check");
|
|
10
|
+
/**
|
|
11
|
+
* - `signup`: above.
|
|
12
|
+
* - `signin`: the code (and link) of an email sign-in (`POST /auth/signin/email/start`).
|
|
13
|
+
* - `reauth`: a signed-in person proving it is them before a sensitive step
|
|
14
|
+
* (`POST /users/me/reauth/email`): a password, an authenticator, deleting the
|
|
15
|
+
* account, linking Commons.
|
|
16
|
+
*/
|
|
17
|
+
exports.EMAIL_VERIFICATION_PURPOSES = ['signup', 'signin', 'reauth'];
|
|
18
|
+
/** Digits in a code. */
|
|
19
|
+
exports.EMAIL_CODE_LENGTH = 6;
|
|
20
|
+
/** How long a code can be confirmed. */
|
|
21
|
+
exports.EMAIL_CODE_TTL_MS = 10 * 60 * 1000;
|
|
22
|
+
/** Wrong codes before a verification is spent and a new code is needed. */
|
|
23
|
+
exports.EMAIL_CODE_MAX_ATTEMPTS = 5;
|
|
24
|
+
/** How long a confirmed code's ticket can be spent. */
|
|
25
|
+
exports.EMAIL_TICKET_TTL_MS = 15 * 60 * 1000;
|
|
26
|
+
/**
|
|
27
|
+
* Stable error codes (`error.code` in the API error body). Clients map these
|
|
28
|
+
* through their localization, never the English message.
|
|
29
|
+
*/
|
|
30
|
+
exports.EMAIL_VERIFICATION_ERROR_CODES = {
|
|
31
|
+
/** The code is wrong, or its verification expired or was spent. */
|
|
32
|
+
codeInvalid: 'EMAIL_CODE_INVALID',
|
|
33
|
+
/** Too many wrong codes: request a new one. */
|
|
34
|
+
tooManyAttempts: 'EMAIL_CODE_TOO_MANY_ATTEMPTS',
|
|
35
|
+
/** The ticket is unknown, expired, spent, or for another email or purpose. */
|
|
36
|
+
ticketInvalid: 'EMAIL_TICKET_INVALID',
|
|
37
|
+
/** A sign-up without a confirmed email. */
|
|
38
|
+
ticketRequired: 'EMAIL_TICKET_REQUIRED',
|
|
39
|
+
/** This server cannot send mail. */
|
|
40
|
+
unavailable: 'EMAIL_UNAVAILABLE',
|
|
41
|
+
};
|
|
42
|
+
/* -------------------------------------------------------------------------- */
|
|
43
|
+
/* Checks */
|
|
44
|
+
/* -------------------------------------------------------------------------- */
|
|
45
|
+
exports.emailAddressCheck = (0, check_1.string)(check_1.trim, check_1.toLowerCase, (0, check_1.minLength)(3), (0, check_1.maxLength)(254), check_1.email);
|
|
46
|
+
exports.emailTicketCheck = (0, check_1.string)(check_1.trim, (0, check_1.pattern)(/^[A-Za-z0-9_-]{43}$/, 'ticket must be 32 bytes of base64url'));
|
|
47
|
+
exports.emailVerificationStartResponseCheck = (0, check_1.exact)()((0, check_1.object)({ verificationId: (0, check_1.string)((0, check_1.minLength)(1), (0, check_1.maxLength)(64)), expiresAt: (0, check_1.number)(check_1.int, check_1.positive) }));
|
|
48
|
+
exports.emailVerificationConfirmResponseCheck = (0, check_1.exact)()((0, check_1.object)({ ticket: exports.emailTicketCheck, expiresAt: (0, check_1.number)(check_1.int, check_1.positive) }));
|