@sema-agent/server 7.128.0 → 7.129.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +118 -0
- package/USAGE.md +89 -18
- package/dist/approval-card.d.ts +53 -26
- package/dist/approval-card.js +40 -11
- package/dist/approval-crash-convergence.js +4 -4
- package/dist/bake-runner/main.js +2 -1
- package/dist/boot/memory-consolidation.d.ts +46 -16
- package/dist/boot/memory-consolidation.js +15 -8
- package/dist/boot/side-query-lane.d.ts +7 -20
- package/dist/boot/side-query-lane.js +0 -24
- package/dist/boot/stage-01-config.js +3 -0
- package/dist/boot/stage-06-runners.js +1 -1
- package/dist/boot/stores.js +2 -2
- package/dist/boot/web-admin.js +17 -10
- package/dist/boot/webfetch-summarize-lane.d.ts +10 -7
- package/dist/boot/webfetch-summarize-lane.js +2 -3
- package/dist/brain.js +6 -9
- package/dist/capabilities/builtin-tools.d.ts +2 -2
- package/dist/capabilities/engine-capabilities.d.ts +14 -0
- package/dist/capabilities/engine-capabilities.js +12 -0
- package/dist/capability-facts.d.ts +3 -1
- package/dist/capability-facts.js +1 -0
- package/dist/config-types.d.ts +4 -3
- package/dist/egress-redirect.d.ts +12 -0
- package/dist/egress-redirect.js +7 -0
- package/dist/entry-mode-clamp-notice.d.ts +30 -0
- package/dist/entry-mode-clamp-notice.js +13 -0
- package/dist/fleet/fleet-bus.d.ts +7 -0
- package/dist/fleet/fleet-bus.js +1 -0
- package/dist/hooks/hook-llm.js +6 -2
- package/dist/host-lsp-manager.d.ts +3 -3
- package/dist/http/admission.js +5 -2
- package/dist/http/resume-legs.js +46 -27
- package/dist/http/route-ctx.d.ts +1 -1
- package/dist/http/routes/approvals-assistant.js +6 -4
- package/dist/http/routes/capabilities.js +1 -0
- package/dist/http/routes/session-sync.js +3 -4
- package/dist/http/routes/sessions.js +4 -17
- package/dist/http/send.d.ts +1 -1
- package/dist/http/send.js +4 -3
- package/dist/http/wire-types.d.ts +3 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/observability/fail-open.d.ts +7 -3
- package/dist/observability/fail-open.js +7 -3
- package/dist/observability/secret-env-scrub.d.ts +37 -3
- package/dist/observability/secret-env-scrub.js +2 -2
- package/dist/parked-decide.js +5 -2
- package/dist/plugins/memory-embedder.js +5 -0
- package/dist/plugins/one-time-migrations.d.ts +180 -9
- package/dist/plugins/one-time-migrations.js +315 -3
- package/dist/plugins/pg-pool.js +3 -1
- package/dist/plugins/remote-env-host.d.ts +17 -20
- package/dist/plugins/remote-env-host.js +13 -25
- package/dist/plugins/session-policy-store-sql.d.ts +16 -4
- package/dist/plugins/session-policy-store-sql.js +17 -20
- package/dist/plugins/session-rules-column.d.ts +16 -0
- package/dist/plugins/session-rules-column.js +6 -0
- package/dist/plugins/tidb-pool.js +4 -1
- package/dist/read-face-posture.d.ts +2 -1
- package/dist/request-value-closure.js +1 -1
- package/dist/retired-card-words.d.ts +17 -0
- package/dist/retired-card-words.js +49 -0
- package/dist/rule-entry-list.js +2 -0
- package/dist/run-local.js +10 -3
- package/dist/server-secret-env.d.ts +77 -85
- package/dist/server-secret-env.js +40 -26
- package/dist/session-policy-wire.d.ts +61 -124
- package/dist/session-policy-wire.js +59 -121
- package/dist/session-sync.d.ts +8 -6
- package/dist/session-sync.js +6 -5
- package/dist/spec-fields.d.ts +3 -2
- package/dist/standing-answer-grant.d.ts +17 -9
- package/dist/standing-answer-grant.js +11 -8
- package/dist/task-settings.d.ts +6 -1
- package/dist/task-settings.js +1 -1
- package/dist/tool-approval.d.ts +14 -7
- package/dist/tool-approval.js +23 -18
- package/dist/trace/core-keyset-guard.d.ts +3 -3
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +1 -0
- package/dist/trace/project.d.ts +7 -4
- package/dist/trace/project.js +6 -75
- package/dist/trace/tool-output-media.d.ts +2 -1
- package/dist/trace/tool-output-media.js +3 -25
- package/dist/web-admin-client/apply-effective.js +28 -11
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/facade.js +1 -1
- package/dist/web-admin-client/read-face.d.ts +73 -20
- package/dist/web-admin-client/read-face.js +76 -36
- package/dist/web-admin-client/skills-mcp.d.ts +1 -1
- package/dist/web-admin-client/skills-mcp.js +1 -1
- package/dist/web-admin-client/types.d.ts +3 -3
- package/package.json +3 -3
- package/dist/mcp-tool-axes.d.ts +0 -62
- package/dist/mcp-tool-axes.js +0 -47
|
@@ -43,9 +43,9 @@ export declare const FAIL_OPEN_TAGS: {
|
|
|
43
43
|
readonly cls: "F";
|
|
44
44
|
readonly note: "core 7.50.0 媒体块提货(`trace/tool-output-media.ts` 的 `liveToolEndForBacklog`,三处活面写口共用的那一只判据 —— 同步流出口 `sseData`、子代 tail 路由写环、tail 总线每订阅者队列):本帧媒体字节(`output` 媒体块的 `data` 与 `structured` 媒体卡的 `file.base64` 一起计)+ 这条连接 / 这个订阅者还没送出去的字节 > 上界(64 MiB)⇒ 本帧媒体降成持久面那只形(媒体块换描述符 `{ type, mimeType?, bytes, truncated: true }`,帧级 `truncated` + `totalChars`;媒体卡去掉 `file.base64`)。每降一帧记一次,只在这只函数里记(三处写口不各记)。放行的最坏后果 = 一个读得慢的观众在 SSE 上看不到这张图,只见「这里有一张多大的什么图、没送达」(账本面本就恒是描述符),不是门、不是凭据、不改任何裁决;反方向(不降)让一条停读的连接随帧数线性压住几百 MiB。帧上它与引擎自己的媒体预算降级同形不可分,所以计数是运维唯一能看出「多少观众丢了图」的位;计数持续非零 = 有消费端读流太慢(或网络瓶颈),去看那几条连接。detail = `backlog=<待发字节> media=<本帧媒体字节>`。";
|
|
45
45
|
};
|
|
46
|
-
readonly "server.memory-consolidation.operator-valve-
|
|
46
|
+
readonly "server.memory-consolidation.operator-valve-layers-unfed": {
|
|
47
47
|
readonly cls: "P-DEBT";
|
|
48
|
-
readonly note: "core 7.
|
|
48
|
+
readonly note: "core 7.51.0 #1718 提货(`boot/memory-consolidation.ts` `createOperatorValveWriteJudge`):运维手动整理阀门的写判官座已是引擎的那一只构造器,但三层没喂 —— 人的持久规则层(阀门没有「库属于谁」的来源,无 principal / 不声明 local-owner)、部署的调用方策略层(`APPROVAL_REQUIRE` / `APPROVAL_DENY` / `AUTONOMY` / 敏感路径守卫集是每任务现合成的活配置、无部署级单例;敏感路径层另需引擎豁免根入参,宿主构造器输入没有这一位)、项目根(项目层 scope 键是任务根的单向散列,反推不出)。每被问一次(早问库目录一次 + 每个产物一次)记一次。放行的最坏后果 = 运维手动整理时,一条点名记忆库路径的人的持久规则或部署写策略(例如 `APPROVAL_DENY=Write`)拦不住这一轮折叠(与 7.128.x 逐字同;只是判官不再是代答);自动整理腿走引擎腿自己的判官,不在本 tag 射程。收口 = 三层各自有了来源(人:「读谁的桶」裁定;策略:一份设计 + 向 core 请托引擎豁免根入参;根:无来源则永久缺席并改写本债)那一版,本 tag 删。";
|
|
49
49
|
};
|
|
50
50
|
readonly "server.workflow-park-index.sync-failed": {
|
|
51
51
|
readonly cls: "P-DEBT";
|
|
@@ -261,7 +261,7 @@ export declare const FAIL_OPEN_TAGS: {
|
|
|
261
261
|
};
|
|
262
262
|
readonly "server.resume.reopen-confirm-unreadable": {
|
|
263
263
|
readonly cls: "F";
|
|
264
|
-
readonly note: "S-447(#60 M2 自查项,`http/resume-legs.ts` 的 `confirmCheckpointReopened`)
|
|
264
|
+
readonly note: "S-447(#60 M2 自查项,`http/resume-legs.ts` 的 `confirmCheckpointReopened`):续跑腿交回一条没 park 的失败结果后(7.129.0 起每一条都问,不再只在三个重开码上问)按 **token** 复核「这张 checkpoint 是不是又 pending 了」,这一读抛(库拖/版本太新/店不可达)。**方向本来就是 fail-closed**:读不出 ⇒ `return true` ⇒ 「不写任何终局、重新 park」(`:1206-1212` 头注已把取舍与有界代价写死:错 park 由 `reapSuspended` 兑,错终局会孤儿化一张活 park 到 TTL)—— 所以这条腿不是 P 类,缺的只是**留痕**。放行的最坏后果 = 多一次多余的 re-park(一张已经被决掉的卡重新挂到 reaper 窗里),人面上是「这条续跑没动」而不是谁被放行了。必须登记的理由是 **uniformity**:同文件三只同形读(`:249` `server.approvals.stale-echoed-token-unreadable` · `:288` `server.approvals.stale-current-pending-unreadable` · 本腿)中只有它是黑的,于是「店一直读不出所以每条续跑都在白白 re-park」与「一切正常」在遥测上同形。计数非零 = 这台机器的 checkpoint 店在拖,运维要去看库。";
|
|
265
265
|
};
|
|
266
266
|
readonly "server.approvals.stale-current-pending-unreadable": {
|
|
267
267
|
readonly cls: "F";
|
|
@@ -327,6 +327,10 @@ export declare const FAIL_OPEN_TAGS: {
|
|
|
327
327
|
readonly cls: "F";
|
|
328
328
|
readonly note: "S-249(`approval-card.ts` 的边界窄读族;今天四个成员:`readRuleOffersAbsence`、S-934 ② 起的 `readAskClassPair`(core 7.37.0 #1214 的类对 `askClass` / `classes`,活卡帧 / 呈卡帧的卡 / 运维队列行同一只,判法 = core 屏 `screenAskClassMembers`(S-955 ⑥ / core 7.38.0 #1249,本仓零自写对判),两键同在同缺,半对 / 集外 / 首员不符 / 重复员 = 屏拒 = 读不出;detail 前缀 `askClass=` / `classes=`),与 S-721 起的 `readClosedWordSeat` —— 一座一只 core 成员筛,座是参数:`mandate`(core 7.32.0 #1092,活卡帧 / 活挂起行 / 运维队列行同一只,闭集筛 = core `isPersistedRuleMandate`)与 S-755 起的 `origin`(运维队列行读 park 行孪生座,闭集筛 = core `isAskOrigin`,与 inbox 行 core 投影处同一只筛)、S-1170 起的 `classifierNoRuling`(core 7.43.0 #1353 的成因词,活卡帧读 `AskRequest.classifierNoRuling`,闭集筛 = core `isAutoModeFallbackCause`)与 `differs`(core 7.44.0 #1374,载体是 `runs.ts` 的 409 `steering.duplicate_input_id` 体读的引擎拒错 `detail.differs`,闭集筛 = core `STEER_REPLAY_FACETS` 的非空子集;集外成员 / 空 / 非数组 ⇒ 不铸 `detail`,码仍是契约);detail 前缀 `ruleOffersAbsence=` / `mandate=` / `origin=` / `classifierNoRuling=` / `differs=` 判别是哪一座;第四个成员是 `approval-content-kind.ts` 的 `readApprovalCard` —— 卡词 `approvalCard` 自己的闭集窄读,活 ask / LOCAL 店停驻门 / SQL 店读出的门子树三个载体共用一只,闭集 = core `TOOL_APPROVAL_CARDS`,detail 前缀 `approvalCard=`):活卡帧 / `card_json` / (S-700 起)运维队列行(`parkRowFacts` 读寄存行上的 park 孪生座;队列是热读面 ⇒ 同一行每读一次计一次)的一个**闭集词**座上,键在场而词不在本仓认得的那张表里(世代差,或第三方 producer)⇒ 该座**按缺席**处置。放行的最坏后果=卡上少一行「为什么这次没有规则候选」的解释(壳退回不显示该行),它**不改变任何裁决**——门在引擎里早已判完,本座是展示/观测面;反方向(把一个消费端词表外的值原样上卡)更坏:下游按闭集写的分支会落进 default 臂或渲染出生词。本臂存在的全部理由是**判别**:修前「上游发了个生词」与「上游根本没发这个键」在遥测上同形,而前者意味着本仓的词表该跟着 core 加词了(型面另有两向编译围栏,但那只在**重新编译**时说话,跑在线上的那一版不会自己红)。detail 带座名与那个词(经 redactSecrets 截 40);数 / 布尔等原始值原样,对象 / 数组 / 函数 / null 只报形名(`<object>` / `<array>` / `<function>` / `<null>`,S-700 codex r1:格式化从不调用值自己的转换方法 —— 持久层里一格 `{\"toString\":null}` 曾让诊断本身抛出、打掉整只队列)。";
|
|
329
329
|
};
|
|
330
|
+
readonly "server.approval-card.retired-card-word-read": {
|
|
331
|
+
readonly cls: "F";
|
|
332
|
+
readonly note: "S-1562(core 7.51.0 #1515 / #1702;一次性迁移 M18 的**读侧半场**,`approval-card.ts` 的 `readStoredCardEnvelope` / `currentParkArm`,窗与删法见 `plugins/one-time-migrations.ts` 登记表 M18 —— 窗关随 M18 删本 tag):存下的审批卡(`approval_ask.card_json`)或停驻行(`pendingAction` 的 `tool_approval` 臂)上带着引擎 7.51.0 退役的词 —— `ruleOffersAbsence: \"shadowed\"` 或类对里的 `governance_unavailable` —— 读时按 M18 那一只改写读(前者删键 = 合法缺席,后者换成 `rule_unreadable`、类集去重按引擎序)。每改写一次记一次;detail = 载体(`card_json` / `parked row`)与座名,不带值。放行的最坏后果 = 无:这一读与存卡的起服改写对同一份字节给同一个答案(一只函数);它不是兜底,它登记在这里是为了**响亮** —— 载体 `card_json` 计数非零 = 有起服改写够不着的卡(滚动升级窗里 7.128.x 副本新写的卡、local 文件 ask 账);载体 `parked row` 计数非零 = 读到了带旧词的停驻行(引擎写的文档,本服务从不改写它 —— 行摘要覆盖类对 `askClass` / `classes`,改写 = 续跑判 `damaged`;所以这一格在窗内随每次读到那样的行而涨,直到那些行被决掉 / 收割),运维据它判断旧副本是否都已换下、窗关删码前是否还有这种行在飞。反方向(不改写)= 修前:整张存卡读不出(断连重放跳过、幂等重入走 park、回决口按要人)、停驻行的 `shadowed` 读成「读不出 ⇒ 按强制」(拿不到「本会话放行」)。";
|
|
333
|
+
};
|
|
330
334
|
readonly "server.pg-pool.idle-client-error": {
|
|
331
335
|
readonly cls: "F";
|
|
332
336
|
readonly note: "S-55(test [5864] 独立复现):pg 连接池里一条连接被外部终止(pg_terminate_backend / 云端故障切换 / LB 空闲回收)或自身网络错误。**两态一 tag,detail 判别**(`state=idle` / `state=checked-out`;先例=park 墓碑行的两臂 detail 判别):①idle 态 —— node-postgres 语义(pg-pool@3.14.0 makeIdleListener):池在 emit 'error' **之前**已 `_remove` 掉该 client,坏连接自然淘汰,下次 acquire 发新连接,在飞查询零影响;修前 Pool 上无 'error' 监听 ⇒ EventEmitter 把事件转 throw ⇒ uncaughtException ⇒ 整进程 exit 1。②checked-out 态(codex R1-[high] 补,同批修)—— pg-pool 借出时摘 idle 监听(index.js),`pool.connect()` 显式持有的连接(事务)在 checkout 期死时 client 直接 emit 'error' 同样打死进程;守卫只观察:中毒 client 的后续查询由 pg 以 `_queryable=false` 响亮拒,归还时池淘汰;同一次 checkout 的死可能双发事件(FATAL 消息 + socket end),warn 逐枚、计数按 checkout 去重。放行的最坏后果 = 下一次 acquire 多付一次建连,故 F 类。必须留痕:「连接不断被外部杀」(故障切换风暴 / 回收策略过激 / 有人在库上清连接)与「一切正常」在服务面同形;每次事件另有逐次结构化 warn(`pg_pool_idle_client_error` / `pg_pool_checked_out_client_error`,含 code/severity),本计数让频率曲线可读。`pool.query()` 快路不在洞内(pg-pool 自带 checkout 期 once('error') 守卫)。mysql2 孪生(tidb-pool)**不同病**:PoolConnection 构造器恒挂 once('error') 库内吞并淘汰、借出期同在(坐标成文在 createTidbPool 头注),故无同族 tag。";
|
|
@@ -24,9 +24,9 @@ export const FAIL_OPEN_TAGS = {
|
|
|
24
24
|
cls: "F",
|
|
25
25
|
note: "core 7.50.0 媒体块提货(`trace/tool-output-media.ts` 的 `liveToolEndForBacklog`,三处活面写口共用的那一只判据 —— 同步流出口 `sseData`、子代 tail 路由写环、tail 总线每订阅者队列):本帧媒体字节(`output` 媒体块的 `data` 与 `structured` 媒体卡的 `file.base64` 一起计)+ 这条连接 / 这个订阅者还没送出去的字节 > 上界(64 MiB)⇒ 本帧媒体降成持久面那只形(媒体块换描述符 `{ type, mimeType?, bytes, truncated: true }`,帧级 `truncated` + `totalChars`;媒体卡去掉 `file.base64`)。每降一帧记一次,只在这只函数里记(三处写口不各记)。放行的最坏后果 = 一个读得慢的观众在 SSE 上看不到这张图,只见「这里有一张多大的什么图、没送达」(账本面本就恒是描述符),不是门、不是凭据、不改任何裁决;反方向(不降)让一条停读的连接随帧数线性压住几百 MiB。帧上它与引擎自己的媒体预算降级同形不可分,所以计数是运维唯一能看出「多少观众丢了图」的位;计数持续非零 = 有消费端读流太慢(或网络瓶颈),去看那几条连接。detail = `backlog=<待发字节> media=<本帧媒体字节>`。",
|
|
26
26
|
},
|
|
27
|
-
"server.memory-consolidation.operator-valve-
|
|
27
|
+
"server.memory-consolidation.operator-valve-layers-unfed": {
|
|
28
28
|
cls: "P-DEBT",
|
|
29
|
-
note: "core 7.
|
|
29
|
+
note: "core 7.51.0 #1718 提货(`boot/memory-consolidation.ts` `createOperatorValveWriteJudge`):运维手动整理阀门的写判官座已是引擎的那一只构造器,但三层没喂 —— 人的持久规则层(阀门没有「库属于谁」的来源,无 principal / 不声明 local-owner)、部署的调用方策略层(`APPROVAL_REQUIRE` / `APPROVAL_DENY` / `AUTONOMY` / 敏感路径守卫集是每任务现合成的活配置、无部署级单例;敏感路径层另需引擎豁免根入参,宿主构造器输入没有这一位)、项目根(项目层 scope 键是任务根的单向散列,反推不出)。每被问一次(早问库目录一次 + 每个产物一次)记一次。放行的最坏后果 = 运维手动整理时,一条点名记忆库路径的人的持久规则或部署写策略(例如 `APPROVAL_DENY=Write`)拦不住这一轮折叠(与 7.128.x 逐字同;只是判官不再是代答);自动整理腿走引擎腿自己的判官,不在本 tag 射程。收口 = 三层各自有了来源(人:「读谁的桶」裁定;策略:一份设计 + 向 core 请托引擎豁免根入参;根:无来源则永久缺席并改写本债)那一版,本 tag 删。",
|
|
30
30
|
},
|
|
31
31
|
"server.workflow-park-index.sync-failed": {
|
|
32
32
|
cls: "P-DEBT",
|
|
@@ -242,7 +242,7 @@ export const FAIL_OPEN_TAGS = {
|
|
|
242
242
|
},
|
|
243
243
|
"server.resume.reopen-confirm-unreadable": {
|
|
244
244
|
cls: "F",
|
|
245
|
-
note: "S-447(#60 M2 自查项,`http/resume-legs.ts` 的 `confirmCheckpointReopened`)
|
|
245
|
+
note: "S-447(#60 M2 自查项,`http/resume-legs.ts` 的 `confirmCheckpointReopened`):续跑腿交回一条没 park 的失败结果后(7.129.0 起每一条都问,不再只在三个重开码上问)按 **token** 复核「这张 checkpoint 是不是又 pending 了」,这一读抛(库拖/版本太新/店不可达)。**方向本来就是 fail-closed**:读不出 ⇒ `return true` ⇒ 「不写任何终局、重新 park」(`:1206-1212` 头注已把取舍与有界代价写死:错 park 由 `reapSuspended` 兑,错终局会孤儿化一张活 park 到 TTL)—— 所以这条腿不是 P 类,缺的只是**留痕**。放行的最坏后果 = 多一次多余的 re-park(一张已经被决掉的卡重新挂到 reaper 窗里),人面上是「这条续跑没动」而不是谁被放行了。必须登记的理由是 **uniformity**:同文件三只同形读(`:249` `server.approvals.stale-echoed-token-unreadable` · `:288` `server.approvals.stale-current-pending-unreadable` · 本腿)中只有它是黑的,于是「店一直读不出所以每条续跑都在白白 re-park」与「一切正常」在遥测上同形。计数非零 = 这台机器的 checkpoint 店在拖,运维要去看库。",
|
|
246
246
|
},
|
|
247
247
|
"server.approvals.stale-current-pending-unreadable": {
|
|
248
248
|
cls: "F",
|
|
@@ -287,6 +287,10 @@ export const FAIL_OPEN_TAGS = {
|
|
|
287
287
|
cls: "F",
|
|
288
288
|
note: "S-249(`approval-card.ts` 的边界窄读族;今天四个成员:`readRuleOffersAbsence`、S-934 ② 起的 `readAskClassPair`(core 7.37.0 #1214 的类对 `askClass` / `classes`,活卡帧 / 呈卡帧的卡 / 运维队列行同一只,判法 = core 屏 `screenAskClassMembers`(S-955 ⑥ / core 7.38.0 #1249,本仓零自写对判),两键同在同缺,半对 / 集外 / 首员不符 / 重复员 = 屏拒 = 读不出;detail 前缀 `askClass=` / `classes=`),与 S-721 起的 `readClosedWordSeat` —— 一座一只 core 成员筛,座是参数:`mandate`(core 7.32.0 #1092,活卡帧 / 活挂起行 / 运维队列行同一只,闭集筛 = core `isPersistedRuleMandate`)与 S-755 起的 `origin`(运维队列行读 park 行孪生座,闭集筛 = core `isAskOrigin`,与 inbox 行 core 投影处同一只筛)、S-1170 起的 `classifierNoRuling`(core 7.43.0 #1353 的成因词,活卡帧读 `AskRequest.classifierNoRuling`,闭集筛 = core `isAutoModeFallbackCause`)与 `differs`(core 7.44.0 #1374,载体是 `runs.ts` 的 409 `steering.duplicate_input_id` 体读的引擎拒错 `detail.differs`,闭集筛 = core `STEER_REPLAY_FACETS` 的非空子集;集外成员 / 空 / 非数组 ⇒ 不铸 `detail`,码仍是契约);detail 前缀 `ruleOffersAbsence=` / `mandate=` / `origin=` / `classifierNoRuling=` / `differs=` 判别是哪一座;第四个成员是 `approval-content-kind.ts` 的 `readApprovalCard` —— 卡词 `approvalCard` 自己的闭集窄读,活 ask / LOCAL 店停驻门 / SQL 店读出的门子树三个载体共用一只,闭集 = core `TOOL_APPROVAL_CARDS`,detail 前缀 `approvalCard=`):活卡帧 / `card_json` / (S-700 起)运维队列行(`parkRowFacts` 读寄存行上的 park 孪生座;队列是热读面 ⇒ 同一行每读一次计一次)的一个**闭集词**座上,键在场而词不在本仓认得的那张表里(世代差,或第三方 producer)⇒ 该座**按缺席**处置。放行的最坏后果=卡上少一行「为什么这次没有规则候选」的解释(壳退回不显示该行),它**不改变任何裁决**——门在引擎里早已判完,本座是展示/观测面;反方向(把一个消费端词表外的值原样上卡)更坏:下游按闭集写的分支会落进 default 臂或渲染出生词。本臂存在的全部理由是**判别**:修前「上游发了个生词」与「上游根本没发这个键」在遥测上同形,而前者意味着本仓的词表该跟着 core 加词了(型面另有两向编译围栏,但那只在**重新编译**时说话,跑在线上的那一版不会自己红)。detail 带座名与那个词(经 redactSecrets 截 40);数 / 布尔等原始值原样,对象 / 数组 / 函数 / null 只报形名(`<object>` / `<array>` / `<function>` / `<null>`,S-700 codex r1:格式化从不调用值自己的转换方法 —— 持久层里一格 `{\"toString\":null}` 曾让诊断本身抛出、打掉整只队列)。",
|
|
289
289
|
},
|
|
290
|
+
"server.approval-card.retired-card-word-read": {
|
|
291
|
+
cls: "F",
|
|
292
|
+
note: "S-1562(core 7.51.0 #1515 / #1702;一次性迁移 M18 的**读侧半场**,`approval-card.ts` 的 `readStoredCardEnvelope` / `currentParkArm`,窗与删法见 `plugins/one-time-migrations.ts` 登记表 M18 —— 窗关随 M18 删本 tag):存下的审批卡(`approval_ask.card_json`)或停驻行(`pendingAction` 的 `tool_approval` 臂)上带着引擎 7.51.0 退役的词 —— `ruleOffersAbsence: \"shadowed\"` 或类对里的 `governance_unavailable` —— 读时按 M18 那一只改写读(前者删键 = 合法缺席,后者换成 `rule_unreadable`、类集去重按引擎序)。每改写一次记一次;detail = 载体(`card_json` / `parked row`)与座名,不带值。放行的最坏后果 = 无:这一读与存卡的起服改写对同一份字节给同一个答案(一只函数);它不是兜底,它登记在这里是为了**响亮** —— 载体 `card_json` 计数非零 = 有起服改写够不着的卡(滚动升级窗里 7.128.x 副本新写的卡、local 文件 ask 账);载体 `parked row` 计数非零 = 读到了带旧词的停驻行(引擎写的文档,本服务从不改写它 —— 行摘要覆盖类对 `askClass` / `classes`,改写 = 续跑判 `damaged`;所以这一格在窗内随每次读到那样的行而涨,直到那些行被决掉 / 收割),运维据它判断旧副本是否都已换下、窗关删码前是否还有这种行在飞。反方向(不改写)= 修前:整张存卡读不出(断连重放跳过、幂等重入走 park、回决口按要人)、停驻行的 `shadowed` 读成「读不出 ⇒ 按强制」(拿不到「本会话放行」)。",
|
|
293
|
+
},
|
|
290
294
|
"server.pg-pool.idle-client-error": {
|
|
291
295
|
cls: "F",
|
|
292
296
|
note: "S-55(test [5864] 独立复现):pg 连接池里一条连接被外部终止(pg_terminate_backend / 云端故障切换 / LB 空闲回收)或自身网络错误。**两态一 tag,detail 判别**(`state=idle` / `state=checked-out`;先例=park 墓碑行的两臂 detail 判别):①idle 态 —— node-postgres 语义(pg-pool@3.14.0 makeIdleListener):池在 emit 'error' **之前**已 `_remove` 掉该 client,坏连接自然淘汰,下次 acquire 发新连接,在飞查询零影响;修前 Pool 上无 'error' 监听 ⇒ EventEmitter 把事件转 throw ⇒ uncaughtException ⇒ 整进程 exit 1。②checked-out 态(codex R1-[high] 补,同批修)—— pg-pool 借出时摘 idle 监听(index.js),`pool.connect()` 显式持有的连接(事务)在 checkout 期死时 client 直接 emit 'error' 同样打死进程;守卫只观察:中毒 client 的后续查询由 pg 以 `_queryable=false` 响亮拒,归还时池淘汰;同一次 checkout 的死可能双发事件(FATAL 消息 + socket end),warn 逐枚、计数按 checkout 去重。放行的最坏后果 = 下一次 acquire 多付一次建连,故 F 类。必须留痕:「连接不断被外部杀」(故障切换风暴 / 回收策略过激 / 有人在库上清连接)与「一切正常」在服务面同形;每次事件另有逐次结构化 warn(`pg_pool_idle_client_error` / `pg_pool_checked_out_client_error`,含 code/severity),本计数让频率曲线可读。`pool.query()` 快路不在洞内(pg-pool 自带 checkout 期 once('error') 守卫)。mysql2 孪生(tidb-pool)**不同病**:PoolConnection 构造器恒挂 once('error') 库内吞并淘汰、借出期同在(坐标成文在 createTidbPool 头注),故无同族 tag。",
|
|
@@ -1,4 +1,38 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* [ref]([ref])—— **密钥形 env 剥除的留痕面**(core D1 `scrubSecretEnv` 的可观测半场)。
|
|
3
|
+
*
|
|
4
|
+
* ## 它解决的问题
|
|
5
|
+
* `scrubSecretEnv` 是本仓两条 shell/子进程腿的**安全默认**:模型可驱动的 shell(`inheritEnv:"scrub"`)与
|
|
6
|
+
* git 子进程(钩子/凭证助手)拿到的 env 里,`*_KEY`/`*_TOKEN`/`*_SECRET`/`*_PASSWORD`… 一律先丢掉。
|
|
7
|
+
* 两处都以**单参形**调用,于是「这一次到底丢了哪些 key、按哪条规则(core 7.35.0 起五词:exact-name / prefix-rule / namespace-rule / name-rule /
|
|
8
|
+
* value-rule)、置信度多少」
|
|
9
|
+
* **零留痕** —— 部署方既证明不了保护生效过,也发现不了它悄悄不生效了(词表漂移 / 一个新的密钥命名法从
|
|
10
|
+
* 规则的缝里穿过去 / 某条腿被改成 `inheritEnv:"all"`)。core 早就把收集口开好了(`findings?:
|
|
11
|
+
* SecretEnvFinding[]`,d.ts 原话:the VALUE is never carried — this record is meant to be loggable),
|
|
12
|
+
* 缺的只是本仓这半场。本模块就是那半场,**不是**一个新的执法面:它一个字节也不改变剥除行为。
|
|
13
|
+
*
|
|
14
|
+
* ## 形(照 `fail-open.ts` 的仓内先例)
|
|
15
|
+
* 1. **计数(逐次)** —— `secret_env_scrubbed_total{site,kind,confidence}`;
|
|
16
|
+
* 2. **结构化披露(每 site×key 一次)** —— 首次在某条腿上丢掉某个 key 时一条 `info`,之后同 key 只走计数。
|
|
17
|
+
* 有部署级出路的现场(S-699:`server.lsp.spawn-env`;7.103.0 起 + `server.bake-runner.spawn-env`)升 `warn`,并带当前放行名单与出路句
|
|
18
|
+
* —— 规则见 `SecretEnvScrubSiteSpec`。
|
|
19
|
+
* 不是「每 site 一次」:一个**新**的密钥形 key 后来才出现(部署加了一个凭证)时,那才是最该看见的一行。
|
|
20
|
+
* findings 全部是 core 的 `SecretEnvFinding`(7.129.0 / core 7.51.1 起只有引擎一只写手,经 `server-secret-env.ts` 的唯一组合):形状臂的五词
|
|
21
|
+
* `exact-name` / `prefix-rule`(`OTEL_*`)/ `namespace-rule`(`SEMA_` 命名空间)/ `name-rule`(名字形状)/ `value-rule`(值里带凭据),加
|
|
22
|
+
* `own-credential`(本进程起服声明的自有凭据名 —— 配置目录 secret 名 ∪ 名单型旋钮名 —— 被形状臂漏下、由声明臂扣的;`all` 词下也扣)。
|
|
23
|
+
* `kind` 原样进标签、不做穷举 switch,core 换词即自成新桶;本仓 7.99.0–7.128.x 自铸的 `config-catalog` / `name-list-knob` 两桶随目录臂退役,
|
|
24
|
+
* 它们的读数今天在 `own-credential` 桶 —— 那一桶就是 core 形状规则的缺口读数。git 的 env 配置族与代理变量一族自 core 7.35.0 起是**豁免族**
|
|
25
|
+
* (名与值都不读、原样交出),不产 finding;此前(7.33.2–7.33.8)被扣的成员记 core 的 `family-rule`,本仓 7.103.0 的 `git-config-group` 桶与 7.103.1
|
|
26
|
+
* 中间态的 `secret_env_git_config_pairs_withheld_total` / warn `git_config_pair_withheld` 更早随本仓那一层退役(车PG)。
|
|
27
|
+
* 值永不进任何一件(core 的 finding 本身就不携带值)。
|
|
28
|
+
*
|
|
29
|
+
* ## 为什么是进程级自由函数而不是注入
|
|
30
|
+
* 与 `recordFailOpen` 同因:调用点都在**没有 logger/metrics 句柄**的深处(`plugins/remote-env-host.ts` 的 `mergeEnv` 全文零观测通道;
|
|
31
|
+
* git 腿是自由函数 / 闭包)。7.103.0 起各腿不再直接调本函数 —— 只经 `server-secret-env.ts` 的唯一组合 `hostSubprocessEnv`。
|
|
32
|
+
* 装配层用 {@link installSecretEnvScrubRecorder} 把句柄接上,装配之前命中的次数不会丢(计数照常累加,
|
|
33
|
+
* install 时一次性补进 metrics),披露行则在下一次命中时补发(未成功披露的 key 不进 `disclosed` 集)。
|
|
34
|
+
*/
|
|
35
|
+
import { type SecretEnvFinding } from "@sema-agent/core";
|
|
2
36
|
import type { Logger } from "./logger.js";
|
|
3
37
|
import type { Metrics } from "./metrics.js";
|
|
4
38
|
/**
|
|
@@ -16,7 +50,7 @@ export interface SecretEnvScrubSiteSpec {
|
|
|
16
50
|
/** 登记过的剥除现场。闭集:未登记的 site 传不进 {@link recordSecretEnvScrub}(编译期拒,同 FAIL_OPEN_TAGS 纪律)。 */
|
|
17
51
|
export declare const SECRET_ENV_SCRUB_SITES: {
|
|
18
52
|
readonly "server.remote-env-host.inherit-scrub": {
|
|
19
|
-
readonly note: "模型可驱动的 host shell 继承 env(`inheritEnv
|
|
53
|
+
readonly note: "模型可驱动的 host shell 继承 env(`inheritEnv` 三词任一,缺省 `\"scrub\"`;`\"all\"` 词下扣的只有本服务自己的凭据名)——这条腿上的一次泄漏等于把编排器的脑钥/仓库令牌交给模型选的命令";
|
|
20
54
|
readonly remedy: null;
|
|
21
55
|
};
|
|
22
56
|
readonly "server.project-memory.git-subprocess": {
|
|
@@ -52,7 +86,7 @@ interface Sink {
|
|
|
52
86
|
* `findings` 只许装**没有按原样交给子进程**的键(剥掉 / 换成 core 占位半条)—— 点名放回的键取回源值,不是剥除(不计数、不披露)。
|
|
53
87
|
* `allowed` = 这一次生效的点名放行名单(S-699),只在有出路的现场(`remedy` 在场)写进披露行;没有放行面的腿传 `[]`。
|
|
54
88
|
*/
|
|
55
|
-
export declare function recordSecretEnvScrub(site: SecretEnvScrubSite, findings: readonly
|
|
89
|
+
export declare function recordSecretEnvScrub(site: SecretEnvScrubSite, findings: readonly SecretEnvFinding[], allowed: readonly string[]): void;
|
|
56
90
|
/** 装配层把 logger/metrics 接上(main.ts,与 `installFailOpenRecorder` 同一处)。装配前累计的次数在此补进 metrics。 */
|
|
57
91
|
export declare function installSecretEnvScrubRecorder(deps: Sink): void;
|
|
58
92
|
/** 已留驻的「现场×键」条数(测试/诊断读面)。恒 ≤ {@link DISCLOSED_CAP}。 */
|
|
@@ -2,7 +2,7 @@ import { summarizeRedactions } from "@sema-agent/core";
|
|
|
2
2
|
import { describeAllowlistPostures } from "../env-name-allowlist-knobs.js";
|
|
3
3
|
export const SECRET_ENV_SCRUB_SITES = {
|
|
4
4
|
"server.remote-env-host.inherit-scrub": {
|
|
5
|
-
note: "模型可驱动的 host shell 继承 env(`inheritEnv
|
|
5
|
+
note: "模型可驱动的 host shell 继承 env(`inheritEnv` 三词任一,缺省 `\"scrub\"`;`\"all\"` 词下扣的只有本服务自己的凭据名)——这条腿上的一次泄漏等于把编排器的脑钥/仓库令牌交给模型选的命令",
|
|
6
6
|
remedy: null,
|
|
7
7
|
},
|
|
8
8
|
"server.project-memory.git-subprocess": {
|
|
@@ -27,7 +27,7 @@ export const SECRET_ENV_SCRUB_SITES = {
|
|
|
27
27
|
},
|
|
28
28
|
};
|
|
29
29
|
const SCRUB_COUNTER = "secret_env_scrubbed_total";
|
|
30
|
-
const SCRUB_COUNTER_HELP = "secret env entries not handed on as written (dropped) to a spawned child process, by site/kind/confidence (core
|
|
30
|
+
const SCRUB_COUNTER_HELP = "secret env entries not handed on as written (dropped) to a spawned child process, by site/kind/confidence (core inheritedHostEnv: the scrub's rules + this deployment's declared own credentials, kind own-credential)";
|
|
31
31
|
const DISCLOSED_CAP = 512;
|
|
32
32
|
const SEP = "=";
|
|
33
33
|
let sink = {};
|
package/dist/parked-decide.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readClosedWordSeat } from "./approval-card.js";
|
|
1
2
|
import { routeWorkflowPark } from "./orchestration/workflow-agent-session-index.js";
|
|
2
3
|
import { defaultSubagentTailBus } from "./fleet/subagent-tail-bus.js";
|
|
3
4
|
import { backgroundScopesForCheckpointScope, decodeCheckpointScope } from "./security.js";
|
|
@@ -313,8 +314,9 @@ export async function decideParkedAgent(deps, req, match) {
|
|
|
313
314
|
if (isErr) {
|
|
314
315
|
const disp = await rollback("execute_rejected");
|
|
315
316
|
const content = receipt.content;
|
|
316
|
-
const
|
|
317
|
-
if (
|
|
317
|
+
const receiptDetails = receipt.details;
|
|
318
|
+
if (receiptDetails?.error === "parked_resume.startup_failed") {
|
|
319
|
+
const cause = readClosedWordSeat(receiptDetails, "cause");
|
|
318
320
|
return {
|
|
319
321
|
status: 422,
|
|
320
322
|
body: {
|
|
@@ -322,6 +324,7 @@ export async function decideParkedAgent(deps, req, match) {
|
|
|
322
324
|
errorCode: "parked_resume.startup_failed",
|
|
323
325
|
taskId: match.handle,
|
|
324
326
|
rollback: disp,
|
|
327
|
+
...(cause !== undefined ? { cause } : {}),
|
|
325
328
|
},
|
|
326
329
|
};
|
|
327
330
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { joinRequestUrl } from "@sema-agent/core";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import { egressRedirectRefusal } from "../egress-redirect.js";
|
|
3
4
|
import { buildDisplaySafeRefusal, buildDisplaySafeUrl } from "../trace/redact.js";
|
|
4
5
|
const EmbeddingsResponse = z.object({
|
|
5
6
|
data: z.array(z.object({ embedding: z.array(z.number()) })).min(1),
|
|
@@ -43,11 +44,15 @@ export function createOpenAiCompatEmbedder(opts) {
|
|
|
43
44
|
},
|
|
44
45
|
body: JSON.stringify({ model, input: text }),
|
|
45
46
|
signal: AbortSignal.timeout(timeoutMs),
|
|
47
|
+
redirect: "manual",
|
|
46
48
|
});
|
|
47
49
|
}
|
|
48
50
|
catch (transportErr) {
|
|
49
51
|
throw new Error(`memory embedder POST ${shownUrl}: transport failure — ${safeSlice(String(transportErr))}`);
|
|
50
52
|
}
|
|
53
|
+
const redirected = egressRedirectRefusal(res, "declare the final endpoint as MEMORY_EMBEDDER_ENDPOINT");
|
|
54
|
+
if (redirected !== undefined)
|
|
55
|
+
throw new Error(`memory embedder POST ${shownUrl}: ${redirected}`);
|
|
51
56
|
const raw = await res.text().catch((readErr) => {
|
|
52
57
|
throw new Error(`memory embedder POST ${shownUrl}: response body unreadable — ${safeSlice(String(readErr))}`);
|
|
53
58
|
});
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* 占位日期)—— 不计到期;抬 `package.json` 到那一版的发布准备提交把两格回填成发布日 / +30 天。到期门同时是回填门:`package.json` 版本
|
|
12
12
|
* **≥** 某条未发布形的 `introducedIn` 而两格仍是 `null` ⇒ 红(发布准备提交就是回填时刻,忘了就当场红;版本更低 = 还在开发,不红)。
|
|
13
13
|
* 最后一条删掉时,整个文件连同 `StoreBackend.runOneTimeMigrations()`(npm 公面上的接口成员)、`NO_SQL_MIGRATIONS`、
|
|
14
|
-
* `logOneTimeMigrations`、三只后端与两只测试夹具上的实现、`boot/stores.ts` 的调用点一起删 —— 唯一例外是退役 schema 的拒启臂
|
|
14
|
+
* `logOneTimeMigrations` / `runAndLogOneTimeMigrations`、三只后端与两只测试夹具上的实现、`boot/stores.ts` 的调用点一起删 —— 唯一例外是退役 schema 的拒启臂
|
|
15
15
|
* ({@link assertRetiredSchemaAbsent}、探针口 {@link assertRetiredSchemaAbsentOnPool} 与它们的错误类型、两件退役 schema 的坐标):它没有窗,跳版升级的库永远可能出现,
|
|
16
16
|
* 删最后一条的车要把它搬进启动期对账(`schema-consistency.ts` 一族)并保住它先于一切建表与改写的位置(现位:`store-backend.ts` 里 SQL 两后端的 `ensureSchema()` 自身,探针先于它的第一条 CREATE),不要随文件删掉。
|
|
17
17
|
* 其余文件一律只写「窗口见本文件登记表」,不各写一个日期或版本 —— S-590 之前本文件头写死了一个删除版本号(7.75.0),
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
* 发出的任何一条 CREATE —— 一次会拒的起服不许先在库里建出几十张本版新表(`task_run` 还带着新列),否则拒句里「没动过库」就是假话,而按拒句指路去 7.125.x 起服的人会撞上
|
|
38
38
|
* 「库比 7.125.x 新」的第二道拒。探针与建表的先后只写在 `store-backend.ts` 里 SQL 两后端的 `ensureSchema()` 自身(装配处包一次)。迁移段入口({@link runSqlOneTimeMigrations})**不再问**这一问:
|
|
39
39
|
* 它只在 `ensureSchema()` 之后被起服序列调用,一个事实不在两处各读一遍;嵌入方走公开序列 `createStoreBackend()` → `ensureSchema()` → `runOneTimeMigrations()` 即得到这一问,零动作。
|
|
40
|
-
* 残余(如实):运维在第一次起带迁移的版本之前就把两件退役 schema
|
|
41
|
-
*
|
|
42
|
-
* (下游不改上游盘上格式),同由那条读腿接住。
|
|
40
|
+
* 残余(如实):运维在第一次起带迁移的版本之前就把两件退役 schema 都手工删掉的库,残留的旧拼法由门记录的读腿接住 —— 7.129.0 起(core 7.51.0 #1731)
|
|
41
|
+
* 那只读腿按 core 的档案读法读,`unresolvable` 是 core 退役词注册表里的词 ⇒ 记录原词原样读回、不改写(`trace/project.ts` `screenedGate`);local 文件车道
|
|
42
|
+
* 没有表与列,没有这一问的探针 —— 引擎 File 店里已决 checkpoint 的记录按契约物理不可变,本仓没有合法缝改写它们(下游不改上游盘上格式),同由那条读腿接住。
|
|
43
43
|
*
|
|
44
44
|
* ## 窗内的迁移(逐条的失败方向刻意不同)
|
|
45
45
|
* · **M4 审计明细里的 JSON 文本 `null`** —— S-550 把 `device_audit.detail` 的读回收进唯一属主并判形之后,
|
|
@@ -122,10 +122,58 @@
|
|
|
122
122
|
* 调契约的目录迁移 `migrateConfigDirectory`(覆盖面 = 本地读腿会读的那几份:便携域 + 退役域 `runtime`),整域终判通过才原子写回、搬空的
|
|
123
123
|
* `runtime.json` 删;读腿不读的域文件(`hosts` / `workers` …)不碰;
|
|
124
124
|
* 迁不动 ⇒ 一字不写、`config_dir_migration_refused` 一行。没有读数键(它不写库)。
|
|
125
|
+
* · **M17 会话规则一列一文法**(7.129.0,引擎 7.51.0 #1480)—— 引擎把会话规则的 `toolDeny` / `toolAllow` 换成规则条目文法(`Bash(rm:*)` 是一条拒 `rm`
|
|
126
|
+
* 的规则),退役 `commandAllow` / `commandDeny` 两只命令桶。持久面三件事,同一步做:
|
|
127
|
+
* ① **列改名** `session_policy.rules` → `rule_entries`(列定义唯一属主 `session-rules-column.ts`):7.128.x 及以前的副本按整串工具名读 `rules`,
|
|
128
|
+
* `Bash(rm:*)` 在那种读法下匹配不到任何工具 —— 一只没改名的列会让混跑窗里的旧副本、回滚上来的旧二进制把本版写下的命令拒读成「没有这条拒」。
|
|
129
|
+
* 改名之后它们找不到那一列:已在跑的旧副本每一条规则语句响亮失败(新任务起不来、规则面 500,在跑的腿留着它已执行的快照),旧二进制起服被列册探针拒启 ——
|
|
130
|
+
* 没有一只副本按旧文法读到新文法的行。行里不带文法版本(一个旧写者维护不了的第二个事实,恰在混跑窗里说谎),也不读规则体猜版本。
|
|
131
|
+
* MySQL 协议方言 `CHANGE COLUMN`(MariaDB 10.5 以前没有 `RENAME COLUMN`;定义内插同一串),PG `RENAME COLUMN`;成功判据是后置条件(列名换过来了)。
|
|
132
|
+
* ② **改名那一拍的改写:每一行在它自己的文法里由引擎读,改写成当前文法的同一句话**(core 7.51.2 #1761,行自带规则文法戳 `grammar`:写口判官盖、店整只存、
|
|
133
|
+
* 引擎按行自带的戳读;无戳行 = 戳之前写的行,引擎读成文法 0)。改名那一刻库里每一行都是无戳行(≤7.128.x 写的)—— 判据只有引擎的:行(体 + `rev`)经
|
|
134
|
+
* `readSessionRulesShape` 读成它自己的文法,`compileSessionRuleBucket` 在那种文法下编译 `toolAllow`,归 `earlier_grammar` 的条目(文法 0 里拼写不是它所指名字的条目
|
|
135
|
+
* —— `Bash(rm:*)` / `Edit(src/**)` / `Bash(*)`:什么都不放行,文法 1 里是一条放行规则)删掉,其余原样,盖 `grammar: SESSION_RULES_GRAMMAR` —— 文法 0 与 1 在引擎里只差
|
|
136
|
+
* 这一条子句,所以改写后的行是引擎对原行读法的逐调用同义重述(名单保持在场:删到空 = 在场的空名单,什么都不放行)。**每一行**都改写(只盖戳的也写):改写之后
|
|
137
|
+
* 部署里零无戳行(被 `*` 遮蔽的行除外:引擎把带 `*` 的 allow 名单整张读成 `wildcard_all`,遮住其余条目的旧文法读法 ⇒ 不改写、不盖戳、只点名,留在原文法里),引擎的文法 0 路径与每层一次的 `earlier_grammar` 通告在本服务上只剩这类行会触发。`toolDeny` 一个字节不动、不点名:引擎的文法只修订 allow 方向的读法
|
|
138
|
+
* (deny 条目在任何文法下读法相同),「deny 条目升级后开始拒」是本仓对 7.128.x 实际行为的自铸判断,引擎没有它的席位 —— deny 条目留在行里,谁要知道都读得到。
|
|
139
|
+
* 本仓零自铸文法判断、零 `readRuleEntry` 直调(修前的 `oldGrammarReadingOf` 按条目种类自铸三分类,是第二只文法读者)。按原文 CAS 回写(MySQL 协议两边
|
|
140
|
+
* `CAST(… AS BINARY)`),`rev` / `gen` 不动;有被删条目的行一条 warn `session_rule_row_old_grammar_entries`(键哈希 / 会话 / 被删的条目,过脱敏器)。
|
|
141
|
+
* 这一拍没有别的写者(旧副本找不到 `rules`,本版副本在起服锁上等)。
|
|
142
|
+
* **终名只在每一行都判完之后出现**:`rules` 先改成进行中的名 `rule_entries_old_grammar`(旧副本从此找不到列),判读在这个名下跑(幂等:已改写的行再判零动作),
|
|
143
|
+
* 判完才改成 `rule_entries`。于是判读没走完 —— 抛了、或进程被杀 —— 列都停在进行中的名,下一次起服从它续判(已带戳的行引擎按它的戳读:零 `earlier_grammar`、
|
|
144
|
+
* 已有戳 ⇒ 零动作);没有「改回」臂(一条自己也可能失败的补偿),也没有「改名即终名」的窄窗(被杀后下一次起服把没判的行当新文法行读)。
|
|
145
|
+
* **收据随提交落,不随成功落**:一行改写提交(CAS 命中)的那一刻,它被删的条目就记进本次起服的收据账({@link SessionRuleReceipts});之后本次起服的**任何**一步
|
|
146
|
+
* 失败 —— 判读半途、终名改名、改名后的退役桶扫描、其后的迁移(M11)—— 拒因都带着账里已有的收据({@link OneTimeMigrationInterruptedError}),起服日志在抛之前把它们打出来
|
|
147
|
+
* ({@link runAndLogOneTimeMigrations})。理由:被删的条目没有第二次被报出来的机会 —— 下一次起服续判时那一行已是新形、没有可删的条目,零命中。只盖戳的改写不记:
|
|
148
|
+
* 戳不丢任何信息,重来再判零动作。
|
|
149
|
+
* 如实的残余:改写与那一行日志之间进程被杀、或一条改写的确认在连接上丢了 —— 收据没有耐久载体(不为一条短命的迁移另建迁移账表,见 M4 一节的同一条论证)。
|
|
150
|
+
* ③ **存量命令桶只点名、不改写**:新文法写不出旧命令桶的拒 —— 旧桶(引擎 7.50.x 粗命令名策略,`defaultAction: "deny"`)对读不成「一条命令名」的命令行
|
|
151
|
+
* 一律拒(`/bin/rm …`、管道、`&&`),`Bash(rm:*)` 只按命令名判、放过 `/bin/rm`。任何改写都是放宽(`commandDeny`)或改变放行面(`commandAllow`),
|
|
152
|
+
* 不由本仓替人做。⇒ 退役桶**一个字节不动**,读回照旧 `corrupt`(引擎形读法点名那只桶;与引擎文件店对同一形同判 —— 每一种店一个结局),
|
|
153
|
+
* 每次起服一行一条 warn `session_rule_row_retired_bucket`(键哈希 / 会话 / 桶名;规则正文不出店),出路是人(按新文法改写那一行,或删会话)。
|
|
154
|
+
* 同一行其余的桶照 ② 判、盖戳(人按出路删掉退役桶的那一刻,行已是文法 1 的真话)。
|
|
155
|
+
* 够不到的两格(如实登记):local 车道的会话规则在引擎自己的文件店里(盘上格式归引擎,本仓没有合法缝改写),读数 `file-store`;带命令桶的文件由引擎读侧判坏
|
|
156
|
+
* (句子给出路),引擎按行自带的文法读无戳文件(文法 0),旧文法写下的 `toolAllow` 规则形条目照旧什么都不放行、不放宽(MIGRATION 写了)。待决停驻行里持久化的
|
|
157
|
+
* 祖先会话规则快照(`checkpoint` 文档 `state.inheritedGate.ancestorRules`)同理照新文法读,而它是引擎行摘要(`requirementsDigest`)覆盖的成员 ——
|
|
158
|
+
* 改写它 = 续跑被判 `requirements_damaged`;本仓不重铸引擎的摘要 ⇒ 不改写,引擎续跑同样按文法 0 读它(不放宽;MIGRATION 写了)。
|
|
159
|
+
* · **M18 存卡上两个退役词(停驻行只有读侧半场)**(7.129.0,引擎 7.51.0 #1515 / #1702)—— 7.128.x 写下的 `approval_ask.card_json`(卡)与停驻行
|
|
160
|
+
* (`checkpoint.checkpoint` 文档 `pendingAction` 的 `tool_approval` 臂)上两座可能带引擎退役的词:`ruleOffersAbsence: "shadowed"`、类对里的
|
|
161
|
+
* `governance_unavailable`。今天的读者只读引擎的今日闭集 ⇒ 修前整张存卡读不出(断连重放跳过、幂等重入走 park、回决口按要人)、停驻行的
|
|
162
|
+
* `shadowed` 读成「读不出 ⇒ 按强制」。⇒ **一只改写规则**(`src/retired-card-words.ts`:前者删键 = 合法缺席 —— 一词两义不可确定拆;后者换成
|
|
163
|
+
* `rule_unreadable`,类集去重、按引擎序、首员重取),**两处两种用法,按谁写的字节分**:
|
|
164
|
+
* · **卡 = 本服务自己写的**(`approval_ask.card_json`):起服**一次性改写** + 应用侧解析 + CAS 回写(`WHERE <列文本> = <读到的原文>`;第二跑零命中)。
|
|
165
|
+
* 全表按字样扫(`card_json` 是 TEXT,按 `ask_id` 键集分页)。
|
|
166
|
+
* · **停驻行 = 引擎写的文档**(`checkpoint.checkpoint`):本服务**一个字节不改写**。引擎的行摘要(`requirementsDigest`,引擎 7.49.0 #1320 起每条 v10 行都带)
|
|
167
|
+
* 覆盖 `pendingAction` 的 `askClass` / `classes`(`decision-read` 成员),续跑入口 `judgeCheckpointRequirements` 重算摘要 —— 成员被改 = 摘要不符 =
|
|
168
|
+
* 判 `damaged` ⇒ 拒续跑(`checkpoint.invalid_outcome`,行留 pending、无人能续);盖章的函数不在引擎包根出口,重铸摘要不是本服务的事
|
|
169
|
+
* (与 M17 对祖先会话规则快照同一条纪律)。停驻行上的退役词对引擎续跑无害:续跑入口读的是摘要,引擎里 `askClass` 只在铸造 / 拒数 / 出门路径读(core 7.51.1 dist 亲读)。
|
|
170
|
+
* **读侧半场**(同一行、同一窗,不另起登记行):由存卡唯一读者入口 `approval-card.ts` `readStoredCardEnvelope`(起服改写够不着的卡 —— 滚动升级窗里
|
|
171
|
+
* 7.128.x 副本新写的、local 车道的文件 ask 账)与停驻行入口 `currentParkArm`(**所有**停驻行 —— SQL 与 local 车道引擎 File 店的同一条路径)读时过同一只改写,
|
|
172
|
+
* **响亮**(`server.approval-card.retired-card-word-read`);读的是浅拷贝,被读的行一个字节不动。local 车道读数恒零(`NO_SQL_MIGRATIONS`)。
|
|
125
173
|
*
|
|
126
174
|
* ## 幂等
|
|
127
175
|
* 改写的几条都可重复跑(M4:`detail IS NOT NULL AND … = 'null'`;M5:列在场探针 + `WHERE incarnation = ''`;M6:`WHERE error_code IS NULL`;
|
|
128
|
-
* M8
|
|
176
|
+
* M8 / M18:字样扫描 + CAS 回写 —— 写过的行不再命中;M17 的改写只在改名那一拍跑,第二跑列名已是新名 ⇒ 零读零写;续判时已带戳的行零动作)。并发起动由 {@link runSqlOneTimeMigrations} 的 advisory 锁 + 每步的后置条件判据兜住(见那里)。
|
|
129
177
|
*/
|
|
130
178
|
import type { Pool as MysqlPool } from "mysql2/promise";
|
|
131
179
|
import type { Pool as PgPool } from "pg";
|
|
@@ -160,6 +208,61 @@ export interface OneTimeMigrationReport {
|
|
|
160
208
|
/** M11:读腿整桶拒的桶(唯一判官判不过:形 / 指纹 / behavior 闭集 / 墓碑规范文本 / 单一验证器)—— 一个字节没动,一桶一条拒因
|
|
161
209
|
* (不带行内容),启动日志逐桶 warn;local 车道恒空(见头注 M11 段)。 */
|
|
162
210
|
readonly undurableScopeRuleBucketsUnreadable: readonly UnreadableRuleBucket[];
|
|
211
|
+
/** M17:`session_policy` 装规则的那一列 —— `renamed` = 本次把 `rules` 改名成 `rule_entries`;`current` = 早已是新名(新库 / 第二跑);
|
|
212
|
+
* `no-table` = 这只库上没有 `session_policy`(中央 DDL 之后不可达,只为不编一个读数);`file-store` = local 文件车道(规则在引擎自己的文件店里)。 */
|
|
213
|
+
readonly sessionRuleColumn: "renamed" | "current" | "no-table" | "file-store";
|
|
214
|
+
/** M17:带退役命令桶的行 —— 退役桶一个字节不动,读回 `corrupt`;一行一条 warn 点名(不带规则正文)。每次起服都报,直到有人改写或删掉它。 */
|
|
215
|
+
readonly sessionRuleRowsWithRetiredBuckets: readonly SessionRuleRowRetiredBuckets[];
|
|
216
|
+
/** M17:改名那一拍(`sessionRuleColumn: "renamed"`)按引擎的条目读法判过、两种文法下读法不同的行 —— toolAllow 里被剔的条目(行已按原文 CAS 回写)、
|
|
217
|
+
* toolDeny 里升级后开始生效的条目(不改写);一行一条 warn 点名。只在改名那一拍有;第二跑起恒空(列名已是新名,行由本版的写者按新文法写)。 */
|
|
218
|
+
readonly sessionRuleRowsWithOldGrammarEntries: readonly SessionRuleRowOldGrammarEntries[];
|
|
219
|
+
/** M18:本次把 `approval_ask.card_json` 上引擎 7.51.0 退役的两个词改写掉的卡行数(SQL 独有;local 恒 0)。非零 = 真写了存量行。 */
|
|
220
|
+
readonly retiredCardWordAskRowsRewritten: number;
|
|
221
|
+
/** M18:带字样、但 `approval_ask.card_json` 的 JSON 读不懂 ⇒ 没改写的卡行数(留给读者自己的坏行臂;非零 = 运维该看一眼这些行)。SQL 独有;local 恒 0。 */
|
|
222
|
+
readonly retiredCardWordRowsUnreadable: number;
|
|
223
|
+
}
|
|
224
|
+
/** 退役的两只命令桶(引擎 7.51.0 起不是桶;只给 M17 点名认)。 */
|
|
225
|
+
export type RetiredSessionRuleBucket = "commandAllow" | "commandDeny";
|
|
226
|
+
/** M17 点名的一行(键是单向哈希;只带桶名,规则正文不出店)。 */
|
|
227
|
+
export interface SessionRuleRowRetiredBuckets {
|
|
228
|
+
readonly policyKey: string;
|
|
229
|
+
readonly sessionId: string;
|
|
230
|
+
readonly buckets: readonly RetiredSessionRuleBucket[];
|
|
231
|
+
}
|
|
232
|
+
/** M17 改名那一拍的一条收据(键是单向哈希;只带被删的那几条条目,过本仓唯一脱敏器 —— 其余规则正文不出店)。 */
|
|
233
|
+
export interface SessionRuleRowOldGrammarEntries {
|
|
234
|
+
readonly policyKey: string;
|
|
235
|
+
readonly sessionId: string;
|
|
236
|
+
/** toolAllow 里删掉的条目:引擎在行自己的文法(0)里读成 `earlier_grammar` —— 拼写不是它所指的名字,什么都不放行;当前文法里是一条放行规则 ——
|
|
237
|
+
* 删掉后盖戳的行是引擎对原行读法的逐调用同义重述。 */
|
|
238
|
+
readonly toolAllowDropped: readonly string[];
|
|
239
|
+
/** 在场 = 这一行没改写也没盖戳:引擎在它的文法里把 toolAllow 整张读成作废(名单里有 `*`),其余条目的读法被遮住(见 {@link OldGrammarEntries.wildcardMasked})。 */
|
|
240
|
+
readonly wildcardMasked?: true;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* M17 收据账 —— **收据随提交落,不随成功落**:一行有被删条目的改写提交(CAS 命中)的那一刻就记进来,不等本段走完。本次起服之后的任何一步抛了,{@link interruptedWith}
|
|
244
|
+
* 把账里已有的收据装进 {@link OneTimeMigrationInterruptedError} 随拒因交出 —— 下一次起服续判时这些行已是新形、零命中,收据只有这一拍说得出。
|
|
245
|
+
* · `rows` —— 本次起服提交了的、有被删条目的改写(只盖戳的改写不记:戳不丢信息,重来再判零动作);两次起服的账并起来恰是一次不被打断的全部事实;
|
|
246
|
+
* · `renamed` —— 终名由本次起服发布了(下一次起服读到的是 `current`)。
|
|
247
|
+
*/
|
|
248
|
+
export interface SessionRuleReceipts {
|
|
249
|
+
rows: SessionRuleRowOldGrammarEntries[];
|
|
250
|
+
renamed: boolean;
|
|
251
|
+
}
|
|
252
|
+
/** 一本空的 M17 收据账(迁移段每次起服一本;{@link migrateSessionRuleGrammar} 往里记)。 */
|
|
253
|
+
export declare function buildSessionRuleReceipts(): SessionRuleReceipts;
|
|
254
|
+
/** 迁移段被打断时随拒因交出的收据(读数键与 {@link OneTimeMigrationReport} 同名同形;`sessionRuleColumn` 只在终名已由本次起服发布时在场)。 */
|
|
255
|
+
export interface OneTimeMigrationReceipts {
|
|
256
|
+
readonly sessionRuleColumn?: "renamed";
|
|
257
|
+
readonly sessionRuleRowsWithOldGrammarEntries: readonly SessionRuleRowOldGrammarEntries[];
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* 一次起服的迁移在**已提交**一些下次起服推不出来的改写之后失败了:原错误在 `cause` 与句子里原样在场,已提交的收据在 `receipts`(结构化)与句子尾(同一份读数的人读形)。
|
|
261
|
+
* 没有提交过这类改写就失败的路径不包这只错(原错误原样抛)。起服调用点({@link runAndLogOneTimeMigrations})在抛之前把 `receipts` 打进日志。
|
|
262
|
+
*/
|
|
263
|
+
export declare class OneTimeMigrationInterruptedError extends Error {
|
|
264
|
+
readonly receipts: OneTimeMigrationReceipts;
|
|
265
|
+
constructor(cause: unknown, receipts: OneTimeMigrationReceipts);
|
|
163
266
|
}
|
|
164
267
|
/**
|
|
165
268
|
* S-590 —— 一条一次性迁移的窗(登记表的一行;纯数据)。字段注写着每个值的取证方式,改一行之前照着重核。
|
|
@@ -195,7 +298,7 @@ export declare const ONE_TIME_MIGRATIONS: readonly OneTimeMigrationWindow[];
|
|
|
195
298
|
* 只给**窗内才生效的行为臂**用(M10 的认领):那种臂过了窗就停,不等删码车 —— 删码因此是零行为变化,而窗只写在本表这一处。
|
|
196
299
|
*/
|
|
197
300
|
export declare function migrationWindowOpen(window: Pick<OneTimeMigrationWindow, "removableAfter">, today: string): boolean;
|
|
198
|
-
/** local 车道上 SQL 独有的几条(M4 / M5 / M8 / M9 / M11)的读数(M6 两车道都有,local 腿的读数由 `LocalBackend.runOneTimeMigrations` 现算):那几张表 / 列在文件底座上从来不存在 ⇒ 如实答 absent / 0。 */
|
|
301
|
+
/** local 车道上 SQL 独有的几条(M4 / M5 / M8 / M9 / M11 / M17 / M18)的读数(M6 两车道都有,local 腿的读数由 `LocalBackend.runOneTimeMigrations` 现算):那几张表 / 列在文件底座上从来不存在 ⇒ 如实答 absent / 0。 */
|
|
199
302
|
export declare const NO_SQL_MIGRATIONS: Omit<OneTimeMigrationReport, "holderDeathCodeRowsBackfilled">;
|
|
200
303
|
/** 启动期的日志口(logger 的子集)。两级各有其用,见 {@link logOneTimeMigrations}。 */
|
|
201
304
|
export interface MigrationLogSink {
|
|
@@ -213,6 +316,14 @@ export declare class RetiredSchemaPresentError extends StoreBootRefusalError {
|
|
|
213
316
|
readonly code = "config.schema_mismatch";
|
|
214
317
|
constructor(found: readonly string[]);
|
|
215
318
|
}
|
|
319
|
+
/** 方言无关的最小查询口(两方言的返回形不同,由下面两只适配器收平)。`params` 只给带值的语句用(M5 的回填:会话 id 是
|
|
320
|
+
* 调用方自选的任意串,不许内插进 SQL 文本);占位符形由调用方按方言写(`?` / `$n`)。 */
|
|
321
|
+
export interface MigrationDb {
|
|
322
|
+
/** 取行(只读探针用)。 */
|
|
323
|
+
rows(sql: string, params?: readonly unknown[]): Promise<Record<string, unknown>[]>;
|
|
324
|
+
/** 执行并回报受影响行数(DDL 返回 0)。 */
|
|
325
|
+
exec(sql: string, params?: readonly unknown[]): Promise<number>;
|
|
326
|
+
}
|
|
216
327
|
/** 探针口的池参数:方言与它的池一起走(判别联合 ⇒ 不靠调用方断言「这个池是哪种」)。 */
|
|
217
328
|
export type RetiredSchemaProbeTarget = {
|
|
218
329
|
readonly dialect: "tidb";
|
|
@@ -239,17 +350,55 @@ export declare function assertRetiredSchemaAbsentOnPool(target: RetiredSchemaPro
|
|
|
239
350
|
* 一次滚动升级会让 N 个副本同时跑到这里。整段因此跑在**一条连接**上、握着**与 `ensureSchema` 同一把**
|
|
240
351
|
* advisory 锁(MySQL 具名锁 / PG `pg_try_advisory_lock`,两方言都是非阻塞轮询形):本段是「启动期改 schema 的活」,与 ensure 属同一类,
|
|
241
352
|
* 复用同一把锁 ⇒ 本仓这一类工作只有**一个**锁身份,而且本段也不会与另一个副本的 ensure 交错。
|
|
242
|
-
*
|
|
243
|
-
*
|
|
353
|
+
* 锁拿不到时**不降级**(7.83.0 起 `tidb-pool.ts` / `pg-pool.ts` 的锁腿永不无锁跑 schema 活:拿不到就等到拿到或拒启)—— 所以进行中的改名列下只有一个写者;
|
|
354
|
+
* 每条改表 DDL 的成功判据仍是它的**后置条件**({@link execUntil}),「另一个副本抢先把同一张表换了形」不会把滚动升级变成启动失败循环。
|
|
244
355
|
*
|
|
245
356
|
* ## 次序(codex r1 [medium] 同轮)
|
|
246
|
-
* 非破坏改写(M4–M9:改值不丢信息 / 加法 DDL / 复制 + 换名)在前,破坏性步骤(M11 的删行)排在最后;
|
|
357
|
+
* 非破坏改写(M4–M9、M18:改值不丢信息 / 加法 DDL / 复制 + 换名)在前,破坏性步骤(M11 的删行)排在最后;
|
|
247
358
|
* M11 自己半途失败时,拒因自带已删的行(`purgeUndurableScopeRows`)—— 否则重试看不见已删的行,证据永久消失。
|
|
248
359
|
*
|
|
249
360
|
* 本函数**不问**退役 schema:带着它的库在更早处就被 `ensureSchema()` 自身拒掉了({@link assertRetiredSchemaAbsentOnPool},先于建表);走公开序列
|
|
250
361
|
* `createStoreBackend()` → `ensureSchema()` → `runOneTimeMigrations()` 的嵌入方与本服务的起服序列一样,有这一问、零动作。
|
|
251
362
|
*/
|
|
252
363
|
export declare function runSqlOneTimeMigrations(dialect: "tidb" | "pg", pool: MysqlPool | PgPool): Promise<OneTimeMigrationReport>;
|
|
364
|
+
/**
|
|
365
|
+
* M17 —— 一份存量规则体带哪几只退役命令桶(纯函数,点名判据):只认**对象上自有**的 `commandAllow` / `commandDeny` 键(不论值形 —— 坏形的退役桶照样是退役桶);
|
|
366
|
+
* 不是对象 / 没有这两个键 / 条目文字里出现同名字样 ⇒ 空。不改写:新文法写不出旧命令桶的拒(头注 M17 段 ③)。
|
|
367
|
+
*/
|
|
368
|
+
export declare function retiredSessionRuleBucketsOf(body: unknown): readonly RetiredSessionRuleBucket[];
|
|
369
|
+
/** M17 —— 一份存量规则体按引擎在它自己的文法里的读法改写成当前文法的同一句话({@link oldGrammarEntriesOf} 的读数)。 */
|
|
370
|
+
export interface OldGrammarEntries {
|
|
371
|
+
/** toolAllow 里删掉的条目(引擎的 `earlier_grammar` 读数;见 {@link SessionRuleRowOldGrammarEntries.toolAllowDropped})。 */
|
|
372
|
+
readonly toolAllowDropped: readonly string[];
|
|
373
|
+
/** 这一行要落的新体 —— 被删条目去掉、其余键原样(退役命令桶也原样)、`grammar: SESSION_RULES_GRAMMAR`;在场 = 要写。缺席 = 零动作:行已带戳且没有可删的条目
|
|
374
|
+
* (上一次没走完的判读已改写过的行),或 {@link wildcardMasked}。 */
|
|
375
|
+
readonly rewritten?: Record<string, unknown>;
|
|
376
|
+
/** 在场 = 引擎在这一行自己的文法里把 `toolAllow` 整张读成作废(`wildcard_all`:名单里有 `*`),遮住了其余条目在那种文法里各算什么 ——
|
|
377
|
+
* 本函数因此**不改写、不盖戳**(改写会把被遮住的条目定成当前文法的规则;引擎修正文法 0 的 `*` 读法后,留在原文法里的行自动读真),只点名。 */
|
|
378
|
+
readonly wildcardMasked?: true;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* M17 —— 一行存量规则(体 + 它的 `rev`)的改写判读(纯函数,判据只有引擎的):
|
|
382
|
+
* · 行按引擎的形读法在**它自己的文法**里读 —— `readSessionRulesShape` 对与 `rev` 并排的值按戳读,无戳 ⇒ 文法 0(戳之前写的行);退役命令桶先放一边(形读法拒它们,
|
|
383
|
+
* 而改写的是同一行其余的桶 —— 人按出路删掉退役桶的那一刻,行已是当前文法的真话);
|
|
384
|
+
* · `toolAllow` 经 `compileSessionRuleBucket` 在那种文法下编译,归 `earlier_grammar` 的条目删掉(文法 0 与 1 在引擎里只差这一条子句:拼写不是它所指名字的 allow 条目
|
|
385
|
+
* 在文法 0 里什么都不放行、在文法 1 里是一条放行规则),名单**保持在场**(在场的空 `toolAllow` 引擎读作「什么都不放行」);别的桶一个字节不动;
|
|
386
|
+
* · 新体盖 `grammar: SESSION_RULES_GRAMMAR`:无戳行每一行都写(改写之后部署里零无戳行);已带戳且没有可删条目的行零动作(幂等)。
|
|
387
|
+
* 读不出形(不是对象、有别的非桶键、桶不是一列字符串、坏戳 / 比引擎新的戳)⇒ `undefined`,不判(读回照旧 `corrupt`)。本函数零处读 / 比较戳的数值:
|
|
388
|
+
* 「有没有戳」是形读法自己判戳之前的同一问;条目在哪种文法下算什么只有引擎读。
|
|
389
|
+
*/
|
|
390
|
+
export declare function oldGrammarEntriesOf(body: unknown, rev: number): OldGrammarEntries | undefined;
|
|
391
|
+
/**
|
|
392
|
+
* M17 —— 会话规则一列一文法(规则与理由见头注 M17 段)。三段,每段的成功判据都是**列此刻叫什么**(后置条件,{@link execUntil}),所以任何一拍被杀都能从列名续上:
|
|
393
|
+
* ① 旧名 `rules` 在 ⇒ 改成进行中的名 `rule_entries_old_grammar`(≤7.128.x 副本从此找不到列,响亮失败;MySQL 协议方言 `CHANGE COLUMN`,定义内插 `SESSION_RULES_COLUMN`
|
|
394
|
+
* 同一串;PG `RENAME COLUMN`);
|
|
395
|
+
* ② 进行中的名在 ⇒ 改写它下面的每一行({@link judgeOldGrammarRows}:这个名下的行只可能是 ≤7.128.x 写的无戳行,或上一次没走完的判读已改写过的带戳行 —— 再判零动作),
|
|
396
|
+
* 判完才改成终名 `rule_entries`;判读抛了 ⇒ 原样上抛,列停在进行中的名,下一次起服从这里续。**收据随提交落**:有被删条目的改写提交的那一刻记进 `receipts` ——
|
|
397
|
+
* 本函数之后的任何一步(含终名改名本身、其后的退役桶扫描、`migrateOn` 里排在它后面的迁移)失败,收据都由 `migrateOn` 外层随拒因带出去;
|
|
398
|
+
* ③ 带退役命令桶的行每次起服在终名下逐页扫、逐行点名(文字预筛 + {@link retiredSessionRuleBucketsOf} 精判)—— 退役桶一个字节不动(读回照旧 `corrupt`)。
|
|
399
|
+
* 表不在(中央 DDL 之前被调到)⇒ `no-table`,不编读数。`renamed` = 本次把终名发布出来(含从进行中的名续判到底的那一次);`current` = 起服时已是终名。
|
|
400
|
+
*/
|
|
401
|
+
export declare function migrateSessionRuleGrammar(db: MigrationDb, dialect: "tidb" | "pg", receipts: SessionRuleReceipts): Promise<Pick<OneTimeMigrationReport, "sessionRuleColumn" | "sessionRuleRowsWithRetiredBuckets" | "sessionRuleRowsWithOldGrammarEntries">>;
|
|
253
402
|
/** M8 一行改写的结论:改写后的文本 / 这一行不用动 / 读不懂(解析错误原样交出,调用方计数进读数)。 */
|
|
254
403
|
export type ShadowedRuleRewrite = {
|
|
255
404
|
readonly kind: "rewrite";
|
|
@@ -266,6 +415,19 @@ export type ShadowedRuleRewrite = {
|
|
|
266
415
|
* JSON 读不懂 ⇒ `unreadable`(这一行不动,交给读口自己的响亮臂;迁移不替它猜,但把它数进读数,不静默)。
|
|
267
416
|
*/
|
|
268
417
|
export declare function migrateShadowedRuleDescriptor(text: string): ShadowedRuleRewrite;
|
|
418
|
+
/** M18 一行改写的结论(与 M8 同形,不共用型 —— 两条各自窗关各自删):改写后的文本 / 这一行不用动 / 读不懂(解析错误原样交出,调用方计数进读数)。 */
|
|
419
|
+
export type RetiredCardWordsRowRewrite = {
|
|
420
|
+
readonly kind: "rewrite";
|
|
421
|
+
readonly text: string;
|
|
422
|
+
readonly value: Record<string, unknown>;
|
|
423
|
+
} | {
|
|
424
|
+
readonly kind: "untouched";
|
|
425
|
+
} | {
|
|
426
|
+
readonly kind: "unreadable";
|
|
427
|
+
readonly error: unknown;
|
|
428
|
+
};
|
|
429
|
+
/** M18 —— `approval_ask.card_json` 一行的改写(纯函数;导出给钉用):信封里 `card` 两座上的退役词按 `retired-card-words.ts` 那一只改写。 */
|
|
430
|
+
export declare function migrateRetiredCardWordsInCardJson(text: string): RetiredCardWordsRowRewrite;
|
|
269
431
|
/**
|
|
270
432
|
* 启动日志的读数行。零命中(第二跑起的常态)也照发 —— 「跑过了、什么都没改」与「压根没跑」必须可分辨。
|
|
271
433
|
*
|
|
@@ -273,4 +435,13 @@ export declare function migrateShadowedRuleDescriptor(text: string): ShadowedRul
|
|
|
273
435
|
* 没动 ⇒ `info`。把恒常的空转也发成 warn 会训练运维忽略 warn —— 那是在为了本段的可见性去损耗整条告警轴。
|
|
274
436
|
*/
|
|
275
437
|
export declare function logOneTimeMigrations(log: MigrationLogSink, backend: string, report: OneTimeMigrationReport): void;
|
|
438
|
+
/**
|
|
439
|
+
* **起服调用点用的那一只**(`boot/stores.ts`;嵌入方走公开序列自己调 `runOneTimeMigrations()` 时拿到的是 {@link OneTimeMigrationInterruptedError} 本身,收据在 `receipts`):
|
|
440
|
+
* 跑迁移、成功则打读数行({@link logOneTimeMigrations});被打断(已提交了下次起服推不出来的改写)则**先把收据打进日志再抛**,抛的就是迁移段那只错。
|
|
441
|
+
* 其余失败原样抛、不多打一行。
|
|
442
|
+
*/
|
|
443
|
+
export declare function runAndLogOneTimeMigrations(log: MigrationLogSink, backend: {
|
|
444
|
+
readonly kind: string;
|
|
445
|
+
runOneTimeMigrations(): Promise<OneTimeMigrationReport>;
|
|
446
|
+
}): Promise<void>;
|
|
276
447
|
//# sourceMappingURL=one-time-migrations.d.ts.map
|