@sema-agent/server 7.138.0 → 7.140.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 +457 -7
- package/README.md +7 -4
- package/README.zh-CN.md +6 -4
- package/USAGE.md +91 -41
- package/deploy/sema-up/README.md +1 -1
- package/deploy/sema-up/lib/lanes.json +3 -2
- package/dist/adoption/runner.js +1 -1
- package/dist/adoption/sql.js +1 -1
- package/dist/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +26 -26
- package/dist/bench/s1/arms.d.ts +1 -1
- package/dist/bench/s1/arms.js +1 -3
- package/dist/bench/s1/live-deps.js +3 -2
- package/dist/bench/s1/row.d.ts +5 -2
- package/dist/bench/s1/row.js +2 -22
- package/dist/bench/s1/run-firm.js +2 -2
- package/dist/boot/adoption.js +1 -1
- package/dist/boot/device-lane.d.ts +8 -3
- package/dist/boot/device-lane.js +7 -2
- package/dist/boot/execution-env.d.ts +4 -2
- package/dist/boot/execution-env.js +28 -34
- package/dist/boot/execution-lane.d.ts +9 -1
- package/dist/boot/execution-lane.js +6 -1
- package/dist/boot/governance-seams.d.ts +3 -2
- package/dist/boot/governance-seams.js +9 -11
- package/dist/boot/memory-boundary.d.ts +14 -51
- package/dist/boot/memory-boundary.js +10 -20
- package/dist/boot/memory-consolidation.d.ts +15 -11
- package/dist/boot/memory-consolidation.js +25 -14
- package/dist/boot/resolve-spec.d.ts +4 -6
- package/dist/boot/resolve-spec.js +10 -13
- package/dist/boot/retention-lane.d.ts +5 -5
- package/dist/boot/retention-lane.js +0 -6
- package/dist/boot/runner-deps.d.ts +6 -4
- package/dist/boot/runner-deps.js +3 -1
- package/dist/boot/session-faces.d.ts +0 -3
- package/dist/boot/session-faces.js +15 -8
- package/dist/boot/stage-02-web-admin-pull.js +2 -2
- package/dist/boot/stage-03-store-backend.d.ts +2 -6
- package/dist/boot/stage-03-store-backend.js +2 -3
- package/dist/boot/stage-04-stores.d.ts +2 -6
- package/dist/boot/stage-04-stores.js +5 -5
- package/dist/boot/stage-05-execution-env.d.ts +2 -6
- package/dist/boot/stage-05-execution-env.js +2 -2
- package/dist/boot/stage-06-runners.d.ts +2 -6
- package/dist/boot/stage-06-runners.js +2 -3
- package/dist/boot/stage-07-capability-layer.d.ts +2 -6
- package/dist/boot/stage-08-reapers.d.ts +2 -6
- package/dist/boot/stage-09-leader.d.ts +2 -6
- package/dist/boot/stage-09-leader.js +1 -2
- package/dist/boot/stage-10-http-server.d.ts +2 -6
- package/dist/boot/stage-10-http-server.js +7 -6
- package/dist/boot/stores.d.ts +3 -6
- package/dist/boot/stores.js +27 -40
- package/dist/boot/task-list-lane.d.ts +1 -1
- package/dist/boot/task-list-lane.js +1 -1
- package/dist/boot/web-admin.js +37 -11
- package/dist/capabilities/execution-lane.d.ts +2 -2
- package/dist/capabilities/mcp-probe.js +1 -1
- package/dist/capabilities/scenarios.d.ts +1 -1
- package/dist/capability-facts.d.ts +15 -7
- package/dist/capability-facts.js +8 -3
- package/dist/config-catalog.js +9 -8
- package/dist/config-invariants.d.ts +23 -3
- package/dist/config-invariants.js +42 -0
- package/dist/config-provider.d.ts +33 -37
- package/dist/config-provider.js +51 -30
- package/dist/config-types.d.ts +21 -7
- package/dist/config.d.ts +33 -0
- package/dist/config.js +46 -16
- package/dist/delegated-session-owner.d.ts +4 -3
- package/dist/delegated-session-owner.js +1 -1
- package/dist/deployment-shape.d.ts +10 -9
- package/dist/deployment-shape.js +4 -4
- package/dist/device-enrollment.d.ts +41 -2
- package/dist/device-enrollment.js +27 -12
- package/dist/device-store.d.ts +58 -85
- package/dist/device-store.js +19 -49
- package/dist/device-ws-hub.js +2 -1
- package/dist/env-name-allowlist-knobs.d.ts +5 -4
- package/dist/exec-cut.d.ts +60 -0
- package/dist/exec-cut.js +36 -0
- package/dist/execution-lane-caps.d.ts +115 -105
- package/dist/execution-lane-caps.js +76 -82
- package/dist/execution-placement.d.ts +259 -0
- package/dist/execution-placement.js +199 -0
- package/dist/field-conflict.d.ts +3 -2
- package/dist/field-conflict.js +1 -0
- package/dist/hosted-posture.d.ts +2 -2
- package/dist/http/admission.js +8 -19
- package/dist/http/checkpoint-ctx.d.ts +21 -12
- package/dist/http/checkpoint-ctx.js +4 -2
- package/dist/http/claimed-run.d.ts +1 -1
- package/dist/http/durable-run-leg.js +9 -5
- package/dist/http/execution-context.d.ts +218 -0
- package/dist/http/execution-context.js +330 -0
- package/dist/http/memory-compliance-failure-reply.d.ts +3 -1
- package/dist/http/memory-compliance-failure-reply.js +5 -0
- package/dist/http/memory-layer-reply.d.ts +30 -0
- package/dist/http/memory-layer-reply.js +24 -0
- package/dist/http/resume-legs.js +63 -36
- package/dist/http/retired-service-deps.d.ts +1 -1
- package/dist/http/retired-service-deps.js +1 -1
- package/dist/http/route-ctx.d.ts +14 -8
- package/dist/http/routes/adoption.js +1 -1
- package/dist/http/routes/background.d.ts +29 -1
- package/dist/http/routes/background.js +29 -2
- package/dist/http/routes/devices.d.ts +13 -19
- package/dist/http/routes/devices.js +21 -26
- package/dist/http/routes/memory-bundle.js +3 -0
- package/dist/http/routes/memory-compliance.js +8 -1
- package/dist/http/routes/memory-consolidation.js +12 -1
- package/dist/http/routes/memory-origin.js +14 -2
- package/dist/http/routes/memory-policy.js +5 -0
- package/dist/http/routes/session-sync.js +110 -15
- package/dist/http/routes/sessions.d.ts +6 -0
- package/dist/http/routes/sessions.js +143 -22
- package/dist/http/routes/side-query.d.ts +12 -4
- package/dist/http/routes/side-query.js +4 -5
- package/dist/http/routes/tasks.js +41 -33
- package/dist/http/server.d.ts +40 -44
- package/dist/http/server.js +13 -2
- package/dist/http/session-inherit-env.d.ts +3 -4
- package/dist/http/session-inherit-env.js +1 -1
- package/dist/http/wire-types.d.ts +8 -12
- package/dist/identity-source.d.ts +1 -1
- package/dist/identity-source.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/lane-home-probe.d.ts +68 -42
- package/dist/lane-home-probe.js +53 -30
- package/dist/leader/wire.js +5 -4
- package/dist/memory-bundle-engine.d.ts +16 -9
- package/dist/memory-bundle-engine.js +29 -6
- package/dist/memory-operator-faces.d.ts +85 -30
- package/dist/memory-operator-faces.js +136 -30
- package/dist/memory-project-layer.d.ts +3 -21
- package/dist/memory-project-layer.js +11 -8
- package/dist/memory-scope-stores.d.ts +73 -0
- package/dist/memory-scope-stores.js +86 -0
- package/dist/memory-scope.d.ts +29 -5
- package/dist/memory-scope.js +16 -4
- package/dist/memory-sync-client.d.ts +70 -18
- package/dist/memory-sync-client.js +215 -117
- package/dist/memory-sync.d.ts +1 -1
- package/dist/memory-sync.js +3 -2
- package/dist/observability/cost-taxonomy.d.ts +2 -2
- package/dist/observability/fail-open.d.ts +12 -0
- package/dist/observability/fail-open.js +12 -0
- package/dist/observability/run-terminal.js +0 -1
- package/dist/orchestration/workflow-notify-journal.js +4 -4
- package/dist/org-memory-admission.d.ts +4 -3
- package/dist/org-memory-admission.js +6 -6
- package/dist/parked-decide.d.ts +34 -9
- package/dist/parked-decide.js +12 -19
- package/dist/parked-revive-surface.d.ts +12 -15
- package/dist/parked-revive-surface.js +3 -6
- package/dist/peer-seat.d.ts +13 -7
- package/dist/peer-seat.js +37 -3
- package/dist/plugins/adoption-log-sql.js +4 -4
- package/dist/plugins/approval-ask-store-file.d.ts +7 -0
- package/dist/plugins/approval-ask-store-file.js +11 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +6 -0
- package/dist/plugins/approval-ask-store-memory.js +12 -0
- package/dist/plugins/approval-ask-store-sql.d.ts +22 -5
- package/dist/plugins/approval-ask-store-sql.js +44 -26
- package/dist/plugins/approval-nonce-store.js +4 -4
- package/dist/plugins/blob-backend.d.ts +4 -4
- package/dist/plugins/blob-backend.js +7 -7
- package/dist/plugins/breaker-state-sql.js +2 -2
- package/dist/plugins/caching-session-store.d.ts +6 -2
- package/dist/plugins/caching-session-store.js +9 -3
- package/dist/plugins/checkpoint-index-columns.js +2 -2
- package/dist/plugins/checkpoint-store-sql.d.ts +6 -5
- package/dist/plugins/checkpoint-store-sql.js +21 -23
- package/dist/plugins/device-store-sql.d.ts +25 -51
- package/dist/plugins/device-store-sql.js +68 -122
- package/dist/plugins/ensure-index.d.ts +1 -2
- package/dist/plugins/execution-placement-sql.d.ts +151 -0
- package/dist/plugins/execution-placement-sql.js +223 -0
- package/dist/plugins/file-history-store-sql.d.ts +9 -8
- package/dist/plugins/file-history-store-sql.js +9 -9
- package/dist/plugins/file-run-store.d.ts +6 -1
- package/dist/plugins/file-run-store.js +4 -0
- package/dist/plugins/fork-routing-session-store.d.ts +6 -0
- package/dist/plugins/fork-routing-session-store.js +16 -0
- package/dist/plugins/image-bake-store-sql.js +9 -9
- package/dist/plugins/image-index-sql.js +11 -11
- package/dist/plugins/leader-run-store-sql.js +4 -4
- package/dist/plugins/local-session-store.d.ts +149 -50
- package/dist/plugins/local-session-store.js +382 -107
- package/dist/plugins/mailbox-store-sql.d.ts +2 -1
- package/dist/plugins/mailbox-store-sql.js +4 -4
- package/dist/plugins/memory-engine-tidb.js +5 -5
- package/dist/plugins/memory-key-guards.d.ts +4 -0
- package/dist/plugins/memory-key-guards.js +1 -0
- package/dist/plugins/memory-optout-grant-store-sql.js +1 -1
- package/dist/plugins/memory-run-store.d.ts +1 -1
- package/dist/plugins/memory-sync-store-tidb.js +3 -3
- package/dist/plugins/one-time-migrations.d.ts +117 -8
- package/dist/plugins/one-time-migrations.js +408 -38
- package/dist/plugins/org-delivery-quota-store.js +2 -2
- package/dist/plugins/outcome-ledger-sql.d.ts +2 -2
- package/dist/plugins/outcome-ledger-sql.js +2 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +17 -19
- package/dist/plugins/permission-rule-store-sql.js +29 -32
- package/dist/plugins/pg-pool.d.ts +7 -3
- package/dist/plugins/pg-session-storage.d.ts +31 -20
- package/dist/plugins/pg-session-storage.js +120 -52
- package/dist/plugins/remote-env-adb.d.ts +18 -19
- package/dist/plugins/remote-env-adb.js +91 -66
- package/dist/plugins/remote-env-device.d.ts +23 -31
- package/dist/plugins/remote-env-device.js +19 -17
- package/dist/plugins/remote-env-e2b.d.ts +27 -21
- package/dist/plugins/remote-env-e2b.js +91 -45
- package/dist/plugins/remote-env-file-error.d.ts +3 -1
- package/dist/plugins/remote-env-file-error.js +9 -3
- package/dist/plugins/remote-env-host.d.ts +31 -34
- package/dist/plugins/remote-env-host.js +91 -72
- package/dist/plugins/remote-env-k8s.d.ts +13 -29
- package/dist/plugins/remote-env-k8s.js +63 -55
- package/dist/plugins/remote-env-local-docker.d.ts +24 -12
- package/dist/plugins/remote-env-local-docker.js +49 -61
- package/dist/plugins/remote-env-ssh.d.ts +11 -19
- package/dist/plugins/remote-env-ssh.js +74 -57
- package/dist/plugins/remote-shell.d.ts +100 -3
- package/dist/plugins/remote-shell.js +166 -2
- package/dist/plugins/resume-anchor-store-sql.js +2 -2
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/retention-lane-store-sql.js +2 -2
- package/dist/plugins/retention-store-sql.d.ts +10 -7
- package/dist/plugins/retention-store-sql.js +13 -7
- package/dist/plugins/run-store-sql.d.ts +13 -3
- package/dist/plugins/run-store-sql.js +20 -15
- package/dist/plugins/schema-consistency.d.ts +21 -11
- package/dist/plugins/schema-consistency.js +15 -9
- package/dist/plugins/schema-drift-sentence.d.ts +27 -0
- package/dist/plugins/schema-drift-sentence.js +38 -0
- package/dist/plugins/schema-ensure-legs.d.ts +2 -3
- package/dist/plugins/schema-ensure-legs.js +2 -2
- package/dist/plugins/schema-live-columns.d.ts +1 -1
- package/dist/plugins/session-capture-record-store-sql.js +1 -1
- package/dist/plugins/session-fork.d.ts +54 -0
- package/dist/plugins/session-fork.js +38 -1
- package/dist/plugins/session-row-sql.d.ts +22 -0
- package/dist/plugins/session-row-sql.js +81 -0
- package/dist/plugins/session-rules-column.d.ts +1 -1
- package/dist/plugins/session-rules-column.js +1 -1
- package/dist/plugins/session-store.d.ts +1 -1
- package/dist/plugins/session-workspace-cell.d.ts +1 -1
- package/dist/plugins/session-workspace-cell.js +1 -1
- package/dist/plugins/shared-memory-store-sql.js +2 -2
- package/dist/plugins/sql-driver.d.ts +10 -5
- package/dist/plugins/sql-driver.js +6 -6
- package/dist/plugins/sql-errors.js +1 -1
- package/dist/plugins/store-backend.d.ts +5 -7
- package/dist/plugins/store-backend.js +23 -11
- package/dist/plugins/store-contracts.d.ts +25 -5
- package/dist/plugins/task-list-store-sql.js +11 -11
- package/dist/plugins/tidb-pool.d.ts +12 -7
- package/dist/plugins/tidb-pool.js +13 -7
- package/dist/plugins/tidb-session-storage.js +4 -4
- package/dist/plugins/tidb-session-store.d.ts +57 -26
- package/dist/plugins/tidb-session-store.js +127 -59
- package/dist/plugins/tool-result-store-sql.d.ts +5 -4
- package/dist/plugins/tool-result-store-sql.js +21 -13
- package/dist/plugins/user-input-ledger-sql.js +2 -2
- package/dist/plugins/workflow-journal-store-sql.js +5 -5
- package/dist/plugins/workflow-run-store-sql.js +19 -19
- package/dist/plugins/write-behind-counter.d.ts +2 -3
- package/dist/plugins/write-behind-counter.js +5 -5
- package/dist/project-memory.d.ts +9 -15
- package/dist/project-memory.js +5 -4
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +6 -7
- package/dist/request-value-closure.js +1 -3
- package/dist/resource-suspend.d.ts +14 -12
- package/dist/resource-suspend.js +1 -1
- package/dist/resource-window.d.ts +4 -3
- package/dist/run-local.d.ts +6 -0
- package/dist/run-local.js +34 -35
- package/dist/runs.d.ts +10 -5
- package/dist/runs.js +52 -66
- package/dist/security.d.ts +38 -12
- package/dist/security.js +8 -2
- package/dist/server-secret-env.d.ts +9 -5
- package/dist/session-children-retire.d.ts +27 -9
- package/dist/session-children-retire.js +9 -5
- package/dist/session-incarnation.d.ts +20 -10
- package/dist/session-incarnation.js +5 -3
- package/dist/session-policy-wire.d.ts +1 -1
- package/dist/session-row.d.ts +114 -5
- package/dist/session-row.js +55 -5
- package/dist/session-titler.d.ts +2 -2
- package/dist/sql-engine-posture.d.ts +1 -1
- package/dist/sql-engine-posture.js +1 -1
- package/dist/{plugins → stores-sql}/background-agent-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/background-agent-store-sql.js +8 -8
- package/dist/{plugins → stores-sql}/session-policy-store-sql.d.ts +7 -5
- package/dist/{plugins → stores-sql}/session-policy-store-sql.js +12 -12
- package/dist/{plugins → stores-sql}/usage-window-store-sql.d.ts +1 -1
- package/dist/{plugins → stores-sql}/usage-window-store-sql.js +3 -3
- package/dist/task-a2a.d.ts +1 -1
- package/dist/task-a2a.js +5 -6
- package/dist/task-cwd.d.ts +6 -1
- package/dist/task-mcp.d.ts +22 -9
- package/dist/task-mcp.js +17 -9
- package/dist/terminal.d.ts +27 -0
- package/dist/terminal.js +6 -0
- package/dist/tool-approval.d.ts +6 -0
- package/dist/tool-approval.js +8 -1
- package/dist/trace/project.d.ts +1 -0
- package/dist/trace/project.js +1 -0
- package/dist/trace/redact.d.ts +3 -1
- package/dist/trace/redact.js +80 -28
- package/dist/trace/self-minted-wire.d.ts +169 -2
- package/dist/trace/self-minted-wire.js +54 -1
- package/dist/url-refusal.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +17 -3
- package/dist/web-admin-client/apply-effective.js +20 -10
- package/dist/web-admin-client/candidate-gate.d.ts +11 -7
- package/dist/web-admin-client/candidate-gate.js +1 -1
- package/dist/web-admin-client/http-client.d.ts +5 -4
- package/dist/web-admin-client/http-client.js +2 -2
- package/dist/web-admin-client/read-warnings.d.ts +7 -17
- package/dist/web-admin-client/read-warnings.js +5 -9
- package/dist/web-admin-client/skills-mcp.js +3 -2
- package/dist/web-admin-client/types.d.ts +6 -0
- package/package.json +3 -3
- package/wire-changes/server@7.139.0.json +348 -0
- package/wire-changes/server@7.140.0.json +184 -0
- package/dist/http/device-placement.d.ts +0 -175
- package/dist/http/device-placement.js +0 -145
package/dist/config.js
CHANGED
|
@@ -9,6 +9,7 @@ import { parseApprovalHmacKeys, parsePrincipalJwks } from "./auth-keys.js";
|
|
|
9
9
|
import { DEFAULT_ELICITATION_THROTTLE } from "./elicitation.js";
|
|
10
10
|
import { buildRuleListJudgeOptions } from "./permission-rule-list.js";
|
|
11
11
|
import { isV2ScopeKey, memoryReplicationCoverage, replicatesProjectLayersOf } from "./memory-scope.js";
|
|
12
|
+
import { memorySyncPeerOf } from "./memory-sync-client.js";
|
|
12
13
|
import { assertProjectLayerOwnable } from "./project-identity.js";
|
|
13
14
|
import { projectLayerOwnerOf } from "./project-layer-key.js";
|
|
14
15
|
import { DEFAULT_QUESTION_THROTTLE } from "./question.js";
|
|
@@ -26,7 +27,7 @@ import { THINKING_LEVELS, THINKING_FORMATS, buildModelCompat, isThinkingFormat,
|
|
|
26
27
|
import {} from "./posture-source.js";
|
|
27
28
|
import { COST_QUOTA_WINDOW_SEC_RANGE, costQuotaWindowSecInRange } from "./observability/cost-quota.js";
|
|
28
29
|
import { NAME_TABLE_BEHAVIOR, TOOL_NAME_ROSTER, describeUnmatchableRuleName, ruleEntryToolName, unmatchableRuleNameOf } from "./namespaced-rule-name.js";
|
|
29
|
-
import { bakeOperatorPrincipalsRefusal, bakeRunnerCredentialRefusal, centerIdentityRefusal, halfOpenDirectDoorRefusal, leaderDurableStoreRefusal, operatorPrincipalsRequiredRefusal, operatorSingleUserRefusal, workflowParkDecisionDomainRefusal } from "./config-invariants.js";
|
|
30
|
+
import { bakeOperatorPrincipalsRefusal, bakeRunnerCredentialRefusal, centerIdentityRefusal, halfOpenDirectDoorRefusal, leaderDurableStoreRefusal, operatorPrincipalsRequiredRefusal, operatorSingleUserRefusal, remoteConfigProviderUrlRefusal, retentionLaneRefusal, workflowParkDecisionDomainRefusal } from "./config-invariants.js";
|
|
30
31
|
import { declaredSemaConfigDir } from "./sema-config-dir.js";
|
|
31
32
|
import { lkgPathOverrideOf } from "./config-lkg.js";
|
|
32
33
|
import { K8S_WORKSPACE_MOUNT_DEFAULT, WORKSPACE_PERSIST_DEFAULT, WORKSPACE_PERSIST_WORDS, WORKSPACE_SNAPSHOT_KEEP_DEFAULT, WORKSPACE_SNAPSHOT_KEEP_RANGE, WORKSPACE_SNAPSHOT_TIMEOUT_MS_DEFAULT, WORKSPACE_SNAPSHOT_TIMEOUT_MS_RANGE, parseWorkspaceSnapshotExclude, parseWorkspaceSnapshotPrefix } from "./workspace-space.js";
|
|
@@ -35,7 +36,7 @@ import { laneLivenessOf } from "./exec-bounds.js";
|
|
|
35
36
|
import { SANDBOX_IPV6_DEFAULT, SANDBOX_IPV6_WORDS } from "./sandbox-egress-policy.js";
|
|
36
37
|
import { WORKSPACE_CACHE_DEFAULT, WORKSPACE_CACHE_MOUNT_DEFAULT, WORKSPACE_CACHE_MOUNT_RESERVED, WORKSPACE_CACHE_SIZE_DEFAULT, WORKSPACE_CACHE_WORDS, isK8sQuantity, mountsOverlap, reservedMountCollision } from "./workspace-cache.js";
|
|
37
38
|
import { DEPLOYMENT_SHAPE_PREDICATES } from "./deployment-shape.js";
|
|
38
|
-
import { REMOTE_EXEC_PROVIDER_WORDS, executionLaneOf, executionLaneRequiredRefusal,
|
|
39
|
+
import { REMOTE_EXEC_PROVIDER_WORDS, executionLaneOf, executionLaneRequiredRefusal, laneMissingEnv } from "./execution-lane-caps.js";
|
|
39
40
|
import { MEMORY_ENGINE_BACKENDS, SESSION_BACKENDS, STORE_BACKENDS } from "@sema-agent/settings-schema/execution-lanes";
|
|
40
41
|
import { AUTONOMY_MODES } from "./runtime-governance.js";
|
|
41
42
|
import { MAX_NAMED_INERT_ENTRIES, allowLayerEntryCountIssue, describeInertRuleEntries, inertRuleEntriesOf, inertRuleEntryGuidance, ruleEntryListShapeOk } from "./rule-entry-list.js";
|
|
@@ -195,7 +196,7 @@ function buildExecLaneNotice(remoteExec) {
|
|
|
195
196
|
};
|
|
196
197
|
}
|
|
197
198
|
const ENV_VALUE_ECHO_CHARS = 120;
|
|
198
|
-
function parseConfigProvider() {
|
|
199
|
+
export function parseConfigProvider() {
|
|
199
200
|
const raw = process.env.CONFIG_PROVIDER;
|
|
200
201
|
if (raw === undefined || raw === "")
|
|
201
202
|
return undefined;
|
|
@@ -509,11 +510,32 @@ function parseNameListEnv(name, raw, opts) {
|
|
|
509
510
|
}
|
|
510
511
|
const ENV_VAR_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
511
512
|
const ENV_NAME_ALLOWLIST_WITHHELD = "<withheld: entries are not echoed — a value pasted in place of a name can pass the name check>";
|
|
512
|
-
|
|
513
|
+
const OWN_CREDENTIAL_HANDOFF = {
|
|
514
|
+
"host-put-back": { where: "a put-back list hands the named variable back, as written, to the child the engine withheld it from", whom: "that child" },
|
|
515
|
+
"sandbox-grant": { where: "a sandbox list puts the named variable, as written, into a sandbox the model can read", whom: "the sandbox" },
|
|
516
|
+
};
|
|
517
|
+
function ownCredentialNameProblem(name, channel) {
|
|
513
518
|
const engine = inheritEnvPolicyProblem([name]);
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
519
|
+
if (engine === undefined)
|
|
520
|
+
return undefined;
|
|
521
|
+
const { where, whom } = OWN_CREDENTIAL_HANDOFF[channel];
|
|
522
|
+
return `this deployment's own credential — ${where}; give ${whom} a credential of its own (another name and another value) and list that name instead (the engine refuses it on any allow list: ${engine})`;
|
|
523
|
+
}
|
|
524
|
+
const NAMES_IN_FORCE = {
|
|
525
|
+
LSP_ENV_ALLOW: (c) => c.lspEnvAllow,
|
|
526
|
+
E2B_SANDBOX_ENV: (c) => (c.remoteExec?.provider === "e2b" ? Object.keys(c.remoteExec.sandboxEnv ?? {}) : []),
|
|
527
|
+
K8S_SANDBOX_ENV: (c) => (c.remoteExec?.provider === "k8s" ? Object.keys(c.remoteExec.sandboxEnv ?? {}) : []),
|
|
528
|
+
DOCKER_SANDBOX_ENV: (c) => (c.remoteExec?.provider === "local-docker" ? Object.keys(c.remoteExec.env ?? {}) : []),
|
|
529
|
+
};
|
|
530
|
+
const SERVER_ENV_NAME_ALLOWLIST_KNOBS = Object.keys(NAMES_IN_FORCE);
|
|
531
|
+
export function sandboxEnvNamesInForce(seats) {
|
|
532
|
+
return SERVER_ENV_NAME_ALLOWLIST_KNOBS.filter((knob) => ENV_NAME_ALLOWLIST_KNOBS[knob].channel === "sandbox-grant").flatMap((knob) => NAMES_IN_FORCE[knob](seats));
|
|
533
|
+
}
|
|
534
|
+
export function ownCredentialHitsInForce(seats) {
|
|
535
|
+
return SERVER_ENV_NAME_ALLOWLIST_KNOBS.flatMap((knob) => NAMES_IN_FORCE[knob](seats).flatMap((name) => {
|
|
536
|
+
const problem = ownCredentialNameProblem(name, ENV_NAME_ALLOWLIST_KNOBS[knob].channel);
|
|
537
|
+
return problem === undefined ? [] : [{ knob, name, problem }];
|
|
538
|
+
}));
|
|
517
539
|
}
|
|
518
540
|
export function parseEnvNameAllowlist(knob, singleUserTurnkey) {
|
|
519
541
|
const raw = process.env[knob];
|
|
@@ -528,9 +550,7 @@ export function parseEnvNameAllowlist(knob, singleUserTurnkey) {
|
|
|
528
550
|
? 'not an environment-variable name (letters, digits and "_", not starting with a digit)'
|
|
529
551
|
: ENV_NAME_ALLOWLIST_KNOB_NAMES.has(seg.toUpperCase())
|
|
530
552
|
? `the name of a name-list knob (${[...ENV_NAME_ALLOWLIST_KNOB_NAMES].join(" / ")}: their raw text is withheld from every child process and sandbox; naming one would put that text back)`
|
|
531
|
-
: spec.channel
|
|
532
|
-
? ownCredentialPutBackProblem(seg)
|
|
533
|
-
: undefined;
|
|
553
|
+
: ownCredentialNameProblem(seg, spec.channel);
|
|
534
554
|
if (problem === undefined)
|
|
535
555
|
return;
|
|
536
556
|
throw new Error(`env ${knob}: entry #${i + 1} of ${segments.length} is ${problem}` +
|
|
@@ -1704,6 +1724,7 @@ function parseMemoryDomain(ctx) {
|
|
|
1704
1724
|
if (memorySyncToken === undefined) {
|
|
1705
1725
|
throw new Error("MEMORY_SYNC_URL is set but MEMORY_SYNC_TOKEN is not — refusing to start half-configured (the central sync face requires a bearer token)");
|
|
1706
1726
|
}
|
|
1727
|
+
memorySyncPeerOf(memorySyncUrl);
|
|
1707
1728
|
if (memorySyncScopeRaw === undefined && memoryScope !== undefined && !isV2ScopeKey(memoryScope)) {
|
|
1708
1729
|
throw new Error(`MEMORY_SYNC_URL is set but MEMORY_SYNC_SCOPE is not set and MEMORY_SCOPE (${JSON.stringify(memoryScope)}) is not a typed scope key — the sync leg replicates exactly ONE scope by name ` +
|
|
1709
1730
|
"(core syncMemoryScope takes the entries whose scope === the sync scope and POSTs them under that same name), so deriving `user:<MEMORY_SCOPE>` would name a scope this deployment never writes and nothing would ever be synced (S-964). " +
|
|
@@ -1902,10 +1923,10 @@ function parseOrchestrationDomain(ctx) {
|
|
|
1902
1923
|
throw new Error(`REMOTE_EXEC="${lane}" is not an execution lane — valid: ${REMOTE_EXEC_PROVIDER_WORDS.join(" | ")}. ` +
|
|
1903
1924
|
`An unrecognized value used to fall through to the host/in-process lane silently; refusing to start instead (#157).`);
|
|
1904
1925
|
}
|
|
1905
|
-
const missing =
|
|
1926
|
+
const missing = laneMissingEnv(word, process.env);
|
|
1906
1927
|
if (missing.length > 0) {
|
|
1907
|
-
throw new Error(`REMOTE_EXEC=${lane} but required env ${missing.join(", ")} ${missing.length === 1 ? "is" : "are"}
|
|
1908
|
-
`refusing to start rather than silently downgrading to the host/in-process lane (#157; unset REMOTE_EXEC if you meant no sandbox lane).`);
|
|
1928
|
+
throw new Error(`REMOTE_EXEC=${lane} but required env ${missing.join(", ")} ${missing.length === 1 ? "is" : "are"} unset, empty or whitespace-only — it counts as absent: ` +
|
|
1929
|
+
`refusing to start rather than silently downgrading to the host/in-process lane (#157; set ${missing.length === 1 ? "it" : "them"}, or unset REMOTE_EXEC if you meant no sandbox lane).`);
|
|
1909
1930
|
}
|
|
1910
1931
|
}
|
|
1911
1932
|
}
|
|
@@ -1923,6 +1944,7 @@ function parseOrchestrationDomain(ctx) {
|
|
|
1923
1944
|
assertReadDenyBuiltinsResolvable(tiers, exclude);
|
|
1924
1945
|
return { ...(tiers !== undefined ? { readDenyBuiltinTiers: tiers } : {}), ...(exclude !== undefined ? { readDenyBuiltinExclude: exclude } : {}) };
|
|
1925
1946
|
})(),
|
|
1947
|
+
readDenyFloorRequired: boolEnv("READ_DENY_FLOOR_REQUIRED", false),
|
|
1926
1948
|
...((dir) => (dir !== undefined ? { agentConfigDir: dir } : {}))(declaredSemaConfigDir()),
|
|
1927
1949
|
...((p) => (p !== undefined ? { configLkgPath: p } : {}))(lkgPathOverrideOf(process.env.CONFIG_LKG_PATH)),
|
|
1928
1950
|
configLkgEnabled: boolEnv("CONFIG_LKG_ENABLED", true),
|
|
@@ -1951,7 +1973,7 @@ function parseOrchestrationDomain(ctx) {
|
|
|
1951
1973
|
orphanReclaim: boolEnv("E2B_ORPHAN_RECLAIM", true),
|
|
1952
1974
|
}
|
|
1953
1975
|
:
|
|
1954
|
-
process.env.REMOTE_EXEC === "k8s" && process.env.K8S_SANDBOX_IMAGE
|
|
1976
|
+
process.env.REMOTE_EXEC === "k8s" && process.env.K8S_SANDBOX_IMAGE && process.env.K8S_NAMESPACE
|
|
1955
1977
|
? {
|
|
1956
1978
|
provider: "k8s",
|
|
1957
1979
|
image: process.env.K8S_SANDBOX_IMAGE,
|
|
@@ -1959,7 +1981,7 @@ function parseOrchestrationDomain(ctx) {
|
|
|
1959
1981
|
...(process.env.K8S_TOKEN ? { token: process.env.K8S_TOKEN } : {}),
|
|
1960
1982
|
...(process.env.K8S_CA_CERT_B64 ? { caCert: Buffer.from(process.env.K8S_CA_CERT_B64, "base64").toString("utf8") } : {}),
|
|
1961
1983
|
...(boolEnv("K8S_INSECURE_TLS", false) ? { insecureTls: true } : {}),
|
|
1962
|
-
|
|
1984
|
+
namespace: process.env.K8S_NAMESPACE,
|
|
1963
1985
|
...(process.env.K8S_RUNTIME_CLASS != null ? { runtimeClass: process.env.K8S_RUNTIME_CLASS } : {}),
|
|
1964
1986
|
...(process.env.K8S_MOUNT_PATH ? { mountPath: process.env.K8S_MOUNT_PATH } : {}),
|
|
1965
1987
|
...((n) => (n !== undefined ? { timeoutMs: n } : {}))(optNumEnvStrict("K8S_TIMEOUT_MS")),
|
|
@@ -2450,7 +2472,7 @@ const ORCHESTRATION_GROUP_KEYS = [
|
|
|
2450
2472
|
"workflowSizeGuideline", "backgroundAgentRetentionMs", "backgroundAgentStaleRunningMs",
|
|
2451
2473
|
"backgroundAgentParkClaimStaleMs", "delegationEntryCaps", "rosterRetentionMs", "leaderRunStaleMs", "scratchpadSweepTtlMs", "sandboxPkgSource", "sandboxPkgSourceCustom",
|
|
2452
2474
|
"sessionAutoTitle", "sessionAutoTitleSource", "selectEnvironmentTool", "envFactsEnabled", "toolDeferLongtail", "lspEnabled", "lspHostEnabled", "lspEnvAllow",
|
|
2453
|
-
"imageBakes", "readFace", "readFaceSource", "taskWriteFaceEscalation", "readDenyPatterns", "readDenyBuiltinTiers", "readDenyBuiltinExclude",
|
|
2475
|
+
"imageBakes", "readFace", "readFaceSource", "taskWriteFaceEscalation", "readDenyPatterns", "readDenyBuiltinTiers", "readDenyBuiltinExclude", "readDenyFloorRequired",
|
|
2454
2476
|
"agentConfigDir", "configLkgPath", "configLkgEnabled",
|
|
2455
2477
|
];
|
|
2456
2478
|
const LIMITS_HTTP_GROUP_KEYS = [
|
|
@@ -2602,6 +2624,14 @@ export function loadConfig() {
|
|
|
2602
2624
|
if (centerIdentity !== undefined) {
|
|
2603
2625
|
throw new Error(centerIdentity);
|
|
2604
2626
|
}
|
|
2627
|
+
const remoteSourceRefusal = remoteConfigProviderUrlRefusal({ configProvider: integrations.configProvider, webAdmin: integrations.webAdmin });
|
|
2628
|
+
if (remoteSourceRefusal !== undefined) {
|
|
2629
|
+
throw new Error(remoteSourceRefusal);
|
|
2630
|
+
}
|
|
2631
|
+
const retentionRefusal = retentionLaneRefusal({ retentionPolicy: auth.retentionPolicy, retentionSweep: auth.retentionSweep });
|
|
2632
|
+
if (retentionRefusal !== undefined) {
|
|
2633
|
+
throw new Error(retentionRefusal);
|
|
2634
|
+
}
|
|
2605
2635
|
const { directApprovalDoor, durableApproval: dgDurable, approvalHmacKeys: dgHmacKeys } = approval;
|
|
2606
2636
|
const { principalJwtPubkeys, principalJwtIss, principalJwtAud, operatorPrincipals: dgOperators, operatorSingleUser, authTokens } = auth;
|
|
2607
2637
|
const directDoorActive = directApprovalDoor && dgDurable && dgHmacKeys.length > 0 && principalJwtPubkeys.length > 0 && !!principalJwtIss && !!principalJwtAud;
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
* M23 回填了无主的父)⇒ 写下的仍是判断时的读数 —— 按律如此;那一行若因此无主,照上一节处置。
|
|
39
39
|
* · **停驻挂点**(`plugins/session-store.ts` 的 `ensureChildSessionDurableWithPromotion`;快路 + 晋升):来源 = **调用方交出的委派树根,只有这一只**,连同
|
|
40
40
|
* 调用方判断那一刻读到的根行住客({@link DelegationRootWitness};见证值,判断用,不进 CAS):请求腿 = 本请求经鉴权解析的会话,住客 = 受理时那一读
|
|
41
|
-
* (`boot/resolve-spec.ts`);`/decide` 的赎回腿 = 行上的 `rootSessionId`,住客 =
|
|
41
|
+
* (`boot/resolve-spec.ts`);`/decide` 的赎回腿 = 行上的 `rootSessionId`,住客 = 赎回腿写口放行的那一位(认领之前解析器那一读;`parked-revive-surface.ts`,每一行都交)。
|
|
42
42
|
* 挂点先读一次根行:它在而住客不是见证的那一位 ⇒ 根被删、同 id 换了住客 ⇒ **拒**(不按新住客晋升 / 认领,{@link assertRootStillWitnessed});它不在 ⇒ 律给哨兵
|
|
43
43
|
* (根真没了)。不回落父:core 的挂点 `ensureChildSessionDurable(sessionId)` 只交子代 id,父 id 在这一写点拿不到;两条候选读法都读不到东西 ——
|
|
44
44
|
* ① 读 `session_meta(子代).placement_parent_session_id`:晋升的拷贝分支恰恰只在子代**没有** placed 行时才走(有 placed 行 ⇒ 快路),这一列按构造为空;
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
*/
|
|
53
53
|
import type { SessionPlacement } from "@sema-agent/core";
|
|
54
54
|
import { type HeadRead, type SessionFace } from "./session-incarnation.js";
|
|
55
|
+
import type { SqlDialect } from "./plugins/sql-driver.js";
|
|
55
56
|
/** 孤行哨兵属主的前缀(保留主体前缀:`security.ts` 的 `RESERVED_PRINCIPAL_PREFIXES` 登记它,任何身份来源报出带它的主体都在鉴权边界被拒)。 */
|
|
56
57
|
export declare const ORPHAN_SESSION_OWNER_PREFIX = "_orphan:";
|
|
57
58
|
/** 一只推不出属主的子代会话的哨兵属主(每只会话一个值:即便哪天有谁误配出这个串,也只够得着这一只)。 */
|
|
@@ -112,7 +113,7 @@ export declare function reportWrittenOwner(log: OrphanOwnerLog, site: DelegatedO
|
|
|
112
113
|
* 不改变写进去的值(律:属主 = 判断时见证到的,本文件头注)。两方言只差占位符。
|
|
113
114
|
* MySQL 协议下 mysql2 缺省带 FOUND_ROWS,但条件里有 `owner IS NULL` ⇒ 匹配行数 = 改写行数。
|
|
114
115
|
*/
|
|
115
|
-
export declare const CLAIM_OWNERLESS_PLACED_SQL: Readonly<Record<
|
|
116
|
+
export declare const CLAIM_OWNERLESS_PLACED_SQL: Readonly<Record<SqlDialect, string>>;
|
|
116
117
|
/** 认领句的绑参(两方言同序;店与 M23 都经它,不各排一份):`incarnation` = 判断时读到的子行化身。 */
|
|
117
118
|
export declare function claimOwnerlessParams(sessionId: string, incarnation: string, owner: string): readonly [string, string, string];
|
|
118
119
|
/** 店的认领口(SQL 两店 + 缓存包装层同一个签名):这只会话的那一位住客(`incarnation`)仍是无主的 placed 行 ⇒ 写 `owner`,返回是否写成。 */
|
|
@@ -134,7 +135,7 @@ export interface PlacedRowWriter {
|
|
|
134
135
|
export declare function createPlacedSessionRow(sessionId: string, placement: PlacementSources, io: PlacedRowWriter, log: OrphanOwnerLog): Promise<void>;
|
|
135
136
|
/**
|
|
136
137
|
* 停驻挂点的**见证**:调用方交出的委派树根 + 调用方判断那一刻读到的根行住客(化身;`null` = 那一读里根行不在)。请求腿 = 鉴权解析的会话与受理时那一读;
|
|
137
|
-
* 赎回腿 =
|
|
138
|
+
* 赎回腿 = 行上的根与写口放行的那一位住客(认领之前解析器那一读)。
|
|
138
139
|
*/
|
|
139
140
|
export interface DelegationRootWitness {
|
|
140
141
|
readonly sessionId: string;
|
|
@@ -47,7 +47,7 @@ export function reportWrittenOwner(log, site, childId, judged) {
|
|
|
47
47
|
});
|
|
48
48
|
}
|
|
49
49
|
export const CLAIM_OWNERLESS_PLACED_SQL = {
|
|
50
|
-
|
|
50
|
+
mysql: "UPDATE session_meta SET owner = ? WHERE session_id = ? AND incarnation = ? AND owner IS NULL AND placement_kind IS NOT NULL",
|
|
51
51
|
pg: "UPDATE session_meta SET owner = $1 WHERE session_id = $2 AND incarnation = $3 AND owner IS NULL AND placement_kind IS NOT NULL",
|
|
52
52
|
};
|
|
53
53
|
export function claimOwnerlessParams(sessionId, incarnation, owner) {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* ## 两根轴,每根轴一个读口(原始配置键只在这两个函数里被读)
|
|
10
10
|
* · `principal` —— 运维的 `REQUIRE_PRINCIPAL` 声明({@link readPrincipalAxis})。
|
|
11
11
|
* · `lane` —— `REMOTE_EXEC` 的归一车道词(`executionLaneOf`,认不出 ⇒ `undefined`,行必须 fail-closed)+ 那条车道的能力表行 +
|
|
12
|
-
*
|
|
12
|
+
* 这份部署上执行环境的能力块(唯一作者 `capabilitiesFor`;k8s 的快照店是它的输入)+ 车道子旋钮(k8s 运行时类、隐式 host 尾臂记号)({@link readLaneAxis})。
|
|
13
13
|
*
|
|
14
14
|
* ## 轴列不是注释,是型
|
|
15
15
|
* 每行的判官只收到它**声明**的那几根轴的事实({@link DeploymentShapeFacts}),读不到配置本身 —— 判官碰一根没声明的轴 = 编译红;
|
|
@@ -21,8 +21,9 @@
|
|
|
21
21
|
* (`mcpInjectionHonored` = 锁 ∧ 合规 ∧ `!multiTenant`;`taskHooksHonored`;身份门 …),读行、不读原始键。
|
|
22
22
|
* 车道表(`execution-lane-caps.ts`)按车道词键控的布尔列(`laneIsolated` 等)是车道轴自己的事实表,不是「部署」的谓词;行读它们。
|
|
23
23
|
*
|
|
24
|
-
* 依赖纪律:叶模块 —— 值导入只有 `execution-lane-caps.ts`(它本身是叶)
|
|
24
|
+
* 依赖纪律:叶模块 —— 值导入只有 `execution-lane-caps.ts`(它本身是叶),零运行期环(引擎只 type-import)。
|
|
25
25
|
*/
|
|
26
|
+
import type { ExecutionEnvCapabilities } from "@sema-agent/core";
|
|
26
27
|
import { type ExecutionLane, type ExecutionLaneCaps } from "./execution-lane-caps.js";
|
|
27
28
|
/** `principal` 轴读的配置键(`ServiceConfig` 结构上满足)。 */
|
|
28
29
|
export interface PrincipalAxisInput {
|
|
@@ -48,10 +49,10 @@ export interface LaneAxisFacts {
|
|
|
48
49
|
readonly lane: ExecutionLane | undefined;
|
|
49
50
|
/** 那条车道的能力表行(认不出 ⇒ `undefined`)。 */
|
|
50
51
|
readonly caps: ExecutionLaneCaps | undefined;
|
|
52
|
+
/** 这份部署上执行环境的能力块(`capabilitiesFor`;认不出 ⇒ `undefined`)。 */
|
|
53
|
+
readonly block: ExecutionEnvCapabilities | undefined;
|
|
51
54
|
/** k8s 的 `runtimeClass`(别的车道 `undefined`)。 */
|
|
52
55
|
readonly k8sRuntimeClass: string | undefined;
|
|
53
|
-
/** k8s 配了 S3 工作区快照店(别的车道 `false`)。 */
|
|
54
|
-
readonly k8sSnapshotStore: boolean;
|
|
55
56
|
/** host 车道值上带「单机形缺省」记号(唯一写者 = `config.ts` 三元链的隐式 host 尾臂;显式 `REMOTE_EXEC=host` 与文件覆写都不带)。 */
|
|
56
57
|
readonly singleMachineDefault: boolean;
|
|
57
58
|
}
|
|
@@ -92,7 +93,7 @@ export declare const DEPLOYMENT_SHAPE_PREDICATES: Readonly<{
|
|
|
92
93
|
* 签发方配置是身份验签轴、不算租户证据)—— 两个问题、一根轴、一个读口;「鉴权必需」与「多租形」拆成两个声明时只改这一行的判官。
|
|
93
94
|
*/
|
|
94
95
|
multiTenant: DeploymentShapePredicate<"principal">;
|
|
95
|
-
/** 读能力表 `callerCwd` 位(host = 单主才开;device =
|
|
96
|
+
/** 读能力表 `callerCwd` 位(host = 单主才开;device = 路径落在发起者自己的设备上,归属由根会话行执行格上的设备绑定验过,不要求单主)。 */
|
|
96
97
|
callerCwd: DeploymentShapePredicate<"lane" | "principal">;
|
|
97
98
|
/** 调用方给的宿主绝对路径(附加目录 / 项目上下文 / 本机 SendUserFile / 指令文件探针)只在「手就在本 worker 的盘上 ∧ 单主」时指向调用方自己的东西。 */
|
|
98
99
|
callerOwnsWorkerDisk: DeploymentShapePredicate<"lane" | "principal">;
|
|
@@ -102,7 +103,7 @@ export declare const DEPLOYMENT_SHAPE_PREDICATES: Readonly<{
|
|
|
102
103
|
inProcessSingleUser: DeploymentShapePredicate<"lane" | "principal">;
|
|
103
104
|
/** 任务层替部署声明宿主姿态(bypassPermissions 开写面 / host shell 继承整份环境)的射程:device 车道上跨租户宿主穿越结构性不存在(clay 裁定③)。 */
|
|
104
105
|
taskHostPostureDeclarations: DeploymentShapePredicate<"lane" | "principal">;
|
|
105
|
-
/**
|
|
106
|
+
/** 写门走代理裁决(执行环境块 `hostLocalPaths` 为假:路径不是本 worker 盘上的文件);认不出的词 ⇒ 走代理(代理 slot 空 ⇒ 写门 fail-closed)。 */
|
|
106
107
|
sandboxPathAdjudication: DeploymentShapePredicate<"lane">;
|
|
107
108
|
/** 读能力表 `sandboxSendUserFile` 位(e2b / k8s 每任务一只沙箱 ⇒ 任何租户;ssh 共享一台真机 ⇒ 只单主)。 */
|
|
108
109
|
sandboxSendUserFile: DeploymentShapePredicate<"lane" | "principal">;
|
|
@@ -111,13 +112,13 @@ export declare const DEPLOYMENT_SHAPE_PREDICATES: Readonly<{
|
|
|
111
112
|
/** 读能力表 `tenantSeparation` 位(值来自 settings-schema 车道词表正本);唯一读者 = 跨域不变量 `multi-tenant-shared-lane`。 */
|
|
112
113
|
laneSeparatesTenants: DeploymentShapePredicate<"lane" | "principal">;
|
|
113
114
|
/**
|
|
114
|
-
* [ref] —— **VM 级**隔离强度(独立内核:e2b 的 Firecracker microVM;k8s 只在 Kata / gVisor 运行时类上)
|
|
115
|
+
* [ref] —— **VM 级**隔离强度(独立内核:e2b 的 Firecracker microVM;k8s 只在 Kata / gVisor 运行时类上)。与执行环境块 `isolation` 键
|
|
115
116
|
* (OS 级边界,容器即算;wire `executionLane.isolated` 的属主 `laneIsolated`)是两个问题,所以不叫「isolated」。读者:A 值路由。
|
|
116
117
|
*/
|
|
117
118
|
vmIsolatedHands: DeploymentShapePredicate<"lane">;
|
|
118
119
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
120
|
+
* 执行环境可挂起 = 这份部署上执行环境块的 `suspendable`(唯一作者 `capabilitiesFor`,k8s 的快照店是它的输入;适配器的块是同一只函数铸的)。
|
|
121
|
+
* 读者:boot `remote_exec_enabled.suspendable`。
|
|
121
122
|
*/
|
|
122
123
|
suspendableHands: DeploymentShapePredicate<"lane">;
|
|
123
124
|
/** 读者两处:`config.ts` 车道落点一行的 `source`(覆写之前)与 `boot/execution-env.ts` 的 `remote_exec_real_system.note`(覆写之后)—— 同一个记号、两个时刻。 */
|
package/dist/deployment-shape.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { executionLaneCaps, executionLaneOf, handsOnWorkerFilePlane } from "./execution-lane-caps.js";
|
|
1
|
+
import { capabilitiesFor, executionLaneCaps, executionLaneOf, handsOnWorkerFilePlane } from "./execution-lane-caps.js";
|
|
2
2
|
function readPrincipalAxis(deployment) {
|
|
3
3
|
return { declared: deployment.requirePrincipal === true };
|
|
4
4
|
}
|
|
@@ -8,8 +8,8 @@ function readLaneAxis(deployment) {
|
|
|
8
8
|
return {
|
|
9
9
|
lane,
|
|
10
10
|
caps: lane === undefined ? undefined : executionLaneCaps(lane),
|
|
11
|
+
block: capabilitiesFor(deployment),
|
|
11
12
|
k8sRuntimeClass: lane === "k8s" ? declaration?.runtimeClass : undefined,
|
|
12
|
-
k8sSnapshotStore: lane === "k8s" && Boolean(declaration?.s3Snapshot),
|
|
13
13
|
singleMachineDefault: lane === "host" && declaration?.singleMachineDefault === true,
|
|
14
14
|
};
|
|
15
15
|
}
|
|
@@ -54,7 +54,7 @@ export const DEPLOYMENT_SHAPE_PREDICATES = Object.freeze({
|
|
|
54
54
|
toolsOnThisHost: createPredicate(["lane"], "车道:工具跑的那台机器就是本进程这台(手挂上了且文件平面在本 worker 盘上;车道列 handsOnWorkerFilePlane)。", ({ lane }) => lane.lane !== undefined && handsOnWorkerFilePlane(lane.lane)),
|
|
55
55
|
inProcessSingleUser: createPredicate(["lane", "principal"], "车道 × 租户:进程内车道(REMOTE_EXEC 未设)且部署只有一个主人。", ({ lane, principal }) => lane.lane === "in-process" && !principal.declared),
|
|
56
56
|
taskHostPostureDeclarations: createPredicate(["lane", "principal"], "车道 × 租户 / 设备归属:任务层可以替部署声明宿主姿态 —— device 车道(发起者自己的设备),或单主部署。", ({ lane, principal }) => lane.lane === "device" || !principal.declared),
|
|
57
|
-
sandboxPathAdjudication: createPredicate(["lane"], "车道:写门的路径事实要经代理到执行环境里取(文件平面不在本 worker 盘上;认不出的车道也走代理)。", ({ lane }) => lane.
|
|
57
|
+
sandboxPathAdjudication: createPredicate(["lane"], "车道:写门的路径事实要经代理到执行环境里取(文件平面不在本 worker 盘上;认不出的车道也走代理)。", ({ lane }) => lane.block === undefined || !lane.block.hostLocalPaths),
|
|
58
58
|
sandboxSendUserFile: createPredicate(["lane", "principal"], "车道 × 租户:SendUserFile 的沙箱直传腿可以挂(沙箱盘 = 租户自己的任务工作区,或共享真机上的单主部署)。", ({ lane, principal }) => lane.caps !== undefined && capabilityHolds(lane.caps.sandboxSendUserFile, principal)),
|
|
59
59
|
remoteScratchpad: createPredicate(["lane"], "车道:执行环境里按会话分的远端 scratchpad 约定适用。", ({ lane }) => lane.caps !== undefined && lane.caps.remoteScratchpad === "supported"),
|
|
60
60
|
laneSeparatesTenants: createPredicate(["lane", "principal"], "车道 × 租户:这条车道在这台部署上不让两个租户的命令落在同一个共享目标上(单主部署恒成立;认不出的车道不成立)。", ({ lane, principal }) => lane.caps !== undefined && capabilityHolds(lane.caps.tenantSeparation, principal)),
|
|
@@ -66,7 +66,7 @@ export const DEPLOYMENT_SHAPE_PREDICATES = Object.freeze({
|
|
|
66
66
|
const runtimeClass = (lane.k8sRuntimeClass ?? "").trim().toLowerCase();
|
|
67
67
|
return runtimeClass.startsWith("kata") || VM_ISOLATION_RUNTIME_CLASSES.has(runtimeClass);
|
|
68
68
|
}),
|
|
69
|
-
suspendableHands: createPredicate(["lane"], "车道:执行环境可挂起(e2b;k8s 以配了 S3 工作区快照店为前提)。", ({ lane }) => lane.
|
|
69
|
+
suspendableHands: createPredicate(["lane"], "车道:执行环境可挂起(e2b;k8s 以配了 S3 工作区快照店为前提)。", ({ lane }) => lane.block?.suspendable === true),
|
|
70
70
|
singleMachineDefaultLane: createPredicate(["lane"], "车道:host 车道是单机形缺省落点(REMOTE_EXEC 未设 ∧ CONFIG_PROVIDER=local,没人点名)。", ({ lane }) => lane.singleMachineDefault),
|
|
71
71
|
});
|
|
72
72
|
//# sourceMappingURL=deployment-shape.js.map
|
|
@@ -18,12 +18,21 @@
|
|
|
18
18
|
* 上是**同一个** `device.enrollment_invalid`;设备读面的「不存在」与「不是你的」是同一个
|
|
19
19
|
* `not_found.device`。细分只进审计。
|
|
20
20
|
*
|
|
21
|
+
* ── 绑定从哪读(一只读)─────────────────────────────────────────────────────────────────────────────
|
|
22
|
+
* 根会话 ↔ 设备的绑定是根会话行上这一位住客的执行格 writer(device, D)(`execution-placement.ts` 头注)。准入链**不另读**:
|
|
23
|
+
* 读只有会话店的执行席 `seat.read(root)` 一只({@link DeviceEnrollment.readPlacement},装配点把会话店的执行席交进来 ——
|
|
24
|
+
* device 车道只在 SQL 后端 ⇒ 席恒在,缺 ⇒ 装配期响亮抛);{@link DeviceEnrollment.admitSession} 判的是调用方交进来的**那一读**,
|
|
25
|
+
* 于是提交意图「判已绑 / 未绑」与它记下的住客出自同一次行读。「这一格放在哪台设备上」只有一种读法 `boundDeviceOf`。
|
|
26
|
+
*
|
|
21
27
|
* ── 吊销在途语义(§8-R4)──────────────────────────────────────────────────────────────────────────
|
|
22
28
|
* `revoked` 是终态:①绑定的 session 后续提交 = `device.revoked`(admitSession 步 2,**先于** presence
|
|
23
29
|
* 判定);②吊销同事务把连接租约作废并把 `conn_generation` 推进一格 ⇒ 在途连接的每一次带世代谓词的写
|
|
24
30
|
* 都会影响 0 行,设备侧因此立刻失权(§4.6 步 2);③重新 enrollment = 新 deviceId,不复活旧行。
|
|
25
31
|
*/
|
|
26
|
-
import { type DeviceErrorCode, type DeviceOwner, type DeviceRejectCode, type DeviceEnrollTokenRow, type DeviceRow, type
|
|
32
|
+
import { type DeviceErrorCode, type DeviceOwner, type DeviceRejectCode, type DeviceEnrollTokenRow, type DeviceRow, type DeviceStore, type NewDeviceInput } from "./device-store.js";
|
|
33
|
+
import { type ExecutionDeviceCell, type ExecutionPlacementReading, type ExecutionPlacementSeat } from "./execution-placement.js";
|
|
34
|
+
import type { ExecutionLane } from "./execution-lane-caps.js";
|
|
35
|
+
import type { SessionFace } from "./session-incarnation.js";
|
|
27
36
|
/** typed 拒绝 —— 端点层只负责把它翻成 HTTP(status 已在体内,不许调用方另算)。 */
|
|
28
37
|
export interface DeviceRejection {
|
|
29
38
|
/** [ref]:含两个借用位(`limit.rate_exceeded` 429 / `draining` 503);enrollment 本文件只铸前者,
|
|
@@ -68,10 +77,34 @@ export interface EnrollDeviceValue {
|
|
|
68
77
|
}
|
|
69
78
|
export interface AdmitSessionInput {
|
|
70
79
|
rootSessionId: string;
|
|
80
|
+
/** 调用方读的**那一读**(会话店执行席 `seat.read(rootSessionId)` 的答案,经 {@link DeviceEnrollment.readPlacement})—— 准入链只判它,不另读。 */
|
|
81
|
+
placement: ExecutionPlacementReading | undefined;
|
|
71
82
|
requester: DeviceOwner;
|
|
72
83
|
/** 提交体携带的 deviceId(§4.3.2:仅根任务携;缺席 = 沿用绑定)。 */
|
|
73
84
|
requestedDeviceId?: string;
|
|
74
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* 首绑({@link DeviceEnrollment.bindPlacement})的结果:成立(`device` = 落下的格)、设备闭集的 typed 拒(异设备 `device.claim_conflict` /
|
|
88
|
+
* 设备 404 / 已吊销),或会话行那一侧的三种结局 —— 住客不是判过的那一位 / 行不在(`gone`)、写者在别处(`mirror`)、格在别的车道上(`tree_bound`)。
|
|
89
|
+
* 后三者不在设备闭集里(它们说的是会话,不是设备),由提交点(`http/execution-context.ts` 的 `commitExecutionContext`)各答各的码。
|
|
90
|
+
*/
|
|
91
|
+
export type BindPlacementOutcome = {
|
|
92
|
+
readonly ok: true;
|
|
93
|
+
readonly device: ExecutionDeviceCell;
|
|
94
|
+
} | {
|
|
95
|
+
readonly ok: false;
|
|
96
|
+
readonly reject: DeviceRejection;
|
|
97
|
+
} | {
|
|
98
|
+
readonly ok: false;
|
|
99
|
+
readonly placement: "gone";
|
|
100
|
+
} | {
|
|
101
|
+
readonly ok: false;
|
|
102
|
+
readonly placement: "mirror";
|
|
103
|
+
} | {
|
|
104
|
+
readonly ok: false;
|
|
105
|
+
readonly placement: "tree_bound";
|
|
106
|
+
readonly boundLane: ExecutionLane;
|
|
107
|
+
};
|
|
75
108
|
export interface AdmitSessionValue {
|
|
76
109
|
deviceId: string;
|
|
77
110
|
device: DeviceRow;
|
|
@@ -110,11 +143,15 @@ export interface DeviceEnrollment {
|
|
|
110
143
|
/** §7-T5 五件的第 ①②③ 件的**写入侧**:绑定复合身份 + TTL + 一次性摘要落库(明文一现)。 */
|
|
111
144
|
issueEnrollToken(input: IssueEnrollTokenRequest): Promise<DeviceOutcome<IssuedEnrollToken>>;
|
|
112
145
|
enroll(input: EnrollDeviceInput): Promise<DeviceOutcome<EnrollDeviceValue>>;
|
|
146
|
+
/** 绑定的唯一读:会话店执行席的 `read(root)`(一次行读:住客 + 格;行不在 ⇒ `undefined`;读故障抛,不吞成「未绑」)。 */
|
|
147
|
+
readPlacement(rootSessionId: string): Promise<ExecutionPlacementReading | undefined>;
|
|
148
|
+
/** 首绑(认领之后的初始放置写):按意图那一读的住客定址,设备店一只事务。 */
|
|
113
149
|
bindPlacement(input: {
|
|
114
150
|
rootSessionId: string;
|
|
151
|
+
occupant: SessionFace;
|
|
115
152
|
deviceId: string;
|
|
116
153
|
requester: DeviceOwner;
|
|
117
|
-
}): Promise<
|
|
154
|
+
}): Promise<BindPlacementOutcome>;
|
|
118
155
|
admitSession(input: AdmitSessionInput): Promise<DeviceOutcome<AdmitSessionValue>>;
|
|
119
156
|
revoke(input: {
|
|
120
157
|
deviceId: string;
|
|
@@ -125,6 +162,8 @@ export interface DeviceEnrollment {
|
|
|
125
162
|
}
|
|
126
163
|
export interface DeviceEnrollmentDeps {
|
|
127
164
|
store: DeviceStore;
|
|
165
|
+
/** 会话店的执行席(绑定的唯一载体与唯一读;装配点交会话店的 `executionPlacement`)。 */
|
|
166
|
+
seat: ExecutionPlacementSeat;
|
|
128
167
|
/** 缺席 = 不限速(端点车必须传;见文件头注 ⑤)。 */
|
|
129
168
|
rateLimiter?: DeviceEnrollRateLimiter;
|
|
130
169
|
/** 测试可注入确定性铸造;默认 `mintDeviceId()`。 */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DEVICE_ERROR_CODES, DEVICE_ERROR_STATUS, DEVICE_RATE_LIMIT_CODE, assertDeviceIdShape, assertDeviceOwnerShape, assertDevicePubkeyShape, assertEnrollTokenHashShape, assertRootSessionIdShape, hashEnrollToken, mintDeviceId, mintEnrollToken, } from "./device-store.js";
|
|
2
|
+
import { boundDeviceOf } from "./execution-placement.js";
|
|
2
3
|
export const DEFAULT_ENROLL_TOKEN_TTL_SEC = 900;
|
|
3
4
|
export function buildDeviceRejection(errorCode, message) {
|
|
4
5
|
return { code: errorCode, status: DEVICE_ERROR_STATUS[errorCode], message };
|
|
@@ -13,7 +14,7 @@ function rejectNotFound() {
|
|
|
13
14
|
return reject(DEVICE_ERROR_CODES.NOT_FOUND, "device not found");
|
|
14
15
|
}
|
|
15
16
|
export function createDeviceEnrollment(deps) {
|
|
16
|
-
const { store } = deps;
|
|
17
|
+
const { store, seat } = deps;
|
|
17
18
|
const mintId = deps.mintId ?? mintDeviceId;
|
|
18
19
|
async function rateGate(key) {
|
|
19
20
|
if (!deps.rateLimiter)
|
|
@@ -87,21 +88,35 @@ export function createDeviceEnrollment(deps) {
|
|
|
87
88
|
return rejectEnrollment();
|
|
88
89
|
}
|
|
89
90
|
}
|
|
91
|
+
async function readPlacement(rootSessionId) {
|
|
92
|
+
assertRootSessionIdShape(rootSessionId);
|
|
93
|
+
return seat.read(rootSessionId);
|
|
94
|
+
}
|
|
90
95
|
async function bindPlacement(input) {
|
|
91
96
|
assertRootSessionIdShape(input.rootSessionId);
|
|
92
97
|
assertDeviceIdShape(input.deviceId);
|
|
93
98
|
assertDeviceOwnerShape(input.requester);
|
|
94
|
-
const result = await store.
|
|
99
|
+
const result = await store.placeDeviceExecution({ root: input.rootSessionId, occupant: input.occupant, deviceId: input.deviceId, owner: input.requester });
|
|
95
100
|
switch (result.outcome) {
|
|
96
101
|
case "bound":
|
|
97
|
-
case "
|
|
98
|
-
return { ok: true,
|
|
99
|
-
case "
|
|
102
|
+
case "same":
|
|
103
|
+
return { ok: true, device: result.device };
|
|
104
|
+
case "device_conflict":
|
|
100
105
|
return reject(DEVICE_ERROR_CODES.CLAIM_CONFLICT, "this session is already bound to a different device");
|
|
101
106
|
case "device_not_found":
|
|
102
107
|
return rejectNotFound();
|
|
103
108
|
case "device_revoked":
|
|
104
109
|
return reject(DEVICE_ERROR_CODES.REVOKED, "device has been revoked");
|
|
110
|
+
case "gone":
|
|
111
|
+
return { ok: false, placement: "gone" };
|
|
112
|
+
case "mirror":
|
|
113
|
+
return { ok: false, placement: "mirror" };
|
|
114
|
+
case "tree_bound":
|
|
115
|
+
return { ok: false, placement: "tree_bound", boundLane: result.boundLane };
|
|
116
|
+
default: {
|
|
117
|
+
const unhandled = result;
|
|
118
|
+
throw new Error(`bindPlacement: unknown store outcome ${JSON.stringify(unhandled)}`);
|
|
119
|
+
}
|
|
105
120
|
}
|
|
106
121
|
}
|
|
107
122
|
async function admitSession(input) {
|
|
@@ -109,22 +124,22 @@ export function createDeviceEnrollment(deps) {
|
|
|
109
124
|
assertDeviceOwnerShape(input.requester);
|
|
110
125
|
if (input.requestedDeviceId !== undefined)
|
|
111
126
|
assertDeviceIdShape(input.requestedDeviceId);
|
|
112
|
-
const
|
|
113
|
-
if (!
|
|
127
|
+
const bound = input.placement === undefined ? undefined : boundDeviceOf(input.placement.cell);
|
|
128
|
+
if (!bound)
|
|
114
129
|
return reject(DEVICE_ERROR_CODES.NOT_BOUND, "this session has no device binding");
|
|
115
|
-
if (
|
|
130
|
+
if (bound.owner.tenant !== input.requester.tenant || bound.owner.subject !== input.requester.subject)
|
|
116
131
|
return rejectNotFound();
|
|
117
|
-
if (input.requestedDeviceId !== undefined && input.requestedDeviceId !==
|
|
132
|
+
if (input.requestedDeviceId !== undefined && input.requestedDeviceId !== bound.id) {
|
|
118
133
|
return reject(DEVICE_ERROR_CODES.IDENTITY_MISMATCH, "the requested device is not the one bound to this session");
|
|
119
134
|
}
|
|
120
|
-
const view = await store.readDeviceForAdmission(
|
|
135
|
+
const view = await store.readDeviceForAdmission(bound.id, input.requester);
|
|
121
136
|
if (!view)
|
|
122
137
|
return rejectNotFound();
|
|
123
138
|
if (view.row.status === "revoked")
|
|
124
139
|
return reject(DEVICE_ERROR_CODES.REVOKED, "device has been revoked");
|
|
125
140
|
if (!view.online)
|
|
126
141
|
return reject(DEVICE_ERROR_CODES.OFFLINE, "device is not connected");
|
|
127
|
-
return { ok: true, value: { deviceId:
|
|
142
|
+
return { ok: true, value: { deviceId: bound.id, device: view.row, connGeneration: view.row.connGeneration } };
|
|
128
143
|
}
|
|
129
144
|
async function revoke(input) {
|
|
130
145
|
assertDeviceIdShape(input.deviceId);
|
|
@@ -138,7 +153,7 @@ export function createDeviceEnrollment(deps) {
|
|
|
138
153
|
return rejectNotFound();
|
|
139
154
|
}
|
|
140
155
|
}
|
|
141
|
-
return { issueEnrollToken, enroll, bindPlacement, admitSession, revoke };
|
|
156
|
+
return { issueEnrollToken, enroll, readPlacement, bindPlacement, admitSession, revoke };
|
|
142
157
|
}
|
|
143
158
|
export function createFixedWindowRateLimiter(opts) {
|
|
144
159
|
const now = opts.now ?? (() => Date.now());
|