import type { ServiceConfig, ServiceConfigGroups } from "./config-types.js"; import type { ConfigKnobRecord } from "./config.js"; import type { RestartSlice } from "./config-center/restart-signal.js"; export declare const CATALOG_VALUE_TYPES: readonly ["boolean", "number", "string", "enum", "csv", "json", "path", "url", "secret", "opaque"]; export type CatalogValueType = (typeof CATALOG_VALUE_TYPES)[number]; export declare const CATALOG_TIMINGS: readonly ["hot", "restart", "deploy", "inert"]; export type CatalogTiming = (typeof CATALOG_TIMINGS)[number]; export declare const CATALOG_DANGER_AXES: readonly ["security", "billing", "data"]; export type CatalogDangerAxis = (typeof CATALOG_DANGER_AXES)[number]; /** 域 = 配置九组(类型锁步:组集变了这里跟着红)。 */ export type CatalogDomain = keyof ServiceConfigGroups; export declare const CATALOG_RESTART_SLICES: readonly RestartSlice[]; /** center 联接座(spec 层)。`models-plane` 是内部时机词:build 时按 tier 表在场性实算成 hot/restart。 */ export interface CatalogCenterSeatSpec { readonly domain: string; readonly path: string; /** `centerManagedKeys`(config-center 在管键集)里查「在管」用的键;models 面统一 "models"。 */ readonly centerKey: string; readonly precedence: "center-wins" | "env-wins"; readonly timing: "hot" | "restart" | "inert" | "models-plane"; readonly restartSlice?: RestartSlice; readonly restartReason?: string; } export type CatalogValue = string | number | boolean | readonly string[] | null | { readonly present: boolean; readonly length?: number; }; export interface ConfigCatalogSpec { readonly name: string; readonly domain: CatalogDomain; readonly type: CatalogValueType; readonly semantics: string; readonly staticDefault?: string; readonly derivedDefaultNote?: string; readonly danger?: readonly CatalogDangerAxis[]; readonly enumValues?: readonly string[]; /** * S-201① —— 本行**回显**得出的词集(`enumValues` 的子集;缺席 ⇒ 与 `enumValues` 同集)。 * * 🔴 `enumValues` 一直是**两义**的:它既是行对外宣告的「你可以写哪些词」([ref] 件⑤/⑧ 两条钉逐字锚 * 这一义:窄了=少宣告一档、宽了=宣告一个 boot 会拒的词),又被回显校验当成「实算值合不合法」的闭集。 * 两义在**多数**行上碰巧同集,于是差别只活在散文里 —— `MANUAL_MODE_SHELL_GATE` 的 * `derivedDefaultNote` 写着「真姿态只有 always/classify 两个」,`MODEL_DEFAULT_THINKING` 写着 * 「缺席/off ⇒ 不铸」,而**没有任何一条腿读那两句话**:`off` 照样留在回显闭集里,回显校验对它放行。 * * ⇒ 把那半句散文变成一处**校验腿真读的声明**:`sanitizeEnumValue` 问 `echoWords ?? enumValues`, * 于是「这一格的合法回显值」从此只有一个属主,不再靠人脑对两个词表做差集。 * * 🔴 **不上 wire**:消费方(UI 下拉、非法值的纠错提示)要的是「可写集」= `enumValues`,那一义不变; * 本字段服务的是服务端自己的回显纪律。一个词进得了 `enumValues` 却不在这里 ⇒ 它的语义恒是 * 「**缺席的另一种拼法**」(写下去与不写同效),那正是目前仅有的两行的形。 */ readonly echoWords?: readonly string[]; /** * S-100 —— **底层布尔 ↔ 闭集词**的行内映射,只给「实算腿回布尔、而行对外说词」的 enum 行。 * * 为什么写在行上而不是建第二张全局极性表:`config.ts` 的极性表(`ConfigKnobRecord`)记的是 * **布尔旋钮**的来源与默认方向,它压根不带词 —— 拿它当 `true→enumValues[0]` 的位置约定用,等于 * 在两个文件之间约定一个不写下来的下标。行自己声明,是同一处声明它 `enumValues` 的地方。 * * 某一极**没有词**(该极的真实投影是「键不在场」)⇒ 显式写 `null`,不是省略 —— 省略与「这一行忘了 * 声明映射」在形上同形,而后者必须落到响亮的 `effectiveValueInvalid` 臂。 */ readonly booleanEnum?: { readonly true: string | null; readonly false: string | null; }; /** `ServiceConfig` 的平铺键(实算兜底 + center managedNow 判据对表用;嵌套块不填,走 resolve)。 */ readonly configKey?: string; /** * 本进程实算(非 secret/opaque 行才可用;返回 undefined = 本行没有实算腿,落 env 原文/staticDefault)。 * * 🔴 第二参是**部署 env**,不是第五条供值腿:有几根旋钮的属主不在 `ServiceConfig` 上(它在装配点按 * env 现算,如 WebSearch 后端),而目录的纪律是「回显属主算出来的值」—— 只能把同一条实算腿的入参放宽, * 不能在目录里再抄一遍属主的读法(S-100 / codex r1 F3 的成案:抄一遍就是第二个写者,当场分歧)。 */ readonly resolve?: (config: ServiceConfig, env: NodeJS.ProcessEnv) => CatalogValue | undefined; readonly center?: CatalogCenterSeatSpec; /** 缺省 "deploy";retired/零消费键标 "inert"(设计稿 ⚪ 的 env 腿投影)。 */ readonly envTiming?: "inert"; readonly scope?: "bootstrap-only"; } export interface ConfigCatalogRowCenter { readonly domain: string; readonly path: string; readonly precedence: "center-wins" | "env-wins"; readonly timing: Exclude; readonly restartSlice?: RestartSlice; readonly restartReason?: string; /** settings-schema 现行 DOMAINS 里真有这个域(false = 设计稿 ⚪ 成因 b「该片暂无配置中心写腿」)。 */ readonly domainExists: boolean; /** center 的最近一份 effective **当前在管**本键(没有配置管道 ⇒ 恒 false)。 */ readonly managedNow: boolean; /** center 写**现在真的在生效**(在管 ∧ 未被 env 占位压住;env-wins 族 env 占位 ⇒ false = ⚪ 成因 a)。 */ readonly effectiveNow: boolean; } export interface ConfigCatalogRow { readonly name: string; readonly domain: CatalogDomain; readonly type: CatalogValueType; readonly semantics: string; readonly writeLanes: readonly ("env" | "center")[]; readonly effectiveLane: "env" | "center" | "default"; readonly envHeld: boolean; readonly envTiming: "deploy" | "inert"; readonly staticDefault?: string; readonly derivedDefaultNote?: string; readonly effectiveValue: CatalogValue; /** * S-100(additive;**只在真非法时铸,恒不铸 `false`**)—— 本行的实算值**落在它自己宣告的 * 回显闭集之外**(`echoWords ?? enumValues`,S-201①),或它的实算腿回了一个本行没有声明映射的布尔。 * * 在场时 `effectiveValue` 恒 `null`:回显一个集外值等于目录在教消费方写一个写回去就非法的词, * 而**静默丢**会让「配错了」与「真的没设」在 wire 上同形([ref] 响亮臂)。 * 缺席 = 这一格没问题(不是「不知道」)。 */ readonly effectiveValueInvalid?: true; readonly valueClass: "plain" | "secret" | "opaque"; readonly danger: readonly CatalogDangerAxis[]; readonly center?: ConfigCatalogRowCenter; readonly centerDomain?: string; readonly centerPath?: string; readonly scope?: "bootstrap-only"; readonly enumValues?: readonly string[]; } export interface ConfigCatalogInputs { readonly config: ServiceConfig; readonly env: NodeJS.ProcessEnv; readonly knobs: readonly ConfigKnobRecord[]; /** settings-schema 现行 DOMAINS(调用方传入 —— 本模块保持纯数据层,零包依赖)。 */ readonly centerDomains: readonly string[]; /** config-center 当前在管的 ServiceConfig 键集(缺席 = 没有配置管道)。 */ readonly centerManagedKeys?: ReadonlySet | undefined; } export interface ConfigCatalogWire { readonly catalogVersion: 1; /** env 腿的统一时机(env 运行期不可变 ⇒ 改 env=改部署面;行级 `envTiming:"inert"` 覆写)。 */ readonly envLaneTiming: "deploy"; readonly restartSlices: readonly RestartSlice[]; readonly centerDomains: readonly string[]; readonly summary: { readonly total: number; readonly envHeld: number; readonly secret: number; readonly centerManaged: number; }; readonly rows: readonly ConfigCatalogRow[]; } /** * 目录表(按名排序 —— 卫生格执法)。语义句以读取点实现为准(不信注释纪律:本表成文时逐键对过 * config.ts / boot / plugins 的真实读取臂;后续漂移由 D1 对账门逼着回到这里补行)。 */ export declare const CONFIG_CATALOG: readonly ConfigCatalogSpec[]; /** `build*` 命名(工厂纪律):产物是纯数据(wire 投影),零方法零捕获行为。 */ export declare function buildConfigCatalog(inputs: ConfigCatalogInputs): ConfigCatalogWire; //# sourceMappingURL=config-catalog.d.ts.map