@sema-agent/server 7.43.0 → 7.44.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/USAGE.md +18 -0
- package/dist/adoption/plan.js +31 -192
- package/dist/adoption/quiesce.js +3 -86
- package/dist/adoption/runner.js +3 -140
- package/dist/adoption/sql.js +0 -74
- package/dist/adoption/wire.js +0 -80
- package/dist/approval-ask-machine.js +0 -75
- package/dist/approval-card.js +0 -323
- package/dist/approval-deny-reasons.js +0 -42
- package/dist/approval-hmac.js +0 -35
- package/dist/approval-reconciler.js +8 -166
- package/dist/approval.js +4 -67
- package/dist/audit.js +1 -44
- package/dist/auth-bridge.js +4 -47
- package/dist/auth-keys.js +0 -23
- package/dist/bake-runner/main.js +4 -65
- package/dist/bake-runner/protocol.js +3 -58
- package/dist/bake-runner/runner.js +5 -91
- package/dist/bench/l8/artifact.js +2 -61
- package/dist/bench/l8/escape.js +0 -25
- package/dist/bench/l8/index.js +0 -14
- package/dist/bench/l8/probes.js +0 -60
- package/dist/bench/l8/run-probes.js +2 -45
- package/dist/bench/s1/arms.js +14 -189
- package/dist/bench/s1/live-deps.js +11 -253
- package/dist/bench/s1/oracle.js +1 -36
- package/dist/bench/s1/repair-oracle-adapter.js +0 -30
- package/dist/bench/s1/reviewer.js +0 -34
- package/dist/bench/s1/row.js +0 -62
- package/dist/bench/s1/run-firm.js +4 -70
- package/dist/bench/s1/runner-ctx.js +0 -40
- package/dist/bench/s1/tasks.js +0 -115
- package/dist/boot/adoption.js +0 -20
- package/dist/boot/budget-tracing.js +3 -55
- package/dist/boot/config-center.js +43 -551
- package/dist/boot/coordinators.js +1 -69
- package/dist/boot/crash-last.js +0 -18
- package/dist/boot/deferred-sandbox-path-env.js +3 -119
- package/dist/boot/execution-env.js +5 -171
- package/dist/boot/governance-seams.js +0 -92
- package/dist/boot/leader.js +0 -69
- package/dist/boot/limit-sync.js +0 -2
- package/dist/boot/memory-boundary.js +3 -91
- package/dist/boot/org-memory.js +1 -25
- package/dist/boot/parked-revive-gate.js +0 -150
- package/dist/boot/permission-rules-audit.js +1 -56
- package/dist/boot/reapers.js +15 -273
- package/dist/boot/resolve-spec.js +9 -768
- package/dist/boot/retention-lane.js +4 -87
- package/dist/boot/runner-deps.js +3 -297
- package/dist/boot/runtime-caps.js +0 -40
- package/dist/boot/session-faces.js +2 -133
- package/dist/boot/shutdown.js +9 -83
- package/dist/boot/side-query-lane.js +2 -137
- package/dist/boot/stores.js +15 -215
- package/dist/boot/task-list-lane.js +0 -18
- package/dist/boot/webfetch-summarize-lane.js +0 -47
- package/dist/boot/workflow-orchestration.js +3 -99
- package/dist/boot-reclaim.js +0 -20
- package/dist/bounded-session-map.js +0 -19
- package/dist/brain.js +2 -139
- package/dist/budget.js +9 -244
- package/dist/capabilities/builtin-tools.js +0 -3
- package/dist/capabilities/center-plugins.js +6 -51
- package/dist/capabilities/center-prompts.js +6 -71
- package/dist/capabilities/code-review-council.js +7 -40
- package/dist/capabilities/collab-workflows.js +1 -44
- package/dist/capabilities/hands-lane.js +0 -65
- package/dist/capabilities/memory-notice.js +0 -70
- package/dist/capabilities/prompt.js +0 -14
- package/dist/capabilities/prompts/code-review.js +0 -14
- package/dist/capabilities/prompts/identity.js +0 -6
- package/dist/capabilities/prompts/team.js +0 -4
- package/dist/capabilities/repo-tools.js +0 -34
- package/dist/capabilities/sandbox-file-send.js +3 -92
- package/dist/capabilities/scenarios.d.ts +0 -1
- package/dist/capabilities/scenarios.js +18 -279
- package/dist/capabilities/select-environment-tool.js +0 -32
- package/dist/capabilities/send-user-file-tool.js +2 -66
- package/dist/capabilities/skills.d.ts +1 -2
- package/dist/capabilities/skills.js +3 -21
- package/dist/capabilities/team.d.ts +3 -11
- package/dist/capabilities/team.js +3 -51
- package/dist/capabilities/tool-defer.js +0 -3
- package/dist/config-center/apply-effective.js +15 -330
- package/dist/config-center/apply-ledger.js +5 -38
- package/dist/config-center/facade.js +0 -41
- package/dist/config-center/hot-keys-registry.js +0 -20
- package/dist/config-center/http-client.js +2 -125
- package/dist/config-center/mcp-revocation.js +2 -34
- package/dist/config-center/read-face.js +0 -59
- package/dist/config-center/restart-signal.js +1 -85
- package/dist/config-center/skills-mcp.d.ts +1 -1
- package/dist/config-center/skills-mcp.js +9 -76
- package/dist/config-center/stage-limits.js +8 -35
- package/dist/config-invariants.js +0 -16
- package/dist/config-lkg.js +0 -42
- package/dist/config-provider.js +3 -186
- package/dist/config-types.js +0 -5
- package/dist/config.js +107 -1145
- package/dist/degenerate-instrument.js +3 -67
- package/dist/deployment-governance.js +0 -124
- package/dist/digest-form.js +0 -12
- package/dist/elicitation.js +3 -86
- package/dist/env-facts.js +7 -75
- package/dist/fleet/fleet-bus.js +34 -507
- package/dist/fleet/fleet-reconciler.js +9 -149
- package/dist/fleet/fleet-terminal-window.js +10 -178
- package/dist/fleet/subagent-tail-bus.js +3 -72
- package/dist/fleet-client.js +10 -70
- package/dist/fleet-lease.js +5 -79
- package/dist/git-api-kind.js +0 -3
- package/dist/governance-ask-marks.js +2 -78
- package/dist/hooks/branch-transcript.js +0 -74
- package/dist/hooks/cc-agent-hook-prompt.js +0 -29
- package/dist/hooks/cc-stop-prompt.js +1 -46
- package/dist/hooks/hook-llm.js +1 -53
- package/dist/hooks/hook-runner.js +20 -414
- package/dist/http/active-run-conflict.js +4 -129
- package/dist/http/cursor-fingerprint.d.ts +5 -0
- package/dist/http/cursor-fingerprint.js +5 -0
- package/dist/http/idempotency.js +0 -37
- package/dist/http/principal-gate.js +3 -40
- package/dist/http/route-ctx.js +0 -9
- package/dist/http/routes/a2a-serve.js +7 -319
- package/dist/http/routes/admin-config-refresh.js +0 -4
- package/dist/http/routes/admin-drain.js +0 -10
- package/dist/http/routes/adoption.js +1 -29
- package/dist/http/routes/agents-roster.js +1 -47
- package/dist/http/routes/approvals-assistant.js +32 -395
- package/dist/http/routes/attachments.js +4 -22
- package/dist/http/routes/capabilities.js +3 -420
- package/dist/http/routes/diagnostics.js +1 -81
- package/dist/http/routes/fleet.js +9 -185
- package/dist/http/routes/images.js +14 -239
- package/dist/http/routes/leader.js +0 -13
- package/dist/http/routes/memory-bundle.js +1 -61
- package/dist/http/routes/memory-policy.js +9 -99
- package/dist/http/routes/notify-wake.js +3 -37
- package/dist/http/routes/observability.js +2 -19
- package/dist/http/routes/retention-ops.js +2 -34
- package/dist/http/routes/rules.js +1 -93
- package/dist/http/routes/runs.js +64 -873
- package/dist/http/routes/session-sync.js +19 -258
- package/dist/http/routes/sessions-list.js +17 -43
- package/dist/http/routes/sessions.js +34 -226
- package/dist/http/routes/shared-memory.js +5 -36
- package/dist/http/routes/side-query.js +1 -87
- package/dist/http/routes/tasks.js +52 -722
- package/dist/http/routes/trace-usage.js +32 -195
- package/dist/http/routes/workflows.js +19 -195
- package/dist/http/run-meta.js +0 -6
- package/dist/http/send.js +0 -32
- package/dist/http/server.js +92 -1597
- package/dist/http/sse-lifecycle.js +2 -13
- package/dist/http/sse-log.js +3 -48
- package/dist/http/tar.js +5 -21
- package/dist/http/verify-rounds.js +0 -5
- package/dist/http/wire-gate.js +0 -9
- package/dist/http/workspace-content.js +0 -10
- package/dist/images/bake-validate.js +1 -70
- package/dist/images/manifest.js +1 -6
- package/dist/index.js +0 -21
- package/dist/key-resolver.js +2 -17
- package/dist/leader/diffout.js +1 -20
- package/dist/leader/diffup.js +0 -47
- package/dist/leader/endpoint.js +2 -57
- package/dist/leader/fanout.js +3 -45
- package/dist/leader/grader-env-factory.js +3 -72
- package/dist/leader/leader.js +5 -156
- package/dist/leader/merge.js +8 -115
- package/dist/leader/planner.js +3 -54
- package/dist/leader/repair-oracle.js +1 -60
- package/dist/leader/repair-wire.js +2 -79
- package/dist/leader/wire.js +8 -307
- package/dist/lsp/e2b-bridge.js +4 -64
- package/dist/lsp/e2b-manager.js +6 -94
- package/dist/lsp/lsp-frames.js +0 -12
- package/dist/lsp/manager.js +4 -96
- package/dist/lsp/ws-transport.js +5 -55
- package/dist/lsp-evict.js +1 -15
- package/dist/main.js +57 -765
- package/dist/memory-bundle-engine.js +0 -55
- package/dist/memory-export.js +0 -4
- package/dist/memory-posture.js +1 -15
- package/dist/memory-scope.js +11 -148
- package/dist/memory-sync-client.js +2 -44
- package/dist/memory-sync.js +1 -80
- package/dist/model-select.js +3 -80
- package/dist/observability/cost-quota.js +1 -17
- package/dist/observability/cost-taxonomy.js +0 -34
- package/dist/observability/fail-open.js +7 -86
- package/dist/observability/logger.js +0 -6
- package/dist/observability/metrics.js +0 -94
- package/dist/observability/otel-exporter.js +3 -13
- package/dist/observability/principal-context.js +0 -9
- package/dist/observability/prompt-manifest.js +1 -37
- package/dist/observability/rate-limit.js +0 -4
- package/dist/observability/secret-env-scrub.js +2 -56
- package/dist/observability/tool-trace.js +1 -70
- package/dist/orchestration/hardened-vm-runner.js +4 -118
- package/dist/orchestration/hardened-vm-worker-runner.js +1 -26
- package/dist/orchestration/hardened-vm-worker.js +0 -27
- package/dist/orchestration/subagent-steer.js +1 -45
- package/dist/orchestration/workflow-agent-steer.js +1 -80
- package/dist/orchestration/workflow-completion-inbox.js +32 -285
- package/dist/orchestration/workflow-notify-journal.js +16 -259
- package/dist/org-memory-admission.js +3 -47
- package/dist/parent-watch.js +2 -48
- package/dist/parked-decide.js +1 -109
- package/dist/per-task-image.js +0 -57
- package/dist/plan-cache-probe.js +3 -27
- package/dist/plugins/adoption-log-sql.js +2 -119
- package/dist/plugins/approval-ask-store-memory.js +3 -38
- package/dist/plugins/approval-ask-store-sql.js +6 -188
- package/dist/plugins/approval-exemption-store.js +2 -28
- package/dist/plugins/background-agent-store-sql.js +4 -105
- package/dist/plugins/background-shell-support.js +14 -122
- package/dist/plugins/blob-backend.js +6 -169
- package/dist/plugins/breaker-state-sql.js +8 -46
- package/dist/plugins/caching-session-store.js +4 -106
- package/dist/plugins/checkpoint-store-sql.js +18 -505
- package/dist/plugins/e2b-orphan-reclaim.js +0 -45
- package/dist/plugins/file-outcome-sink.js +0 -9
- package/dist/plugins/file-resume-anchor-store.js +4 -43
- package/dist/plugins/file-run-store.js +26 -364
- package/dist/plugins/file-snapshot-store-sql.js +10 -181
- package/dist/plugins/fork-routing-session-store.js +8 -111
- package/dist/plugins/host-platform.js +2 -91
- package/dist/plugins/image-bake-store-sql.js +7 -250
- package/dist/plugins/image-index-sql.js +4 -123
- package/dist/plugins/k8s-bg-scripts.js +4 -88
- package/dist/plugins/k8s-exec-protocol.js +0 -41
- package/dist/plugins/leader-run-store-sql.js +0 -101
- package/dist/plugins/local-checkpoint-store.js +8 -128
- package/dist/plugins/local-session-store.js +34 -296
- package/dist/plugins/local-task-attachment-store.js +2 -16
- package/dist/plugins/mailbox-store-sql.js +8 -65
- package/dist/plugins/memory-embedder-fingerprint.js +5 -166
- package/dist/plugins/memory-embedder.js +4 -70
- package/dist/plugins/memory-engine-pg.js +6 -170
- package/dist/plugins/memory-engine-tidb.js +7 -155
- package/dist/plugins/memory-engine-vector-util.js +0 -10
- package/dist/plugins/memory-key-guards.js +0 -34
- package/dist/plugins/memory-origin-law.js +0 -187
- package/dist/plugins/memory-resume-anchor-store.js +0 -17
- package/dist/plugins/memory-run-store.js +12 -89
- package/dist/plugins/memory-session-policy-store.js +0 -17
- package/dist/plugins/memory-sync-store-pg.js +4 -49
- package/dist/plugins/memory-sync-store-tidb.js +3 -35
- package/dist/plugins/outcome-ledger-sql.js +3 -97
- package/dist/plugins/permission-rule-store-file.js +5 -133
- package/dist/plugins/permission-rule-store-sql.d.ts +3 -0
- package/dist/plugins/permission-rule-store-sql.js +50 -307
- package/dist/plugins/pg-cost-quota.js +0 -7
- package/dist/plugins/pg-pool.js +0 -92
- package/dist/plugins/pg-rate-limiter.js +2 -13
- package/dist/plugins/pg-safe-json.js +4 -40
- package/dist/plugins/pg-session-storage.js +25 -189
- package/dist/plugins/posix-shell-fs.js +1 -31
- package/dist/plugins/remote-env-adb.js +12 -101
- package/dist/plugins/remote-env-e2b.js +40 -371
- package/dist/plugins/remote-env-file-error.js +0 -37
- package/dist/plugins/remote-env-host.js +63 -483
- package/dist/plugins/remote-env-k8s.js +32 -326
- package/dist/plugins/remote-env-local-docker.js +24 -157
- package/dist/plugins/remote-env-ssh.js +20 -128
- package/dist/plugins/remote-scratchpad.js +2 -32
- package/dist/plugins/remote-shell.js +1 -32
- package/dist/plugins/resume-anchor-store-sql.js +0 -11
- package/dist/plugins/retention-lane-store-sql.js +0 -108
- package/dist/plugins/retention-store-sql.js +4 -383
- package/dist/plugins/roster-store-sql.js +0 -55
- package/dist/plugins/run-store-sql.js +14 -251
- package/dist/plugins/s3-presign.js +2 -49
- package/dist/plugins/scheduler-support.js +3 -80
- package/dist/plugins/send-file-ledger.js +4 -53
- package/dist/plugins/send-user-file.js +4 -94
- package/dist/plugins/session-placement.js +1 -89
- package/dist/plugins/session-policy-store-sql.js +3 -81
- package/dist/plugins/session-store.js +0 -57
- package/dist/plugins/shared-memory-store-sql.js +4 -167
- package/dist/plugins/sql-driver.js +0 -17
- package/dist/plugins/sql-errors.js +0 -7
- package/dist/plugins/sql-escape.js +0 -8
- package/dist/plugins/sql-row-helpers.js +0 -25
- package/dist/plugins/store-backend.js +42 -222
- package/dist/plugins/store-contracts.js +2 -46
- package/dist/plugins/task-attachment-store.js +3 -49
- package/dist/plugins/task-list-store-sql.js +0 -79
- package/dist/plugins/tidb-cost-quota.js +1 -4
- package/dist/plugins/tidb-pool.js +1 -207
- package/dist/plugins/tidb-rate-limiter.js +3 -9
- package/dist/plugins/tidb-session-storage.js +4 -70
- package/dist/plugins/tidb-session-store.js +19 -341
- package/dist/plugins/tool-result-store-sql.js +4 -179
- package/dist/plugins/usage-window-store-sql.js +0 -8
- package/dist/plugins/web-search.js +10 -132
- package/dist/plugins/workflow-journal-store-sql.js +2 -58
- package/dist/plugins/workflow-run-store-sql.js +6 -91
- package/dist/plugins/worktree-isolation.js +6 -126
- package/dist/plugins/write-behind-counter.js +16 -75
- package/dist/principal-jwt.js +5 -60
- package/dist/project-memory.js +15 -146
- package/dist/prompts-domain-validate.js +1 -51
- package/dist/question.js +2 -111
- package/dist/resource-suspend.js +0 -18
- package/dist/router/route-orchestration.js +0 -77
- package/dist/rules-consent.d.ts +44 -5
- package/dist/rules-consent.js +75 -215
- package/dist/run-local.js +14 -381
- package/dist/runs.js +29 -617
- package/dist/runtime-caps-resolver.js +6 -132
- package/dist/runtime-governance.js +1 -232
- package/dist/sandbox-pkg-source.js +0 -37
- package/dist/sealed-key.js +3 -68
- package/dist/security.js +6 -291
- package/dist/session-leaf-bus.js +0 -32
- package/dist/session-sync-content.js +1 -69
- package/dist/session-sync-kernel.js +3 -60
- package/dist/session-sync.js +3 -66
- package/dist/session-titler.js +7 -41
- package/dist/session-watch.js +9 -73
- package/dist/shared-memory-scope-authorizer.js +0 -18
- package/dist/sighup-idle.js +1 -12
- package/dist/spec-fields.js +4 -143
- package/dist/store-live-probe.js +3 -49
- package/dist/task-a2a.js +1 -126
- package/dist/task-cwd.js +1 -103
- package/dist/task-mcp.js +1 -89
- package/dist/task-settings.js +10 -300
- package/dist/task-workflow.js +8 -75
- package/dist/tool-approval.d.ts +28 -1
- package/dist/tool-approval.js +70 -1430
- package/dist/trace/artifacts.js +5 -20
- package/dist/trace/engine-notice-wire.js +6 -138
- package/dist/trace/ledger-sink.js +7 -96
- package/dist/trace/project.js +4 -448
- package/dist/trace/redact.js +9 -77
- package/dist/turn-activity.js +1 -27
- package/dist/usage-analytics.js +4 -34
- package/dist/wall-clock-jump-guard.js +1 -68
- package/package.json +3 -3
- package/dist/capabilities/scenario-alias.d.ts +0 -27
- package/dist/capabilities/scenario-alias.js +0 -61
package/dist/config-provider.js
CHANGED
|
@@ -1,40 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ConfigProvider — the dual-mode seam over WHERE the effective config comes from (see
|
|
3
|
-
* sema-registry docs/DUAL-MODE-DESIGN.md §4).
|
|
4
|
-
*
|
|
5
|
-
* The service consumes the config-center through EXACTLY two transport calls — `fetchEffective` (pull the
|
|
6
|
-
* effective config, ETag-conditional) and `fetchSkillContent` (lazy-pull one skill body by content hash).
|
|
7
|
-
* Everything downstream (applyEffective / applyRuntimeGates / resolveMcpServers / mcpForScenario / the
|
|
8
|
-
* skill overlay) is transport-agnostic: it operates on the returned `EffectiveConfig` / skill string.
|
|
9
|
-
*
|
|
10
|
-
* STATUS — FULLY provider-routed (提示词装配协议 §9.5-1/-3): boot AND the 60s refresh loop both pull
|
|
11
|
-
* through `configProvider.fetchEffective` (main.ts), so `CONFIG_PROVIDER=local` gets the same ongoing
|
|
12
|
-
* poll as the fleet path — a config.d edit lands within one poll (the local etag is the store's raws
|
|
13
|
-
* hash). The caller runs a whole-candidate gate over `domainErrors` (§9.5-5): on refresh an invalid
|
|
14
|
-
* domain rejects the candidate and the last-known-good keeps serving; boot stays tolerant per-domain
|
|
15
|
-
* (no LKG exists yet).
|
|
16
|
-
*
|
|
17
|
-
* This module factors those two calls behind a `ConfigProvider` interface with two backends:
|
|
18
|
-
*
|
|
19
|
-
* - {@link RemoteConfigProvider} — the existing behaviour. DELEGATES verbatim to the exported
|
|
20
|
-
* `facade.fetchEffective` / `facade.fetchSkillContent` (HTTP + Bearer + ETag + hash
|
|
21
|
-
* verify). No HTTP is reimplemented here; this is a thin wrapper that binds baseUrl/token/worker.
|
|
22
|
-
*
|
|
23
|
-
* - {@link LocalConfigProvider} — reads the SAME config contract from the local filesystem via
|
|
24
|
-
* `@sema-agent/registry-core/node` `FileConfigStore` (`.env` + `config.d/<domain>.json` → an
|
|
25
|
-
* `EffectiveConfig` through the SAME resolver the center uses). The registry `EffectiveConfig`
|
|
26
|
-
* is a structural SUPERSET of the service-local `EffectiveConfig` the consumers expect, so we map
|
|
27
|
-
* it down to EXACTLY that shape (see `mapToServiceEffective`). Skills are stored locally WITH their
|
|
28
|
-
* bodies (the local store doesn't split content into a manifest), so `fetchSkillContent` is a
|
|
29
|
-
* content-addressed lookup over the local skills domain (absent → undefined, mirroring a remote 404).
|
|
30
|
-
*
|
|
31
|
-
* SECRET BOUNDARY (unchanged in both modes): the config plane carries only env-NAME refs — `apiKeyEnv`,
|
|
32
|
-
* `envRefs`/`headerRefs`, `tokenEnv`. The real secret VALUE is never stored in config.d/<domain>.json and
|
|
33
|
-
* never read by this module; it is resolved from `process.env` downstream (config-center/facade.ts
|
|
34
|
-
* `applyEffective`/`resolveMcpServers`). The local store is symmetric with the remote center on this: it
|
|
35
|
-
* ships NAMEs only. (Unit test asserts the local path resolves env-NAME→value via process.env and never
|
|
36
|
-
* persists a value.)
|
|
37
|
-
*/
|
|
38
1
|
import { createHmac, randomBytes } from "node:crypto";
|
|
39
2
|
import { FileConfigStore } from "@sema-agent/registry-core/node";
|
|
40
3
|
import { findSkillContent, skillContentHash, refIntegrityIssues, siblingResolver, } from "@sema-agent/registry-core";
|
|
@@ -42,35 +5,14 @@ import { redactSecrets } from "./trace/redact.js";
|
|
|
42
5
|
import { fetchEffective as remoteFetchEffective, fetchSkillContent as remoteFetchSkillContent, ConfigCenterHttpError, } from "./config-center/facade.js";
|
|
43
6
|
import { createLogger } from "./observability/logger.js";
|
|
44
7
|
const logger = createLogger();
|
|
45
|
-
/**
|
|
46
|
-
* domainError strings must not echo raw config operands (self-review, information-surface lens):
|
|
47
|
-
* ref-integrity messages quote the referenced value verbatim, and tolerant-read parse failures carry
|
|
48
|
-
* zod/JSON.parse fragments of the file text — a controlled value pasted into the wrong slot (say, a
|
|
49
|
-
* credential in a model-ref position) would otherwise ride `config_candidate_rejected` /
|
|
50
|
-
* `config_domain_invalid` into the structured log stream. This runs at the producing boundary (the
|
|
51
|
-
* local provider is the only domainErrors producer): shared secret-shape redaction first, then every
|
|
52
|
-
* quoted operand becomes a short one-way fingerprint — keyed per process so the fingerprint is not a
|
|
53
|
-
* dictionary-comparable digest of the value, while equal operands still correlate within one log
|
|
54
|
-
* stream. The issue `path` stays clear; it is how the operator locates the entry.
|
|
55
|
-
*/
|
|
56
8
|
const OPERAND_FINGERPRINT_KEY = randomBytes(16);
|
|
57
9
|
function redactConfigError(text) {
|
|
58
10
|
return redactSecrets(text).replace(/"[^"]*"|'[^']*'/g, (m) => `"#${createHmac("sha256", OPERAND_FINGERPRINT_KEY).update(m.slice(1, -1)).digest("hex").slice(0, 8)}"`);
|
|
59
11
|
}
|
|
60
|
-
/** Sentinel returned by {@link raceBootFetch} when the boot pull outlived its budget — the caller
|
|
61
|
-
* starts serving on the env fallback and the SAME promise settles in the background (never cancelled). */
|
|
62
12
|
export const BOOT_FETCH_DEFERRED = Symbol("boot-fetch-deferred");
|
|
63
|
-
/**
|
|
64
|
-
* Race the boot config pull against a wall-clock budget (clay 2026-07-17: a black-holed center made
|
|
65
|
-
* the SYNCHRONOUS boot pull hang ~5.7s on the TOC lane — the "local server takes 5s to start" report).
|
|
66
|
-
* Inside the budget → the fetch result verbatim (the healthy-center fast path is unchanged, typically
|
|
67
|
-
* <300ms). Past it → {@link BOOT_FETCH_DEFERRED}; the fetch is NOT aborted — the caller chains a
|
|
68
|
-
* background continuation that triggers a refresh tick when it finally settles. The timer is unref'd
|
|
69
|
-
* (never holds the loop) and cleared as soon as the fetch wins.
|
|
70
|
-
*/
|
|
71
13
|
export function raceBootFetch(fetch, budgetMs) {
|
|
72
14
|
if (budgetMs <= 0)
|
|
73
|
-
return Promise.resolve(BOOT_FETCH_DEFERRED);
|
|
15
|
+
return Promise.resolve(BOOT_FETCH_DEFERRED);
|
|
74
16
|
let timer;
|
|
75
17
|
const budget = new Promise((res) => {
|
|
76
18
|
timer = setTimeout(() => res(BOOT_FETCH_DEFERRED), budgetMs);
|
|
@@ -78,11 +20,6 @@ export function raceBootFetch(fetch, budgetMs) {
|
|
|
78
20
|
});
|
|
79
21
|
return Promise.race([fetch.finally(() => clearTimeout(timer)), budget]);
|
|
80
22
|
}
|
|
81
|
-
/**
|
|
82
|
-
* RemoteConfigProvider — DELEGATES to the exported config-center HTTP functions. No HTTP is reimplemented;
|
|
83
|
-
* baseUrl/token/worker are bound once and passed through. The two delegate fns are injectable (defaulting
|
|
84
|
-
* to the real config-center exports) so a unit test can assert delegation without module-mocking.
|
|
85
|
-
*/
|
|
86
23
|
export class RemoteConfigProvider {
|
|
87
24
|
cc;
|
|
88
25
|
deps;
|
|
@@ -93,22 +30,13 @@ export class RemoteConfigProvider {
|
|
|
93
30
|
}
|
|
94
31
|
async fetchEffective(etag) {
|
|
95
32
|
const fn = this.deps.fetchEffective ?? remoteFetchEffective;
|
|
96
|
-
// 5th arg = worker scope; transport (fetchImpl) stays the config-center's default.
|
|
97
33
|
const r = await fn(this.cc.baseUrl, this.cc.token, etag, undefined, this.cc.worker);
|
|
98
34
|
if (r === null || r.domainErrors === undefined)
|
|
99
35
|
return r;
|
|
100
|
-
// [2281] 裁B:远程腿从此也产 domainErrors(http-client 消费端校验)。与本地腿同一条产出边界纪律:
|
|
101
|
-
// error 文本先过 redactConfigError(zod 错误会回声违规值——operand 指纹化,防受控值经
|
|
102
|
-
// config_candidate_rejected/config_domain_invalid 进结构化日志流)。
|
|
103
36
|
return { ...r, domainErrors: r.domainErrors.map((de) => ({ domain: de.domain, error: redactConfigError(de.error) })) };
|
|
104
37
|
}
|
|
105
38
|
async fetchSkillContent(contentHash) {
|
|
106
39
|
const fn = this.deps.fetchSkillContent ?? remoteFetchSkillContent;
|
|
107
|
-
// Honor the ConfigProvider contract symmetrically with the local backend: an UNKNOWN hash → undefined
|
|
108
|
-
// (caller keeps its baseline), and ONLY a hard error (non-404 HTTP / hash mismatch) throws. The remote
|
|
109
|
-
// transport throws a ConfigCenterHttpError(status=404) for an unknown hash; we translate that single
|
|
110
|
-
// case to undefined and re-throw everything else, so both backends return the same thing for the same
|
|
111
|
-
// "unknown hash" input (substitutability — the whole point of this seam).
|
|
112
40
|
try {
|
|
113
41
|
return await fn(this.cc.baseUrl, this.cc.token, contentHash);
|
|
114
42
|
}
|
|
@@ -119,20 +47,10 @@ export class RemoteConfigProvider {
|
|
|
119
47
|
}
|
|
120
48
|
}
|
|
121
49
|
}
|
|
122
|
-
/**
|
|
123
|
-
* LocalConfigProvider — reads the SAME config contract from disk via `FileConfigStore`. `getEffective()`
|
|
124
|
-
* returns the registry `EffectiveConfig` (all domains, defaults filled); `getVersion()` returns a
|
|
125
|
-
* stable change-detector. We map that down to the service-local `EffectiveConfig` shape and surface the
|
|
126
|
-
* version as the etag (so the caller's "skip re-apply if etag unchanged" works locally too).
|
|
127
|
-
*/
|
|
128
50
|
export class LocalConfigProvider {
|
|
129
51
|
kind = "local";
|
|
130
52
|
store;
|
|
131
|
-
/** [875]b 可观测性:config_loaded 日志要能回答「到底读的哪个目录」——复验实录:只设 LOCAL_DATA_ROOT 时
|
|
132
|
-
* config.d 静默读不到且 0 模型无告警(CONFIG_LOCAL_DIR 才是本 lane 的选目录旋钮)。 */
|
|
133
53
|
root;
|
|
134
|
-
/** 注入 store(测试缝)时保持其自带行为;自建时 fetchEffective 每次按调用铸新 store 挂 warning 座
|
|
135
|
-
* (见 fetchEffective 头注)。 */
|
|
136
54
|
#injectedStore;
|
|
137
55
|
constructor(root, store) {
|
|
138
56
|
this.root = root;
|
|
@@ -140,29 +58,12 @@ export class LocalConfigProvider {
|
|
|
140
58
|
this.store = store ?? new FileConfigStore(root);
|
|
141
59
|
}
|
|
142
60
|
async fetchEffective(etag) {
|
|
143
|
-
// SINGLE store read: derive BOTH the etag AND the mapped payload from ONE atomic raws snapshot. Reading
|
|
144
|
-
// getVersion() and getEffective() separately would pair an etag from snapshot A with a payload from
|
|
145
|
-
// snapshot B if config.d is rewritten between the two awaits — a consumer could then cache etag=A bound
|
|
146
|
-
// to payload-B and, once files settle back to A, skip re-applying the now-correct config (304-skip
|
|
147
|
-
// staleness). `eff.version` IS the authoritative version of THIS payload (file-store getEffective()
|
|
148
|
-
// invariant), so it is the only correct source for the etag. Cost: we compute `eff` even on an
|
|
149
|
-
// unchanged poll, but that preserves snapshot consistency — see finding #3.
|
|
150
|
-
// [898] tolerant read(0.10.12):catalog 域坏文件 ⇒ 该域 default+domainErrors 单列(不再连坐整包回落
|
|
151
|
-
// env);gate 域坏文件仍 throw(走 caller 的整包 catch)。坏文件文本 hash 参与 version(坏≠absent、
|
|
152
|
-
// 坏→修好均 bump),304-skip 纪律不漏拍——所以坏域场景下 etag 对比照旧安全。
|
|
153
|
-
// [3073]#204④:判形失败(schema 坏形/重名条目)走的是 buildEffective 的 `onWarning`(parse 层落
|
|
154
|
-
// default),不走 READ 层 throw——不接这个座,domainErrors 恒空,域被静默清空而排障 hint 只能谎报
|
|
155
|
-
// 「文件空」。warning 座是 store 构造级而 fetch 可能重叠(boot 超窗后台腿 vs 首拍 refresh),
|
|
156
|
-
// 共享缓冲会把别次快照的警告错记到本次结果(codex F2)——故自建形每次 fetch 铸新 store 配本地
|
|
157
|
-
// 收集器(FileConfigStore 无跨调用状态,按次构造零成本);注入 store(测试缝)保持其自带行为。
|
|
158
61
|
const parseWarnings = [];
|
|
159
62
|
const store = this.#injectedStore ??
|
|
160
63
|
new FileConfigStore(this.root, {
|
|
161
64
|
onWarning: (w) => {
|
|
162
65
|
if (w.kind === "domain-defaulted")
|
|
163
66
|
parseWarnings.push({ domain: w.domain, error: w.error instanceof Error ? w.error.message : String(w.error) });
|
|
164
|
-
// registry-core 0.19.0 响亮化三 kind(LANDING-7.38 接线件③):dropped/unread=operator 写了但没生效
|
|
165
|
-
// (与 defaulted 同级),carried=承运但键表方(stage-limits)才认——都入诊断面,禁静默丢。
|
|
166
67
|
else if (w.kind === "unknown-keys-dropped")
|
|
167
68
|
parseWarnings.push({ domain: w.domain, error: `unknown keys dropped by domain schema: ${w.keys.join(", ")}` });
|
|
168
69
|
else if (w.kind === "unknown-keys-carried")
|
|
@@ -174,46 +75,25 @@ export class LocalConfigProvider {
|
|
|
174
75
|
const { effective: eff, domainErrors } = await store.getEffective({ tolerant: true });
|
|
175
76
|
const tag = String(eff.version);
|
|
176
77
|
if (etag !== undefined && etag === tag)
|
|
177
|
-
return null;
|
|
178
|
-
// 提示词装配协议 §9.5-4 read-side cross-domain reference validation: dangling refs (a roster naming a
|
|
179
|
-
// model that isn't in the catalog, …) fold into domainErrors, so the caller's candidate gate rejects
|
|
180
|
-
// the tree whole on refresh (boot warns and proceeds — no LKG exists yet). Write-side zod is
|
|
181
|
-
// per-domain only and the center runs this check on its write path; the local lane never had it.
|
|
182
|
-
// The resolver gets THIS snapshot's domain values as `pending` (builder output is default-filled for
|
|
183
|
-
// every domain), so the check never re-reads config.d — the one-atomic-snapshot invariant above holds.
|
|
78
|
+
return null;
|
|
184
79
|
const refErrors = [];
|
|
185
80
|
const resolve = siblingResolver(store, eff);
|
|
186
81
|
for (const d of ["rosters", "workers", "models", "collab", "systems", "entitlement"]) {
|
|
187
82
|
const issues = await refIntegrityIssues(d, eff[d], resolve);
|
|
188
|
-
// path CLEAR (locates the entry) + message operand-fingerprinted (see redactConfigError).
|
|
189
83
|
if (issues.length > 0)
|
|
190
84
|
refErrors.push({ domain: d, error: issues.map((i) => `${i.path.join(".")}: ${redactConfigError(i.message)}`).join("; ") });
|
|
191
85
|
}
|
|
192
|
-
// parse 层判形失败与 READ 层坏文件同渠道:两者都是「坏域落 default」,候选门(§9.5-5)与排障 hint
|
|
193
|
-
// 需要同样看见——此前判形失败静默(domainErrors 空+域被清空),比坏文件更隐蔽。
|
|
194
86
|
const parseErrors = parseWarnings.map((w) => ({ domain: w.domain, error: redactConfigError(w.error) }));
|
|
195
87
|
const errors = [...domainErrors.map((de) => ({ domain: de.domain, error: redactConfigError(de.error) })), ...parseErrors, ...refErrors];
|
|
196
88
|
return { effective: mapToServiceEffective(eff, eff.version), etag: tag, ...(errors.length > 0 ? { domainErrors: errors } : {}) };
|
|
197
89
|
}
|
|
198
90
|
async fetchSkillContent(contentHash) {
|
|
199
|
-
// The local store keeps skill BODIES inline (no manifest split), so this is a content-addressed lookup
|
|
200
|
-
// over the skills domain. Absent hash → undefined (mirrors a remote 404 → caller keeps the baseline).
|
|
201
91
|
const skills = await this.store.getDomain("skills");
|
|
202
92
|
if (!skills)
|
|
203
93
|
return undefined;
|
|
204
94
|
return findSkillContent(skills, contentHash);
|
|
205
95
|
}
|
|
206
96
|
}
|
|
207
|
-
/**
|
|
208
|
-
* Map the registry `EffectiveConfig` (superset, all domains) → the service-local `EffectiveConfig`
|
|
209
|
-
* the consumers (`applyEffective`, `resolveMcpServers`, …) expect. The two are structurally compatible
|
|
210
|
-
* for every field the consumers read; this projection makes that explicit (and drops control-plane-only
|
|
211
|
-
* domains the service never consumes: rosters, systems, workers, hosts, integrations, access).
|
|
212
|
-
*
|
|
213
|
-
* Skills are mapped to the MANIFEST shape (name/description/scenarios/contentHash/enabled) — the same
|
|
214
|
-
* shape RemoteConfigProvider's `/effective` ships — so the lazy `fetchSkillContent`-by-hash path is
|
|
215
|
-
* identical in both modes. The local content hash is the `contentHash` the store already computed.
|
|
216
|
-
*/
|
|
217
97
|
export function mapToServiceEffective(eff, version) {
|
|
218
98
|
return {
|
|
219
99
|
version,
|
|
@@ -226,62 +106,33 @@ export function mapToServiceEffective(eff, version) {
|
|
|
226
106
|
api: m.api,
|
|
227
107
|
...(m.baseUrl !== undefined ? { baseUrl: m.baseUrl } : {}),
|
|
228
108
|
...(m.apiKeyEnv !== undefined ? { apiKeyEnv: m.apiKeyEnv } : {}),
|
|
229
|
-
// RL-1(P4 A0 发现,2026-08-02;autoCompactTokens/promptGuidance 同类病族):CLOSED 投影剥掉
|
|
230
|
-
// sealedApiKey 会让本地 lane 的 sealed 模型绕过 applyEffective 的毒丸臂(严格互斥纪律)⇒
|
|
231
|
-
// 静默烧网关共享 key——正是毒丸臂声称杜绝的事故。携带它,无 opener 时毒丸自然接管(fail-loud)。
|
|
232
109
|
...(m.sealedApiKey !== undefined ? { sealedApiKey: m.sealedApiKey } : {}),
|
|
233
|
-
// 同族连带:quotaWeight 被剥 ⇒ 本地 lane 配额倍率静默归 1(weight-at-burn 面失真)。
|
|
234
110
|
...(m.quotaWeight !== undefined ? { quotaWeight: m.quotaWeight } : {}),
|
|
235
111
|
tier: m.tier,
|
|
236
112
|
reasoning: m.reasoning,
|
|
237
113
|
vision: m.vision,
|
|
238
114
|
...(m.contextWindow !== undefined ? { contextWindow: m.contextWindow } : {}),
|
|
239
115
|
...(m.maxTokens !== undefined ? { maxTokens: m.maxTokens } : {}),
|
|
240
|
-
// codex F5 ([818]① 1M dual-window): an EXPLICIT `autoCompactTokens` must survive this CLOSED
|
|
241
|
-
// projection. [2373]B-6d:registry-core 0.13.0 已把它收进 ModelEntry schema(types.d.ts:157/212)
|
|
242
|
-
// ——旧注的「strip-mode 会在上游丢值」的 honest gap 已随那次 schema addition 关闭,结构读改类型直读。
|
|
243
116
|
...(typeof m.autoCompactTokens === "number" ? { autoCompactTokens: m.autoCompactTokens } : {}),
|
|
244
|
-
// A-067 C2-M1(F1a,本函数第 6 例同形丢字段):charsPerToken 远程腿 toModel 一直消费
|
|
245
|
-
// (apply-effective charsPerTokenOf 判形),本 CLOSED 投影此前剥掉 ⇒ 本地 lane 的 token
|
|
246
|
-
// 估算静默退回 env 默认/core 4。判形归 toModel 单点(此处只过境,不重判)。
|
|
247
117
|
...(typeof m.charsPerToken === "number" ? { charsPerToken: m.charsPerToken } : {}),
|
|
248
118
|
...(m.cost !== undefined ? { cost: m.cost } : {}),
|
|
249
119
|
...(m.extraBody !== undefined ? { extraBody: m.extraBody } : {}),
|
|
250
|
-
// registry-core 0.10.13 promptGuidance ([998]⑤c): the CLOSED projection must pass it through or
|
|
251
|
-
// the local lane silently drops the configured sentences (autoCompactTokens 同类病).
|
|
252
120
|
...(m.promptGuidance !== undefined ? { promptGuidance: m.promptGuidance } : {}),
|
|
253
121
|
enabled: m.enabled,
|
|
254
122
|
})),
|
|
255
123
|
roles: eff.models.roles ?? {},
|
|
256
|
-
|
|
257
|
-
// 本 mapper 是 CLOSED 投影——不直通则本地 lane 静默丢键(autoCompactTokens 同类病),applyEffective 的
|
|
258
|
-
// resolveDefaultModelName 第一优先级在本地 lane 永远点不亮。写面悬空 ref 由 registry-core superRefine
|
|
259
|
-
// fail-loud;存量/未经 schema 的路径仍由消费方 warn 降级(config-center/facade.ts resolveDefaultModelName)。
|
|
260
|
-
...(eff.models.default !== undefined ? { default: eff.models.default } : {}), // [2373]B-6c:0.13.0 类型直读(types.d.ts:641)
|
|
124
|
+
...(eff.models.default !== undefined ? { default: eff.models.default } : {}),
|
|
261
125
|
...(eff.models.atModelAllowlist !== undefined ? { atModelAllowlist: eff.models.atModelAllowlist } : {}),
|
|
262
|
-
// registry-core 0.9.0 档位组: verbatim passthrough — applyEffective's resolveActiveTiers reads
|
|
263
|
-
// these structurally off eff.models (the remote lane ships them JSON-verbatim; the local lane must too).
|
|
264
|
-
// [2373]B-6b:0.13.0 类型直读(EffectiveConfig.models 面已声明四键,宽铸删)。本地 lane 的
|
|
265
|
-
// eff 来自 FileConfigStore 原始 JSON(非 zod 输出),tierGroups 的 ZodDefault 恒在场性不适用——门保留。
|
|
266
126
|
...(eff.models.tierGroups !== undefined ? { tierGroups: eff.models.tierGroups } : {}),
|
|
267
127
|
...(eff.models.activeTierGroup !== undefined ? { activeTierGroup: eff.models.activeTierGroup } : {}),
|
|
268
128
|
},
|
|
269
|
-
// registry-core 0.7 DELETED the teams domain (BREAKING, no compat key) — the local lane ships an EMPTY
|
|
270
|
-
// teams face: applyEffective's teams branch no-ops and the team scenario falls back to the builtin
|
|
271
|
-
// TEAM_PERSONAS base (a permanent base, not a stopgap). Its successor is `collab` below.
|
|
272
129
|
teams: { teams: [] },
|
|
273
|
-
// collab domain: verbatim structural passthrough — FileConfigStore reads
|
|
274
|
-
// config.d/collab.json (PORTABLE_DOMAINS includes collab since 0.7) and applyEffective's
|
|
275
|
-
// projectCollabToTeams consumes the same shape on both lanes. Optional-chained against shape drift.
|
|
276
130
|
...(eff.collab?.templates?.length ? { collab: { templates: eff.collab.templates } } : {}),
|
|
277
131
|
skills: {
|
|
278
132
|
skills: (eff.skills.skills ?? []).map((s) => ({
|
|
279
133
|
name: s.name,
|
|
280
134
|
description: s.description,
|
|
281
135
|
scenarios: s.scenarios ?? [],
|
|
282
|
-
// The local store keeps the body inline; content-address it HERE so the manifest carries the same
|
|
283
|
-
// `sha256:<hex>` the remote /effective ships — and `fetchSkillContent` (findSkillContent) resolves
|
|
284
|
-
// the same hash back to the body. (skillContentHash is byte-identical to the center's hash.)
|
|
285
136
|
contentHash: skillContentHash(s.content),
|
|
286
137
|
enabled: s.enabled,
|
|
287
138
|
})),
|
|
@@ -293,8 +144,6 @@ export function mapToServiceEffective(eff, version) {
|
|
|
293
144
|
scenarios: s.scenarios ?? [],
|
|
294
145
|
enabled: s.enabled,
|
|
295
146
|
...(s.allowTools !== undefined ? { allowTools: s.allowTools } : {}),
|
|
296
|
-
// E23: carry the per-server inbound-elicitation opt-in (default OFF). Typed end-to-end since
|
|
297
|
-
// registry-core 0.1.34 added `McpServerSpec.elicitation?: boolean`.
|
|
298
147
|
...(s.elicitation !== undefined ? { elicitation: s.elicitation } : {}),
|
|
299
148
|
};
|
|
300
149
|
if (s.transport.kind === "stdio") {
|
|
@@ -319,22 +168,13 @@ export function mapToServiceEffective(eff, version) {
|
|
|
319
168
|
};
|
|
320
169
|
}),
|
|
321
170
|
},
|
|
322
|
-
// prompts 域投影(a 实现班车,[985]a §3/[1234]① 位):**catalog 轴打通 local lane**——catalog 是
|
|
323
|
-
// center 铸好的 immutable envelope(免 covering 解析,server 零解析义务红线 [1042]②b 不破),
|
|
324
|
-
// config.d/prompts.json 携带 `catalog` 即以 wire 双轴形(registry-core `EffectivePromptsWire`)下发,
|
|
325
|
-
// 与 remote lane 的 additive prompts key 同门(adoptCenterPrompts→validatePromptsDomain,core verify
|
|
326
|
-
// 全管线)。bindings(declaration 轴原料)仍不投影:covering 解析半场恒在 center,local lane 的
|
|
327
|
-
// declaration 轴维持不透传(那不是遗漏,是分工)。
|
|
328
171
|
...(eff.prompts?.catalog !== undefined
|
|
329
172
|
? { prompts: { schemaVersion: 1, catalog: eff.prompts.catalog } }
|
|
330
173
|
: {}),
|
|
331
174
|
scenarios: {
|
|
332
|
-
// ([1057] 注记保留:declaration 轴 remote lane only——covering 解析半场在 center(web),
|
|
333
|
-
// local FileConfigStore 只有 bindings 原文而 server 零解析义务([1042]②b 红线)。)
|
|
334
175
|
scenarios: (eff.scenarios.scenarios ?? []).map((sc) => ({
|
|
335
176
|
name: sc.name,
|
|
336
177
|
toolset: sc.toolset,
|
|
337
|
-
// ([1053] 0.10.15:ScenarioEntry.prompt 字段已删——scenario 级提示词走 center prompts binding)
|
|
338
178
|
enabled: sc.enabled,
|
|
339
179
|
})),
|
|
340
180
|
},
|
|
@@ -345,39 +185,16 @@ export function mapToServiceEffective(eff, version) {
|
|
|
345
185
|
...(eff.runtime.maxPrincipalCostUsd !== undefined ? { maxPrincipalCostUsd: eff.runtime.maxPrincipalCostUsd } : {}),
|
|
346
186
|
...(eff.runtime.costQuotaWindowSec !== undefined ? { costQuotaWindowSec: eff.runtime.costQuotaWindowSec } : {}),
|
|
347
187
|
},
|
|
348
|
-
// #322 批1(registry-core 0.19.0 第 17 域):`limits` 整包透传——本地腿的最后一米在此收口;漏了
|
|
349
|
-
// 这行,14 键在 local lane 整域消失、继续吃 env 基线(LANDING-7.38 接线件②的事故形)。
|
|
350
188
|
...(eff.limits !== undefined ? { limits: eff.limits } : {}),
|
|
351
|
-
// Governance trio (autonomy/commandPolicy/approvalRequire): moved OUT of runtime into the dedicated
|
|
352
|
-
// governance domain (registry-core 0.6, runtime double-write mirror removed in 0.7.1 — buildEffective
|
|
353
|
-
// still READ-lifts legacy raw runtime values into governance, so old on-disk config keeps working).
|
|
354
|
-
// Mapped to the service-local `governance` slot; applyEffective's gatesView consumes it with priority.
|
|
355
|
-
// The registry shapes are IDENTICAL to the service's Autonomy/CommandRule declarations (straight passthrough).
|
|
356
189
|
governance: {
|
|
357
190
|
...(eff.governance.autonomy !== undefined ? { autonomy: eff.governance.autonomy } : {}),
|
|
358
191
|
...(eff.governance.commandPolicy !== undefined ? { commandPolicy: eff.governance.commandPolicy } : {}),
|
|
359
192
|
...(eff.governance.approvalRequire !== undefined ? { approvalRequire: eff.governance.approvalRequire } : {}),
|
|
360
193
|
},
|
|
361
|
-
// NOTE: entitlement is NOT mapped — the ruling is that the local lane never carries it (by design;
|
|
362
|
-
// TOB governance concept) and the fleet scenario ruling rides center's caps view, not /effective.
|
|
363
194
|
};
|
|
364
195
|
}
|
|
365
|
-
/**
|
|
366
|
-
* Pick the backend off a CLOSED `provider` enum (`local` | `remote` | undefined): LOCAL when
|
|
367
|
-
* `CONFIG_PROVIDER=local`, OR when no config-center URL is configured (a lone box with config.d/ on disk
|
|
368
|
-
* and no control plane). REMOTE otherwise (a configured center URL, the default fleet posture). A
|
|
369
|
-
* `CONFIG_PROVIDER=remote` with no URL is a misconfiguration — we fall through to local rather than
|
|
370
|
-
* constructing a remote provider with no endpoint (the caller would have skipped the remote pull entirely
|
|
371
|
-
* under the old code path; local-with-empty-config.d degrades to env the same way). An UNRECOGNIZED value
|
|
372
|
-
* (typo / wrong case) is NOT treated as remote: it defaults to local (non-network) with a warn, so a
|
|
373
|
-
* fat-fingered knob can never silently source config from an unintended/stale network endpoint.
|
|
374
|
-
*/
|
|
375
196
|
export function createConfigProvider(input) {
|
|
376
197
|
const p = input.provider;
|
|
377
|
-
// Closed enum: only `local` | `remote` | undefined are valid. An unrecognized/typo'd value (`Local`,
|
|
378
|
-
// `LOCAL`, ` local`, garbage) must NOT silently fall through to the network source — pick the non-network
|
|
379
|
-
// safe default (local) and warn, so a misconfigured knob never sources config (incl. env-NAME refs that
|
|
380
|
-
// gate secret wiring) from a possibly-stale remote URL the operator didn't intend. See finding #4.
|
|
381
198
|
if (p !== undefined && p !== "local" && p !== "remote") {
|
|
382
199
|
logger.warn("config_provider_unrecognized", {
|
|
383
200
|
provider: p,
|
package/dist/config-types.js
CHANGED
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* #270 §4 —— 托管留存的**灰度档**闭集。`as const` 数组是词表的唯一真源(config 解析、能力位、审计行
|
|
3
|
-
* 的 `mode` 列共读它);两词之外的值在启动期响亮拒 —— 一个拼错的档位静默落回 `audit-only` 会让运维
|
|
4
|
-
* 以为在删、其实没删,而拼成别的方向就是反过来那件更坏的事。
|
|
5
|
-
*/
|
|
6
1
|
export const RETENTION_MODES = ["audit-only", "enforce"];
|
|
7
2
|
//# sourceMappingURL=config-types.js.map
|