@oxy.so/contracts 4.11.0-oxy-one.0 → 4.11.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/.tsbuildinfo +1 -1
- package/dist/cjs/accountGraph.js +5 -3
- package/dist/cjs/agency.js +178 -96
- package/dist/cjs/agentKeys.js +80 -26
- package/dist/cjs/capabilityBindings.js +2 -2
- package/dist/cjs/capabilityInvocation.js +3 -1
- package/dist/cjs/commonsSignIn.js +2 -2
- package/dist/cjs/deviceSession.js +5 -1
- package/dist/cjs/email/messages.js +70 -4
- package/dist/cjs/emailAgentContext.js +16 -8
- package/dist/cjs/externalIdentity.js +30 -12
- package/dist/cjs/identity.js +14 -6
- package/dist/cjs/identityLink.js +7 -2
- package/dist/cjs/identityProof.js +2 -1
- package/dist/cjs/index.js +5 -3
- package/dist/cjs/inference/catalogue.js +2 -12
- package/dist/cjs/inference/decisions.js +102 -83
- package/dist/cjs/inference/economics.js +15 -5
- package/dist/cjs/inference/embeddings.js +44 -6
- package/dist/cjs/inference/inbox.js +33 -2
- package/dist/cjs/inference/providerConnection.js +21 -6
- package/dist/cjs/inference/realtime.js +114 -107
- package/dist/cjs/inference/scopedExecution.js +12 -12
- package/dist/cjs/inference/usage.js +2 -9
- package/dist/cjs/notifications.js +25 -5
- package/dist/cjs/oauth.js +30 -14
- package/dist/cjs/oxyRecordTypes.js +2 -2
- package/dist/cjs/products/access.js +146 -57
- package/dist/cjs/products/billing.js +71 -17
- package/dist/cjs/products/checkout.js +24 -6
- package/dist/cjs/products/plans.js +22 -7
- package/dist/cjs/recommendations.js +4 -6
- package/dist/cjs/reputation.js +3 -6
- package/dist/cjs/sessionStatus.js +1 -6
- package/dist/cjs/signIn.js +17 -4
- package/dist/cjs/transparency.js +3 -1
- package/dist/cjs/updates.js +2 -4
- package/dist/cjs/userResponse.js +27 -7
- package/dist/cjs/username.js +3 -1
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/accountGraph.js +5 -3
- package/dist/esm/agency.js +178 -96
- package/dist/esm/agentKeys.js +80 -26
- package/dist/esm/capabilityBindings.js +2 -2
- package/dist/esm/capabilityInvocation.js +3 -1
- package/dist/esm/commonsSignIn.js +2 -2
- package/dist/esm/deviceSession.js +5 -1
- package/dist/esm/email/messages.js +69 -3
- package/dist/esm/emailAgentContext.js +16 -8
- package/dist/esm/externalIdentity.js +30 -12
- package/dist/esm/identity.js +14 -6
- package/dist/esm/identityLink.js +7 -2
- package/dist/esm/identityProof.js +2 -1
- package/dist/esm/index.js +7 -7
- package/dist/esm/inference/aliaModelRelease.js +1 -1
- package/dist/esm/inference/catalogue.js +3 -13
- package/dist/esm/inference/decisions.js +108 -89
- package/dist/esm/inference/economics.js +16 -6
- package/dist/esm/inference/embeddings.js +44 -6
- package/dist/esm/inference/inbox.js +32 -1
- package/dist/esm/inference/providerConnection.js +21 -6
- package/dist/esm/inference/realtime.js +123 -116
- package/dist/esm/inference/scopedExecution.js +15 -15
- package/dist/esm/inference/usage.js +2 -9
- package/dist/esm/notifications.js +25 -5
- package/dist/esm/oauth.js +30 -14
- package/dist/esm/oxyRecordTypes.js +2 -2
- package/dist/esm/products/access.js +146 -57
- package/dist/esm/products/billing.js +71 -17
- package/dist/esm/products/checkout.js +24 -6
- package/dist/esm/products/plans.js +22 -7
- package/dist/esm/recommendations.js +4 -6
- package/dist/esm/reputation.js +3 -6
- package/dist/esm/sessionStatus.js +1 -6
- package/dist/esm/signIn.js +17 -4
- package/dist/esm/transparency.js +3 -1
- package/dist/esm/updates.js +2 -4
- package/dist/esm/userResponse.js +27 -7
- package/dist/esm/username.js +3 -1
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/accountGraph.d.ts +1 -1
- package/dist/types/commonsSignIn.d.ts +2 -2
- package/dist/types/email/messages.d.ts +208 -2
- package/dist/types/identity.d.ts +1 -1
- package/dist/types/index.d.ts +8 -8
- package/dist/types/inference/decisions.d.ts +1 -1
- package/dist/types/inference/inbox.d.ts +129 -5
- package/dist/types/inference/realtime.d.ts +1 -1
- package/dist/types/inference/scopedExecution.d.ts +1 -1
- package/dist/types/moderationReputation.d.ts +1 -1
- package/dist/types/oxyRecordTypes.d.ts +2 -2
- package/dist/types/products/access.d.ts +102 -102
- package/dist/types/products/checkout.d.ts +3 -3
- package/dist/types/products/plans.d.ts +40 -40
- package/dist/types/reputation.d.ts +4 -4
- package/dist/types/updates.d.ts +1 -1
- package/dist/types/userResponse.d.ts +22 -23
- package/package.json +1 -2
package/dist/esm/accountGraph.js
CHANGED
|
@@ -108,7 +108,7 @@ export function isOperatorSwitchTargetKind(kind) {
|
|
|
108
108
|
* Narrow an unknown value to an {@link AccountKind}.
|
|
109
109
|
*
|
|
110
110
|
* The user-DTO serializers read from structurally-permissive `unknown` sources
|
|
111
|
-
* (a Drizzle row, a
|
|
111
|
+
* (a Drizzle row, a raw document, an already-formatted object), so each one
|
|
112
112
|
* would otherwise hand-roll this check and they would drift on what counts.
|
|
113
113
|
*/
|
|
114
114
|
export function isAccountKind(value) {
|
|
@@ -386,7 +386,8 @@ const accountNameSchema = z
|
|
|
386
386
|
* accept categories would break that reasoning silently, so
|
|
387
387
|
* `__tests__/accountGraph.test.ts` asserts the two lists agree.
|
|
388
388
|
*/
|
|
389
|
-
export const createAccountRequestSchema = z
|
|
389
|
+
export const createAccountRequestSchema = z
|
|
390
|
+
.object({
|
|
390
391
|
parentAccountId: z.string().trim().min(1).optional(),
|
|
391
392
|
kind: childAccountKindSchema,
|
|
392
393
|
/**
|
|
@@ -465,7 +466,8 @@ export const createAccountRequestSchema = z.object({
|
|
|
465
466
|
* remedy must not either.
|
|
466
467
|
*/
|
|
467
468
|
isPrivateAccount: z.boolean().optional(),
|
|
468
|
-
})
|
|
469
|
+
})
|
|
470
|
+
.superRefine((request, ctx) => {
|
|
469
471
|
// The ONE place `kind` and `username` arrive in the same object, so it is the
|
|
470
472
|
// only place a wire schema CAN apply the per-kind half of the policy: a bot's
|
|
471
473
|
// handle must end in `bot`. Not a second rule — it asks
|
package/dist/esm/agency.js
CHANGED
|
@@ -2,17 +2,17 @@ import { z } from 'zod';
|
|
|
2
2
|
import { catalogInvocationPathParameters, findOverlappingCatalogInvocations, } from './capabilityInvocation.js';
|
|
3
3
|
const nonEmptyStringSchema = z.string().trim().min(1);
|
|
4
4
|
const identifierSchema = z.string().trim().min(1).max(255);
|
|
5
|
-
const limitKeySchema = z
|
|
5
|
+
const limitKeySchema = z
|
|
6
|
+
.string()
|
|
7
|
+
.regex(/^[A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z][A-Za-z0-9_]*)*$/, 'limit keys must be dot-separated input property names')
|
|
8
|
+
.max(255);
|
|
6
9
|
const auditCodeSchema = z.string().regex(/^[A-Za-z0-9_.:-]{1,128}$/);
|
|
7
10
|
const sha256HexSchema = z.string().regex(/^[a-f0-9]{64}$/);
|
|
8
|
-
const invocationPathSchema = z
|
|
11
|
+
const invocationPathSchema = z
|
|
12
|
+
.string()
|
|
13
|
+
.regex(/^\/(?!\/)[^\\?#]*$/, 'invocation paths must be absolute app-local paths without backslashes, query or fragment');
|
|
9
14
|
/** Autonomy is ordered from least to most permissive. */
|
|
10
|
-
export const AUTONOMY_LEVELS = [
|
|
11
|
-
'read_only',
|
|
12
|
-
'draft',
|
|
13
|
-
'execute_on_request',
|
|
14
|
-
'autonomous',
|
|
15
|
-
];
|
|
15
|
+
export const AUTONOMY_LEVELS = ['read_only', 'draft', 'execute_on_request', 'autonomous'];
|
|
16
16
|
export const autonomyLevelSchema = z.enum(AUTONOMY_LEVELS);
|
|
17
17
|
export const CAPABILITY_PACKAGES = [
|
|
18
18
|
'read',
|
|
@@ -26,14 +26,18 @@ export const CAPABILITY_PACKAGES = [
|
|
|
26
26
|
];
|
|
27
27
|
export const capabilityPackageSchema = z.enum(CAPABILITY_PACKAGES);
|
|
28
28
|
export const actorRefSchema = z.discriminatedUnion('type', [
|
|
29
|
-
z
|
|
29
|
+
z
|
|
30
|
+
.object({
|
|
30
31
|
type: z.literal('alia'),
|
|
31
32
|
ownerAccountId: identifierSchema,
|
|
32
|
-
})
|
|
33
|
-
|
|
33
|
+
})
|
|
34
|
+
.strict(),
|
|
35
|
+
z
|
|
36
|
+
.object({
|
|
34
37
|
type: z.literal('agent'),
|
|
35
38
|
accountId: identifierSchema,
|
|
36
|
-
})
|
|
39
|
+
})
|
|
40
|
+
.strict(),
|
|
37
41
|
]);
|
|
38
42
|
/** Present requester only; standing grants/automation retain actorRefSchema. */
|
|
39
43
|
export const executionActorRefSchema = z.discriminatedUnion('type', [
|
|
@@ -41,63 +45,84 @@ export const executionActorRefSchema = z.discriminatedUnion('type', [
|
|
|
41
45
|
z.object({ type: z.literal('requester'), accountId: identifierSchema }).strict(),
|
|
42
46
|
]);
|
|
43
47
|
/** Separate bearer lives only in the SDK option / authority request body. */
|
|
44
|
-
export const foregroundExecutionAuthorizationInputSchema = z
|
|
48
|
+
export const foregroundExecutionAuthorizationInputSchema = z
|
|
49
|
+
.object({
|
|
45
50
|
tool: z.enum(['recommendProfiles', 'readViewerGraph']),
|
|
46
|
-
expectedCatalog: z
|
|
51
|
+
expectedCatalog: z
|
|
52
|
+
.object({
|
|
47
53
|
registrationId: identifierSchema,
|
|
48
54
|
version: identifierSchema,
|
|
49
55
|
digest: sha256HexSchema,
|
|
50
|
-
})
|
|
56
|
+
})
|
|
57
|
+
.strict(),
|
|
51
58
|
runId: identifierSchema,
|
|
52
59
|
stepId: identifierSchema.optional(),
|
|
53
60
|
expiresAt: z.string().datetime(),
|
|
54
|
-
})
|
|
55
|
-
|
|
61
|
+
})
|
|
62
|
+
.strict();
|
|
63
|
+
export const resourceRefSchema = z
|
|
64
|
+
.object({
|
|
56
65
|
appId: identifierSchema,
|
|
57
66
|
effectiveAccountId: identifierSchema,
|
|
58
67
|
resourceType: identifierSchema,
|
|
59
68
|
resourceId: identifierSchema,
|
|
60
|
-
})
|
|
61
|
-
|
|
69
|
+
})
|
|
70
|
+
.strict();
|
|
71
|
+
export const toolGrantOverrideSchema = z
|
|
72
|
+
.object({
|
|
62
73
|
tool: identifierSchema,
|
|
63
74
|
decision: z.enum(['allow', 'deny']),
|
|
64
|
-
})
|
|
65
|
-
|
|
75
|
+
})
|
|
76
|
+
.strict();
|
|
77
|
+
export const grantLimitSchema = z
|
|
78
|
+
.object({
|
|
66
79
|
tool: identifierSchema,
|
|
67
80
|
key: limitKeySchema,
|
|
68
81
|
// Persisted limits are deliberately closed scalar bounds. Strings and
|
|
69
82
|
// arrays are tool arguments in disguise (recipient lists, prompts, search
|
|
70
83
|
// queries) and ADR 0016 forbids persisting those in Oxy.
|
|
71
84
|
value: z.union([z.number().finite(), z.boolean()]),
|
|
72
|
-
})
|
|
73
|
-
|
|
85
|
+
})
|
|
86
|
+
.strict();
|
|
87
|
+
export const capabilityCatalogBindingSchema = z
|
|
88
|
+
.object({
|
|
74
89
|
registrationId: identifierSchema,
|
|
75
90
|
version: identifierSchema,
|
|
76
91
|
digest: sha256HexSchema,
|
|
77
|
-
})
|
|
92
|
+
})
|
|
93
|
+
.strict();
|
|
78
94
|
export const executionAuthorizationRefSchema = z.discriminatedUnion('kind', [
|
|
79
|
-
z
|
|
95
|
+
z
|
|
96
|
+
.object({
|
|
80
97
|
kind: z.literal('direct_request'),
|
|
81
98
|
id: identifierSchema,
|
|
82
|
-
})
|
|
83
|
-
|
|
99
|
+
})
|
|
100
|
+
.strict(),
|
|
101
|
+
z
|
|
102
|
+
.object({
|
|
84
103
|
kind: z.literal('automation'),
|
|
85
104
|
id: identifierSchema,
|
|
86
105
|
automationId: identifierSchema,
|
|
87
|
-
})
|
|
106
|
+
})
|
|
107
|
+
.strict(),
|
|
88
108
|
]);
|
|
89
|
-
export const capabilityCoordinatorSchema = z
|
|
109
|
+
export const capabilityCoordinatorSchema = z
|
|
110
|
+
.object({
|
|
90
111
|
applicationId: identifierSchema,
|
|
91
112
|
credentialId: identifierSchema,
|
|
92
|
-
})
|
|
113
|
+
})
|
|
114
|
+
.strict();
|
|
93
115
|
/** Opt-in catalogue pin; legacy issuance omits expectedCatalog and its claim. */
|
|
94
|
-
export const capabilityTicketRequestSchema = z
|
|
116
|
+
export const capabilityTicketRequestSchema = z
|
|
117
|
+
.object({
|
|
95
118
|
executionAuthorizationId: z.string().min(1),
|
|
96
119
|
runId: z.string().min(1).optional(),
|
|
97
120
|
stepId: z.string().min(1).optional(),
|
|
98
121
|
expectedCatalog: capabilityCatalogBindingSchema.optional(),
|
|
99
|
-
})
|
|
100
|
-
|
|
122
|
+
})
|
|
123
|
+
.strict();
|
|
124
|
+
export const delegationGrantSchema = z
|
|
125
|
+
.object({
|
|
101
126
|
id: identifierSchema,
|
|
102
127
|
ownerAccountId: identifierSchema,
|
|
103
128
|
actor: actorRefSchema,
|
|
@@ -113,30 +138,38 @@ export const delegationGrantSchema = z.object({
|
|
|
113
138
|
revokedAt: z.string().datetime().nullable().default(null),
|
|
114
139
|
createdAt: z.string().datetime(),
|
|
115
140
|
updatedAt: z.string().datetime(),
|
|
116
|
-
})
|
|
141
|
+
})
|
|
142
|
+
.strict();
|
|
117
143
|
export const automationTriggerSchema = z.discriminatedUnion('type', [
|
|
118
144
|
z.object({ type: z.literal('manual') }).strict(),
|
|
119
|
-
z
|
|
145
|
+
z
|
|
146
|
+
.object({
|
|
120
147
|
type: z.literal('event'),
|
|
121
148
|
appId: identifierSchema,
|
|
122
149
|
eventType: identifierSchema,
|
|
123
150
|
resource: resourceRefSchema.optional(),
|
|
124
|
-
})
|
|
125
|
-
|
|
151
|
+
})
|
|
152
|
+
.strict(),
|
|
153
|
+
z
|
|
154
|
+
.object({
|
|
126
155
|
type: z.literal('schedule'),
|
|
127
156
|
cron: nonEmptyStringSchema,
|
|
128
157
|
timezone: nonEmptyStringSchema,
|
|
129
|
-
})
|
|
158
|
+
})
|
|
159
|
+
.strict(),
|
|
130
160
|
]);
|
|
131
161
|
export const automationActorSelectionSchema = z.discriminatedUnion('mode', [
|
|
132
162
|
z.object({ mode: z.literal('fixed'), actor: actorRefSchema }).strict(),
|
|
133
163
|
z.object({ mode: z.literal('automatic') }).strict(),
|
|
134
164
|
]);
|
|
135
|
-
export const automationDataFlowSchema = z
|
|
165
|
+
export const automationDataFlowSchema = z
|
|
166
|
+
.object({
|
|
136
167
|
sources: z.array(resourceRefSchema),
|
|
137
168
|
destinations: z.array(resourceRefSchema),
|
|
138
|
-
})
|
|
139
|
-
|
|
169
|
+
})
|
|
170
|
+
.strict();
|
|
171
|
+
export const automationDefinitionSchema = z
|
|
172
|
+
.object({
|
|
140
173
|
id: identifierSchema,
|
|
141
174
|
ownerAccountId: identifierSchema,
|
|
142
175
|
objective: nonEmptyStringSchema,
|
|
@@ -150,8 +183,10 @@ export const automationDefinitionSchema = z.object({
|
|
|
150
183
|
enabled: z.boolean(),
|
|
151
184
|
createdAt: z.string().datetime(),
|
|
152
185
|
updatedAt: z.string().datetime(),
|
|
153
|
-
})
|
|
154
|
-
|
|
186
|
+
})
|
|
187
|
+
.strict();
|
|
188
|
+
export const capabilityTicketClaimsSchema = z
|
|
189
|
+
.object({
|
|
155
190
|
iss: nonEmptyStringSchema,
|
|
156
191
|
aud: identifierSchema,
|
|
157
192
|
sub: identifierSchema,
|
|
@@ -174,10 +209,10 @@ export const capabilityTicketClaimsSchema = z.object({
|
|
|
174
209
|
capabilities: z.array(identifierSchema).min(1),
|
|
175
210
|
limits: z.array(grantLimitSchema).default([]),
|
|
176
211
|
autonomy: autonomyLevelSchema,
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
212
|
+
})
|
|
213
|
+
.strict()
|
|
214
|
+
.superRefine((claims, context) => {
|
|
215
|
+
const expectedSubject = claims.actor.type !== 'alia' ? claims.actor.accountId : `alia:${claims.actor.ownerAccountId}`;
|
|
181
216
|
if (claims.sub !== expectedSubject) {
|
|
182
217
|
context.addIssue({
|
|
183
218
|
code: z.ZodIssueCode.custom,
|
|
@@ -192,13 +227,17 @@ export const capabilityTicketClaimsSchema = z.object({
|
|
|
192
227
|
path: ['actor', 'ownerAccountId'],
|
|
193
228
|
});
|
|
194
229
|
}
|
|
195
|
-
if (claims.actor.type === 'requester' &&
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
230
|
+
if (claims.actor.type === 'requester' &&
|
|
231
|
+
(claims.actor.accountId !== claims.requesterAccountId ||
|
|
232
|
+
claims.executionAuthorization.kind !== 'direct_request' ||
|
|
233
|
+
claims.autonomy !== 'read_only' ||
|
|
234
|
+
claims.grantId !== undefined ||
|
|
235
|
+
claims.automationId !== undefined)) {
|
|
236
|
+
context.addIssue({
|
|
237
|
+
code: z.ZodIssueCode.custom,
|
|
238
|
+
path: ['actor'],
|
|
239
|
+
message: 'requester actors require their exact principal and direct read-only authority without standing grants',
|
|
240
|
+
});
|
|
202
241
|
}
|
|
203
242
|
if (claims.exp <= claims.iat) {
|
|
204
243
|
context.addIssue({
|
|
@@ -235,7 +274,8 @@ export const capabilityTicketClaimsSchema = z.object({
|
|
|
235
274
|
});
|
|
236
275
|
/** Structural projections only: an authenticated transport must produce these. */
|
|
237
276
|
export const invocationPrincipalSchema = z.discriminatedUnion('kind', [
|
|
238
|
-
z
|
|
277
|
+
z
|
|
278
|
+
.object({
|
|
239
279
|
kind: z.literal('oauth'),
|
|
240
280
|
subject: identifierSchema,
|
|
241
281
|
clientId: identifierSchema,
|
|
@@ -243,25 +283,33 @@ export const invocationPrincipalSchema = z.discriminatedUnion('kind', [
|
|
|
243
283
|
activeAccountId: identifierSchema,
|
|
244
284
|
scopes: z.array(identifierSchema),
|
|
245
285
|
resource: z.string().url(),
|
|
246
|
-
})
|
|
247
|
-
|
|
286
|
+
})
|
|
287
|
+
.strict(),
|
|
288
|
+
z
|
|
289
|
+
.object({
|
|
248
290
|
kind: z.literal('capability'),
|
|
249
291
|
claims: capabilityTicketClaimsSchema.refine((claims) => claims.catalog !== undefined, {
|
|
250
292
|
message: 'internal MCP requires a signed catalogue binding',
|
|
251
293
|
}),
|
|
252
|
-
})
|
|
294
|
+
})
|
|
295
|
+
.strict(),
|
|
253
296
|
]);
|
|
254
|
-
export const policyDecisionSchema = z
|
|
297
|
+
export const policyDecisionSchema = z
|
|
298
|
+
.object({
|
|
255
299
|
allowed: z.boolean(),
|
|
256
300
|
reason: identifierSchema,
|
|
257
301
|
effectiveAutonomy: autonomyLevelSchema.optional(),
|
|
258
302
|
grantId: identifierSchema.optional(),
|
|
259
|
-
})
|
|
260
|
-
|
|
303
|
+
})
|
|
304
|
+
.strict();
|
|
305
|
+
export const auditResultSchema = z
|
|
306
|
+
.object({
|
|
261
307
|
status: z.enum(['planned', 'allowed', 'denied', 'succeeded', 'failed', 'rolled_back']),
|
|
262
308
|
code: auditCodeSchema.optional(),
|
|
263
|
-
})
|
|
264
|
-
|
|
309
|
+
})
|
|
310
|
+
.strict();
|
|
311
|
+
export const auditEventSchema = z
|
|
312
|
+
.object({
|
|
265
313
|
eventId: identifierSchema,
|
|
266
314
|
occurredAt: z.string().datetime(),
|
|
267
315
|
requesterAccountId: identifierSchema,
|
|
@@ -274,20 +322,26 @@ export const auditEventSchema = z.object({
|
|
|
274
322
|
capabilities: z.array(identifierSchema),
|
|
275
323
|
policyDecision: policyDecisionSchema,
|
|
276
324
|
result: auditResultSchema,
|
|
277
|
-
rollback: z
|
|
325
|
+
rollback: z
|
|
326
|
+
.object({
|
|
278
327
|
supported: z.boolean(),
|
|
279
328
|
attempted: z.boolean(),
|
|
280
329
|
succeeded: z.boolean().optional(),
|
|
281
|
-
})
|
|
282
|
-
|
|
330
|
+
})
|
|
331
|
+
.strict(),
|
|
332
|
+
correlation: z
|
|
333
|
+
.object({
|
|
283
334
|
runId: identifierSchema,
|
|
284
335
|
stepId: identifierSchema.optional(),
|
|
285
336
|
automationId: identifierSchema.optional(),
|
|
286
337
|
idempotencyKeyHash: sha256HexSchema.optional(),
|
|
287
338
|
capabilityTicketId: identifierSchema.optional(),
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
|
|
339
|
+
})
|
|
340
|
+
.strict(),
|
|
341
|
+
})
|
|
342
|
+
.strict();
|
|
343
|
+
export const catalogToolSchema = z
|
|
344
|
+
.object({
|
|
291
345
|
name: identifierSchema,
|
|
292
346
|
version: identifierSchema,
|
|
293
347
|
description: nonEmptyStringSchema,
|
|
@@ -300,15 +354,23 @@ export const catalogToolSchema = z.object({
|
|
|
300
354
|
idempotency: z.enum(['none', 'supported', 'required']),
|
|
301
355
|
rollback: z.enum(['none', 'manual', 'supported']),
|
|
302
356
|
exposure: z.array(z.enum(['internal', 'mcp'])).min(1),
|
|
303
|
-
limitKeys: z
|
|
357
|
+
limitKeys: z
|
|
358
|
+
.array(z
|
|
359
|
+
.object({
|
|
304
360
|
key: limitKeySchema,
|
|
305
361
|
kind: z.enum(['maximum_number', 'exact_boolean']),
|
|
306
|
-
})
|
|
307
|
-
|
|
362
|
+
})
|
|
363
|
+
.strict())
|
|
364
|
+
.default([]),
|
|
365
|
+
invocation: z
|
|
366
|
+
.object({
|
|
308
367
|
method: z.enum(['GET', 'POST', 'PATCH', 'PUT', 'DELETE']),
|
|
309
368
|
path: invocationPathSchema,
|
|
310
|
-
})
|
|
311
|
-
|
|
369
|
+
})
|
|
370
|
+
.strict(),
|
|
371
|
+
})
|
|
372
|
+
.strict()
|
|
373
|
+
.superRefine((tool, context) => {
|
|
312
374
|
const requireUnique = (values, path) => {
|
|
313
375
|
if (new Set(values).size !== values.length) {
|
|
314
376
|
context.addIssue({
|
|
@@ -385,7 +447,8 @@ export const catalogToolSchema = z.object({
|
|
|
385
447
|
path: ['capabilityPackage'],
|
|
386
448
|
});
|
|
387
449
|
}
|
|
388
|
-
if ((tool.effect === 'financial' || tool.effect === 'security') &&
|
|
450
|
+
if ((tool.effect === 'financial' || tool.effect === 'security') &&
|
|
451
|
+
tool.idempotency !== 'required') {
|
|
389
452
|
context.addIssue({
|
|
390
453
|
code: z.ZodIssueCode.custom,
|
|
391
454
|
message: 'Financial and security effects require idempotency keys',
|
|
@@ -404,16 +467,17 @@ export const catalogToolSchema = z.object({
|
|
|
404
467
|
// not declare as a REQUIRED property can never be filled, and a GET input
|
|
405
468
|
// that is not a scalar has no query-string form — both are refused here so
|
|
406
469
|
// the builder never has to guess.
|
|
407
|
-
const declared = typeof tool.inputSchema.properties === 'object'
|
|
408
|
-
|
|
409
|
-
|
|
470
|
+
const declared = typeof tool.inputSchema.properties === 'object' &&
|
|
471
|
+
tool.inputSchema.properties !== null &&
|
|
472
|
+
!Array.isArray(tool.inputSchema.properties)
|
|
410
473
|
? tool.inputSchema.properties
|
|
411
474
|
: {};
|
|
412
475
|
const required = Array.isArray(tool.inputSchema.required) ? tool.inputSchema.required : [];
|
|
413
476
|
const parameters = catalogInvocationPathParameters(tool.invocation.path);
|
|
414
477
|
requireUnique(parameters, 'invocation.path parameters');
|
|
415
478
|
for (const parameter of parameters) {
|
|
416
|
-
if (!Object.prototype.hasOwnProperty.call(declared, parameter) ||
|
|
479
|
+
if (!Object.prototype.hasOwnProperty.call(declared, parameter) ||
|
|
480
|
+
!required.includes(parameter)) {
|
|
417
481
|
context.addIssue({
|
|
418
482
|
code: z.ZodIssueCode.custom,
|
|
419
483
|
message: `Path parameter {${parameter}} must be a required input property`,
|
|
@@ -436,20 +500,26 @@ export const catalogToolSchema = z.object({
|
|
|
436
500
|
}
|
|
437
501
|
}
|
|
438
502
|
});
|
|
439
|
-
export const catalogEventSchema = z
|
|
503
|
+
export const catalogEventSchema = z
|
|
504
|
+
.object({
|
|
440
505
|
type: identifierSchema,
|
|
441
506
|
version: identifierSchema,
|
|
442
507
|
description: nonEmptyStringSchema,
|
|
443
508
|
dataSchema: z.record(z.unknown()),
|
|
444
509
|
resourceTypes: z.array(identifierSchema).min(1),
|
|
445
|
-
})
|
|
446
|
-
|
|
510
|
+
})
|
|
511
|
+
.strict();
|
|
512
|
+
export const appCapabilityCatalogSchema = z
|
|
513
|
+
.object({
|
|
447
514
|
schemaVersion: z.literal('1'),
|
|
448
515
|
appId: identifierSchema,
|
|
449
516
|
version: identifierSchema,
|
|
450
517
|
audience: identifierSchema,
|
|
451
518
|
/** HTTPS origin that serves the catalog's internal invocation paths. */
|
|
452
|
-
internalBaseUrl: z
|
|
519
|
+
internalBaseUrl: z
|
|
520
|
+
.string()
|
|
521
|
+
.url()
|
|
522
|
+
.superRefine((value, context) => {
|
|
453
523
|
const url = new URL(value);
|
|
454
524
|
const localDevelopment = url.hostname === 'localhost' || url.hostname === '127.0.0.1';
|
|
455
525
|
if (url.protocol !== 'https:' && !(localDevelopment && url.protocol === 'http:')) {
|
|
@@ -468,12 +538,16 @@ export const appCapabilityCatalogSchema = z.object({
|
|
|
468
538
|
/** Account-scoped resource used for native Alia bindings without app-specific code. */
|
|
469
539
|
accountResourceType: identifierSchema,
|
|
470
540
|
/** Canonical protected-resource URI when this catalog is also exposed as an external MCP server. */
|
|
471
|
-
externalMcp: z
|
|
472
|
-
|
|
541
|
+
externalMcp: z
|
|
542
|
+
.object({
|
|
543
|
+
resource: z
|
|
544
|
+
.string()
|
|
545
|
+
.url()
|
|
546
|
+
.superRefine((value, context) => {
|
|
473
547
|
const url = new URL(value);
|
|
474
|
-
const localDevelopment = url.hostname === 'localhost'
|
|
475
|
-
|
|
476
|
-
|
|
548
|
+
const localDevelopment = url.hostname === 'localhost' ||
|
|
549
|
+
url.hostname === '127.0.0.1' ||
|
|
550
|
+
url.hostname === '[::1]';
|
|
477
551
|
if (url.protocol !== 'https:' && !(localDevelopment && url.protocol === 'http:')) {
|
|
478
552
|
context.addIssue({
|
|
479
553
|
code: z.ZodIssueCode.custom,
|
|
@@ -487,10 +561,14 @@ export const appCapabilityCatalogSchema = z.object({
|
|
|
487
561
|
});
|
|
488
562
|
}
|
|
489
563
|
}),
|
|
490
|
-
})
|
|
564
|
+
})
|
|
565
|
+
.strict()
|
|
566
|
+
.optional(),
|
|
491
567
|
tools: z.array(catalogToolSchema),
|
|
492
568
|
events: z.array(catalogEventSchema),
|
|
493
|
-
})
|
|
569
|
+
})
|
|
570
|
+
.strict()
|
|
571
|
+
.superRefine((catalog, context) => {
|
|
494
572
|
const names = new Set();
|
|
495
573
|
for (const [index, tool] of catalog.tools.entries()) {
|
|
496
574
|
if (names.has(tool.name)) {
|
|
@@ -509,8 +587,8 @@ export const appCapabilityCatalogSchema = z.object({
|
|
|
509
587
|
for (const [left, right] of findOverlappingCatalogInvocations(catalog.tools)) {
|
|
510
588
|
context.addIssue({
|
|
511
589
|
code: z.ZodIssueCode.custom,
|
|
512
|
-
message: `Tools ${left.name} and ${right.name} have overlapping invocations `
|
|
513
|
-
|
|
590
|
+
message: `Tools ${left.name} and ${right.name} have overlapping invocations ` +
|
|
591
|
+
`(${left.invocation.method} ${left.invocation.path} / ${right.invocation.method} ${right.invocation.path})`,
|
|
514
592
|
path: ['tools'],
|
|
515
593
|
});
|
|
516
594
|
}
|
|
@@ -526,13 +604,16 @@ export const appCapabilityCatalogSchema = z.object({
|
|
|
526
604
|
eventTypes.add(event.type);
|
|
527
605
|
}
|
|
528
606
|
});
|
|
529
|
-
export const catalogRegistrationSchema = z
|
|
607
|
+
export const catalogRegistrationSchema = z
|
|
608
|
+
.object({
|
|
530
609
|
catalog: appCapabilityCatalogSchema,
|
|
531
610
|
digest: z.string().regex(/^[a-f0-9]{64}$/),
|
|
532
611
|
signature: nonEmptyStringSchema,
|
|
533
612
|
deployedAt: z.string().datetime(),
|
|
534
|
-
})
|
|
535
|
-
|
|
613
|
+
})
|
|
614
|
+
.strict();
|
|
615
|
+
export const normalizedAppEventSchema = z
|
|
616
|
+
.object({
|
|
536
617
|
eventId: identifierSchema,
|
|
537
618
|
appId: identifierSchema,
|
|
538
619
|
accountId: identifierSchema,
|
|
@@ -540,4 +621,5 @@ export const normalizedAppEventSchema = z.object({
|
|
|
540
621
|
type: identifierSchema,
|
|
541
622
|
occurredAt: z.string().datetime(),
|
|
542
623
|
data: z.record(z.unknown()),
|
|
543
|
-
})
|
|
624
|
+
})
|
|
625
|
+
.strict();
|
package/dist/esm/agentKeys.js
CHANGED
|
@@ -4,8 +4,15 @@ import { reauthProofSchema } from './signIn.js';
|
|
|
4
4
|
import { canonicalJson } from './identityProof.js';
|
|
5
5
|
export const AGENT_PROOF_AUDIENCE = 'oxy-api/agent';
|
|
6
6
|
export const AGENT_PROOF_TTL_MS = 60000;
|
|
7
|
-
export const AGENT_PROOF_ACTIONS = [
|
|
8
|
-
|
|
7
|
+
export const AGENT_PROOF_ACTIONS = [
|
|
8
|
+
'agent_signin',
|
|
9
|
+
'agent_enroll',
|
|
10
|
+
'agent_rotate',
|
|
11
|
+
'agent_recover',
|
|
12
|
+
'agent_governance',
|
|
13
|
+
];
|
|
14
|
+
export const agentProofClaimsSchema = z
|
|
15
|
+
.object({
|
|
9
16
|
version: z.literal(1),
|
|
10
17
|
audience: z.literal(AGENT_PROOF_AUDIENCE),
|
|
11
18
|
action: z.enum(AGENT_PROOF_ACTIONS),
|
|
@@ -16,48 +23,95 @@ export const agentProofClaimsSchema = z.object({
|
|
|
16
23
|
payloadDigest: z.string().regex(/^[0-9a-f]{64}$/),
|
|
17
24
|
challenge: z.string().regex(/^[0-9a-f]{64}$/),
|
|
18
25
|
expiresAt: z.number().int().positive(),
|
|
19
|
-
})
|
|
26
|
+
})
|
|
27
|
+
.strict();
|
|
20
28
|
/** Different proof roles cannot substitute for one another on the same operation. */
|
|
21
29
|
export function buildAgentProofMessage(claims, timestamp, role = 'credential') {
|
|
22
|
-
return canonicalJson({
|
|
30
|
+
return canonicalJson({
|
|
31
|
+
domain: 'oxy-agent-proof',
|
|
32
|
+
...agentProofClaimsSchema.parse(claims),
|
|
33
|
+
timestamp,
|
|
34
|
+
role,
|
|
35
|
+
});
|
|
23
36
|
}
|
|
24
|
-
export const agentSignatureSchema = z
|
|
37
|
+
export const agentSignatureSchema = z
|
|
38
|
+
.object({
|
|
25
39
|
challenge: z.string().regex(/^[0-9a-f]{64}$/),
|
|
26
|
-
signature: z
|
|
40
|
+
signature: z
|
|
41
|
+
.string()
|
|
42
|
+
.regex(/^[0-9a-f]+$/i)
|
|
43
|
+
.max(160),
|
|
27
44
|
timestamp: z.number().int().positive(),
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
export const
|
|
31
|
-
|
|
45
|
+
})
|
|
46
|
+
.strict();
|
|
47
|
+
export const agentChallengeRequestSchema = z
|
|
48
|
+
.object({ publicKey: z.string().trim().min(1).max(130) })
|
|
49
|
+
.strict();
|
|
50
|
+
export const agentVerifyRequestSchema = agentSignatureSchema
|
|
51
|
+
.extend({ publicKey: z.string().trim().min(1).max(130) })
|
|
52
|
+
.strict();
|
|
53
|
+
const newKey = {
|
|
54
|
+
publicKey: z.string().trim().min(1).max(130),
|
|
55
|
+
label: z.string().trim().min(1).max(120),
|
|
56
|
+
};
|
|
32
57
|
export const agentKeyOperationSchema = z.discriminatedUnion('operation', [
|
|
33
58
|
z.object({ operation: z.literal('enroll'), ...newKey }).strict(),
|
|
34
59
|
z.object({ operation: z.literal('recover'), ...newKey }).strict(),
|
|
35
|
-
z
|
|
60
|
+
z
|
|
61
|
+
.object({ operation: z.literal('rotate'), ...newKey, retireCurrent: z.boolean().optional() })
|
|
62
|
+
.strict(),
|
|
36
63
|
z.object({ operation: z.literal('revoke'), methodId: z.string().min(1) }).strict(),
|
|
37
64
|
]);
|
|
38
|
-
export const agentKeyOperationProofSchema = z
|
|
65
|
+
export const agentKeyOperationProofSchema = z
|
|
66
|
+
.object({
|
|
39
67
|
challenge: z.string().regex(/^[0-9a-f]{64}$/),
|
|
40
68
|
timestamp: z.number().int().positive(),
|
|
41
|
-
keySignature: z
|
|
42
|
-
|
|
69
|
+
keySignature: z
|
|
70
|
+
.string()
|
|
71
|
+
.regex(/^[0-9a-f]+$/i)
|
|
72
|
+
.max(160)
|
|
73
|
+
.optional(),
|
|
74
|
+
governorSignature: z
|
|
75
|
+
.string()
|
|
76
|
+
.regex(/^[0-9a-f]+$/i)
|
|
77
|
+
.max(160)
|
|
78
|
+
.optional(),
|
|
43
79
|
reauth: reauthProofSchema.optional(),
|
|
44
|
-
})
|
|
45
|
-
|
|
80
|
+
})
|
|
81
|
+
.strict();
|
|
82
|
+
export const executeAgentKeyOperationSchema = z
|
|
83
|
+
.object({
|
|
46
84
|
operation: agentKeyOperationSchema,
|
|
47
85
|
proof: agentKeyOperationProofSchema,
|
|
48
|
-
})
|
|
49
|
-
|
|
86
|
+
})
|
|
87
|
+
.strict();
|
|
88
|
+
export const agentKeyOperationChallengeSchema = z
|
|
89
|
+
.object({
|
|
50
90
|
claims: agentProofClaimsSchema,
|
|
51
91
|
governorPublicKey: z.string().nullable(),
|
|
52
|
-
})
|
|
53
|
-
|
|
92
|
+
})
|
|
93
|
+
.strict();
|
|
94
|
+
export const agentKeyOperationResultSchema = z
|
|
95
|
+
.object({
|
|
54
96
|
methodId: z.string().nullable(),
|
|
55
97
|
revokedMethodIds: z.array(z.string()),
|
|
56
|
-
})
|
|
98
|
+
})
|
|
99
|
+
.strict();
|
|
57
100
|
export const ACCOUNT_AUTH_METHODS = ['identity', 'agent_key'];
|
|
58
101
|
/** Public credential inventory. Never includes a proof, bearer or private key. */
|
|
59
|
-
export const agentKeyListResponseSchema = z
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
102
|
+
export const agentKeyListResponseSchema = z
|
|
103
|
+
.object({
|
|
104
|
+
keys: z.array(z
|
|
105
|
+
.object({
|
|
106
|
+
id: z.string(),
|
|
107
|
+
publicKey: z.string(),
|
|
108
|
+
label: z.string(),
|
|
109
|
+
enrolledByUserId: z.string().nullable(),
|
|
110
|
+
enrollmentMethod: z.enum(['governor', 'rotation', 'recovery']),
|
|
111
|
+
linkedAt: z.string().datetime(),
|
|
112
|
+
lastUsedAt: z.string().datetime().nullable(),
|
|
113
|
+
revokedAt: z.string().datetime().nullable(),
|
|
114
|
+
})
|
|
115
|
+
.strict()),
|
|
116
|
+
})
|
|
117
|
+
.strict();
|