@sema-agent/server 7.115.0 → 7.116.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/MIGRATION.md +167 -4
- package/USAGE.md +6 -3
- package/dist/approval-ask-audit-store.d.ts +25 -6
- package/dist/approval-ask-audit-store.js +6 -1
- package/dist/approval-card.d.ts +8 -4
- package/dist/approval-card.js +2 -0
- package/dist/approval-crash-convergence.d.ts +60 -0
- package/dist/approval-crash-convergence.js +75 -0
- package/dist/approval-deny-reasons.d.ts +13 -0
- package/dist/approval-deny-reasons.js +2 -0
- package/dist/approval.js +2 -1
- package/dist/boot/coordinators.js +0 -12
- package/dist/boot/execution-env.js +2 -1
- package/dist/boot/resolve-spec.js +1 -0
- package/dist/boot/stage-07-capability-layer.js +21 -15
- package/dist/boot/stores.js +4 -4
- package/dist/capabilities/hands-lane.d.ts +0 -23
- package/dist/capabilities/hands-lane.js +3 -2
- package/dist/capabilities/send-user-file-tool.d.ts +10 -22
- package/dist/capabilities/send-user-file-tool.js +1 -8
- package/dist/capability-facts.d.ts +296 -0
- package/dist/capability-facts.js +354 -0
- package/dist/config-center/apply-effective.js +1 -1
- package/dist/config.d.ts +16 -13
- package/dist/config.js +12 -12
- package/dist/http/admission.d.ts +6 -0
- package/dist/http/admission.js +22 -5
- package/dist/http/principal-gate.d.ts +3 -0
- package/dist/http/principal-gate.js +3 -0
- package/dist/http/resume-legs.js +10 -1
- package/dist/http/retired-skill-manifest.d.ts +23 -0
- package/dist/http/retired-skill-manifest.js +22 -0
- package/dist/http/route-table.d.ts +3 -2
- package/dist/http/route-table.js +5 -5
- package/dist/http/routes/a2a-serve.js +14 -21
- package/dist/http/routes/admin-config-refresh.js +7 -2
- package/dist/http/routes/admin-drain.js +7 -2
- package/dist/http/routes/admin-memory-optout.js +20 -6
- package/dist/http/routes/adoption.js +19 -5
- package/dist/http/routes/agents-roster.js +4 -2
- package/dist/http/routes/approvals-assistant.js +41 -18
- package/dist/http/routes/background.d.ts +0 -2
- package/dist/http/routes/background.js +4 -5
- package/dist/http/routes/capabilities.d.ts +2 -1
- package/dist/http/routes/capabilities.js +62 -65
- package/dist/http/routes/config-catalog.d.ts +4 -5
- package/dist/http/routes/config-catalog.js +16 -2
- package/dist/http/routes/devices.js +17 -11
- package/dist/http/routes/diagnostics.js +6 -1
- package/dist/http/routes/fleet.js +4 -2
- package/dist/http/routes/images.js +30 -3
- package/dist/http/routes/leader.js +7 -1
- package/dist/http/routes/mcp-reconnect.js +17 -10
- package/dist/http/routes/memory-bundle.js +20 -6
- package/dist/http/routes/memory-compliance.js +19 -5
- package/dist/http/routes/memory-consolidation.d.ts +9 -12
- package/dist/http/routes/memory-consolidation.js +17 -3
- package/dist/http/routes/memory-origin.js +19 -5
- package/dist/http/routes/notify-wake.js +5 -3
- package/dist/http/routes/observability.js +19 -5
- package/dist/http/routes/retention-ops.js +6 -1
- package/dist/http/routes/rules.js +49 -21
- package/dist/http/routes/run-memory-capture.js +5 -2
- package/dist/http/routes/runs.js +90 -60
- package/dist/http/routes/session-sync.js +64 -53
- package/dist/http/routes/sessions-list.js +8 -5
- package/dist/http/routes/sessions.js +39 -24
- package/dist/http/routes/shared-memory.js +5 -3
- package/dist/http/routes/tasks.js +2 -1
- package/dist/http/routes/trace-usage.js +18 -11
- package/dist/http/routes/workflows.js +36 -13
- package/dist/http/server.js +4 -1
- package/dist/http/wire-types.d.ts +6 -0
- package/dist/namespaced-rule-name.d.ts +54 -0
- package/dist/namespaced-rule-name.js +33 -0
- package/dist/observability/corrupt-read-seat.d.ts +4 -3
- package/dist/observability/corrupt-read-seat.js +4 -3
- package/dist/observability/fail-open.d.ts +5 -1
- package/dist/observability/fail-open.js +5 -1
- package/dist/observability/permission-rule-events.d.ts +3 -0
- package/dist/observability/permission-rule-events.js +4 -0
- package/dist/plugins/file-run-store.d.ts +7 -1
- package/dist/plugins/file-run-store.js +20 -7
- package/dist/plugins/memory-run-store.js +2 -1
- package/dist/plugins/one-time-migrations.d.ts +4 -2
- package/dist/plugins/one-time-migrations.js +26 -3
- package/dist/plugins/pg-session-storage.js +1 -1
- package/dist/plugins/run-store-sql.js +4 -4
- package/dist/plugins/session-policy-store-sql.js +4 -2
- package/dist/plugins/store-backend.d.ts +6 -1
- package/dist/plugins/store-backend.js +2 -1
- package/dist/plugins/store-contracts.d.ts +27 -8
- package/dist/plugins/store-contracts.js +12 -3
- package/dist/plugins/tidb-session-store.js +1 -1
- package/dist/request-key-closure.js +1 -1
- package/dist/run-local.d.ts +37 -3
- package/dist/run-local.js +48 -5
- package/dist/runs.d.ts +0 -58
- package/dist/runs.js +15 -20
- package/dist/session-policy-wire.d.ts +40 -60
- package/dist/session-policy-wire.js +60 -32
- package/dist/spec-fields.d.ts +32 -0
- package/dist/spec-fields.js +31 -16
- package/dist/standing-answer-grant.d.ts +8 -0
- package/dist/standing-answer-grant.js +5 -0
- package/dist/task-settings.d.ts +13 -3
- package/dist/tool-approval.d.ts +16 -0
- package/dist/tool-approval.js +29 -7
- package/dist/trace/core-keyset-guard.d.ts +4 -4
- package/dist/trace/self-minted-wire.d.ts +42 -0
- package/dist/trace/self-minted-wire.js +13 -0
- package/dist/user-input-ledger.d.ts +8 -5
- package/package.json +4 -2
- package/scripts/drain-check-local.mjs +115 -25
- package/scripts/drain-check.mysql.sql +67 -0
- package/scripts/drain-check.pg.sql +71 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { sendJson, sendError, httpErrorCode } from "../send.js";
|
|
3
|
-
import { gatedPrincipal, explicitOperatorOk, sendUnauthorized } from "../principal-gate.js";
|
|
3
|
+
import { gatedPrincipal, explicitOperatorOk, sendOperatorPrincipalsRequired, sendUnauthorized } from "../principal-gate.js";
|
|
4
4
|
import { assertNever } from "../route-ctx.js";
|
|
5
|
+
import * as facts from "../../capability-facts.js";
|
|
5
6
|
import { createLogger } from "../../observability/logger.js";
|
|
6
7
|
import { RULE_IMPORT_RETRY_AFTER_SEC, MAX_RULE_SCOPE_CHARS, parseRuleScope, serializeRuleScope } from "../../rules-consent.js";
|
|
7
8
|
import { CONTROL_AND_BIDI_CHARS } from "../../text-bidi.js";
|
|
@@ -93,13 +94,14 @@ export async function handleRules(req, res, match, ctx) {
|
|
|
93
94
|
sendUnauthorized(res, "identity");
|
|
94
95
|
return;
|
|
95
96
|
}
|
|
96
|
-
const
|
|
97
|
-
if (
|
|
97
|
+
const ruleFact = facts.ruleLane(deps);
|
|
98
|
+
if (!ruleFact.available) {
|
|
98
99
|
sendError(res, 501, "capability.rule_store_required", "this deployment has no permission-rule store wired");
|
|
99
100
|
return;
|
|
100
101
|
}
|
|
102
|
+
const lane = ruleFact.lane;
|
|
101
103
|
if (match.decl.id === "rules-list") {
|
|
102
|
-
await handleRuleList(res, match.search, principal, lane, deps.config
|
|
104
|
+
await handleRuleList(res, match.search, principal, lane, deps.config);
|
|
103
105
|
return;
|
|
104
106
|
}
|
|
105
107
|
let rawBody;
|
|
@@ -115,11 +117,11 @@ export async function handleRules(req, res, match, ctx) {
|
|
|
115
117
|
return;
|
|
116
118
|
}
|
|
117
119
|
if (match.decl.id === "rules-revoke") {
|
|
118
|
-
await handleRuleRevoke(res, rawBody, principal, lane, deps.config
|
|
120
|
+
await handleRuleRevoke(res, rawBody, principal, lane, deps.config);
|
|
119
121
|
return;
|
|
120
122
|
}
|
|
121
123
|
if (match.decl.id === "rules-write") {
|
|
122
|
-
await handleRuleWrite(res, rawBody, principal, lane, deps.config
|
|
124
|
+
await handleRuleWrite(res, rawBody, principal, lane, deps.config);
|
|
123
125
|
return;
|
|
124
126
|
}
|
|
125
127
|
if (match.decl.id === "rules-local-import-prepare") {
|
|
@@ -201,19 +203,29 @@ export async function handleRules(req, res, match, ctx) {
|
|
|
201
203
|
}
|
|
202
204
|
sendJson(res, 200, { result: redeemed.result });
|
|
203
205
|
}
|
|
204
|
-
function resolveTargetPrincipal(requested, caller,
|
|
206
|
+
function resolveTargetPrincipal(requested, caller, config) {
|
|
205
207
|
if (requested === undefined || requested === caller)
|
|
206
208
|
return { ok: true, principal: caller };
|
|
207
|
-
if (!
|
|
208
|
-
return { ok: false };
|
|
209
|
+
if (!facts.operatorLane({ config }).available)
|
|
210
|
+
return { ok: false, why: "operator_principals_empty" };
|
|
211
|
+
if (!explicitOperatorOk(caller, config.operatorPrincipals))
|
|
212
|
+
return { ok: false, why: "not_operator" };
|
|
209
213
|
return { ok: true, principal: requested };
|
|
210
214
|
}
|
|
211
|
-
async function handleRuleList(res, search, caller, lane,
|
|
215
|
+
async function handleRuleList(res, search, caller, lane, config) {
|
|
212
216
|
const q = new URLSearchParams(search);
|
|
213
|
-
const target = resolveTargetPrincipal(q.get("principal") ?? undefined, caller,
|
|
217
|
+
const target = resolveTargetPrincipal(q.get("principal") ?? undefined, caller, config);
|
|
214
218
|
if (!target.ok) {
|
|
215
|
-
|
|
216
|
-
|
|
219
|
+
switch (target.why) {
|
|
220
|
+
case "operator_principals_empty":
|
|
221
|
+
sendOperatorPrincipalsRequired(res);
|
|
222
|
+
return;
|
|
223
|
+
case "not_operator":
|
|
224
|
+
sendError(res, 403, "auth.operator_only", "reading another principal's rules is an operator-only action");
|
|
225
|
+
return;
|
|
226
|
+
default:
|
|
227
|
+
return assertNever(target.why);
|
|
228
|
+
}
|
|
217
229
|
}
|
|
218
230
|
const limit = Math.min(RULES_PAGE_MAX, Math.max(1, Number(q.get("limit") ?? RULES_PAGE_DEFAULT) || RULES_PAGE_DEFAULT));
|
|
219
231
|
const scopeRaw = q.get("scope");
|
|
@@ -280,7 +292,7 @@ function sendRuleWriteFailure(res, verb, committed) {
|
|
|
280
292
|
}
|
|
281
293
|
}
|
|
282
294
|
}
|
|
283
|
-
async function handleRuleWrite(res, rawBody, caller, lane,
|
|
295
|
+
async function handleRuleWrite(res, rawBody, caller, lane, config) {
|
|
284
296
|
const parsed = RuleIdentityBodySchema.safeParse(rawBody);
|
|
285
297
|
if (!parsed.success) {
|
|
286
298
|
sendError(res, 400, "request.body_shape", "body must be {behavior, rule, scope} with an optional principal");
|
|
@@ -296,10 +308,18 @@ async function handleRuleWrite(res, rawBody, caller, lane, operatorPrincipals) {
|
|
|
296
308
|
sendError(res, 400, "request.body_shape", "scope must be 'global' or 'project:<root>' with a non-empty root");
|
|
297
309
|
return;
|
|
298
310
|
}
|
|
299
|
-
const target = resolveTargetPrincipal(parsed.data.principal, caller,
|
|
311
|
+
const target = resolveTargetPrincipal(parsed.data.principal, caller, config);
|
|
300
312
|
if (!target.ok) {
|
|
301
|
-
|
|
302
|
-
|
|
313
|
+
switch (target.why) {
|
|
314
|
+
case "operator_principals_empty":
|
|
315
|
+
sendOperatorPrincipalsRequired(res);
|
|
316
|
+
return;
|
|
317
|
+
case "not_operator":
|
|
318
|
+
sendError(res, 403, "auth.operator_only", "writing another principal's rules is an operator-only action");
|
|
319
|
+
return;
|
|
320
|
+
default:
|
|
321
|
+
return assertNever(target.why);
|
|
322
|
+
}
|
|
303
323
|
}
|
|
304
324
|
const written = await lane.writeRule({ principal: target.principal, behavior, rule: parsed.data.rule, scope });
|
|
305
325
|
switch (written.status) {
|
|
@@ -326,7 +346,7 @@ async function handleRuleWrite(res, rawBody, caller, lane, operatorPrincipals) {
|
|
|
326
346
|
}
|
|
327
347
|
}
|
|
328
348
|
}
|
|
329
|
-
async function handleRuleRevoke(res, rawBody, caller, lane,
|
|
349
|
+
async function handleRuleRevoke(res, rawBody, caller, lane, config) {
|
|
330
350
|
const parsed = RuleIdentityBodySchema.safeParse(rawBody);
|
|
331
351
|
if (!parsed.success) {
|
|
332
352
|
sendError(res, 400, "request.body_shape", "body must be {behavior, rule, scope} with an optional principal");
|
|
@@ -337,10 +357,18 @@ async function handleRuleRevoke(res, rawBody, caller, lane, operatorPrincipals)
|
|
|
337
357
|
sendError(res, 400, "request.body_shape", "scope must be 'global' or 'project:<root>' with a non-empty root");
|
|
338
358
|
return;
|
|
339
359
|
}
|
|
340
|
-
const target = resolveTargetPrincipal(parsed.data.principal, caller,
|
|
360
|
+
const target = resolveTargetPrincipal(parsed.data.principal, caller, config);
|
|
341
361
|
if (!target.ok) {
|
|
342
|
-
|
|
343
|
-
|
|
362
|
+
switch (target.why) {
|
|
363
|
+
case "operator_principals_empty":
|
|
364
|
+
sendOperatorPrincipalsRequired(res);
|
|
365
|
+
return;
|
|
366
|
+
case "not_operator":
|
|
367
|
+
sendError(res, 403, "auth.operator_only", "revoking another principal's rules is an operator-only action");
|
|
368
|
+
return;
|
|
369
|
+
default:
|
|
370
|
+
return assertNever(target.why);
|
|
371
|
+
}
|
|
344
372
|
}
|
|
345
373
|
const outcome = await lane.removeRule({ principal: target.principal, behavior: parsed.data.behavior, rule: parsed.data.rule, scope });
|
|
346
374
|
switch (outcome.status) {
|
|
@@ -4,6 +4,7 @@ import { sendJson, sendError } from "../send.js";
|
|
|
4
4
|
import { gatedPrincipal, sendPrincipalRefusal } from "../principal-gate.js";
|
|
5
5
|
import { RUN_NOT_FOUND_MESSAGE, runNotFoundMessage } from "../route-ctx.js";
|
|
6
6
|
import { assertNever } from "../route-ctx.js";
|
|
7
|
+
import * as facts from "../../capability-facts.js";
|
|
7
8
|
const BodySchema = z.object({ reason: z.string().min(1).max(500).optional() }).strict();
|
|
8
9
|
export async function handleRunMemoryCapture(req, res, match, ctx) {
|
|
9
10
|
const { deps } = ctx;
|
|
@@ -11,10 +12,12 @@ export async function handleRunMemoryCapture(req, res, match, ctx) {
|
|
|
11
12
|
case "run-memory-capture-optout": {
|
|
12
13
|
if (ctx.helpers.rateLimited(req, res))
|
|
13
14
|
return;
|
|
14
|
-
|
|
15
|
+
const runs = facts.durableRuns(deps);
|
|
16
|
+
if (!runs.available) {
|
|
15
17
|
sendError(res, 501, "capability.run_store_required", "async runs require a durable run store (DB_BACKEND=mysql|pg|local)");
|
|
16
18
|
return;
|
|
17
19
|
}
|
|
20
|
+
const runStore = runs.runStore;
|
|
18
21
|
const principal = gatedPrincipal(req, deps.config);
|
|
19
22
|
if (deps.config.requirePrincipal && principal === undefined) {
|
|
20
23
|
sendPrincipalRefusal(res, req, deps.config);
|
|
@@ -26,7 +29,7 @@ export async function handleRunMemoryCapture(req, res, match, ctx) {
|
|
|
26
29
|
sendError(res, 400, "request.body_shape", "body must be {} or { reason: string (non-empty, at most 500 chars) } — the session memory-capture opt-out verb takes no other keys");
|
|
27
30
|
return;
|
|
28
31
|
}
|
|
29
|
-
const run = await
|
|
32
|
+
const run = await runStore.getRun(taskId);
|
|
30
33
|
if (!run) {
|
|
31
34
|
sendError(res, 404, "not_found.run", runNotFoundMessage(taskId));
|
|
32
35
|
return;
|