@sema-agent/server 7.130.0 → 7.132.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 +396 -0
- package/README.md +13 -6
- package/README.zh-CN.md +9 -5
- package/USAGE.md +187 -50
- package/dist/approval-card.d.ts +3 -1
- package/dist/approval-card.js +2 -3
- package/dist/audit.d.ts +7 -10
- package/dist/audit.js +4 -1
- package/dist/auth-bridge.d.ts +4 -0
- package/dist/auth-bridge.js +10 -11
- package/dist/bench/s1/live-deps.js +2 -0
- package/dist/boot/deployment-mods.d.ts +31 -0
- package/dist/boot/deployment-mods.js +26 -0
- package/dist/boot/execution-env.d.ts +1 -1
- package/dist/boot/execution-env.js +19 -6
- package/dist/boot/memory-boundary.d.ts +2 -2
- package/dist/boot/read-deny-anchor-audit.d.ts +17 -0
- package/dist/boot/read-deny-anchor-audit.js +36 -0
- package/dist/boot/resolve-spec.d.ts +1 -5
- package/dist/boot/resolve-spec.js +56 -61
- package/dist/boot/runner-deps.d.ts +19 -8
- package/dist/boot/runner-deps.js +14 -2
- package/dist/boot/session-faces.d.ts +1 -7
- package/dist/boot/stage-02-web-admin-pull.js +9 -1
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +4 -4
- package/dist/boot/stage-05-execution-env.js +7 -10
- package/dist/boot/stage-06-runners.d.ts +2 -2
- package/dist/boot/stage-06-runners.js +5 -4
- package/dist/boot/stage-07-capability-layer.d.ts +2 -2
- package/dist/boot/stage-07-capability-layer.js +3 -3
- package/dist/boot/stage-08-reapers.d.ts +2 -2
- package/dist/boot/stage-09-leader.d.ts +3 -9
- package/dist/boot/stage-10-http-server.d.ts +3 -9
- package/dist/boot/stage-10-http-server.js +12 -10
- package/dist/boot/stores.d.ts +1 -1
- package/dist/boot/stores.js +5 -6
- package/dist/boot/web-admin.d.ts +0 -3
- package/dist/boot/web-admin.js +35 -35
- package/dist/brain.js +17 -22
- package/dist/budget.js +5 -4
- package/dist/caller-text-echo.d.ts +20 -0
- package/dist/caller-text-echo.js +24 -0
- package/dist/capabilities/brand-identity.d.ts +26 -0
- package/dist/capabilities/brand-identity.js +27 -0
- package/dist/capabilities/builtin-tools.js +2 -1
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/center-prompts.d.ts +32 -59
- package/dist/capabilities/center-prompts.js +18 -32
- package/dist/capabilities/composite-members.d.ts +1 -0
- package/dist/capabilities/composite-members.js +1 -0
- package/dist/capabilities/engine-capabilities.js +2 -1
- package/dist/capabilities/hands-lane.d.ts +9 -6
- package/dist/capabilities/hands-lane.js +3 -3
- package/dist/capabilities/host-tool-names.d.ts +17 -0
- package/dist/capabilities/host-tool-names.js +15 -0
- package/dist/capabilities/mcp-probe.d.ts +14 -1
- package/dist/capabilities/mcp-probe.js +22 -133
- package/dist/capabilities/repo-tools.js +4 -3
- package/dist/capabilities/scenarios.d.ts +42 -47
- package/dist/capabilities/scenarios.js +19 -35
- package/dist/capabilities/select-environment-tool.js +2 -1
- package/dist/capabilities/send-user-file-tool.d.ts +0 -1
- package/dist/capabilities/send-user-file-tool.js +2 -2
- package/dist/capabilities/skills.d.ts +19 -4
- package/dist/capabilities/skills.js +30 -10
- package/dist/capabilities/tool-defer.js +2 -1
- package/dist/config-catalog.js +22 -11
- package/dist/config-invariants.js +2 -2
- package/dist/config-lkg.d.ts +9 -9
- package/dist/config-lkg.js +20 -4
- package/dist/config-provider.d.ts +3 -1
- package/dist/config-provider.js +14 -6
- package/dist/config-types.d.ts +13 -9
- package/dist/config.d.ts +2 -2
- package/dist/config.js +34 -20
- package/dist/device-ws-protocol.d.ts +1 -1
- package/dist/device-ws-protocol.js +1 -0
- package/dist/elicitation.d.ts +7 -0
- package/dist/elicitation.js +20 -5
- package/dist/env-name-allowlist-knobs.d.ts +12 -2
- package/dist/env-name-allowlist-knobs.js +5 -4
- package/dist/exec-bounds.d.ts +15 -3
- package/dist/exec-bounds.js +4 -0
- package/dist/execution-lane-caps.d.ts +9 -2
- package/dist/execution-lane-caps.js +11 -0
- package/dist/hooks/classic-stations.d.ts +86 -0
- package/dist/hooks/classic-stations.js +27 -0
- package/dist/hooks/hook-llm.d.ts +8 -5
- package/dist/hooks/hook-llm.js +80 -37
- package/dist/hooks/hook-runner.d.ts +273 -75
- package/dist/hooks/hook-runner.js +293 -317
- package/dist/http/admission.d.ts +8 -2
- package/dist/http/admission.js +103 -59
- package/dist/http/approval-sweeps.js +59 -18
- package/dist/http/checkpoint-ctx.d.ts +36 -18
- package/dist/http/checkpoint-ctx.js +14 -10
- package/dist/http/claimed-run.d.ts +13 -0
- package/dist/http/claimed-run.js +15 -0
- package/dist/http/device-placement.js +5 -10
- package/dist/http/dispatch.d.ts +0 -4
- package/dist/http/dispatch.js +6 -10
- package/dist/http/durable-run-leg.d.ts +2 -1
- package/dist/http/durable-run-leg.js +5 -3
- package/dist/http/health-self-report.d.ts +7 -5
- package/dist/http/health-self-report.js +4 -18
- package/dist/http/principal-gate.d.ts +23 -6
- package/dist/http/principal-gate.js +24 -5
- package/dist/http/refusal-body.d.ts +21 -0
- package/dist/http/refusal-body.js +4 -0
- package/dist/http/request-guards.d.ts +27 -0
- package/dist/http/request-guards.js +24 -3
- package/dist/http/resume-legs.d.ts +25 -0
- package/dist/http/resume-legs.js +48 -26
- package/dist/http/routes/approvals-assistant.js +1 -1
- package/dist/http/routes/capabilities.js +7 -17
- package/dist/http/routes/diagnostics.js +1 -1
- package/dist/http/routes/rules.js +2 -2
- package/dist/http/routes/runs.js +13 -17
- package/dist/http/routes/session-sync.js +4 -2
- package/dist/http/routes/sessions.js +23 -11
- package/dist/http/routes/shared-memory.js +2 -13
- package/dist/http/routes/side-query.js +2 -3
- package/dist/http/routes/tasks.js +34 -19
- package/dist/http/scenario-read-face.d.ts +14 -0
- package/dist/http/scenario-read-face.js +5 -0
- package/dist/http/send.d.ts +13 -1
- package/dist/http/send.js +12 -1
- package/dist/http/server.d.ts +37 -23
- package/dist/http/server.js +30 -4
- package/dist/http/stored-body-replay.d.ts +10 -3
- package/dist/http/stored-body-replay.js +27 -6
- package/dist/http/submit-ctx.d.ts +25 -0
- package/dist/http/submit-ctx.js +39 -0
- package/dist/http/wire-types.d.ts +18 -5
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/lane-home-probe.d.ts +43 -0
- package/dist/lane-home-probe.js +35 -0
- package/dist/limit-refusal.d.ts +47 -0
- package/dist/limit-refusal.js +12 -0
- package/dist/main.js +1 -1
- package/dist/mcp-assertion-header.d.ts +3 -11
- package/dist/mcp-assertion-header.js +3 -9
- package/dist/mcp-tool-faces.d.ts +5 -0
- package/dist/mcp-tool-faces.js +5 -1
- package/dist/memory-scope.d.ts +1 -1
- package/dist/model-entry-refusal.d.ts +1 -7
- package/dist/model-provider.d.ts +39 -12
- package/dist/model-provider.js +19 -2
- package/dist/model-route-endpoint.d.ts +52 -12
- package/dist/model-route-endpoint.js +48 -26
- package/dist/model-route-gap.d.ts +5 -4
- package/dist/model-route-gap.js +1 -1
- package/dist/model-select.d.ts +58 -0
- package/dist/model-select.js +31 -0
- package/dist/namespaced-rule-name.d.ts +7 -4
- package/dist/namespaced-rule-name.js +4 -3
- package/dist/observability/cost-taxonomy.d.ts +7 -7
- package/dist/observability/fail-open.d.ts +53 -12
- package/dist/observability/fail-open.js +47 -7
- package/dist/observability/metrics.js +3 -1
- package/dist/observability/prompt-manifest.d.ts +47 -82
- package/dist/observability/prompt-manifest.js +119 -17
- package/dist/observability/run-terminal.js +14 -6
- package/dist/observability/secret-env-scrub.d.ts +13 -1
- package/dist/observability/secret-env-scrub.js +13 -1
- package/dist/observability/tool-trace.d.ts +16 -21
- package/dist/observability/tool-trace.js +51 -42
- package/dist/per-task-image.d.ts +7 -1
- package/dist/per-task-image.js +3 -3
- package/dist/plain-string-record.d.ts +25 -0
- package/dist/plain-string-record.js +32 -0
- package/dist/plugins/blob-backend.d.ts +68 -13
- package/dist/plugins/blob-backend.js +53 -10
- package/dist/plugins/checkpoint-store-sql.d.ts +14 -4
- package/dist/plugins/checkpoint-store-sql.js +39 -26
- package/dist/plugins/k8s-bg-scripts.d.ts +11 -0
- package/dist/plugins/k8s-bg-scripts.js +22 -0
- package/dist/plugins/local-checkpoint-store.js +5 -2
- package/dist/plugins/local-session-store.js +3 -3
- package/dist/plugins/one-time-migrations.d.ts +147 -91
- package/dist/plugins/one-time-migrations.js +372 -208
- package/dist/plugins/permission-rule-store-sql.d.ts +13 -7
- package/dist/plugins/permission-rule-store-sql.js +4 -18
- package/dist/plugins/pg-session-storage.d.ts +4 -5
- package/dist/plugins/pg-session-storage.js +7 -17
- package/dist/plugins/remote-env-adb.d.ts +6 -0
- package/dist/plugins/remote-env-adb.js +9 -4
- package/dist/plugins/remote-env-device.js +3 -0
- package/dist/plugins/remote-env-e2b.d.ts +1 -1
- package/dist/plugins/remote-env-e2b.js +21 -9
- package/dist/plugins/remote-env-host.d.ts +9 -9
- package/dist/plugins/remote-env-host.js +10 -32
- package/dist/plugins/remote-env-k8s.d.ts +95 -26
- package/dist/plugins/remote-env-k8s.js +265 -90
- package/dist/plugins/remote-env-local-docker.d.ts +20 -1
- package/dist/plugins/remote-env-local-docker.js +77 -9
- package/dist/plugins/remote-env-ssh.d.ts +15 -0
- package/dist/plugins/remote-env-ssh.js +109 -3
- package/dist/plugins/remote-shell.d.ts +0 -1
- package/dist/plugins/remote-shell.js +1 -2
- package/dist/plugins/retention-store-sql.js +6 -2
- package/dist/plugins/schema-consistency.d.ts +54 -0
- package/dist/plugins/schema-consistency.js +52 -0
- package/dist/plugins/session-epoch-anchor.d.ts +13 -0
- package/dist/plugins/session-epoch-anchor.js +23 -0
- package/dist/plugins/shared-memory-store-sql.d.ts +9 -3
- package/dist/plugins/shared-memory-store-sql.js +5 -16
- package/dist/plugins/sql-driver.d.ts +141 -0
- package/dist/plugins/sql-driver.js +115 -1
- package/dist/plugins/sql-errors.d.ts +41 -0
- package/dist/plugins/sql-errors.js +36 -0
- package/dist/plugins/store-backend.js +2 -1
- package/dist/plugins/tidb-session-storage.d.ts +7 -11
- package/dist/plugins/tidb-session-storage.js +6 -16
- package/dist/plugins/tidb-session-store.js +1 -1
- package/dist/prompts-domain-validate.d.ts +17 -61
- package/dist/prompts-domain-validate.js +9 -119
- package/dist/question.d.ts +18 -9
- package/dist/question.js +21 -13
- package/dist/request-key-closure.d.ts +4 -4
- package/dist/request-key-closure.js +18 -13
- package/dist/rule-entry-list.d.ts +134 -24
- package/dist/rule-entry-list.js +162 -30
- package/dist/run-local.d.ts +3 -3
- package/dist/run-local.js +26 -25
- package/dist/runs.d.ts +48 -2
- package/dist/runs.js +61 -2
- package/dist/server-secret-env.d.ts +44 -18
- package/dist/server-secret-env.js +49 -8
- package/dist/session-incarnation.d.ts +15 -5
- package/dist/session-incarnation.js +16 -9
- package/dist/session-titler.js +12 -2
- package/dist/spec-fields.d.ts +34 -18
- package/dist/spec-fields.js +46 -53
- package/dist/sql-engine-posture.d.ts +29 -4
- package/dist/sql-engine-posture.js +36 -1
- package/dist/stored-request-hooks-m20.d.ts +23 -0
- package/dist/stored-request-hooks-m20.js +124 -0
- package/dist/stored-request-tool-axes-m19.d.ts +20 -5
- package/dist/stored-request-tool-axes-m19.js +30 -2
- package/dist/task-a2a.d.ts +9 -1
- package/dist/task-a2a.js +73 -47
- package/dist/task-mcp.d.ts +54 -102
- package/dist/task-mcp.js +194 -92
- package/dist/task-settings.d.ts +47 -25
- package/dist/task-settings.js +46 -61
- package/dist/text-bidi.d.ts +3 -46
- package/dist/text-bidi.js +3 -3
- package/dist/tool-approval.d.ts +1 -1
- package/dist/trace/core-keyset-guard.d.ts +24 -4
- package/dist/trace/engine-notice-wire.d.ts +11 -3
- package/dist/trace/engine-notice-wire.js +8 -1
- package/dist/trace/ledger-events.d.ts +3 -1
- package/dist/trace/ledger-sink.d.ts +29 -0
- package/dist/trace/ledger-sink.js +15 -1
- package/dist/trace/model-segment.js +1 -1
- package/dist/trace/project.d.ts +25 -6
- package/dist/trace/project.js +68 -22
- package/dist/trace/wire-projection-faces.d.ts +80 -2
- package/dist/trace/wire-projection-faces.js +23 -1
- package/dist/user-authored-text.d.ts +7 -0
- package/dist/user-authored-text.js +3 -0
- package/dist/web-admin-client/apply-effective.js +10 -5
- package/dist/web-admin-client/candidate-gate.d.ts +6 -6
- package/dist/web-admin-client/candidate-gate.js +3 -3
- package/dist/web-admin-client/http-client.js +0 -6
- package/dist/web-admin-client/read-warnings.d.ts +13 -0
- package/dist/web-admin-client/read-warnings.js +10 -0
- package/dist/web-admin-client/skills-mcp.d.ts +3 -0
- package/dist/web-admin-client/skills-mcp.js +9 -6
- package/dist/web-admin-client/types.d.ts +3 -4
- package/dist/workspace-cache.d.ts +35 -0
- package/dist/workspace-cache.js +36 -0
- package/dist/workspace-space.d.ts +3 -2
- package/dist/workspace-space.js +2 -0
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +8 -1
- package/package.json +4 -4
- package/scripts/drain-check-local.mjs +37 -3
- package/scripts/drain-check.mysql.sql +30 -2
- package/scripts/drain-check.pg.sql +29 -2
- package/dist/capabilities/memory-notice.d.ts +0 -138
- package/dist/capabilities/memory-notice.js +0 -64
- package/dist/capabilities/prompt.d.ts +0 -17
- package/dist/capabilities/prompt.js +0 -6
- package/dist/mcp-content-origin.d.ts +0 -34
- package/dist/mcp-content-origin.js +0 -10
- package/dist/tool-axis-words.d.ts +0 -27
- package/dist/tool-axis-words.js +0 -9
- package/dist/wire-name-bound.d.ts +0 -14
- package/dist/wire-name-bound.js +0 -13
package/dist/approval-card.d.ts
CHANGED
|
@@ -295,7 +295,9 @@ export declare function readProbeCause(req: unknown): ProbeCauseProjection | und
|
|
|
295
295
|
*
|
|
296
296
|
* 姿势逐条(与 {@link readProbeCause} / {@link readRuleEvidence} 同款分工):
|
|
297
297
|
* · `safeParse`,非串 ⇒ 按缺席处置(宪法 [ref]);空串 / 纯空白 ⇒ 缺席(core 自己也只在 `trim() !== ""` 时铸)。
|
|
298
|
-
* ·
|
|
298
|
+
* · 长度(S-733 信封):core 铸不出的长度 ⇒ **整只丢,不截**(判据与 `probeCause.code` 超限同形;截出来的是**另一句话**)。判官是 core 包根导出的
|
|
299
|
+
* `isMintableProbeReason`(core 7.53.0 #1883:上限 = core 的 cap + 它那一枚截断记号的宽度,「+1」只写在 core 一处;修前本仓手抄
|
|
300
|
+
* `MAX_PROBE_REASON_CODEPOINTS = 201` —— 数字与「+1」两件事都是抄的)。超过它的值**不是 core 铸的**(第三方 producer / 世代差)。
|
|
299
301
|
* 先判长度再脱敏 ⇒ 喂给脱敏器的永远是个短串(脱敏器的 RangeError 面是超大输入)。
|
|
300
302
|
* · 内容族(部署自写的探针散文,人眼信任边界上的文本)⇒ `redactSecrets`。脱敏后**不再截**:耐久面同样不截,
|
|
301
303
|
* 两面逐字节同值比「帧上短一截」重要(allow 层披露那一格 R2-[medium] 的反面:那里有卡面要对齐,这里没有)。
|
package/dist/approval-card.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { ALLOW_RULE_MEMBERS, ASK_EVIDENCE_ABSENCE_VALUES, BOUND_GRANT_ABSENCES, MAX_RULE_TEXT_CHARS, READ_ROOT_CANDIDATE_DIR_MAX, RESUME_STARTUP_CAUSES, RULE_OFFERS_ABSENCES, STEER_REPLAY_FACETS, isAskClass, isAskOrigin, isAutoModeFallbackCause, isPersistedRuleMandate, screenAskClassMembers } from "@sema-agent/core";
|
|
2
|
+
import { ALLOW_RULE_MEMBERS, ASK_EVIDENCE_ABSENCE_VALUES, BOUND_GRANT_ABSENCES, MAX_RULE_TEXT_CHARS, READ_ROOT_CANDIDATE_DIR_MAX, RESUME_STARTUP_CAUSES, RULE_OFFERS_ABSENCES, STEER_REPLAY_FACETS, isAskClass, isAskOrigin, isAutoModeFallbackCause, isMintableProbeReason, isPersistedRuleMandate, screenAskClassMembers } from "@sema-agent/core";
|
|
3
3
|
import { redactSecrets } from "./trace/redact.js";
|
|
4
4
|
import { recordFailOpen } from "./observability/fail-open.js";
|
|
5
5
|
import { retireParkArmWords, retireStoredCardWords } from "./retired-card-words.js";
|
|
@@ -161,14 +161,13 @@ export function readProbeCause(req) {
|
|
|
161
161
|
...(raw.further !== undefined ? { further: family(raw.further) } : {}),
|
|
162
162
|
};
|
|
163
163
|
}
|
|
164
|
-
const MAX_PROBE_REASON_CODEPOINTS = 201;
|
|
165
164
|
const ProbeReasonEnvelopeSchema = z.object({ probeReason: z.string().optional() });
|
|
166
165
|
export function readProbeReason(req) {
|
|
167
166
|
const parsed = ProbeReasonEnvelopeSchema.safeParse(req);
|
|
168
167
|
const raw = parsed.success ? parsed.data.probeReason : undefined;
|
|
169
168
|
if (raw === undefined || raw.trim() === "")
|
|
170
169
|
return undefined;
|
|
171
|
-
if (
|
|
170
|
+
if (!isMintableProbeReason(raw))
|
|
172
171
|
return undefined;
|
|
173
172
|
const redacted = redactSecrets(raw);
|
|
174
173
|
return redacted === "" ? undefined : redacted;
|
package/dist/audit.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type StoredPromptEpoch } from "@sema-agent/core";
|
|
1
2
|
import type { Pool } from "mysql2/promise";
|
|
2
3
|
import type { Pool as PgPool } from "pg";
|
|
3
4
|
/**
|
|
@@ -21,16 +22,12 @@ export interface SessionAudit {
|
|
|
21
22
|
* 再回给调用方;直接消费本视图的宿主(`buildSessionAudit` 是包根导出)自己负责同一道脱敏。
|
|
22
23
|
* 唯一一处服务端添键:用户消息行的回退手柄 `taskId`(给了 {@link RewindHandles} 才投,见 {@link buildRewindHandles})。 */
|
|
23
24
|
messages: unknown[];
|
|
24
|
-
/** [ref]① web 观测切片 B: the session's prompt-epoch
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
packId: string;
|
|
31
|
-
assemblyApi: number;
|
|
32
|
-
activatedBy: "session_start" | "compaction" | "legacy_migration";
|
|
33
|
-
};
|
|
25
|
+
/** [ref]① web 观测切片 B: the session's prompt-epoch record as the engine reads it, verbatim (`session.getPromptEpoch()` —
|
|
26
|
+
* first-class `prompt_epoch` entry, compaction restatement, [ref] anchor, the reading itself all inside the engine):
|
|
27
|
+
* `{ kind: "pin", descriptor }` for a current-shape record, `{ kind: "legacy", centerPinned }` for a record an engine
|
|
28
|
+
* ≤ 7.51 wrote (recognized by its retired field names). This view adds no reading of its own. A pre-epoch session omits
|
|
29
|
+
* the key entirely (undefined). */
|
|
30
|
+
promptEpoch?: StoredPromptEpoch;
|
|
34
31
|
}
|
|
35
32
|
/**
|
|
36
33
|
* 用户消息行的**回退手柄**表:用户条目 id → 回退时交给 `resumeAt` 的那个 `event_id`(R8 用户消息锚按 run 的 taskId 键入)。
|
package/dist/audit.js
CHANGED
|
@@ -5,7 +5,7 @@ import { createLocalSessionRepo } from "./plugins/local-session-store.js";
|
|
|
5
5
|
import { redactModelText } from "./observability/run-terminal.js";
|
|
6
6
|
import { redactDeepWith } from "./trace/redact.js";
|
|
7
7
|
import { projectToolStructured } from "./trace/tool-output-media.js";
|
|
8
|
-
import { INJECTED_BLOCK_RE } from "./user-authored-text.js";
|
|
8
|
+
import { INJECTED_BLOCK_RE, isAttachmentFrame } from "./user-authored-text.js";
|
|
9
9
|
export function buildRewindHandles(anchors, reader) {
|
|
10
10
|
const byEntry = new Map();
|
|
11
11
|
for (const a of anchors) {
|
|
@@ -153,9 +153,12 @@ const MESSAGE_READ_TREATMENT = {
|
|
|
153
153
|
unsummarizedMessages: "verbatim", tokensAfter: "verbatim", firstKeptEntryId: "verbatim",
|
|
154
154
|
},
|
|
155
155
|
};
|
|
156
|
+
const ATTACHMENT_FRAME_READ_TREATMENT = { ...MESSAGE_READ_TREATMENT.user, content: "parts" };
|
|
156
157
|
function readMessage(m) {
|
|
157
158
|
if (isPlainRecord(m)) {
|
|
158
159
|
const role = m.role;
|
|
160
|
+
if (role === "user" && isAttachmentFrame(m))
|
|
161
|
+
return readByTable(m, ATTACHMENT_FRAME_READ_TREATMENT);
|
|
159
162
|
if (typeof role === "string" && Object.hasOwn(MESSAGE_READ_TREATMENT, role)) {
|
|
160
163
|
return readByTable(m, MESSAGE_READ_TREATMENT[role]);
|
|
161
164
|
}
|
package/dist/auth-bridge.d.ts
CHANGED
|
@@ -45,6 +45,10 @@ export type VerifyOutcome = {
|
|
|
45
45
|
export interface WebAdminJwtVerifier {
|
|
46
46
|
verify: (bearer: string) => Promise<VerifyOutcome>;
|
|
47
47
|
}
|
|
48
|
+
/** 缓存键的常规刷新周期缺省(秒):过期后下一发在后台重拉,当前请求不等。 */
|
|
49
|
+
export declare const DEFAULT_JWKS_TTL_SEC: number;
|
|
50
|
+
/** 一次 JWKS 拉取的时限(毫秒):kid 未知、超离线宽限、后台刷新三条路用同一只拉取,同一个时限。 */
|
|
51
|
+
export declare const JWKS_FETCH_TIMEOUT_MS = 10000;
|
|
48
52
|
/**
|
|
49
53
|
* registry-JWT verifier(单例,进程级 JWKS 缓存)。`verify(bearer)` 全程不 throw——一切异常折为
|
|
50
54
|
* AUTH_BRIDGE_ERROR_CODES(HTTP 面由调用方恒答 generic 401,码只进日志/metrics,R9)。
|
package/dist/auth-bridge.js
CHANGED
|
@@ -8,7 +8,8 @@ export function authBridgeIssuerOf(config) {
|
|
|
8
8
|
return { issuer: config.webAdmin.baseUrl, source: "fallback" };
|
|
9
9
|
return undefined;
|
|
10
10
|
}
|
|
11
|
-
const DEFAULT_JWKS_TTL_SEC = 15 * 60;
|
|
11
|
+
export const DEFAULT_JWKS_TTL_SEC = 15 * 60;
|
|
12
|
+
export const JWKS_FETCH_TIMEOUT_MS = 10_000;
|
|
12
13
|
const MAX_JWKS_BYTES = 256 * 1024;
|
|
13
14
|
const MAX_TOKEN_CHARS = 16 * 1024;
|
|
14
15
|
const MAX_SEGMENT_BYTES = 64 * 1024;
|
|
@@ -39,6 +40,7 @@ export function createWebAdminJwtVerifier(opts) {
|
|
|
39
40
|
let lastFetchAttemptMs;
|
|
40
41
|
let lastFetchSuccessMs;
|
|
41
42
|
let inflight;
|
|
43
|
+
const withinGrace = () => lastFetchSuccessMs !== undefined && jwksWithinOfflineGrace({ lastFetchSuccessMs, nowMs: now() }, { offlineGraceSec });
|
|
42
44
|
const fail = (error, kid) => {
|
|
43
45
|
opts.metrics?.inc("auth_bridge_verify_total", { outcome: error });
|
|
44
46
|
opts.logger?.warn?.("auth_bridge_rejected", { error, ...(kid ? { kid: kid.slice(0, 128) } : {}), iss: displayIssuer });
|
|
@@ -50,7 +52,7 @@ export function createWebAdminJwtVerifier(opts) {
|
|
|
50
52
|
inflight = (async () => {
|
|
51
53
|
lastFetchAttemptMs = now();
|
|
52
54
|
try {
|
|
53
|
-
const res = await doFetch(jwksUrl, { redirect: "error", signal: AbortSignal.timeout(
|
|
55
|
+
const res = await doFetch(jwksUrl, { redirect: "error", signal: AbortSignal.timeout(JWKS_FETCH_TIMEOUT_MS) });
|
|
54
56
|
if (!res.ok)
|
|
55
57
|
throw new Error(`jwks HTTP ${res.status}`);
|
|
56
58
|
const cl = Number(res.headers.get("content-length"));
|
|
@@ -112,8 +114,9 @@ export function createWebAdminJwtVerifier(opts) {
|
|
|
112
114
|
return fail("unknown_issuer", kid);
|
|
113
115
|
if (classifyTimeClaims(payload, Math.floor(now() / 1000), clockSkewSec) !== "ok")
|
|
114
116
|
return fail("expired", kid);
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
+
const usableKey = () => (withinGrace() ? keys.get(kid) : undefined);
|
|
118
|
+
const snapshot = () => ({ cachedKids: withinGrace() ? [...keys.keys()] : [], lastFetchAttemptMs, nowMs: now() });
|
|
119
|
+
if (usableKey()) {
|
|
117
120
|
const ttlStale = lastFetchSuccessMs === undefined || now() - lastFetchSuccessMs > jwksTtlSec * 1000;
|
|
118
121
|
if (ttlStale && !inflight && (lastFetchAttemptMs === undefined || now() - lastFetchAttemptMs >= refreshMin * 1000)) {
|
|
119
122
|
void refreshJwks();
|
|
@@ -122,16 +125,12 @@ export function createWebAdminJwtVerifier(opts) {
|
|
|
122
125
|
else {
|
|
123
126
|
if (inflight)
|
|
124
127
|
await inflight;
|
|
125
|
-
if (!
|
|
128
|
+
if (!usableKey() && shouldForceJwksRefresh(kid, snapshot(), { jwksRefreshMinIntervalSec: refreshMin }))
|
|
126
129
|
await refreshJwks();
|
|
127
130
|
}
|
|
128
|
-
const key =
|
|
131
|
+
const key = usableKey();
|
|
129
132
|
if (!key) {
|
|
130
|
-
|
|
131
|
-
return graceOk ? fail("invalid_signature", kid) : fail("jwks_unavailable", kid);
|
|
132
|
-
}
|
|
133
|
-
if (lastFetchSuccessMs !== undefined && !jwksWithinOfflineGrace({ lastFetchSuccessMs, nowMs: now() }, { offlineGraceSec })) {
|
|
134
|
-
return fail("jwks_unavailable", kid);
|
|
133
|
+
return withinGrace() ? fail("invalid_signature", kid) : fail("jwks_unavailable", kid);
|
|
135
134
|
}
|
|
136
135
|
let sigOk = false;
|
|
137
136
|
try {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { outwardPlane } from "../../terminal.js";
|
|
2
2
|
import { Runner, runWithVerification, resumeWithVerification, runRepairLoop, combinePolicies, createDurableQuestionPolicy, QUESTION_AWAITS_RESUME, } from "@sema-agent/core";
|
|
3
3
|
import { loadConfig } from "../../config.js";
|
|
4
|
+
import { assertServedModelRoute } from "../../model-route-endpoint.js";
|
|
4
5
|
import { withUnattendedLeg } from "../../unattended-permission-mode.js";
|
|
5
6
|
import { createBrain } from "../../brain.js";
|
|
6
7
|
import { buildPricing } from "../../budget.js";
|
|
@@ -51,6 +52,7 @@ function buildBrainIngredients(rt) {
|
|
|
51
52
|
if (rt.costCacheWrite != null)
|
|
52
53
|
process.env.MODEL_COST_CACHE_WRITE = String(rt.costCacheWrite);
|
|
53
54
|
const config = loadConfig();
|
|
55
|
+
assertServedModelRoute(config, { envTableIsPlaceholder: false });
|
|
54
56
|
const brain = createBrain(config, {});
|
|
55
57
|
const pricing = buildPricing(config.models);
|
|
56
58
|
const p = pricing[rt.modelId];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 部署座(`RunnerDeps.mods`)的注册:**铸**({@link createDeploymentMods})与**起服自证**({@link assertDeploymentModsAdmitted})都在这一处。
|
|
3
|
+
*
|
|
4
|
+
* 起服自证(律三:拒形只有引擎一种读法,本仓只负责「不写」与「启动时自证」):
|
|
5
|
+
* 部署座上的注册是本仓自己铸的。它们坏了
|
|
6
|
+
* —— 坏名、坏档、缺 `uses.calls`、`on` 越出 `uses`、只选无站的名字、`register` 抛 —— 引擎在每条腿的 prepare 里拒
|
|
7
|
+
* (`config.mods_invalid`),那就是每个请求都失败。所以起服时让引擎的 admission 判一次:判官仍是引擎(`admitModChain`),
|
|
8
|
+
* 本函数不判形,只把它的拒折成一句起服错误、拒启。两个起服入口(server 第五段、本地 CLI)同调这一只。
|
|
9
|
+
*
|
|
10
|
+
* 也拒启的两形(同一个理由:部署注册一张都不该缺席,也不该带病挂上):
|
|
11
|
+
* · admission 期的报告(引擎对坏 `budgetMs` 只报告、回落缺省,不拒)—— 部署注册不设 `budgetMs`,报告出现就是铸法坏了;
|
|
12
|
+
* · 被 `plugin.register` 判拒的注册(本部署没有这种判官;出现即装配错)。
|
|
13
|
+
* 腿外 admission 只建一只总线并跑一次各注册的 `register`(本仓的 `register` 是纯函数),不碰任何腿。
|
|
14
|
+
*/
|
|
15
|
+
import { type EngineDollar, type ModRegistration } from "@sema-agent/core";
|
|
16
|
+
import type { Logger } from "../observability/logger.js";
|
|
17
|
+
import type { Metrics } from "../observability/metrics.js";
|
|
18
|
+
/**
|
|
19
|
+
* 部署座上的注册列表 —— 两个起服入口(server 第五段与本地 CLI)同一只铸法,哪几张、什么顺序只写在这里:
|
|
20
|
+
* · 拒绝计量恒挂、在前;工具追踪(`TOOL_TRACE=true`,交 `traceLogger`)在后。两张都是 `prepend` 档的观察者,引擎按「档 → 部署先于任务 → 座内顺序」
|
|
21
|
+
* 串行跑观察者、且都在链之前 ⇒ 同一次拒绝先计数、后写追踪行;
|
|
22
|
+
* · 品牌行(`brandIdentity`:品牌部署 = local / TOC)—— `prompt.compose` 上的一条部署类 overlay(`capabilities/brand-identity.ts`),与两只观察者
|
|
23
|
+
* 不在同一个事件上,顺序不影响它们。部署开不开品牌只在这一个入参表态。
|
|
24
|
+
*/
|
|
25
|
+
export declare function createDeploymentMods(input: {
|
|
26
|
+
readonly metrics: Pick<Metrics, "inc">;
|
|
27
|
+
readonly traceLogger?: Logger | undefined;
|
|
28
|
+
readonly brandIdentity?: boolean | undefined;
|
|
29
|
+
}): readonly ModRegistration<EngineDollar>[];
|
|
30
|
+
export declare function assertDeploymentModsAdmitted(mods: readonly ModRegistration<EngineDollar>[]): Promise<void>;
|
|
31
|
+
//# sourceMappingURL=deployment-mods.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { admitModChain } from "@sema-agent/core";
|
|
2
|
+
import { createBrandIdentityRegistration } from "../capabilities/brand-identity.js";
|
|
3
|
+
import { createPermissionDeniedMeter, createToolTracer } from "../observability/tool-trace.js";
|
|
4
|
+
export function createDeploymentMods(input) {
|
|
5
|
+
return [
|
|
6
|
+
createPermissionDeniedMeter(input.metrics),
|
|
7
|
+
...(input.traceLogger !== undefined ? [createToolTracer(input.traceLogger)] : []),
|
|
8
|
+
...(input.brandIdentity === true ? [createBrandIdentityRegistration()] : []),
|
|
9
|
+
];
|
|
10
|
+
}
|
|
11
|
+
const REFUSED = "deployment extension registration refused";
|
|
12
|
+
export async function assertDeploymentModsAdmitted(mods) {
|
|
13
|
+
const reports = [];
|
|
14
|
+
let records;
|
|
15
|
+
try {
|
|
16
|
+
({ records } = await admitModChain({ deployment: mods }, (err) => void reports.push(err.message)));
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
throw new Error(`${REFUSED}: ${e instanceof Error ? e.message : String(e)}`);
|
|
20
|
+
}
|
|
21
|
+
const refused = records.flatMap((r) => ("refusedBy" in r ? [`"${r.name}" refused by ${r.refusedBy}: ${r.reason}`] : []));
|
|
22
|
+
const problems = [...reports, ...refused];
|
|
23
|
+
if (problems.length > 0)
|
|
24
|
+
throw new Error(`${REFUSED}: ${problems.join("; ")}`);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=deployment-mods.js.map
|
|
@@ -62,7 +62,7 @@ export declare function createSessionScopedRegistries(maxEntries?: number): Sess
|
|
|
62
62
|
* · **工作区空间的分区 = 会话化身**(`spaceOccupant.incarnation`):建这只 env 时按 id 读一次会话店的 `incarnationOf`(会话行上的那一格,
|
|
63
63
|
* `session-incarnation.ts`;本工厂不取会话,正是 core 给「没取会话的读者」的那只读)。读数是闭集三臂(`SpaceOccupant`,适配器那边逐臂处置):
|
|
64
64
|
* 答令牌 ⇒ 已知;答 `undefined`(没有这只会话)⇒ `{ unread: "incarnation_unknown" }` —— 没有空间:空间车道不开、缓存卷不挂,各一行;
|
|
65
|
-
* 读抛 / 答出的不是非空串 ⇒ `{ fault: <code> }` —— 读不到空间 ≠ 没有空间:开着的空间车道 / 缓存卷让这只 env 一只 pod 都不建,
|
|
65
|
+
* 读抛 / 超时(`rpcTimeoutMs`,同一次 connect 里读围栏行与 `latest` 的那一只墙)/ 答出的不是非空串 ⇒ `{ fault: <code> }` —— 读不到空间 ≠ 没有空间:开着的空间车道 / 缓存卷让这只 env 一只 pod 都不建,
|
|
66
66
|
* connect 与 resumeVM 都答 `connect_failed`(与 `latest` 读失败同一铸点),一行 `workspace_space_unreadable_occupant`;`code` 是店的错误码,
|
|
67
67
|
* 从不带正文、从不带令牌。**绝不**以会话 id 代替;
|
|
68
68
|
* 同时开这只 env 在空间提交围栏上的座(`spaceOccupant.fence`,run 店的 `workspace_space_commit` 行;法见 `workspace-space-commit.ts`);
|
|
@@ -10,7 +10,7 @@ import { adbExecutionEnvFactory } from "../plugins/remote-env-adb.js";
|
|
|
10
10
|
import { deviceExecutionEnvFactory } from "../plugins/remote-env-device.js";
|
|
11
11
|
import { e2bExecutionEnvFactory } from "../plugins/remote-env-e2b.js";
|
|
12
12
|
import { hostExecutionEnvFactory, RemoteHostExecutionEnv } from "../plugins/remote-env-host.js";
|
|
13
|
-
import { checkSandboxEgressPolicy, createSpaceReclaimer, K8S_SANDBOX_NAMESPACE_DEFAULT, k8sExecutionEnvFactory } from "../plugins/remote-env-k8s.js";
|
|
13
|
+
import { boundedStoreCall, checkSandboxEgressPolicy, createSpaceReclaimer, K8S_SANDBOX_NAMESPACE_DEFAULT, k8sExecutionEnvFactory, rpcTimeoutMsOf } from "../plugins/remote-env-k8s.js";
|
|
14
14
|
import { createRunWorkspaceSnapshotSeat } from "../fleet/workspace-snapshot-residual.js";
|
|
15
15
|
import { createSpaceCommitFence } from "../workspace-space-commit.js";
|
|
16
16
|
import { localDockerExecutionEnvFactory } from "../plugins/remote-env-local-docker.js";
|
|
@@ -23,10 +23,11 @@ import { reapOrphanWorktrees, withWorktreeIsolation } from "../plugins/worktree-
|
|
|
23
23
|
import { customPkgSourceFromEnv, derivePkgSourceEnv } from "../sandbox-pkg-source.js";
|
|
24
24
|
import { effectiveHostWorkspace } from "../task-cwd.js";
|
|
25
25
|
import { taskInheritEnvRefusal } from "../hosted-posture.js";
|
|
26
|
+
import { createCacheMissMemory } from "../workspace-cache.js";
|
|
26
27
|
import { workspaceSnapshotTimeoutOf } from "../workspace-space.js";
|
|
27
28
|
import { sayEgressPolicyReading } from "../sandbox-egress-policy.js";
|
|
28
29
|
import { isSandboxPathAdjudicationLane, sandboxPathEnvSlots, withSandboxPathEnvSlot } from "./deferred-sandbox-path-env.js";
|
|
29
|
-
import { REMOTE_EXEC_PROVIDER_WORDS, executionLaneHomeDir, executionLaneOf, isSingleMachineDefaultLane, laneBindsReads, laneIsolated } from "../execution-lane-caps.js";
|
|
30
|
+
import { REMOTE_EXEC_PROVIDER_WORDS, buildUndeclaredHomeNote, executionLaneHomeDir, executionLaneOf, isSingleMachineDefaultLane, laneBindsReads, laneIsolated } from "../execution-lane-caps.js";
|
|
30
31
|
function boundedSessionSetter(map, maxEntries) {
|
|
31
32
|
return (sid, value) => {
|
|
32
33
|
map.delete(sid);
|
|
@@ -108,15 +109,16 @@ export function createSessionScopedRegistries(maxEntries = MAX_CWD_SESSIONS) {
|
|
|
108
109
|
};
|
|
109
110
|
}
|
|
110
111
|
export function createK8sRunEnvFactory(k8sCfg, seats, deps) {
|
|
112
|
+
const cacheMisses = createCacheMissMemory();
|
|
111
113
|
return async (ctx) => {
|
|
112
114
|
const onWorkspaceSnapshot = createRunWorkspaceSnapshotSeat(ctx.sessionId);
|
|
113
115
|
const child = ctx.placementRootSessionId !== ctx.sessionId;
|
|
114
116
|
const s3Snapshot = child && k8sCfg.s3Snapshot !== undefined ? spaceOff(k8sCfg.s3Snapshot) : k8sCfg.s3Snapshot;
|
|
115
|
-
const spaceOccupant = child ? undefined : await occupantOf(seats, ctx.sessionId, ctx.taskId);
|
|
117
|
+
const spaceOccupant = child ? undefined : await occupantOf(seats, ctx.sessionId, ctx.taskId, rpcTimeoutMsOf(k8sCfg));
|
|
116
118
|
const { cache, ...deploymentCfg } = k8sCfg;
|
|
117
119
|
return k8sExecutionEnvFactory({
|
|
118
120
|
...deploymentCfg,
|
|
119
|
-
...(cache !== undefined && !child ? { cache } : {}),
|
|
121
|
+
...(cache !== undefined && !child ? { cache, cacheMisses } : {}),
|
|
120
122
|
...(s3Snapshot !== undefined ? { s3Snapshot } : {}),
|
|
121
123
|
image: seats.imageOf(ctx.sessionId) ?? k8sCfg.image,
|
|
122
124
|
...(spaceOccupant !== undefined ? { spaceOccupant } : {}),
|
|
@@ -125,10 +127,18 @@ export function createK8sRunEnvFactory(k8sCfg, seats, deps) {
|
|
|
125
127
|
};
|
|
126
128
|
}
|
|
127
129
|
const STORE_ERROR_CODE = /^[A-Za-z0-9_.:-]{1,64}$/;
|
|
128
|
-
|
|
130
|
+
const INCARNATION_READ_TIMEOUT = "incarnation_read_timeout";
|
|
131
|
+
async function occupantOf(seats, sessionId, taskId, boundMs) {
|
|
129
132
|
let answer;
|
|
130
133
|
try {
|
|
131
|
-
|
|
134
|
+
const read = seats.incarnationOf;
|
|
135
|
+
answer =
|
|
136
|
+
read === undefined
|
|
137
|
+
? undefined
|
|
138
|
+
: await boundedStoreCall(() => read(sessionId), {
|
|
139
|
+
ms: boundMs,
|
|
140
|
+
onTimeout: () => Object.assign(new Error(`session occupant read did not answer within ${boundMs}ms`), { code: INCARNATION_READ_TIMEOUT }),
|
|
141
|
+
});
|
|
132
142
|
}
|
|
133
143
|
catch (e) {
|
|
134
144
|
const code = e?.code;
|
|
@@ -404,6 +414,9 @@ export function createExecutionEnv(ctx) {
|
|
|
404
414
|
logger.info("remote_exec_enabled", { provider: config.remoteExec.provider, isolated, suspendable, ...(sandboxEnvKeys.length > 0 ? { sandboxEnvKeys } : {}) });
|
|
405
415
|
if (!isolated)
|
|
406
416
|
logger.warn("remote_exec_real_system", { provider: config.remoteExec.provider, note: buildRealSystemNote(config.remoteExec) });
|
|
417
|
+
const homeNote = buildUndeclaredHomeNote(config);
|
|
418
|
+
if (homeNote !== undefined)
|
|
419
|
+
logger.warn("execution_lane_home_undeclared", { provider: config.remoteExec.provider, note: homeNote });
|
|
407
420
|
if (executionLaneOf(config.remoteExec.provider) === "host")
|
|
408
421
|
logger.info("task_inherit_env_honored", { honored: taskInheritEnvRefusal(config) === undefined });
|
|
409
422
|
}
|
|
@@ -75,8 +75,8 @@ import type { MemoryEngineBackend } from "@sema-agent/settings-schema/execution-
|
|
|
75
75
|
* 而且它断言的是 per-task 事实,不是本键的车道级语义。
|
|
76
76
|
*
|
|
77
77
|
* ## 位置与纪律
|
|
78
|
-
* 单源:resolve-spec 的 spec
|
|
79
|
-
*
|
|
78
|
+
* 单源:resolve-spec 的 spec 直通(引擎据它判「本会话没有持久记忆」的披露与四只记忆面臂)、boot 审计的 declared 位
|
|
79
|
+
* 两处都必须读本函数,禁各自重算(operator-knob 律:显式 env 的优先权在这一个函数里执法一次)。
|
|
80
80
|
* 自动补位在 boot 日志上必须可见(stores.ts 的 info 行),部署方随时可用显式 env 覆盖。
|
|
81
81
|
*/
|
|
82
82
|
export declare function effectiveMemoryPersistenceCapable(config: {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Logger } from "../observability/logger.js";
|
|
2
|
+
/** 一行 warn 里最多点名的行数(超出只报总数与省略数):一份中心发布可以带很多行,启动日志的一行不随之变长。 */
|
|
3
|
+
export declare const READ_DENY_AUDIT_MAX_NAMED_ROWS = 20;
|
|
4
|
+
export interface ReadDenyAnchorAuditCtx {
|
|
5
|
+
/** 部署读拒行(`config.readDenyPatterns`);缺席 / 空 ⇒ 无话可说。 */
|
|
6
|
+
readonly rows: readonly {
|
|
7
|
+
readonly pattern: string;
|
|
8
|
+
readonly caseSensitive: boolean;
|
|
9
|
+
}[] | undefined;
|
|
10
|
+
readonly logger: Pick<Logger, "warn">;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 只由 `announceReadDenyRows` 调(一份值一次)。返回非锚定行的规范形(按配置顺序;无 ⇒ 空),并在有时打**恰一行** warn `read_deny_unanchored_rows`
|
|
14
|
+
* (`rows` 点名前 {@link READ_DENY_AUDIT_MAX_NAMED_ROWS} 行、`count` 总数、超出时 `omitted`;`note` 引 MIGRATION 第 45 条的改法)。绝不抛。
|
|
15
|
+
*/
|
|
16
|
+
export declare function auditReadDenyAnchoring(ctx: ReadDenyAnchorAuditCtx): readonly string[];
|
|
17
|
+
//# sourceMappingURL=read-deny-anchor-audit.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { compileReadDeny, readDenyPatternRun } from "@sema-agent/core";
|
|
2
|
+
import { echoCallerText } from "../caller-text-echo.js";
|
|
3
|
+
export const READ_DENY_AUDIT_MAX_NAMED_ROWS = 20;
|
|
4
|
+
const NAMED_ROW_ECHO_CHARS = 200;
|
|
5
|
+
function isAnchoredCanonicalRow(canonical) {
|
|
6
|
+
return readDenyPatternRun(canonical).homeAnchored || canonical.startsWith("/");
|
|
7
|
+
}
|
|
8
|
+
export function auditReadDenyAnchoring(ctx) {
|
|
9
|
+
if (ctx.rows === undefined || ctx.rows.length === 0)
|
|
10
|
+
return [];
|
|
11
|
+
let canonical;
|
|
12
|
+
try {
|
|
13
|
+
canonical = compileReadDeny(ctx.rows, "boot read-deny anchor audit", { tiers: [] }).entries.map((e) => e.pattern);
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
ctx.logger.warn("read_deny_anchor_audit_failed", {
|
|
17
|
+
error: echoCallerText(err instanceof Error ? err.message : String(err), { maxChars: 400 }),
|
|
18
|
+
note: "the boot audit could not read the deployment read-deny rows, so it names none and changes nothing; the engine itself refuses a row it cannot read when the Runner is built",
|
|
19
|
+
});
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
const unanchored = canonical.filter((p) => !isAnchoredCanonicalRow(p));
|
|
23
|
+
if (unanchored.length === 0)
|
|
24
|
+
return [];
|
|
25
|
+
const named = unanchored.slice(0, READ_DENY_AUDIT_MAX_NAMED_ROWS).map((p) => echoCallerText(p, { maxChars: NAMED_ROW_ECHO_CHARS }));
|
|
26
|
+
ctx.logger.warn("read_deny_unanchored_rows", {
|
|
27
|
+
rows: named,
|
|
28
|
+
count: unanchored.length,
|
|
29
|
+
...(unanchored.length > named.length ? { omitted: unanchored.length - named.length } : {}),
|
|
30
|
+
note: "recursive shell reads (grep -r and the like) are judged by the root the command names: a read-deny row spelled without a root or home anchor does not protect files below that root " +
|
|
31
|
+
"(reading from a parent directory returns their content; naming the directory or file itself is still refused). Anchor the row to protect it — `<workspace root>/…` or `~/…` — see MIGRATION 7.132.0 item 45. " +
|
|
32
|
+
"This notice changes nothing: enforcement is unchanged and the start is not refused",
|
|
33
|
+
});
|
|
34
|
+
return unanchored;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=read-deny-anchor-audit.js.map
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { type MemoryBackend
|
|
2
|
-
import type { PromptsDomainFaces } from "../prompts-domain-validate.js";
|
|
1
|
+
import { type MemoryBackend } from "@sema-agent/core";
|
|
3
2
|
import { SessionEnvironmentSelection, selectEnvironmentTool } from "../capabilities/select-environment-tool.js";
|
|
4
3
|
import { sendUserFileTool } from "../capabilities/send-user-file-tool.js";
|
|
5
4
|
import { selectScenario } from "../capabilities/scenarios.js";
|
|
@@ -28,8 +27,6 @@ export interface ResolveSpecCtx {
|
|
|
28
27
|
scenarios: Record<string, ReturnType<typeof selectScenario>>;
|
|
29
28
|
principalCaps: PrincipalCaps | undefined;
|
|
30
29
|
centerRuntimeCapsResolver: PrincipalCaps["resolveRuntimeCaps"] | undefined;
|
|
31
|
-
/** 活引用(adoptCenterPrompts 每次采用换引用)—— 见文件头「位置即契约」。 */
|
|
32
|
-
getCenterPrompts: () => PromptsDomainFaces | undefined;
|
|
33
30
|
/** 活引用(registry 热应用换引用)—— 见文件头「位置即契约」。 */
|
|
34
31
|
getKeyResolver: () => ReturnType<typeof createKeyResolver>;
|
|
35
32
|
taskAttachmentStore: TaskAttachmentStore | undefined;
|
|
@@ -77,7 +74,6 @@ export interface ResolveSpecCtx {
|
|
|
77
74
|
approverSeat: RunnerDepsOnAsk | undefined;
|
|
78
75
|
approvalExemptionStore: ReturnType<StoreBackend["approvalExemption"]> | undefined;
|
|
79
76
|
checkpointStore: ReturnType<NonNullable<StoreBackend["checkpoint"]>> | undefined;
|
|
80
|
-
deploymentHooks: NonNullable<RunnerDeps["hooks"]>;
|
|
81
77
|
imageIndex: ReturnType<NonNullable<StoreBackend["imageIndex"]>> | undefined;
|
|
82
78
|
perTaskImage: PerTaskImageRegistry;
|
|
83
79
|
sessionEnvSelection: SessionEnvironmentSelection;
|