@sema-agent/settings-schema 10.1.0 → 11.0.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/CHANGELOG.md +419 -0
- package/README.md +141 -65
- package/bin/settings-schema.mjs +13 -6
- package/conformance/VERSION +1 -1
- package/conformance/baseline.json +3 -1
- package/conformance/cases/c01-entry-salvage-then-typo/expected.json +3 -1
- package/conformance/cases/c02-hosts-clamp-stacked/expected.json +12 -5
- package/conformance/cases/c02-hosts-clamp-stacked/meta.json +1 -1
- package/conformance/cases/c03-literal-dotted-top-key/expected.json +22 -2
- package/conformance/cases/c04-all-bad-collection-not-salvaged/expected.json +3 -1
- package/conformance/cases/c06-legacy-governance-lift/expected.json +11 -101
- package/conformance/cases/c06-legacy-governance-lift/meta.json +1 -1
- package/conformance/cases/c07-hooks-is-not-a-config-domain/expected.json +3 -1
- package/conformance/cases/c08-limits-unknown-carried-64/expected.json +203 -2
- package/conformance/cases/c09-limits-unknown-carried-65/expected.json +204 -2
- package/conformance/cases/c10-record-key-secret-redacted-twice/expected.json +3 -1
- package/conformance/cases/c11-unicode-unknown-keys/expected.json +20 -2
- package/conformance/cases/c12-prototype-name-top-keys/expected.json +3 -1
- package/conformance/cases/c13-models-field-null/expected.json +3 -1
- package/conformance/cases/c14-models-field-empty-array/expected.json +6 -1
- package/conformance/cases/c15-models-field-number/expected.json +3 -1
- package/conformance/cases/c16-deep-nesting-205/expected.json +14 -2
- package/conformance/cases/c17-empty-domain-file/expected.json +3 -1
- package/conformance/cases/c18-wire-envelope-not-an-object/expected.json +3 -1
- package/conformance/cases/c19-wire-envelope-no-version/expected.json +3 -1
- package/conformance/cases/c20-governance-absent-lifts/expected.json +11 -86
- package/conformance/cases/c20-governance-absent-lifts/meta.json +1 -1
- package/conformance/cases/c21-governance-empty-object-wins/expected.json +6 -5
- package/conformance/cases/c21-governance-empty-object-wins/input.json +1 -4
- package/conformance/cases/c21-governance-empty-object-wins/meta.json +1 -1
- package/conformance/cases/c23-mixed-validity-models/expected.json +3 -1
- package/conformance/cases/c24-valid-entries-with-unknown-keys/expected.json +22 -2
- package/conformance/cases/c25-published-roundtrip-zero-warnings/expected.json +6 -1
- package/conformance/cases/c26-hosts-array-1024/expected.json +3 -1
- package/conformance/cases/c27-hosts-array-1025/expected.json +6 -7175
- package/conformance/cases/c27-hosts-array-1025/meta.json +1 -1
- package/conformance/cases/c28-large-document-over-1mb/expected.json +14 -2
- package/conformance/cases/c29-salvage-then-domain-refine-fails/expected.json +3 -1
- package/conformance/cases/c30-version-triple-a-first/expected.json +6 -1
- package/conformance/cases/c31-version-triple-b-changed/expected.json +6 -1
- package/conformance/cases/c32-version-triple-a-restored/expected.json +6 -1
- package/conformance/cases/c33-limits-nested-carried-key/expected.json +18 -2
- package/conformance/cases/c34-skills-content-vs-manifest/expected.json +19 -3
- package/conformance/cases/c35-portable-domain-file-is-null/expected.json +3 -1
- package/conformance/cases/c36-skills-entry-without-content/expected.json +6 -2
- package/conformance/cases/c37-skills-field-null/expected.json +6 -2
- package/conformance/cases/c38-remote-exec-is-a-non-domain-file/expected.json +3 -1
- package/conformance/cases/c39-hidden-file-in-config-d/expected.json +3 -1
- package/conformance/cases/c40-s712-identity-only-what-reads-out/expected.json +11 -4
- package/conformance/cases/c41-s792-encoded-pem-identity/expected.json +9 -3
- package/conformance/cases/c42-s792-unknown-key-secret-redacted/expected.json +39 -2
- package/conformance/cases/c43-s792-form-and-deep-encoded-pem/expected.json +4 -1
- package/conformance/cases/c44-s792-utf8-escape-glued-token/expected.json +3 -1
- package/conformance/cases/c45-s792-identity-bounds-and-decode-depth/expected.json +19 -10
- package/conformance/cases/c45-s792-identity-bounds-and-decode-depth/meta.json +1 -1
- package/conformance/cases/{c46-s811-host-name-url-userinfo-characterization → c46-s811-host-name-url-userinfo-withheld}/expected.json +12 -5
- package/conformance/cases/c46-s811-host-name-url-userinfo-withheld/meta.json +9 -0
- package/conformance/cases/{c47-s811-roles-key-url-userinfo-characterization → c47-s811-roles-key-url-userinfo-withheld}/expected.json +23 -3
- package/conformance/cases/{c47-s811-roles-key-url-userinfo-characterization → c47-s811-roles-key-url-userinfo-withheld}/input.json +6 -0
- package/conformance/cases/c47-s811-roles-key-url-userinfo-withheld/meta.json +10 -0
- package/conformance/cases/c48-s935-model-headers-transported/expected.json +6 -1
- package/conformance/cases/c49-s935-model-headers-secret-entry-dropped/expected.json +3 -1
- package/conformance/cases/c50-s784-lane-host-legal/expected.json +3 -1
- package/conformance/cases/c51-s784-lane-e2b-legal/expected.json +3 -1
- package/conformance/cases/c52-s784-lane-k8s-legal/expected.json +3 -1
- package/conformance/cases/c53-s784-lane-ssh-legal/expected.json +3 -1
- package/conformance/cases/c54-s784-lane-adb-legal/expected.json +3 -1
- package/conformance/cases/c55-s784-lane-local-docker-legal/expected.json +3 -1
- package/conformance/cases/c56-s784-lane-device-legal/expected.json +3 -1
- package/conformance/cases/c57-s784-g1-enabled-no-lane/expected.json +3 -1
- package/conformance/cases/c58-s784-g2-multitenant-host/expected.json +3 -1
- package/conformance/cases/c59-s784-g3-k8s-missing-image/expected.json +3 -1
- package/conformance/cases/c60-s784-g3-e2b-missing-key/expected.json +3 -1
- package/conformance/cases/c61-s784-g3-other-lane-key/expected.json +3 -1
- package/conformance/cases/c62-s784-g7a-session-tidb/expected.json +3 -1
- package/conformance/cases/c63-s784-host-two-replicas/expected.json +3 -1
- package/conformance/cases/c64-s784-multitenant-local-store/expected.json +3 -1
- package/conformance/cases/c65-s784-pg-without-db/expected.json +3 -1
- package/conformance/cases/c66-s784-memory-backend-mismatch/expected.json +3 -1
- package/conformance/cases/c67-s784-retired-field-loud/expected.json +3 -1
- package/conformance/cases/c67-s784-retired-field-loud/meta.json +1 -1
- package/conformance/cases/c68-s784-device-local-store/expected.json +3 -1
- package/conformance/cases/c69-deep-encoded-token-past-every-reading/expected.json +3 -1
- package/conformance/cases/c70-rewritten-token-in-front-of-encoded-pem-header/expected.json +3 -1
- package/conformance/cases/c71-one-scanner-write-reads-display-forms/expected.json +119 -0
- package/conformance/cases/c71-one-scanner-write-reads-display-forms/input.json +24 -0
- package/conformance/cases/c71-one-scanner-write-reads-display-forms/meta.json +10 -0
- package/conformance/cases/c72-dangling-reference-write-seat-refuses/expected.json +111 -0
- package/conformance/cases/c72-dangling-reference-write-seat-refuses/input.json +26 -0
- package/conformance/cases/c72-dangling-reference-write-seat-refuses/meta.json +6 -0
- package/conformance/cases/cc01-mcp-toolfaces-non-object/expected.json +3 -1
- package/conformance/cases/cc02-mcp-source-key-is-transported/expected.json +3 -1
- package/conformance/cases/cc03-model-compat-unknown-subkey/expected.json +6 -1
- package/conformance/cases/cli01-model-name-nfc-vs-nfd/expected.json +11 -1
- package/conformance/cases/cli02-control-and-zero-width-chars/expected.json +11 -1
- package/conformance/cases/cli03-credential-pasted-into-unknown-key/expected.json +16 -2
- package/conformance/cases/cli04-env-value-with-newline/expected.json +3 -1
- package/conformance/cases/cli05-long-and-prefix-colliding-names/expected.json +6 -1
- package/conformance/cases/t01-absent-domain-key-not-null/expected.json +3 -1
- package/conformance/cases/t03-prototype-name-key-not-swallowed/expected.json +29 -2
- package/conformance/cases/t04-secret-literal-never-in-warning-value/expected.json +3 -1
- package/conformance/cases/z01-every-domain-empty-object/expected.json +8 -4
- package/conformance/cases/z01-every-domain-empty-object/input.json +0 -1
- package/conformance/cases/z01-every-domain-empty-object/meta.json +1 -1
- package/conformance/cases/z02-every-domain-unknown-key/expected.json +163 -23
- package/conformance/cases/z02-every-domain-unknown-key/input.json +0 -3
- package/conformance/cases/z02-every-domain-unknown-key/meta.json +1 -1
- package/dist/api/auth-bridge.d.ts +51 -181
- package/dist/api/auth-bridge.js +58 -33
- package/dist/api/auth.d.ts +37 -146
- package/dist/api/auth.js +16 -26
- package/dist/api/feedback.d.ts +87 -0
- package/dist/api/feedback.js +66 -0
- package/dist/api/pull-token.d.ts +32 -0
- package/dist/api/pull-token.js +88 -0
- package/dist/api/scopes.d.ts +82 -174
- package/dist/api/scopes.js +23 -18
- package/dist/bundle.d.ts +15 -7
- package/dist/bundle.js +28 -27
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +132 -81
- package/dist/config-d-file.d.ts +14 -0
- package/dist/config-d-file.js +67 -0
- package/dist/config-fns.d.ts +87 -186
- package/dist/config-fns.js +207 -262
- package/dist/conformance/contract-adapter.d.ts +9 -2
- package/dist/conformance/contract-adapter.js +15 -7
- package/dist/conformance/corpus.d.ts +3 -0
- package/dist/conformance/corpus.js +5 -0
- package/dist/conformance/derive.d.ts +3 -0
- package/dist/conformance/index.d.ts +2 -2
- package/dist/conformance/index.js +2 -2
- package/dist/conformance/run.js +67 -22
- package/dist/conformance/types.d.ts +31 -15
- package/dist/conformance/types.js +5 -0
- package/dist/conformance/warnings.d.ts +1 -1
- package/dist/conformance/warnings.js +1 -4
- package/dist/cross-domain.d.ts +66 -22
- package/dist/cross-domain.js +164 -93
- package/dist/cross-session.d.ts +29 -11
- package/dist/default-model.d.ts +43 -0
- package/dist/default-model.js +34 -0
- package/dist/execution-lane-index.d.ts +4 -8
- package/dist/execution-lane-index.js +4 -8
- package/dist/execution-lanes.d.ts +31 -8
- package/dist/execution-lanes.js +23 -5
- package/dist/file-edit.js +5 -2
- package/dist/file-store.d.ts +7 -6
- package/dist/file-store.js +37 -50
- package/dist/fleet.d.ts +364 -762
- package/dist/fleet.js +277 -224
- package/dist/hooks.d.ts +1151 -4737
- package/dist/hooks.js +59 -15
- package/dist/index.d.ts +10 -4
- package/dist/index.js +13 -7
- package/dist/integer.d.ts +11 -0
- package/dist/integer.js +11 -0
- package/dist/issue-path.d.ts +10 -0
- package/dist/issue-path.js +10 -0
- package/dist/loopback.d.ts +26 -0
- package/dist/loopback.js +54 -0
- package/dist/migration-receipt.d.ts +42 -0
- package/dist/migration-receipt.js +12 -0
- package/dist/one-time-migrations.d.ts +56 -0
- package/dist/one-time-migrations.js +819 -0
- package/dist/prompts-digest.d.ts +1 -1
- package/dist/prompts-digest.js +3 -2
- package/dist/reader.d.ts +2 -2
- package/dist/remote-exec.d.ts +45 -187
- package/dist/remote-exec.js +13 -7
- package/dist/resolve-roster.d.ts +18 -3
- package/dist/resolve-roster.js +28 -25
- package/dist/retired-envs.d.ts +24 -0
- package/dist/retired-envs.js +114 -0
- package/dist/retired-form.d.ts +31 -0
- package/dist/retired-form.js +28 -0
- package/dist/safety-merge-spec.d.ts +131 -191
- package/dist/safety-merge-spec.js +18 -14
- package/dist/scheduler-lifetime.d.ts +5 -0
- package/dist/scheduler-lifetime.js +7 -0
- package/dist/scheduler-store-migration.d.ts +14 -0
- package/dist/scheduler-store-migration.js +14 -0
- package/dist/scheduler-store-node.d.ts +24 -9
- package/dist/scheduler-store-node.js +25 -15
- package/dist/scheduler-store.d.ts +47 -14
- package/dist/scheduler-store.js +32 -61
- package/dist/secret-refs.d.ts +3 -3
- package/dist/secret-refs.js +1 -1
- package/dist/secret-scan.d.ts +14 -24
- package/dist/secret-scan.js +45 -23
- package/dist/sha256-core.d.ts +16 -0
- package/dist/sha256-core.js +138 -0
- package/dist/sha256.d.ts +6 -1
- package/dist/sha256.js +8 -98
- package/dist/skills-manifest.js +1 -1
- package/dist/types.d.ts +1501 -13536
- package/dist/types.js +494 -438
- package/dist/url-shape.d.ts +34 -0
- package/dist/url-shape.js +61 -0
- package/dist/web-admin-credential.d.ts +96 -0
- package/dist/{center-credential.js → web-admin-credential.js} +46 -43
- package/dist/web-admin-env.d.ts +33 -0
- package/dist/web-admin-env.js +33 -0
- package/dist/worker-row-verdict.d.ts +16 -0
- package/dist/worker-row-verdict.js +31 -0
- package/dist/workers-rows.d.ts +34 -0
- package/dist/workers-rows.js +42 -0
- package/dist/zod-unwrap.d.ts +11 -0
- package/dist/zod-unwrap.js +25 -0
- package/package.json +17 -9
- package/conformance/cases/c46-s811-host-name-url-userinfo-characterization/meta.json +0 -6
- package/conformance/cases/c47-s811-roles-key-url-userinfo-characterization/meta.json +0 -6
- package/conformance/migrate-workers/m01-g5-k8s-env-lifted/expected.json +0 -49
- package/conformance/migrate-workers/m01-g5-k8s-env-lifted/input.json +0 -26
- package/conformance/migrate-workers/m01-g5-k8s-env-lifted/meta.json +0 -4
- package/conformance/migrate-workers/m02-g5-idempotent/expected.json +0 -38
- package/conformance/migrate-workers/m02-g5-idempotent/input.json +0 -33
- package/conformance/migrate-workers/m02-g5-idempotent/meta.json +0 -5
- package/conformance/migrate-workers/m03-g5-refused-no-lane/expected.json +0 -71
- package/conformance/migrate-workers/m03-g5-refused-no-lane/input.json +0 -42
- package/conformance/migrate-workers/m03-g5-refused-no-lane/meta.json +0 -4
- package/conformance/migrate-workers/m04-g7b-session-tidb-lifted/expected.json +0 -52
- package/conformance/migrate-workers/m04-g7b-session-tidb-lifted/input.json +0 -30
- package/conformance/migrate-workers/m04-g7b-session-tidb-lifted/meta.json +0 -4
- package/conformance/migrate-workers/m05-row-verdict-reserved-env/expected.json +0 -82
- package/conformance/migrate-workers/m05-row-verdict-reserved-env/input.json +0 -68
- package/conformance/migrate-workers/m05-row-verdict-reserved-env/meta.json +0 -4
- package/dist/center-credential.d.ts +0 -116
- package/dist/issue-text.d.ts +0 -10
- package/dist/issue-text.js +0 -8
- package/dist/migrate-workers.d.ts +0 -71
- package/dist/migrate-workers.js +0 -351
- package/dist/migrate.d.ts +0 -255
- package/dist/migrate.js +0 -542
- /package/conformance/cases/{c46-s811-host-name-url-userinfo-characterization → c46-s811-host-name-url-userinfo-withheld}/input.json +0 -0
package/dist/config-fns.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pure config functions + data shapes — LIFTED verbatim out of
|
|
3
|
-
* depends only on `./types`, zero app/DB/next coupling).
|
|
2
|
+
* Pure config functions + data shapes — LIFTED verbatim out of web-admin's `store.ts` (the half that
|
|
3
|
+
* depends only on `./types`, zero app/DB/next coupling). web-admin re-exports these so its existing
|
|
4
4
|
* `@/lib/config` importers keep working unchanged (ONE copy of the code, here).
|
|
5
5
|
*
|
|
6
6
|
* Two DETERMINISM refactors vs. the original store.ts (so the package is wall-clock-free and a local file
|
|
@@ -10,45 +10,22 @@
|
|
|
10
10
|
* 2. `emptyEffective()` seeds the epoch (`new Date(0).toISOString()`) instead of the wall clock, matching
|
|
11
11
|
* the stores' existing "epoch sentinel" reduce seed.
|
|
12
12
|
*
|
|
13
|
-
* The fat `ConfigStore` interface itself STAYS in
|
|
13
|
+
* The fat `ConfigStore` interface itself STAYS in web-admin (app-only, ~32 publish/RBAC/worker-status
|
|
14
14
|
* methods); only the narrow {@link ConfigReader} (reader.ts) is carried here.
|
|
15
15
|
*/
|
|
16
16
|
import { z } from "zod";
|
|
17
|
-
import { type DomainConfig, type DomainName, type EffectiveConfig, type EffectiveWire } from "./types.js";
|
|
18
|
-
/** Redact secret-shaped tokens from a validation MESSAGE — a zod error echoes the offending value (e.g.
|
|
19
|
-
* `received 'sk-live-…'`), so a secret pasted into the WRONG field would leak via the error string. Redacts
|
|
20
|
-
* space-spanning auth credentials (`Bearer <token>`) FIRST (the token pass can't see across the space), then
|
|
21
|
-
* any secret-shaped run (`%` kept in the run so a percent-encoded secret stays whole for the percent-aware
|
|
22
|
-
* containsSecretToken). invariant ①: a secret VALUE never rides an error. R13/R14.
|
|
23
|
-
*
|
|
24
|
-
* **Output invariant** (S-712 verification pass N1 + codex review [high] ×2; 6.3.0): a string holding a private-key
|
|
25
|
-
* PEM header ANYWHERE ({@link PRIVATE_KEY_PEM_HEADER}) in ANY of its {@link secretScanForms} `forms` is withheld WHOLE, a
|
|
26
|
-
* string whose normalization did not finish (`unresolved`) is withheld WHOLE, and no result trips `containsSecretToken` on
|
|
27
|
-
* any of its forms.
|
|
28
|
-
* The whole-string judgement is ONE rule — both detectors run over the normalized forms: the PEM header on every form of
|
|
29
|
-
* the ORIGINAL text, `containsSecretToken` on every form of the targeted result; what could not be normalized does not go
|
|
30
|
-
* out (6.3.0, codex r1 F1: `-----BEGIN+PRIVATE+KEY` form-encoded headers and four-layer encodings both rode out).
|
|
31
|
-
* 6.3.0 (codex review of v6.1.0 [high]): `key=` + a percent-encoded PEM showed its header only on a decoded form
|
|
32
|
-
* (`-----BEGIN%20PRIVATE%20KEY` — `%20` is not in `[A-Z0-9 ]`), and the detector's anchored decode missed it behind
|
|
33
|
-
* the `key=` prefix, so the whole key rode out through coordinates, zod `received` / `message` and entry identity.
|
|
34
|
-
* The PEM header is judged BEFORE any replacement: the token pass can rewrite the header itself away
|
|
35
|
-
* (`sk-note:-----BEGIN` is one token-charset run that starts with `sk-`, so it becomes `[redacted-secret]` and the
|
|
36
|
-
* key body after it would ride out untouched — codex verification round). A PEM header carries spaces, so the
|
|
37
|
-
* targeted passes can never isolate it. Every free-text warning face that goes through here (coordinates, error text)
|
|
38
|
-
* inherits the same guarantee; the entry identity face additionally has to be an identifier ({@link isDisclosableIdentity}).
|
|
39
|
-
* Write and display read the private-key header at the same PLACE and with the same regex since 10.0.0: the validation-side
|
|
40
|
-
* detector `containsSecretToken` reads {@link PRIVATE_KEY_PEM_HEADER} anywhere in a string too, on the raw text and its first three
|
|
41
|
-
* percent layers. They do NOT yet read the same FORMS: this redactor reads more (deeper layers, the `+` and boundary readings of
|
|
42
|
-
* `secretScanForms`), so a header spelled only in one of those forms is withheld on display but still passes write validation —
|
|
43
|
-
* an open gap (a pin in the 10.0.0 test file registers it), not a contract. The redactor also keeps its own PEM check on the ORIGINAL
|
|
44
|
-
* text's forms because the token pass above can rewrite the header away before `containsSecretToken` ever sees the result. */
|
|
17
|
+
import { type DomainConfig, type DomainName, type EffectiveConfig, type EffectiveWire, type RetiredDomainName } from "./types.js";
|
|
45
18
|
export declare function redactSecrets(text: string): string;
|
|
46
|
-
/** Sanitize a ZodError IN PLACE so no surfaced error (message /
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
19
|
+
/** Sanitize a ZodError IN PLACE so no surfaced error (message / any issue field / nested issues) echoes a pasted secret.
|
|
20
|
+
* Every string an issue carries is redacted, string path segments included, and the walk RECURSES into the issues zod nests
|
|
21
|
+
* inside an issue — `invalid_union.errors` (one issue list per union member, e.g. RoleTarget `{model}|{select}`) and
|
|
22
|
+
* `invalid_key` / `invalid_element`.issues — because a nested issue's message can echo the same value. Non-string path
|
|
23
|
+
* segments other than numbers (zod types a path as `PropertyKey[]`) leave as their redacted `String()` form, so a path read
|
|
24
|
+
* off a sanitized error is always `string | number`. The error's `message` is re-derived from the
|
|
25
|
+
* sanitized issues at the end (zod caches it on first read, so an earlier read would otherwise keep the raw text).
|
|
26
|
+
* The ONE sanitizer every validation entry point uses (parseDomain / validateDomain / validateRemoteExec / write*). R14. */
|
|
50
27
|
export declare function sanitizeZodError(err: z.ZodError): z.ZodError;
|
|
51
|
-
/** Result of a CAS write (
|
|
28
|
+
/** Result of a CAS write (web-admin's `ConfigStore.setDomainsIfUnchanged`): applied (new `version`) or
|
|
52
29
|
* rejected because the version moved (`currentVersion` = what it is now, so the caller can re-read + retry). */
|
|
53
30
|
export type CasWriteResult = {
|
|
54
31
|
ok: true;
|
|
@@ -57,10 +34,10 @@ export type CasWriteResult = {
|
|
|
57
34
|
ok: false;
|
|
58
35
|
currentVersion: number;
|
|
59
36
|
};
|
|
60
|
-
/**
|
|
37
|
+
/** web-admin's lifecycle bookkeeping for one worker (its OWN clock — design/25 决策3). */
|
|
61
38
|
export interface WorkerLifecycleRecord {
|
|
62
39
|
name: string;
|
|
63
|
-
/** when
|
|
40
|
+
/** when web-admin FIRST saw this worker — TTL is measured from here. */
|
|
64
41
|
firstSeenAt: string;
|
|
65
42
|
/** last time the reverse-proxy saw traffic to it (idle detection). */
|
|
66
43
|
lastActiveAt?: string;
|
|
@@ -153,6 +130,19 @@ export interface PublishedSnapshot {
|
|
|
153
130
|
* Seeds the epoch (`new Date(0)`) so it's deterministic (the wall-clock default was the original store.ts
|
|
154
131
|
* non-determinism — see the file header). */
|
|
155
132
|
export declare function emptyEffective(): EffectiveConfig;
|
|
133
|
+
/**
|
|
134
|
+
* 一个**retired 域**的文档带着事实 —— 读存储文档的每个读者同一只拒(`parseDomain` 写、`buildEffective` 向店要、`readEffectiveWire` 看 wire、
|
|
135
|
+
* `FileConfigStore` 与 `readBundle` 读 `config.d/`)。`message` 是墓碑表那一行的整句(点名retired版本、事实今天住哪、改写存量的一次性迁移);
|
|
136
|
+
* `code` 是机读码,`domain` / `migration` 是那一行的两格。墓碑是拒,不是读法:它从不把旧文档读成任何值。
|
|
137
|
+
*/
|
|
138
|
+
export declare class RetiredDomainError extends Error {
|
|
139
|
+
readonly domain: RetiredDomainName;
|
|
140
|
+
readonly code: "retired_domain";
|
|
141
|
+
readonly migration: string;
|
|
142
|
+
constructor(domain: RetiredDomainName);
|
|
143
|
+
}
|
|
144
|
+
/** 墓碑判一次:`raw` 是retired 域 `domain` 的文档,带事实 ⇒ 抛 {@link RetiredDomainError}。 */
|
|
145
|
+
export declare function refuseRetiredDomain(domain: RetiredDomainName, raw: unknown): void;
|
|
156
146
|
/** Validate + fill defaults for a domain payload (or the schema's empty default when absent/invalid). */
|
|
157
147
|
export declare function parseDomain<K extends DomainName>(domain: K, raw: unknown): DomainConfig[K];
|
|
158
148
|
/** 一条告警的**坐标**:从域文档根出发的段序列。字符串段 = 对象键(逐字,含 `.` 也逐字);数字段 =
|
|
@@ -173,6 +163,16 @@ export type ConfigPath = readonly (string | number)[];
|
|
|
173
163
|
* **刻意不提供 parse 反函数**:2.1.0 起没有任何一处把坐标读回来(回写走 `keptIndex` 那本账),给它
|
|
174
164
|
* 一个反函数就是给下一个人一条「在串上做事」的路。 */
|
|
175
165
|
export declare function formatConfigPath(p: ConfigPath): string;
|
|
166
|
+
/** 带用户写的键段的坐标出门前的**唯一**一道(6.3.0,codex r1 F2):字符串段过 {@link outgoingSegment} —— 与 `error` 文案
|
|
167
|
+
* ({@link sanitizeZodError})、身份否决({@link isDisclosableIdentity})**同一只**脱敏器,不另设判据;数字段(下标)原样。
|
|
168
|
+
* 键段是用户写的,完全可能就是一条粘错位置的凭据:被丢 Record 条目的键、未知键告警(`unknown-keys-dropped` /
|
|
169
|
+
* `-carried`)的键名都一样(后者 0.19.0 起从不过脱敏器,`sk-…` 形的未知键名原样进告警与投影)。schema 已知的字段名
|
|
170
|
+
* 脱敏器原样放行,所以坐标里「它是哪个字段」照旧可读。经它的坐标就是出门形 —— {@link droppedKeys} /
|
|
171
|
+
* {@link carriedUnknownKeys} 这两只扫描交给告警的 `keys` 同样是它的产物。
|
|
172
|
+
*
|
|
173
|
+
* 11.0.0 起导出:读告警之外还有两处铸坐标的面 —— 一次性迁移的收据(`./one-time-migrations`)与 workers 的逐行终判(`readWorkersRows`
|
|
174
|
+
* 的 `held[].field`),它们与告警走同一道,不另抄一份判据;消费方自己拼坐标出门(日志 / 界面)时也调它。 */
|
|
175
|
+
export declare function outgoingPath(p: ConfigPath): ConfigPath;
|
|
176
176
|
/** 一条被丢掉的条目的**身份**(S-712):只从被丢条目**原文**里取,三键各自可缺。
|
|
177
177
|
*
|
|
178
178
|
* 律(一条,不分域):`name` / `id` 取**字符串**形、`enabled` 取**布尔**形,类型不对 ⇒ 不带该键(不猜、
|
|
@@ -181,8 +181,9 @@ export declare function formatConfigPath(p: ConfigPath): string;
|
|
|
181
181
|
* {@link redactSecrets} 原样放行 —— 坐标段必须在场,所以打码出门;身份是可缺的,打过码的串不再是任何条目的身份,
|
|
182
182
|
* 所以是**不带**而不是打码)。三键都读不出 ⇒ 整个身份缺席(不铸空对象)。
|
|
183
183
|
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
184
|
+
* **扣名 ≠ 读不出**(11.0.0,N-4 / S-759):`name` / `id` 是字符串但不能原样出门 ⇒ 身份带 `nameWithheld: true` / `idWithheld: true`;
|
|
185
|
+
* 不是字符串 ⇒ 什么都不带。两种处置对消费方不同:「这一行在场、有名、名被扣下」的启用行仍是一条在场的条目(server 据此铸无名占位,
|
|
186
|
+
* 不走「零启用」捷径),「没有名」的行不是。标记只说「有一个名、没给出」,不说为什么(秘密形 / 超长 / 字符集外是同一个记号)。
|
|
186
187
|
*
|
|
187
188
|
* 为什么要带:条目被丢之后它的名字从目录里消失,只给坐标的话,消费方要知道「丢的是谁」只能拿坐标回读
|
|
188
189
|
* 原文档 —— 而它手里那份原文档未必是这一次读到的那份。铸告警的这一层判的就是那条原文,在这里取一次、
|
|
@@ -191,6 +192,10 @@ export interface DroppedEntryIdentity {
|
|
|
191
192
|
name?: string;
|
|
192
193
|
id?: string;
|
|
193
194
|
enabled?: boolean;
|
|
195
|
+
/** `name` was a string that {@link isDisclosableIdentity} would not let out (11.0.0). Absent with a `name` present or with no string name. */
|
|
196
|
+
nameWithheld?: true;
|
|
197
|
+
/** `id` was a string that {@link isDisclosableIdentity} would not let out (11.0.0). */
|
|
198
|
+
idWithheld?: true;
|
|
194
199
|
}
|
|
195
200
|
/**
|
|
196
201
|
* 一条条目为什么被丢 —— **机读原因**的闭集(S-1295)。词与**丢弃点**一一对应:`DroppedEntry` 只有一个铸点
|
|
@@ -202,8 +207,7 @@ export interface DroppedEntryIdentity {
|
|
|
202
207
|
* 为什么是词而不是 `error` 句:句子随 zod 小版本改字、可经脱敏,拿它当判据就是拿实现当契约;wire 上也不许有自由文本。
|
|
203
208
|
* 这张表由 `test/dropped-entry-reason-code-s1295.test.ts` 的两格咬住:穷举 `switch`(给表加词而不补臂 ⇒ `tsc` 红,门 = `npm run typecheck`)与
|
|
204
209
|
* 满射格(每个词至少有一个真丢弃点触发它 = 没有死词;每个被丢条目的词都在表里 = 没有无词的丢弃点)。
|
|
205
|
-
*
|
|
206
|
-
* (`hosts-grandfathered`,主机名超长)走它自己的告警臂,不是 `DroppedEntry`,不在本表。
|
|
210
|
+
* 读路径上剔条目的只有 `salvageEntries` 这一处(11.0.0 起 hosts 的读侧夹紧臂已retired),所以本表覆盖读路径上每一条被丢的条目。
|
|
207
211
|
*/
|
|
208
212
|
export declare const DROPPED_ENTRY_REASON_CODES: readonly ["entry-schema-invalid", "entry-key-invalid", "entry-unreadable"];
|
|
209
213
|
export type DroppedEntryReasonCode = (typeof DROPPED_ENTRY_REASON_CODES)[number];
|
|
@@ -232,8 +236,8 @@ export declare const DISCLOSABLE_IDENTITY_RE: RegExp;
|
|
|
232
236
|
* ② **否决**(「无密钥形」):坐标脱敏器 {@link redactSecrets} 原样放行 —— 集内照样有密钥形(`sk-…` / `ghp_…` /
|
|
233
237
|
* `AKIA…` / 三段 JWT 的字符全在集内),而且判它的必须是坐标段、`error` 文案({@link sanitizeZodError})用的**同一只**
|
|
234
238
|
* 脱敏器:两只判据会在同一条告警里给出两种答案(对抗轮 #2 真复现;集内的残例 = `@` 之后的单点 `eyJ…` 串,裸探测器
|
|
235
|
-
* 判阴、脱敏器会改,语料 c41 钉着)
|
|
236
|
-
* (
|
|
239
|
+
* 判阴、脱敏器会改,语料 c41 钉着)。带 userinfo 的 URL(opus 腿 L1:`postgres://svc:pw@h` 的字符全在集内)由同一只脱敏器扣下
|
|
240
|
+
* (11.0.0 S-811 起它对 URL 候选段问 `carriesUserinfo`),不再单列一条否决。
|
|
237
241
|
* 入参是 `string`、返回 `boolean`,**刻意不是**类型谓词(`v is string`):它对一些字符串答 false,谓词形会让调用方的
|
|
238
242
|
* 否定分支把一个 `string` 收窄成 `never`;「是不是字符串」由调用点自己判(运行期收到非字符串照答 false、不抛)。
|
|
239
243
|
* 不可披露的串按**无名**处置(不带,而不是打码:打过码的串不再是身份)。
|
|
@@ -255,7 +259,7 @@ export declare function isReportableRefusalName(name: string): boolean;
|
|
|
255
259
|
* 不动其余键的坐标。 */
|
|
256
260
|
export type EntryKeptIndex = Readonly<Record<string, readonly number[]>>;
|
|
257
261
|
/** {@link salvageEntries} 的结果。`raw` 是剔掉坏条目后的文档;**什么都没丢时返回原引用**
|
|
258
|
-
* (
|
|
262
|
+
* (好数据穿过读路径 byte 不变)。
|
|
259
263
|
*
|
|
260
264
|
* `keptIndex`(2.1.0)是抢救**自带**的坐标账:`raw` 里的数组被压缩了,谁拿这份压缩文档去诊断,谁
|
|
261
265
|
* 报出来的下标就是压缩后的下标。把位移随结果一起交出去,回写就能在**一个**铸点完成
|
|
@@ -293,11 +297,14 @@ export interface EntrySalvageResult {
|
|
|
293
297
|
* ③ 域级判据(重名 / 悬空 ref)不在本函数视野内 —— 丢条目救不了它们,调用方据此回落整域档位;
|
|
294
298
|
* ④ 只认 `ZodArray` / `ZodRecord` 两种条目集合形 —— 别的形(元组等)不抢救,退回整域档位(保守方向)。
|
|
295
299
|
*/
|
|
296
|
-
export declare function salvageEntries(schema: z.
|
|
300
|
+
export declare function salvageEntries(schema: z.ZodType, raw: unknown): EntrySalvageResult;
|
|
297
301
|
/**
|
|
298
302
|
* Shared GC predicate for worker-status rows (F10) — keeps memory/sqlite/tidb identical. Given the rows'
|
|
299
303
|
* `{name, updatedAt}` and the GC options, returns the names to prune (A: not in `keepNames`; B: older than
|
|
300
304
|
* `ttlMs`). Pass neither selector → prunes nothing (guards against a wipe-all). See `ConfigStore.gcWorkerStatuses`.
|
|
305
|
+
*
|
|
306
|
+
* `now` is REQUIRED (11.0.0): this package never reads the wall clock (the determinism rule in the file header) — the
|
|
307
|
+
* TTL arm used to fall back to `new Date()`, the one argless clock left in the package. The caller owns the time.
|
|
301
308
|
*/
|
|
302
309
|
export declare function statusRowsToPrune(rows: {
|
|
303
310
|
name: string;
|
|
@@ -305,41 +312,16 @@ export declare function statusRowsToPrune(rows: {
|
|
|
305
312
|
}[], opts: {
|
|
306
313
|
keepNames?: string[];
|
|
307
314
|
ttlMs?: number;
|
|
308
|
-
now
|
|
315
|
+
now: Date;
|
|
309
316
|
}): string[];
|
|
310
|
-
/**
|
|
311
|
-
* Merge every domain into the effective config a consumer pulls. Shared by all store impls.
|
|
312
|
-
* `updatedAt` is REQUIRED (the determinism refactor — the original store.ts defaulted it to the wall clock,
|
|
313
|
-
* which made `emptyEffective`/the memory store non-deterministic). Every caller now supplies it explicitly.
|
|
314
|
-
*/
|
|
315
|
-
/** Lift the governance trio out of a LEGACY runtime doc (pre-0.6 stored runtime carried autonomy/commandPolicy/
|
|
316
|
-
* approvalRequire). Used as the governance domain's read fallback when governance was NEVER set — so a 0.5
|
|
317
|
-
* store upgrades with zero data migration and zero gate loss. An explicitly-set governance domain WINS
|
|
318
|
-
* (its absence-of-a-key then means "center not managing", never "fall back to legacy runtime").
|
|
319
|
-
*
|
|
320
|
-
* SUNSET (2.0.0): removal is a **persistent-data** break — a store still carrying the 0.5 shape would lose
|
|
321
|
-
* its guardrails silently, so this arm cannot simply be deleted at a minor. It goes at the next MAJOR, with
|
|
322
|
-
* the standard persistent-data treatment (a loud refusal naming the domain + a one-time migration on the
|
|
323
|
-
* writer side), and the closing condition is observable rather than a promise: `buildEffective` now emits
|
|
324
|
-
* `legacy-governance-lifted` every time the arm actually fires, so a deployment can prove it no longer does. */
|
|
325
|
-
export declare function legacyGovernanceFromRuntime(rawRuntime: unknown): unknown;
|
|
326
|
-
/** A warning emitted by {@link buildEffective} when it clamps/degrades instead of throwing (0.8.1), or by
|
|
317
|
+
/** A warning emitted by {@link buildEffective} when it degrades instead of throwing, or by
|
|
327
318
|
* {@link FileConfigStore} when a file it will never read sits in `config.d/` (0.19.0). Callers route it to
|
|
328
319
|
* their audit stream; omitting the callback keeps the resilience but drops the telemetry.
|
|
329
320
|
*
|
|
330
321
|
* 0.19.0 加了两个 kind(additive union member —— 用 `switch` 穷举本类型的消费方需补臂):
|
|
331
322
|
* `"unknown-keys-dropped"` / `"unread-config-file"`,成案见 {@link droppedKeys}(消费方
|
|
332
323
|
* #322:配置写了、进程跑着、值没到,而没有任何一个字说出来)。 */
|
|
333
|
-
export type EffectiveReadWarning =
|
|
334
|
-
/** `droppedNames` 有界(6.3.0,S-813:与未知键同一只 `DROP_SCAN_MAX_KEYS`),超界时带 `droppedTotal`(= 按名剔掉的真实条数)——
|
|
335
|
-
* 缺席 = 列表是穷举。`truncatedFrom` 另是一件事:hosts 数组超 `HOSTS_ARRAY_MAX` 被切片前的长度。 */
|
|
336
|
-
{
|
|
337
|
-
domain: "hosts";
|
|
338
|
-
kind: "hosts-grandfathered";
|
|
339
|
-
droppedNames: string[];
|
|
340
|
-
droppedTotal?: number;
|
|
341
|
-
truncatedFrom?: number;
|
|
342
|
-
} | {
|
|
324
|
+
export type EffectiveReadWarning = {
|
|
343
325
|
domain: DomainName;
|
|
344
326
|
kind: "domain-defaulted";
|
|
345
327
|
error: unknown;
|
|
@@ -349,8 +331,8 @@ export type EffectiveReadWarning =
|
|
|
349
331
|
* `["commandPolicy",0,"typo"]`),见
|
|
350
332
|
* {@link droppedKeys} 的扫描边界。**1.5.0**:①{@link EXTENSION_NAMESPACES} 登记的扩展键(别的写者按契约
|
|
351
333
|
* 放在文档里、本包刻意不认的键,如壳写在 models 条目上的 `sema*`)**不算未知键**——既不点名也不计数;
|
|
352
|
-
* ②`keys` 有界(`DROP_SCAN_MAX_KEYS`),超界时带 `truncatedFrom`(=
|
|
353
|
-
*
|
|
334
|
+
* ②`keys` 有界(`DROP_SCAN_MAX_KEYS`),超界时带 `truncatedFrom`(= 真实未知键总数),消费方据此知道列表**不是穷举**
|
|
335
|
+
* ——把有界诊断当穷举决策输入,是服务端消费方在配置门上三次被复审打穿的根因。 */
|
|
354
336
|
| {
|
|
355
337
|
domain: DomainName;
|
|
356
338
|
kind: "unknown-keys-dropped";
|
|
@@ -365,14 +347,6 @@ export type EffectiveReadWarning =
|
|
|
365
347
|
keys: ConfigPath[];
|
|
366
348
|
truncatedFrom?: number;
|
|
367
349
|
}
|
|
368
|
-
/** 0.5 期的 runtime 文档里还带着治理三闸,而 governance 域从未被设过 —— 读侧抬升腿真生效了。
|
|
369
|
-
* `keys` = 这次抬起来的那几个键。**照旧生效,只是不再无声**:兼容窗要能关掉,前提是有人知道它还开着。
|
|
370
|
-
* 2.0.0 起。 */
|
|
371
|
-
| {
|
|
372
|
-
domain: "governance";
|
|
373
|
-
kind: "legacy-governance-lifted";
|
|
374
|
-
keys: ConfigPath[];
|
|
375
|
-
}
|
|
376
350
|
/** 一条**条目**没通过它自己的 entry schema,被单独丢掉了(域内其余条目照常生效)。`path` = 段坐标
|
|
377
351
|
* (`["models",3]` / `["roles","summarize"]`),与 `unknown-keys-dropped` 的坐标形同一套。逐条一发 —— 载荷是
|
|
378
352
|
* O(域里的条目数),与被读文档同阶,不放大,故不设条数上限(有上限的是**单条**告警里的键列表)。
|
|
@@ -407,7 +381,7 @@ export type EffectiveReadWarning =
|
|
|
407
381
|
* (给联合加一条新臂,实测这三处各红一条,`satisfies` 那行零诊断);而「新 kind 三处都处置了、却忘了登记
|
|
408
382
|
* 进本表」这半条缝,由 `test/warning-projection-derived-4.0.0.test.ts` 的闭集格看着(本表 == 从 AST 解出的
|
|
409
383
|
* 臂集,逐字同集同序)。 */
|
|
410
|
-
export declare const WARNING_KINDS: readonly ["
|
|
384
|
+
export declare const WARNING_KINDS: readonly ["domain-defaulted", "unknown-keys-dropped", "unknown-keys-carried", "entry-dropped", "unread-config-file"];
|
|
411
385
|
export type WarningKind = (typeof WARNING_KINDS)[number];
|
|
412
386
|
/** 逐臂剥字段的**分配式**映射:`W` 是裸类型参数,条件类型因此对联合的每一员分别作用(而不是先塌成交集)。 */
|
|
413
387
|
type PerArmOmit<W, K extends string> = W extends unknown ? Omit<W, K> : never;
|
|
@@ -453,13 +427,13 @@ export declare function projectWarning(w: EffectiveReadWarning): WarningProjecti
|
|
|
453
427
|
* **闭集穷举**:`switch` 覆盖 {@link EffectiveReadWarning} 的每个 `kind`,新 kind 不声明处置 = 编译红
|
|
454
428
|
* (#157 的闭集纪律)。只分两类,没有第三类:**带坐标的回写,不带坐标的原样返回**。
|
|
455
429
|
*
|
|
456
|
-
* 为什么 `entry-dropped`
|
|
457
|
-
* 说的就是这件事。{@link salvageEntries} 铸 `entry-dropped`
|
|
458
|
-
*
|
|
459
|
-
*
|
|
430
|
+
* 为什么 `entry-dropped` 也有回写臂:它**不是**「恒为原坐标」,只是不经**铸它那一层自己**的表 —— 上面那条律
|
|
431
|
+
* 说的就是这件事。{@link salvageEntries} 铸 `entry-dropped` 时用的是它**入参**那份文档的坐标;若那份文档本身被外层
|
|
432
|
+
* 压缩过,外层照样要回写它一次。今天读路径上只有一个压缩点(11.0.0 起 hosts 的读侧夹紧臂已retired),所以这一臂当下
|
|
433
|
+
* 只对 `keptIndex` 为空的表恒等;把「不动」写成一条臂的性质,就是把「哪一层」这件事错记在了「哪个 kind」上。
|
|
460
434
|
*
|
|
461
435
|
* **恒等纪律**:没有任何一条路径真的变了(含 `keptIndex` 为空)⇒ 返回**同一个对象引用**,连 `keys`
|
|
462
|
-
* 数组也不复制(
|
|
436
|
+
* 数组也不复制(好数据穿过读路径 byte 不变)。
|
|
463
437
|
*/
|
|
464
438
|
export declare function rebaseWarningPaths(w: EffectiveReadWarning, keptIndex: EntryKeptIndex): EffectiveReadWarning;
|
|
465
439
|
/**
|
|
@@ -499,59 +473,6 @@ export declare const EXTENSION_NAMESPACES: Partial<Record<DomainName, ReadonlyAr
|
|
|
499
473
|
* 本身——键名里可以含 `.`(`semaX.foo` 是一个键不是两层),段形让这件事不必再靠文法猜;前缀契约就是前缀
|
|
500
474
|
* 契约(`semaGPT_5` / `semaX-v2` 都是成员,后缀不设未声明的文法)。 */
|
|
501
475
|
export declare function isReservedExtensionKey(domain: DomainName, parent: ConfigPath, key: string): boolean;
|
|
502
|
-
/**
|
|
503
|
-
* 一次未知键扫描的结果:`keys` 有界(≤ {@link DROP_SCAN_MAX_KEYS}),`total` 是**截断前**的真实未知键数
|
|
504
|
-
* (超界仍数完 —— 扫描本就 O(文档键数),上限只界**告警载荷**不界扫描);`total > keys.length` ⇔ 列表被截断。
|
|
505
|
-
*
|
|
506
|
-
* **4.0.0(BREAKING)**:{@link droppedKeys} / {@link carriedUnknownKeys} 从「只回 `keys` 数组」改成回本形。
|
|
507
|
-
* 成案:上界与真实总数此前都是私有的,于是一个自装配读腿的消费方(不走 {@link parseDomainLoud} 的
|
|
508
|
-
* `onWarning`、自己拿这两只函数做诊断)在**结构上**铸不出 `truncatedFrom` —— 拿到 64 条,既不知道是不是刚好
|
|
509
|
-
* 64 条,也没有第二个公开面可以问「一共多少」。而本包自己的告警面从 1.5.0 起就带着 `truncatedFrom`:
|
|
510
|
-
* 同一件事在两个公开面上一个说、一个不说。上界 {@link DROP_SCAN_MAX_KEYS} 仍然**私有** —— 它是告警载荷的
|
|
511
|
-
* 上界,不是契约(改它不该让任何消费方红);消费方要的是「有没有截断、截断前多少条」,那就是 `total`。
|
|
512
|
-
*/
|
|
513
|
-
export interface UnknownKeyScan {
|
|
514
|
-
keys: ConfigPath[];
|
|
515
|
-
total: number;
|
|
516
|
-
}
|
|
517
|
-
/**
|
|
518
|
-
* 一份域文档里被域 schema **丢掉的键**(zod 对象默认 `"strip"`),段坐标形({@link ConfigPath})。
|
|
519
|
-
*
|
|
520
|
-
* 成案(消费方 #322 真事故):往 `runtime` 文档里加一个不属于该域的键,两条腿都会把它剥掉,
|
|
521
|
-
* `domainErrors` 空、解析"成功"——配置写了、值没到、零告警。剥除行为本身是**刻意的前向兼容**
|
|
522
|
-
* (新 center 的新键不该炸老消费方),所以修法不是收紧成 `.strict()`,而是让它**响亮**:
|
|
523
|
-
* {@link buildEffective} 每域解析成功后调用本函数,非空即发 `"unknown-keys-dropped"` 警告。
|
|
524
|
-
*
|
|
525
|
-
* **嵌套也扫**(对抗复审 复审 F2 真 finding):`{infraCostRates:{toolCalMicroUsd:10}}` 这种**拼错的嵌套
|
|
526
|
-
* 键**在顶层看不见(`infraCostRates` 键还在),只看顶层等于对计费面的错键完全失明。故按 raw↔parsed
|
|
527
|
-
* 的键集逐层对比(对象逐键、数组同长时逐下标),不依赖任何 zod 内省。
|
|
528
|
-
*
|
|
529
|
-
* `runtime` 域的治理三件({@link GOVERNANCE_MIRROR_KEYS})**不算被丢**:0.5 期 runtime 文档携带它们是
|
|
530
|
-
* 成文的抬升位(本文件的 governance 抬升函数会把它们抬进 governance 域),报出来是噪声。豁免只在顶层。
|
|
531
|
-
*
|
|
532
|
-
* 返回 {@link UnknownKeyScan}:`keys` 是**有界**的点名列表,`total` 是截断前的真实总数(4.0.0 BREAKING,
|
|
533
|
-
* 此前只回 `keys` —— 见 {@link UnknownKeyScan} 的成案)。本包自己的告警(`unknown-keys-dropped`)也是拿这两个
|
|
534
|
-
* 数拼出来的,**一个铸点**:消费方自铸的 `truncatedFrom` 与告警里那个恒等。
|
|
535
|
-
*
|
|
536
|
-
* 边界(如实登记):① 深度上限 {@link DROP_SCAN_MAX_DEPTH}、键数上限 {@link DROP_SCAN_MAX_KEYS}(告警
|
|
537
|
-
* 载荷有界,超出即少报**点名**——`total` 不少报);② 数组长度不同就整段跳过(元素级裁剪由各自的 clamp 告警
|
|
538
|
-
* 负责);③ 只比对纯 JSON 对象——raw 若是类实例/Proxy 这类形状不扫;④ 读 raw 的值可能触发访问器,整段包
|
|
539
|
-
* try/catch 且**绝不**让其错误外泄(错误文案可能带 secret,与 parseDomain 的 R13 同纪律),扫描失败即当作
|
|
540
|
-
* "没看见"(`{ keys: [], total: 0 }`),不影响解析。
|
|
541
|
-
*/
|
|
542
|
-
export declare function droppedKeys(domain: DomainName, raw: unknown, parsed: unknown): UnknownKeyScan;
|
|
543
|
-
/**
|
|
544
|
-
* 一份已解析的 open-world 域文档里,**本包不认识但已承运**的键(段坐标)。非 open-world 域恒空
|
|
545
|
-
* (它们的未知键走 {@link droppedKeys} 那条更重的「被丢了」告警)。
|
|
546
|
-
*
|
|
547
|
-
* 返回 {@link UnknownKeyScan}(4.0.0 BREAKING,与 {@link droppedKeys} 同形同律:`keys` 有界、`total` 是
|
|
548
|
-
* 截断前的真实总数)。非 open-world 域返回的也是这个形(`{ keys: [], total: 0 }`),不是别的东西 ——
|
|
549
|
-
* 「这个域没有承运未知键」与「这个域不参与承运」在消费方那里是同一个处置。
|
|
550
|
-
*
|
|
551
|
-
* 边界(如实):只看 {@link OPEN_WORLD_KNOWN_KEYS} 登记了的层级 —— 未登记层级(如某个未知键自己的
|
|
552
|
-
* 子树)不再下探,那本就是消费方自定义的内容,逐层猜没有意义。
|
|
553
|
-
*/
|
|
554
|
-
export declare function carriedUnknownKeys(domain: DomainName, parsed: unknown): UnknownKeyScan;
|
|
555
476
|
/**
|
|
556
477
|
* 一域的 parse + **静默剥键/静默承运两条告警**(0.19.0)。`buildEffective` 与 `FileConfigStore.getDomain`
|
|
557
478
|
* 共用这一个判据 —— 此前只有 effective 那条路径有门,而 `getDomain` 是 `exportBundle` 的读法
|
|
@@ -565,14 +486,12 @@ export declare function parseDomainLoud<K extends DomainName>(domain: K, raw: un
|
|
|
565
486
|
* this call explicitly (compile error until it's classified). Per-domain rationale:
|
|
566
487
|
* - models/skills/mcp/plugins/scenarios/systems/collab: additive capability catalogs — empty = the
|
|
567
488
|
* capability disappears (fail-closed), no gate is lost.
|
|
568
|
-
* - hosts: empty registry = no auto-placement targets (availability-only); self-registration re-lands
|
|
569
|
-
* entries as approved:false = 待批 (fail-closed).
|
|
489
|
+
* - hosts: empty host registry = no auto-placement targets (availability-only); self-registration re-lands
|
|
490
|
+
* entries as approved:false = 待批 (fail-closed).
|
|
570
491
|
* - rosters: THROW — a lost roster makes resolveEffectiveForWorker fall back to the FULL models catalog
|
|
571
492
|
* ("global(fallback)"), silently WIDENING every restricted worker's model access. 放权,不许.
|
|
572
493
|
* - workers: THROW — an empty fleet spec would make the reconciler RETIRE every managed worker
|
|
573
494
|
* (destructive apply — far worse than a read outage).
|
|
574
|
-
* - runtime: THROW — defaulting drops centrally-published rate/cost ceilings = unbounded spend (fail-open
|
|
575
|
-
* on the budget axis).
|
|
576
495
|
* - governance: THROW — defaulting drops autonomy/commandPolicy/approvalRequire = the consumer falls back
|
|
577
496
|
* to env/defaults with the operator's guardrails silently gone. 放权,不许.
|
|
578
497
|
* - entitlement: THROW — defaulting drops the org kill-switch/budget ceilings/tier restrictions for every
|
|
@@ -596,7 +515,6 @@ export declare const DOMAIN_READ_FALLBACK: {
|
|
|
596
515
|
readonly collab: "default";
|
|
597
516
|
readonly workers: "throw";
|
|
598
517
|
readonly hosts: "default";
|
|
599
|
-
readonly runtime: "throw";
|
|
600
518
|
readonly governance: "throw";
|
|
601
519
|
readonly entitlement: "throw";
|
|
602
520
|
readonly execution: "throw";
|
|
@@ -604,43 +522,27 @@ export declare const DOMAIN_READ_FALLBACK: {
|
|
|
604
522
|
readonly prompts: "default";
|
|
605
523
|
readonly limits: "throw";
|
|
606
524
|
};
|
|
607
|
-
/**
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
droppedTotal: number;
|
|
619
|
-
/** Set when the hosts array (after drops) exceeded HOSTS_ARRAY_MAX (1024) and was sliced — the pre-slice length. */
|
|
620
|
-
truncatedFrom?: number;
|
|
621
|
-
/** 这次夹紧造成的**下标位移表**(与 {@link EntrySalvageResult.keptIndex} 同一种账、同一条律):本函数
|
|
622
|
-
* 是读路径的**第二个压缩点**,`raw` 里的 hosts 数组被剔过条目,谁拿这份文档去诊断,谁报出来的下标就是
|
|
623
|
-
* 夹紧后的下标。只在**按名剔条目**时登记 —— 纯截断保留的是原数组的**前缀**,幸存者下标不动,登记一份
|
|
624
|
-
* 恒等映射只会把「有没有位移」从表的在场性挪成表的内容(见 {@link EntryKeptIndex})。 */
|
|
625
|
-
keptIndex: EntryKeptIndex;
|
|
626
|
-
}
|
|
627
|
-
/** READ-path grandfather clamp for the 0.8.0 hosts tightening (0.8.1, S3 M-1). Clamps ONLY the two bounds
|
|
628
|
-
* 0.8.0 added (name > 63 → drop the entry; array > 1024 → slice) so 0.7-era legal stored data keeps reading;
|
|
629
|
-
* everything else (regex, types, duplicates) is left for parseDomain — this is a targeted grandfather, not a
|
|
630
|
-
* lenient parser. PURE + idempotent; returns the ORIGINAL reference when nothing exceeds the bounds.
|
|
631
|
-
*
|
|
632
|
-
* SUNSET (2.0.0): same persistent-data class as the governance lift — it goes at the next MAJOR. This one was
|
|
633
|
-
* never silent (`hosts-grandfathered` fires whenever it clamps), so the closing condition is already
|
|
634
|
-
* observable: a deployment that has not seen that warning across a full read cycle no longer needs the arm. */
|
|
635
|
-
export declare function grandfatherHostsRead(raw: unknown): GrandfatherHostsReadResult;
|
|
636
|
-
export declare function buildEffective(version: number, getRaw: (d: DomainName) => unknown, updatedAt: string, onWarning?: (w: EffectiveReadWarning) => void): EffectiveConfig;
|
|
525
|
+
/** 一个读者向店要文档的口:配置域,以及墓碑表里的retired 域({@link RETIRED_DOMAINS})—— 后者只为让墓碑看见没迁的旧文档。 */
|
|
526
|
+
export type StoredDocumentReader = (d: DomainName | RetiredDomainName) => unknown;
|
|
527
|
+
/**
|
|
528
|
+
* Merge every domain into the effective config a consumer pulls. Shared by all store impls.
|
|
529
|
+
* `updatedAt` is REQUIRED (the determinism refactor — the original store.ts defaulted it to the wall clock,
|
|
530
|
+
* which made `emptyEffective`/the memory store non-deterministic). Every caller now supplies it explicitly.
|
|
531
|
+
*
|
|
532
|
+
* 11.0.0:`getRaw` 也会被问到墓碑表里的retired 域(今天只有 `runtime`)。店里还留着一份**带事实**的retired 域文档 ⇒ 整份 effective 抛
|
|
533
|
+
* {@link RetiredDomainError}(拒句点名改写它的一次性迁移);缺席或 `{}` ⇒ 不理会。读写两面同一只 schema:读路径上不再有任何抬升臂。
|
|
534
|
+
*/
|
|
535
|
+
export declare function buildEffective(version: number, getRaw: StoredDocumentReader, updatedAt: string, onWarning?: (w: EffectiveReadWarning) => void): EffectiveConfig;
|
|
637
536
|
/** READ-side tolerant judgment for a GET /effective **wire payload**(the {@link EffectiveWire} contract)at
|
|
638
|
-
* its CONSUMPTION boundary — a service pulling from a remote
|
|
537
|
+
* its CONSUMPTION boundary — a service pulling from a remote web-admin passes the parsed JSON here instead of
|
|
639
538
|
* type-asserting it(0.12.0,[2281] 裁B:「两个契约共用一个拼写不是一个被检查的契约」——拼写副本要在
|
|
640
539
|
* 消费端被真校验)。ONE judgment, two legs: every known domain goes through the SAME `parseDomain` +
|
|
641
540
|
* {@link DOMAIN_READ_FALLBACK} policy as {@link buildEffective}(catalog 域坏形 → schema default + warning;
|
|
642
|
-
* gate 域坏形 → throw,caller 的整包 catch 决定回落),including the
|
|
643
|
-
*
|
|
541
|
+
* gate 域坏形 → throw,caller 的整包 catch 决定回落),including the retired-domain tombstone — DELEGATED to
|
|
542
|
+
* buildEffective, not re-implemented(单判据双腿消费,§M4)。A retired domain on the wire (an older web-admin still
|
|
543
|
+
* ships `runtime`) is judged by the same tombstone: carrying facts ⇒ {@link RetiredDomainError}; `{}` (what an older
|
|
544
|
+
* web-admin materialises for an unset domain) carries nothing and is dropped from the result — it never rides through as
|
|
545
|
+
* an open-world key.
|
|
644
546
|
*
|
|
645
547
|
* `skills` is the ONE wire divergence: on the wire it is a MANIFEST(content → contentHash,
|
|
646
548
|
* {@link SkillsManifest}),so the full skills-domain schema would reject every LEGAL manifest and silently
|
|
@@ -648,14 +550,13 @@ export declare function buildEffective(version: number, getRaw: (d: DomainName)
|
|
|
648
550
|
* same "default" fallback tier as the skills domain itself.
|
|
649
551
|
*
|
|
650
552
|
* OPEN-WORLD on unknown top-level keys: they ride through VERBATIM(never validated, never dropped)— a
|
|
651
|
-
* newer
|
|
652
|
-
* and the
|
|
653
|
-
* flowing. Throws ONLY on garbage no caller can partially trust: a non-object payload, or a missing/
|
|
553
|
+
* newer web-admin's new domain reaches an older engine untouched(§M2 能力面语义:读不到即走老路,不该炸),
|
|
554
|
+
* and so does any key no domain names(the 0.6-era `teams` key included — not a domain since 0.7, and no engine reads it). Throws ONLY on garbage no caller can partially trust: a non-object payload, or a missing/
|
|
654
555
|
* non-finite `version` — that is not "a bad domain", it is not an effective config at all. */
|
|
655
556
|
export declare function readEffectiveWire(raw: unknown, onWarning?: (w: EffectiveReadWarning) => void): EffectiveWire;
|
|
656
557
|
/** 档位组→引擎单表的唯一解析点(0.9.0)。返回 ACTIVE 档位组的绑定表(剔除未绑档),即 core
|
|
657
|
-
* `RunnerDeps.tiers` 要吃的那张单表——组切换=
|
|
658
|
-
* 组内一档未绑 → `undefined`(引擎档位层恒惰性,与「未配 tiers」逐字同义)。消费方(
|
|
558
|
+
* `RunnerDeps.tiers` 要吃的那张单表——组切换=web-admin 换这张表下发,零新引擎机制。无 active 组/未命中/
|
|
559
|
+
* 组内一档未绑 → `undefined`(引擎档位层恒惰性,与「未配 tiers」逐字同义)。消费方(web-admin /effective
|
|
659
560
|
* 投影、service applyEffective 接线)都走这一个函数,不要各自解析。 */
|
|
660
561
|
export declare function resolveActiveTiers(models: Pick<DomainConfig["models"], "tierGroups" | "activeTierGroup">): Record<string, string> | undefined;
|
|
661
562
|
export {};
|