@sema-agent/settings-schema 6.0.0 → 6.1.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 +162 -0
- package/README.md +37 -2
- package/conformance/VERSION +1 -1
- package/conformance/cases/c01-entry-salvage-then-typo/expected.json +3 -0
- package/conformance/cases/c02-hosts-clamp-stacked/expected.json +3 -0
- package/conformance/cases/c23-mixed-validity-models/expected.json +3 -0
- package/conformance/cases/c40-s712-identity-only-what-reads-out/expected.json +166 -0
- package/conformance/cases/c40-s712-identity-only-what-reads-out/input.json +64 -0
- package/conformance/cases/c40-s712-identity-only-what-reads-out/meta.json +13 -0
- package/conformance/cases/cli01-model-name-nfc-vs-nfd/expected.json +8 -0
- package/conformance/cases/cli02-control-and-zero-width-chars/expected.json +8 -0
- package/conformance/cases/t04-secret-literal-never-in-warning-value/expected.json +4 -0
- package/dist/api/auth-bridge.d.ts +2 -2
- package/dist/center-credential.d.ts +116 -0
- package/dist/center-credential.js +149 -0
- package/dist/config-fns.d.ts +35 -3
- package/dist/config-fns.js +57 -8
- package/dist/conformance/types.d.ts +6 -1
- package/dist/conformance/warnings.js +9 -2
- package/dist/fleet.d.ts +98 -8
- package/dist/fleet.js +47 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.js +7 -1
- package/package.json +1 -1
package/dist/fleet.d.ts
CHANGED
|
@@ -45,6 +45,42 @@ export type DrainVerdict = "wait" | "exit_clean" | "exit_forced";
|
|
|
45
45
|
/** The drain state machine's single decision point: keep waiting, exit clean (drained), or force the exit
|
|
46
46
|
* (grace exhausted with legs still in flight — durable legs resume cross-instance via resumeFromRunId). */
|
|
47
47
|
export declare function drainVerdict(s: DrainSnapshot): DrainVerdict;
|
|
48
|
+
/**
|
|
49
|
+
* "This instance must restart to apply config" — the engine's OWN observation (S-741), defined ONCE for both exits that
|
|
50
|
+
* carry it: the fleet heartbeat ({@link InstanceAnnouncement}`.restart`, typed) and GET /health (`restart`, read through
|
|
51
|
+
* {@link readRestartSignal} — {@link InstanceHealth} keeps carrying it untyped, see there). One mint point, two exits —
|
|
52
|
+
* never a second judgement.
|
|
53
|
+
*
|
|
54
|
+
* Shape = what the server already ships on /health (`restart: { reasons, version, since }`). PRESENCE is the signal:
|
|
55
|
+
* present ⇔ a restart is required, absent ⇔ not; there is deliberately no `required` boolean inside (a boolean next
|
|
56
|
+
* to presence is redundant, and two spellings of one fact drift).
|
|
57
|
+
* - `reasons` — which restart-to-apply slices differ from the value baked at boot (the vocabulary is the engine's;
|
|
58
|
+
* the contract only guarantees non-empty words, at least one).
|
|
59
|
+
* - `version` — the config-center version that currently differs from boot (the LATEST seen — it moves forward with
|
|
60
|
+
* later publishes, so a "one restart per version" dedupe bounds restarts per config version, not per reason set).
|
|
61
|
+
* Judged exactly as `readEffectiveWire` judges a config version (a finite number) — one quantity, one rule.
|
|
62
|
+
* - `since` — epoch ms when this restart first became required (stable across refreshes while `reasons` holds).
|
|
63
|
+
*/
|
|
64
|
+
export declare const RestartSignal: z.ZodObject<{
|
|
65
|
+
reasons: z.ZodArray<z.ZodString, "many">;
|
|
66
|
+
version: z.ZodNumber;
|
|
67
|
+
since: z.ZodNumber;
|
|
68
|
+
}, "strip", z.ZodTypeAny, {
|
|
69
|
+
reasons: string[];
|
|
70
|
+
version: number;
|
|
71
|
+
since: number;
|
|
72
|
+
}, {
|
|
73
|
+
reasons: string[];
|
|
74
|
+
version: number;
|
|
75
|
+
since: number;
|
|
76
|
+
}>;
|
|
77
|
+
export type RestartSignal = z.infer<typeof RestartSignal>;
|
|
78
|
+
/**
|
|
79
|
+
* The /health exit of {@link RestartSignal}: `health.restart` judged against the one shape. Shape mismatch, a missing
|
|
80
|
+
* key, a non-object body, even a throwing accessor ⇒ `undefined` — never throws (a probe must not die on one odd body).
|
|
81
|
+
* Presence law: only `restart` counts; the top-level `restartRequired` boolean the server also ships is not read.
|
|
82
|
+
*/
|
|
83
|
+
export declare function readRestartSignal(health: unknown): RestartSignal | undefined;
|
|
48
84
|
/** The `/health` self-description every orchestrator reads (shipped shape, server 1.96.0). Liveness and
|
|
49
85
|
* readiness are deliberately SPLIT: `status` stays ok while draining (the process is alive); routability is
|
|
50
86
|
* `isReadyForTraffic`. Unknown fields pass through — health is a self-description, not a closed record. */
|
|
@@ -93,25 +129,52 @@ export declare const InstanceAnnouncement: z.ZodObject<{
|
|
|
93
129
|
/** reachable base URL for the deployment form: k8s pod IP:port / docker net alias / 127.0.0.1:<engine.port> */
|
|
94
130
|
address: z.ZodString;
|
|
95
131
|
version: z.ZodString;
|
|
96
|
-
/** self-declared:
|
|
132
|
+
/** self-declared readiness: model roster landed AND not draining (server ≥7.102.0; older engines: !draining only) */
|
|
97
133
|
ready: z.ZodBoolean;
|
|
98
134
|
draining: z.ZodDefault<z.ZodBoolean>;
|
|
99
135
|
heartbeatMs: z.ZodDefault<z.ZodNumber>;
|
|
136
|
+
/** S-741: present ⇔ this instance must restart to apply config — the SAME {@link RestartSignal} /health carries,
|
|
137
|
+
* minted by the same getter (self-reported: a worker-scoped credential can only report for its own worker).
|
|
138
|
+
* Every heartbeat re-announces the full row, so a later heartbeat WITHOUT it means "no longer required" — the
|
|
139
|
+
* stored row ({@link InstanceRegistration}) is replaced, never merged. */
|
|
140
|
+
restart: z.ZodOptional<z.ZodObject<{
|
|
141
|
+
reasons: z.ZodArray<z.ZodString, "many">;
|
|
142
|
+
version: z.ZodNumber;
|
|
143
|
+
since: z.ZodNumber;
|
|
144
|
+
}, "strip", z.ZodTypeAny, {
|
|
145
|
+
reasons: string[];
|
|
146
|
+
version: number;
|
|
147
|
+
since: number;
|
|
148
|
+
}, {
|
|
149
|
+
reasons: string[];
|
|
150
|
+
version: number;
|
|
151
|
+
since: number;
|
|
152
|
+
}>>;
|
|
100
153
|
}, "strip", z.ZodTypeAny, {
|
|
101
154
|
draining: boolean;
|
|
102
|
-
instanceId: string;
|
|
103
155
|
version: string;
|
|
156
|
+
instanceId: string;
|
|
104
157
|
worker: string;
|
|
105
158
|
address: string;
|
|
106
159
|
ready: boolean;
|
|
107
160
|
heartbeatMs: number;
|
|
161
|
+
restart?: {
|
|
162
|
+
reasons: string[];
|
|
163
|
+
version: number;
|
|
164
|
+
since: number;
|
|
165
|
+
} | undefined;
|
|
108
166
|
}, {
|
|
109
|
-
instanceId: string;
|
|
110
167
|
version: string;
|
|
168
|
+
instanceId: string;
|
|
111
169
|
worker: string;
|
|
112
170
|
address: string;
|
|
113
171
|
ready: boolean;
|
|
114
172
|
draining?: boolean | undefined;
|
|
173
|
+
restart?: {
|
|
174
|
+
reasons: string[];
|
|
175
|
+
version: number;
|
|
176
|
+
since: number;
|
|
177
|
+
} | undefined;
|
|
115
178
|
heartbeatMs?: number | undefined;
|
|
116
179
|
}>;
|
|
117
180
|
export type InstanceAnnouncement = z.infer<typeof InstanceAnnouncement>;
|
|
@@ -139,34 +202,61 @@ export declare const InstanceRegistration: z.ZodObject<{
|
|
|
139
202
|
/** reachable base URL for the deployment form: k8s pod IP:port / docker net alias / 127.0.0.1:<engine.port> */
|
|
140
203
|
address: z.ZodString;
|
|
141
204
|
version: z.ZodString;
|
|
142
|
-
/** self-declared:
|
|
205
|
+
/** self-declared readiness: model roster landed AND not draining (server ≥7.102.0; older engines: !draining only) */
|
|
143
206
|
ready: z.ZodBoolean;
|
|
144
207
|
draining: z.ZodDefault<z.ZodBoolean>;
|
|
145
208
|
heartbeatMs: z.ZodDefault<z.ZodNumber>;
|
|
209
|
+
/** S-741: present ⇔ this instance must restart to apply config — the SAME {@link RestartSignal} /health carries,
|
|
210
|
+
* minted by the same getter (self-reported: a worker-scoped credential can only report for its own worker).
|
|
211
|
+
* Every heartbeat re-announces the full row, so a later heartbeat WITHOUT it means "no longer required" — the
|
|
212
|
+
* stored row ({@link InstanceRegistration}) is replaced, never merged. */
|
|
213
|
+
restart: z.ZodOptional<z.ZodObject<{
|
|
214
|
+
reasons: z.ZodArray<z.ZodString, "many">;
|
|
215
|
+
version: z.ZodNumber;
|
|
216
|
+
since: z.ZodNumber;
|
|
217
|
+
}, "strip", z.ZodTypeAny, {
|
|
218
|
+
reasons: string[];
|
|
219
|
+
version: number;
|
|
220
|
+
since: number;
|
|
221
|
+
}, {
|
|
222
|
+
reasons: string[];
|
|
223
|
+
version: number;
|
|
224
|
+
since: number;
|
|
225
|
+
}>>;
|
|
146
226
|
} & {
|
|
147
227
|
registeredMs: z.ZodNumber;
|
|
148
228
|
lastSeenMs: z.ZodNumber;
|
|
149
229
|
observedReady: z.ZodOptional<z.ZodBoolean>;
|
|
150
230
|
}, "strip", z.ZodTypeAny, {
|
|
151
231
|
draining: boolean;
|
|
152
|
-
instanceId: string;
|
|
153
232
|
version: string;
|
|
233
|
+
instanceId: string;
|
|
154
234
|
worker: string;
|
|
155
235
|
address: string;
|
|
156
236
|
ready: boolean;
|
|
157
237
|
heartbeatMs: number;
|
|
158
238
|
registeredMs: number;
|
|
159
239
|
lastSeenMs: number;
|
|
240
|
+
restart?: {
|
|
241
|
+
reasons: string[];
|
|
242
|
+
version: number;
|
|
243
|
+
since: number;
|
|
244
|
+
} | undefined;
|
|
160
245
|
observedReady?: boolean | undefined;
|
|
161
246
|
}, {
|
|
162
|
-
instanceId: string;
|
|
163
247
|
version: string;
|
|
248
|
+
instanceId: string;
|
|
164
249
|
worker: string;
|
|
165
250
|
address: string;
|
|
166
251
|
ready: boolean;
|
|
167
252
|
registeredMs: number;
|
|
168
253
|
lastSeenMs: number;
|
|
169
254
|
draining?: boolean | undefined;
|
|
255
|
+
restart?: {
|
|
256
|
+
reasons: string[];
|
|
257
|
+
version: number;
|
|
258
|
+
since: number;
|
|
259
|
+
} | undefined;
|
|
170
260
|
heartbeatMs?: number | undefined;
|
|
171
261
|
observedReady?: boolean | undefined;
|
|
172
262
|
}>;
|
|
@@ -410,7 +500,6 @@ export declare const UsageReport: z.ZodObject<{
|
|
|
410
500
|
quotaWeightAtUse?: number | undefined;
|
|
411
501
|
}>, "many">;
|
|
412
502
|
}, "strip", z.ZodTypeAny, {
|
|
413
|
-
instanceId: string;
|
|
414
503
|
entries: {
|
|
415
504
|
principal: string;
|
|
416
505
|
model: string;
|
|
@@ -421,11 +510,11 @@ export declare const UsageReport: z.ZodObject<{
|
|
|
421
510
|
runs?: number | undefined;
|
|
422
511
|
quotaWeightAtUse?: number | undefined;
|
|
423
512
|
}[];
|
|
513
|
+
instanceId: string;
|
|
424
514
|
worker: string;
|
|
425
515
|
windowStartMs: number;
|
|
426
516
|
windowEndMs: number;
|
|
427
517
|
}, {
|
|
428
|
-
instanceId: string;
|
|
429
518
|
entries: {
|
|
430
519
|
principal: string;
|
|
431
520
|
model: string;
|
|
@@ -436,6 +525,7 @@ export declare const UsageReport: z.ZodObject<{
|
|
|
436
525
|
runs?: number | undefined;
|
|
437
526
|
quotaWeightAtUse?: number | undefined;
|
|
438
527
|
}[];
|
|
528
|
+
instanceId: string;
|
|
439
529
|
worker: string;
|
|
440
530
|
windowStartMs: number;
|
|
441
531
|
windowEndMs: number;
|
package/dist/fleet.js
CHANGED
|
@@ -40,6 +40,43 @@ export function drainVerdict(s) {
|
|
|
40
40
|
const grace = Math.max(DRAIN_GRACE_FLOOR_MS, s.graceMs);
|
|
41
41
|
return s.nowMs - s.startedMs >= grace ? "exit_forced" : "wait";
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* "This instance must restart to apply config" — the engine's OWN observation (S-741), defined ONCE for both exits that
|
|
45
|
+
* carry it: the fleet heartbeat ({@link InstanceAnnouncement}`.restart`, typed) and GET /health (`restart`, read through
|
|
46
|
+
* {@link readRestartSignal} — {@link InstanceHealth} keeps carrying it untyped, see there). One mint point, two exits —
|
|
47
|
+
* never a second judgement.
|
|
48
|
+
*
|
|
49
|
+
* Shape = what the server already ships on /health (`restart: { reasons, version, since }`). PRESENCE is the signal:
|
|
50
|
+
* present ⇔ a restart is required, absent ⇔ not; there is deliberately no `required` boolean inside (a boolean next
|
|
51
|
+
* to presence is redundant, and two spellings of one fact drift).
|
|
52
|
+
* - `reasons` — which restart-to-apply slices differ from the value baked at boot (the vocabulary is the engine's;
|
|
53
|
+
* the contract only guarantees non-empty words, at least one).
|
|
54
|
+
* - `version` — the config-center version that currently differs from boot (the LATEST seen — it moves forward with
|
|
55
|
+
* later publishes, so a "one restart per version" dedupe bounds restarts per config version, not per reason set).
|
|
56
|
+
* Judged exactly as `readEffectiveWire` judges a config version (a finite number) — one quantity, one rule.
|
|
57
|
+
* - `since` — epoch ms when this restart first became required (stable across refreshes while `reasons` holds).
|
|
58
|
+
*/
|
|
59
|
+
export const RestartSignal = z.object({
|
|
60
|
+
reasons: z.array(z.string().min(1)).min(1),
|
|
61
|
+
version: z.number().finite(),
|
|
62
|
+
since: z.number().int().nonnegative(),
|
|
63
|
+
});
|
|
64
|
+
/**
|
|
65
|
+
* The /health exit of {@link RestartSignal}: `health.restart` judged against the one shape. Shape mismatch, a missing
|
|
66
|
+
* key, a non-object body, even a throwing accessor ⇒ `undefined` — never throws (a probe must not die on one odd body).
|
|
67
|
+
* Presence law: only `restart` counts; the top-level `restartRequired` boolean the server also ships is not read.
|
|
68
|
+
*/
|
|
69
|
+
export function readRestartSignal(health) {
|
|
70
|
+
try {
|
|
71
|
+
if (health === null || typeof health !== "object" || Array.isArray(health))
|
|
72
|
+
return undefined;
|
|
73
|
+
const parsed = RestartSignal.safeParse(health.restart);
|
|
74
|
+
return parsed.success ? parsed.data : undefined;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
43
80
|
/** The `/health` self-description every orchestrator reads (shipped shape, server 1.96.0). Liveness and
|
|
44
81
|
* readiness are deliberately SPLIT: `status` stays ok while draining (the process is alive); routability is
|
|
45
82
|
* `isReadyForTraffic`. Unknown fields pass through — health is a self-description, not a closed record. */
|
|
@@ -52,6 +89,10 @@ export const InstanceHealth = z
|
|
|
52
89
|
draining: z.boolean().optional(),
|
|
53
90
|
/** epoch ms, present iff draining */
|
|
54
91
|
drainingSince: z.number().optional(),
|
|
92
|
+
// S-741: the server's `restart` (and its redundant top-level `restartRequired` boolean) ride the passthrough
|
|
93
|
+
// UNTYPED on purpose — typing `restart` here would turn today's lenient read into a strict one (a /health body with
|
|
94
|
+
// an odd `restart` would stop parsing), which is a MAJOR by this package's release rules. Read it with
|
|
95
|
+
// {@link readRestartSignal}. Typing it on this schema is an item for the next major.
|
|
55
96
|
})
|
|
56
97
|
.passthrough();
|
|
57
98
|
/** Readiness = the routability predicate (k8s readiness probe, gateway health filter, shell seam switch). */
|
|
@@ -76,10 +117,15 @@ export const InstanceAnnouncement = z.object({
|
|
|
76
117
|
/** reachable base URL for the deployment form: k8s pod IP:port / docker net alias / 127.0.0.1:<engine.port> */
|
|
77
118
|
address: z.string().min(1),
|
|
78
119
|
version: z.string().min(1),
|
|
79
|
-
/** self-declared:
|
|
120
|
+
/** self-declared readiness: model roster landed AND not draining (server ≥7.102.0; older engines: !draining only) */
|
|
80
121
|
ready: z.boolean(),
|
|
81
122
|
draining: z.boolean().default(false),
|
|
82
123
|
heartbeatMs: z.number().int().positive().default(DEFAULT_HEARTBEAT_MS),
|
|
124
|
+
/** S-741: present ⇔ this instance must restart to apply config — the SAME {@link RestartSignal} /health carries,
|
|
125
|
+
* minted by the same getter (self-reported: a worker-scoped credential can only report for its own worker).
|
|
126
|
+
* Every heartbeat re-announces the full row, so a later heartbeat WITHOUT it means "no longer required" — the
|
|
127
|
+
* stored row ({@link InstanceRegistration}) is replaced, never merged. */
|
|
128
|
+
restart: RestartSignal.optional(),
|
|
83
129
|
});
|
|
84
130
|
/** Explicit goodbye (stop signal handler) — removes the row immediately instead of waiting out staleness. */
|
|
85
131
|
export const InstanceDeregistration = z.object({
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@ export * from "./migrate.js"; // 0.5→0.6 migration tools (hosts grandfathering
|
|
|
21
21
|
export * from "./api/auth.js"; // /api/v1/auth/* wire contract (RFC 8628 device flow + rotating refresh + logout + approve) — REGISTRY-REBUILD-DESIGN §2, M1 shipped shapes frozen, pure/browser-safe
|
|
22
22
|
export * from "./api/auth-bridge.js"; // 鉴权桥 contract: worker verifies registry user JWT (RS256-only, JWKS kid-miss refresh + throttle, offline grace fail-closed) → VerifiedIdentity — design §5, the service verifier's spec
|
|
23
23
|
export * from "./api/scopes.js"; // multi-tenant scope contract: /api/v1/scopes* + /api/v1/auth/scope wire shapes + THE minting/switch decision functions (resolveTokenScope / canSwitchScope / effectiveScopeRole / tokenScopeOf) — registry imports these, never re-implements
|
|
24
|
+
export * from "./center-credential.js"; // S-698 center-credential FILE contract: CenterCredentialEnvelope (user-session envelope, strict) + parseCenterCredentialFile (bare / envelope / unreadable — the one discrimination law) + S-742 CENTER_CREDENTIAL_ENV (the two declaration keys) + judgeCenterCredentialDeclaration (pick-exactly-one), pure/browser-safe
|
|
24
25
|
// NOTE: the Node-fs-backed helpers (FileConfigStore + the file editor) are NOT in this barrel — they pull
|
|
25
26
|
// `node:fs`/`node:path` and would break a browser/client bundle that only wants the contract (e.g.
|
|
26
27
|
// sema-registry's client components import the zod types through here). Import them from the Node-only
|
package/dist/types.d.ts
CHANGED
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
* `ENV_NAME` schema (regex) on every `*Env` field — a pasted secret value is rejected, not just discouraged.
|
|
17
17
|
*/
|
|
18
18
|
import { z } from "zod";
|
|
19
|
+
/** A private-key PEM header (`-----BEGIN [RSA |EC |OPENSSH |ENCRYPTED ]PRIVATE KEY`), unanchored — the ONE definition
|
|
20
|
+
* of that shape: {@link SECRET_LITERAL_RE} is composed from it (anchored, as one of its branches), and
|
|
21
|
+
* `redactSecrets` (config-fns) tests it ANYWHERE in a string. It carries spaces, so the token-splitting detector
|
|
22
|
+
* {@link containsSecretToken} only sees it at the very start of a string; a PEM behind a newline or a `key: ` prefix
|
|
23
|
+
* slipped past (S-712 codex review [high]). Public keys / certificates never match (see above). */
|
|
24
|
+
export declare const PRIVATE_KEY_PEM_HEADER: RegExp;
|
|
19
25
|
export declare const SECRET_LITERAL_RE: RegExp;
|
|
20
26
|
export declare const ENV_NAME: z.ZodEffects<z.ZodString, string, string>;
|
|
21
27
|
/** A NUL byte in a string the consumer feeds to spawn()/fs is a FAIL-OPEN config: it validates+persists here
|
package/dist/types.js
CHANGED
|
@@ -26,7 +26,13 @@ import { DispatchPolicy } from "./fleet.js"; // WorkerSpec.fleet.dispatch (sched
|
|
|
26
26
|
// — a PUBLIC KEY / CERTIFICATE is NOT a secret and must NOT be flagged (PRINCIPAL_JWT_PUBKEYS lives in env).
|
|
27
27
|
// 0.1.32: this is the root fix for the public-key false-positive — replaces the 0.1.31 name-based exemption,
|
|
28
28
|
// which review flagged as a bypass (a private key misnamed `*_PUBKEY` skipped scanning entirely).
|
|
29
|
-
|
|
29
|
+
/** A private-key PEM header (`-----BEGIN [RSA |EC |OPENSSH |ENCRYPTED ]PRIVATE KEY`), unanchored — the ONE definition
|
|
30
|
+
* of that shape: {@link SECRET_LITERAL_RE} is composed from it (anchored, as one of its branches), and
|
|
31
|
+
* `redactSecrets` (config-fns) tests it ANYWHERE in a string. It carries spaces, so the token-splitting detector
|
|
32
|
+
* {@link containsSecretToken} only sees it at the very start of a string; a PEM behind a newline or a `key: ` prefix
|
|
33
|
+
* slipped past (S-712 codex review [high]). Public keys / certificates never match (see above). */
|
|
34
|
+
export const PRIVATE_KEY_PEM_HEADER = /-----BEGIN[A-Z0-9 ]*PRIVATE KEY/i;
|
|
35
|
+
export const SECRET_LITERAL_RE = new RegExp(`^(sk-|gh[opus]_|github_pat_|xox[baprse]-|xapp-|bearer\\s|basic\\s|eyJ[A-Za-z0-9_-]{10,}\\.|AKIA[0-9A-Z]{12,}|AIza[0-9A-Za-z_-]{20,}|${PRIVATE_KEY_PEM_HEADER.source})`, "i");
|
|
30
36
|
// 所有 *Env / *tokenEnv 字段的值是宿主机 env 变量的 NAME(不是值)。合法 env 变量名 + 拒绝 secret 形状的值(AKIA…
|
|
31
37
|
// 这类是合法 env-NAME 字符集却是密钥)—— "只存 env-NAME、绝不存 secret 值" 由 SCHEMA 保证。Round-5。
|
|
32
38
|
export const ENV_NAME = z
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/settings-schema",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "Sema settings schema — pure config contract (zod domains + effective-config + roster resolution + ref-integrity + remoteExec) shared by sema-registry, sema-server, and the TOC desktop/CLI. One source of truth. (Renamed at 1.0.0 from @sema-agent/registry-core — name and docs only, no behavior change; note the range moves 0.19.0 -> 1.0.0, so a dependency must become ^1.0.0. The old names @sema-agent/registry-core <=0.19.0 and @sema-ai/registry-core remain published, frozen, for migration.)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BUSL-1.1",
|