Skip to content

fix: egress empty-body guard + edit-comment verb — surgery channel enters the nets#281

Merged
kiki830621 merged 2 commits into
mainfrom
idd/cluster-egress-observability
Jul 27, 2026
Merged

fix: egress empty-body guard + edit-comment verb — surgery channel enters the nets#281
kiki830621 merged 2 commits into
mainfrom
idd/cluster-egress-observability

Conversation

@kiki830621

Copy link
Copy Markdown
Member

Refs #275
Refs #273

Cluster: egress 資料安全 + 觀測性(同 gh-egress 家族,per-issue commit)

Commit 1 — empty-body guard(fe224f5 系列,Refs #275

  • 既有各網全檢查內容性質、無一檢查內容存在 — 空 body 通過所有網照常派送,edit 覆寫語意 = 整個 issue body 清空(2026-07-22 實際事故)。
  • 新 guard:body channel 有提供且 strip 後為空 → 三 verb 一致 refuse;edit(含新 verb)加 <10 chars 覆寫地板(done 類短 comment 合法不受影響)。
  • Exit 15(band ≥10 紀律 — issue 建議的 exit 5 會破壞 [followup] gh-egress gate refusal 專屬 exit-code band — 與 gh 原生碼空間解耦 (follow-up finding from #117 verify) #227「rc<10 必為 gh 自身碼」invariant,diagnosis 修正之);顯式意圖出口 --allow-empty-body(wrapper 消費不轉發,split-token guard 同 attestation flags)。
  • Label-only edit(無 body channel)不受影響。suite +8 fixtures。

Commit 2 — edit-comment verb + batch band 消費(d5e7a3f,Refs #273

過程紀錄(dogfood 亮點)

commit 2 的首次 sweep 被 #163 剛上線的 contract layer 當場抓到新 code 的 $SCRUB_LEVEL 無 provenance(正是它為之而生的 class)— 已改為 block 內顯式解析賦值。該層上線同 session 即立功。

Verification

gh-egress 84/84、idd-edit 37/37、rollout 28/28、idd-edit-contract 17/17;全 sweep 41 suites 0 fail。issue 結案不由本 PR 觸發。

…t 15)

Every existing net inspects what the body CONTAINS; none checked whether it
EXISTS. An empty/whitespace-only body sailed through all nets and, on edit
(overwrite semantics), wiped the target issue body — live incident 2026-07-22
(bestOCR#1: upstream python composition failed silently, '$(cat empty)' went
out at scrub-attested warn, 40s restore only because a local copy existed).
New guard after arg parse: body channel PROVIDED + stripped-empty -> refuse
for all three verbs; edit additionally floors at 10 stripped chars ('done' is
a legit short comment, a 3-char body OVERWRITE almost never is; byte-length
on multibyte only relaxes the floor — safe direction). Wrapper-origin code 15
(band >=10 per #227 — the issue's suggested exit 5 would break the rc<10-is-gh
invariant). Explicit-intent escape --allow-empty-body (consumed, never
forwarded; same pending-value malformed-shape guard as the attestation
flags). Label-only edits with no body channel are untouched. Suite +8
fixtures (RED 6 -> GREEN 75/0).

Refs #275
…the nets, batch consumes the band

Root cause ran deeper than the filed symptom: idd-edit's Step-6 PATCH went
through raw 'gh api', a channel the #226 rollout explicitly whitelisted as
'tracked separately' — so it bypassed EVERY net (privacy / mention /
attestation / tier-floor / #275 empty-body), and classifying wrapper exit
codes in the batch loop without wiring the channel first would have been a
placebo (diagnosis correction on the issue). Two-part fix:

(1) wrapper: new edit-comment verb — 'edit-comment <id> --repo o/r
--body-file <f>' dispatches the comment PATCH ('gh api .../comments/:id -X
PATCH -F body=@file'); the body-file content rides the existing scan
pipeline so all nets apply automatically, and the #275 near-empty floor
covers it (overwrite semantics). --body-file is mandatory (14 otherwise).

(2) idd-edit batch: Step 6 dispatches via the verb; rc>=10 lands in the new
EGRESS_REFUSED bucket (warn-continue, #158 semantics), 0<rc<10 stays honest
gh-failure (skipped, not counted as refusal); Step 7.5 reports both buckets
with source tags; final exit stays 4 for any refusal — per-comment
classification CONSUMES the band, the aggregate exit does not adopt it
(which is exactly what the #227 band exists for). Disaster-recovery restore
recipe deliberately stays raw (re-publishing already-published content must
not be blockable) with the rationale annotated.

Suites: gh-egress +6 (84/84), idd-edit f14 needles synced + f15 x6 (37/37),
rollout whitelist retired + raw-line refuted + idd-edit joins the
privacy-scrubbing cite loop (28/28). Full sweep 42 suites 0 fail.

Refs #273
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant