Skip to content

fix(FAFF-375): harden merge-gate flag surface — drop --admin, fence --human-override/--allow-no-ci on a real TTY#285

Merged
alechill merged 2 commits into
mainfrom
faff-375-harden-faff-merge-gate-flag-surface-drop-admin-fence-human
Jul 7, 2026
Merged

fix(FAFF-375): harden merge-gate flag surface — drop --admin, fence --human-override/--allow-no-ci on a real TTY#285
alechill merged 2 commits into
mainfrom
faff-375-harden-faff-merge-gate-flag-surface-drop-admin-fence-human

Conversation

@alechill

@alechill alechill commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Closes FAFF-375. Hardens the faff merge-gate flag surface (FAFF-316 audit findings F2 + F5) so the mechanical merge interlock no longer depends on callers omitting a flag.

What changed

  • Dropped --admin from MERGE_FLAG_ALLOW — it bypasses the forge branch-protection backstop the floor leans on. --merge-args "--admin" now → exit 2 via the existing rejected-token path.
  • New pure fenceHumanFlags--human-override / --allow-no-ci are honoured only when process.stdin.isTTY === true and --interactive is present. A non-TTY (autonomous / agent-driven) invocation passing either → exit 2 fail-loud before any gh call, naming the real-terminal remedy.
  • decideFloor and the integrity-floor contract are untouched (pure-core/impure-shell split preserved).
  • Extended mergeGateSelftest + test/merge-gate.test.mjs (CLI-boundary, non-TTY by construction).
  • Re-routed graft's interactive no-CI confirm to hand the human the command; updated USAGE + docs/guide/cli.md (lint-cli-doc passes).

Acceptance Criteria

  • MERGE_FLAG_ALLOW no longer contains --admin; --merge-args "--admin" → exit 2
    Verified: test/merge-gate.test.mjs "--merge-args "--admin" → exit 2" + merge-gate --selftest parseMergeArgs cases — passing
  • fenceHumanFlags pure, {human_override,allow_no_ci,interactive,stdin_is_tty} → {ok,violations}
    Verified: merge-gate --selftest fence table (7 legs) — passing
  • decideFloor / integrity-floor fixtures unchanged
    Verified: git diff origin/main shows no edit to decideFloor; contract integrity-floor --selftest passing
  • Fence called with process.stdin.isTTY === true after arg validation, before ghRepoSlug/any gh call; violations → stderr + exit 2; applies under --check-only
    Verified: smoke merge-gate ... --check-only --interactive --human-override (piped stdin) → exit 2, "stdin is not a TTY", no gh spawned
  • Invocation with neither human-only flag behaves byte-identically
    Verified: existing green-path tests + fence "neither flag → ok" selftest — passing
  • graft interactive no-CI bullet re-routed to print-the-command-for-the-human; override flow same shape
    Verified: plugin/skills/faff-graft/SKILL.md diff
  • merge-gate --selftest exits 0, wired in REGION_SELFTEST_ARGV
    Verified: regions selftest → merge-gate PASS
  • USAGE + docs/guide/cli.md updated; lint-cli-doc --selftest passes
    Verified: lint-cli-doc → PASS (49 subcommands)

Spec: docs/specs/2026-07-07-FAFF-375-harden-merge-gate-flag-surface-design.md.

alechill added 2 commits July 7, 2026 14:09
…op --admin, fence --human-override/--allow-no-ci to real interactivity
…override/--allow-no-ci on a real TTY

The merge interlock's value is not depending on caller discipline. Two flag-surface
holes (FAFF-316 audit F2/F5) let an autonomous caller self-assert past the floor:

- --admin sat in MERGE_FLAG_ALLOW and was forwarded to gh pr merge, bypassing the
  forge branch-protection backstop the floor itself leans on. Removed outright; any
  --merge-args "--admin" now lands in rejected → exit 2 via the existing token path.
- --human-override / --allow-no-ci were fenced only by sibling argv flags. New pure
  fenceHumanFlags requires process.stdin.isTTY === true AND --interactive for both,
  checked before any gh call → exit 2 fail-loud naming the real-terminal remedy.

decideFloor and the integrity-floor contract are untouched. Extends mergeGateSelftest
+ test/merge-gate.test.mjs, re-routes graft's interactive no-CI confirm to hand the
human the command, and updates USAGE + docs/guide/cli.md (lint-cli-doc passes).
@alechill alechill merged commit 955d5b2 into main Jul 7, 2026
2 checks passed
@alechill alechill deleted the faff-375-harden-faff-merge-gate-flag-surface-drop-admin-fence-human branch July 7, 2026 14:22
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