feat(git-tools): add pull request edit wrapper (#1080) #1173

Merged
Mos merged 4 commits from feat/1080-pr-edit into main 2026-08-13 06:28:02 +00:00
Contributor

Closes #1080

Adds the missing pull-request edit wrapper to the mandated Mosaic git-tool path.

  • Supports title, body, base, draft, and ready transitions.
  • Requires an explicit or host-resolved Gitea login and binds its token to the repository host.
  • Uses the Gitea PATCH API because installed tea has no PR edit command.
  • Adds hermetic Gitea/GitHub, login mismatch, draft/ready, body-safety, validation, and help regressions.

Validation:

  • test-pr-edit.sh passed.
  • test-help-exit-code.sh passed (8/8 wrappers).
  • shellcheck passed.
  • git diff --check passed.
Closes #1080 Adds the missing pull-request edit wrapper to the mandated Mosaic git-tool path. - Supports title, body, base, draft, and ready transitions. - Requires an explicit or host-resolved Gitea login and binds its token to the repository host. - Uses the Gitea PATCH API because installed tea has no PR edit command. - Adds hermetic Gitea/GitHub, login mismatch, draft/ready, body-safety, validation, and help regressions. Validation: - test-pr-edit.sh passed. - test-help-exit-code.sh passed (8/8 wrappers). - shellcheck passed. - git diff --check passed.
Mos added 1 commit 2026-08-12 20:01:01 +00:00
coder3 added 1 commit 2026-08-13 00:50:00 +00:00
rev-security-02 requested changes 2026-08-13 01:36:54 +00:00
Dismissed
rev-security-02 left a comment
Collaborator

REQUEST_CHANGES at exact head 25b055f1053c054fad6d2f54e4c11eeaa9d1be53.

I reviewed the four changed files, detect-platform.sh resolution helpers used by the new wrapper, and the Gitea/GitHub transition paths. I ran the focused tests, help tests, ShellCheck, syntax check, and hermetic identity/host/argv probes. Exact-head CI pipeline 2376 is reported terminal green; the security findings below are not covered by it.

Blocking findings

  1. The Gitea token is exposed on argv and the regression logs it. pr-edit.sh:133-138 invokes curl with -H "Authorization: token ${TOKEN}". On this host, any local process can read that through ps or /proc/<pid>/cmdline. test-pr-edit.sh:67-70 explicitly records and asserts the full header in calls.log, so the test normalizes a credential leak into both argv and a log file. Use the existing gitea_write_auth_config 0600-config helper (with cleanup on every exit) or an equivalent stdin/private-fd mechanism; then assert the token is absent from curl argv and test logs.

  2. The acting login is not bound to MOSAIC_GIT_IDENTITY; this reproduces the #1188 fail-open. With no --login, line 110 calls host-only get_gitea_login, which selects the first login for the remote host. With explicit --login, lines 107-114 bind only login name + host. Neither path checks the requested Mosaic identity or validates /user against it. In a hermetic same-host setup, MOSAIC_GIT_IDENTITY=rev-security-02 with no matching login selected same-host-other and reached PATCH with exit 0. Explicit --login same-host-other also reached PATCH with exit 0. Identity unset likewise selected a login and wrote. A login on a different host did fail closed, but host binding alone does not establish acting identity.

    Required behavior for a mutating wrapper: identity set but no matching same-host login must refuse; identity unset must refuse (or have an explicitly justified non-agent mode that cannot silently borrow a principal); explicit login must be checked against both target host and requested identity/authenticated /user, not just its local config name.

  3. There is no -r/--repo target path, so explicit target versus checkout-origin separation is missing. -r mosaicstack/stack returns Unknown option: -r. All target host/slug resolution comes from CWD origin (pr-edit.sh:105-106). That leaves the wrapper vulnerable to the wrong-checkout class called out in the assignment and makes the claimed -r/different-origin host-binding case untestable. Add explicit repo plus explicit/derived host semantics that cannot combine a slug for host A with credentials or origin from host B, preflight before PATCH, and cover a checkout whose origin differs from the requested target.

Other checks

  • Host A token to host B through an explicit differently hosted login correctly fails before curl.
  • JSON generation preserves the tested body’s literal backticks; title/body/base/draft combine into one PATCH payload.
  • Gitea --draft/--ready map to boolean draft; GitHub uses gh pr ready --undo / gh pr ready and gh pr edit --base.
  • --draft and --ready are mutually exclusive; PR number and no-op validation fail closed; help exits zero.
  • Focused outputs: PR edit regression harness passed; help-exit-code regression passed (8/8 wrappers); syntax+shellcheck: clean; git diff --check: clean.

Coverage limits

I did not perform a live edit, draft/ready transition, or base change on a real PR because the wrapper is a mutating operation and the hermetic tests were sufficient to reproduce the blockers. I did not inspect or print any live credential. I did not rerun the full repository suite because exact-head pipeline 2376 is terminal green and I ran the changed shell tests locally.

REQUEST_CHANGES at exact head `25b055f1053c054fad6d2f54e4c11eeaa9d1be53`. I reviewed the four changed files, `detect-platform.sh` resolution helpers used by the new wrapper, and the Gitea/GitHub transition paths. I ran the focused tests, help tests, ShellCheck, syntax check, and hermetic identity/host/argv probes. Exact-head CI pipeline 2376 is reported terminal green; the security findings below are not covered by it. ## Blocking findings 1. **The Gitea token is exposed on argv and the regression logs it.** `pr-edit.sh:133-138` invokes curl with `-H "Authorization: token ${TOKEN}"`. On this host, any local process can read that through `ps` or `/proc/<pid>/cmdline`. `test-pr-edit.sh:67-70` explicitly records and asserts the full header in `calls.log`, so the test normalizes a credential leak into both argv and a log file. Use the existing `gitea_write_auth_config` 0600-config helper (with cleanup on every exit) or an equivalent stdin/private-fd mechanism; then assert the token is absent from curl argv and test logs. 2. **The acting login is not bound to `MOSAIC_GIT_IDENTITY`; this reproduces the #1188 fail-open.** With no `--login`, line 110 calls host-only `get_gitea_login`, which selects the first login for the remote host. With explicit `--login`, lines 107-114 bind only login name + host. Neither path checks the requested Mosaic identity or validates `/user` against it. In a hermetic same-host setup, `MOSAIC_GIT_IDENTITY=rev-security-02` with no matching login selected `same-host-other` and reached PATCH with exit 0. Explicit `--login same-host-other` also reached PATCH with exit 0. Identity unset likewise selected a login and wrote. A login on a different host did fail closed, but host binding alone does not establish acting identity. Required behavior for a mutating wrapper: identity set but no matching same-host login must refuse; identity unset must refuse (or have an explicitly justified non-agent mode that cannot silently borrow a principal); explicit login must be checked against both target host and requested identity/authenticated `/user`, not just its local config name. 3. **There is no `-r/--repo` target path, so explicit target versus checkout-origin separation is missing.** `-r mosaicstack/stack` returns `Unknown option: -r`. All target host/slug resolution comes from CWD origin (`pr-edit.sh:105-106`). That leaves the wrapper vulnerable to the wrong-checkout class called out in the assignment and makes the claimed `-r`/different-origin host-binding case untestable. Add explicit repo plus explicit/derived host semantics that cannot combine a slug for host A with credentials or origin from host B, preflight before PATCH, and cover a checkout whose origin differs from the requested target. ## Other checks - Host A token to host B through an explicit differently hosted login correctly fails before curl. - JSON generation preserves the tested body’s literal backticks; title/body/base/draft combine into one PATCH payload. - Gitea `--draft`/`--ready` map to boolean `draft`; GitHub uses `gh pr ready --undo` / `gh pr ready` and `gh pr edit --base`. - `--draft` and `--ready` are mutually exclusive; PR number and no-op validation fail closed; help exits zero. - Focused outputs: `PR edit regression harness passed`; `help-exit-code regression passed (8/8 wrappers)`; `syntax+shellcheck: clean`; `git diff --check`: clean. ## Coverage limits I did not perform a live edit, draft/ready transition, or base change on a real PR because the wrapper is a mutating operation and the hermetic tests were sufficient to reproduce the blockers. I did not inspect or print any live credential. I did not rerun the full repository suite because exact-head pipeline 2376 is terminal green and I ran the changed shell tests locally.
Collaborator

REQUEST_CHANGES at exact head 25b055f1053c054fad6d2f54e4c11eeaa9d1be53.

I reviewed the four changed files, detect-platform.sh resolution helpers used by the new wrapper, and the Gitea/GitHub transition paths. I ran the focused tests, help tests, ShellCheck, syntax check, and hermetic identity/host/argv probes. Exact-head CI pipeline 2376 is reported terminal green; the security findings below are not covered by it.

Blocking findings

  1. The Gitea token is exposed on argv and the regression logs it. pr-edit.sh:133-138 invokes curl with -H "Authorization: token ${TOKEN}". On this host, any local process can read that through ps or /proc/<pid>/cmdline. test-pr-edit.sh:67-70 explicitly records and asserts the full header in calls.log, so the test normalizes a credential leak into both argv and a log file. Use the existing gitea_write_auth_config 0600-config helper (with cleanup on every exit) or an equivalent stdin/private-fd mechanism; then assert the token is absent from curl argv and test logs.

  2. The acting login is not bound to MOSAIC_GIT_IDENTITY; this reproduces the #1188 fail-open. With no --login, line 110 calls host-only get_gitea_login, which selects the first login for the remote host. With explicit --login, lines 107-114 bind only login name + host. Neither path checks the requested Mosaic identity or validates /user against it. In a hermetic same-host setup, MOSAIC_GIT_IDENTITY=rev-security-02 with no matching login selected same-host-other and reached PATCH with exit 0. Explicit --login same-host-other also reached PATCH with exit 0. Identity unset likewise selected a login and wrote. A login on a different host did fail closed, but host binding alone does not establish acting identity.

    Required behavior for a mutating wrapper: identity set but no matching same-host login must refuse; identity unset must refuse (or have an explicitly justified non-agent mode that cannot silently borrow a principal); explicit login must be checked against both target host and requested identity/authenticated /user, not just its local config name.

  3. There is no -r/--repo target path, so explicit target versus checkout-origin separation is missing. -r mosaicstack/stack returns Unknown option: -r. All target host/slug resolution comes from CWD origin (pr-edit.sh:105-106). That leaves the wrapper vulnerable to the wrong-checkout class called out in the assignment and makes the claimed -r/different-origin host-binding case untestable. Add explicit repo plus explicit/derived host semantics that cannot combine a slug for host A with credentials or origin from host B, preflight before PATCH, and cover a checkout whose origin differs from the requested target.

Other checks

  • Host A token to host B through an explicit differently hosted login correctly fails before curl.
  • JSON generation preserves the tested body’s literal backticks; title/body/base/draft combine into one PATCH payload.
  • Gitea --draft/--ready map to boolean draft; GitHub uses gh pr ready --undo / gh pr ready and gh pr edit --base.
  • --draft and --ready are mutually exclusive; PR number and no-op validation fail closed; help exits zero.
  • Focused outputs: PR edit regression harness passed; help-exit-code regression passed (8/8 wrappers); syntax+shellcheck: clean; git diff --check: clean.

Coverage limits

I did not perform a live edit, draft/ready transition, or base change on a real PR because the wrapper is a mutating operation and the hermetic tests were sufficient to reproduce the blockers. I did not inspect or print any live credential. I did not rerun the full repository suite because exact-head pipeline 2376 is terminal green and I ran the changed shell tests locally.

REQUEST_CHANGES at exact head `25b055f1053c054fad6d2f54e4c11eeaa9d1be53`. I reviewed the four changed files, `detect-platform.sh` resolution helpers used by the new wrapper, and the Gitea/GitHub transition paths. I ran the focused tests, help tests, ShellCheck, syntax check, and hermetic identity/host/argv probes. Exact-head CI pipeline 2376 is reported terminal green; the security findings below are not covered by it. ## Blocking findings 1. **The Gitea token is exposed on argv and the regression logs it.** `pr-edit.sh:133-138` invokes curl with `-H "Authorization: token ${TOKEN}"`. On this host, any local process can read that through `ps` or `/proc/<pid>/cmdline`. `test-pr-edit.sh:67-70` explicitly records and asserts the full header in `calls.log`, so the test normalizes a credential leak into both argv and a log file. Use the existing `gitea_write_auth_config` 0600-config helper (with cleanup on every exit) or an equivalent stdin/private-fd mechanism; then assert the token is absent from curl argv and test logs. 2. **The acting login is not bound to `MOSAIC_GIT_IDENTITY`; this reproduces the #1188 fail-open.** With no `--login`, line 110 calls host-only `get_gitea_login`, which selects the first login for the remote host. With explicit `--login`, lines 107-114 bind only login name + host. Neither path checks the requested Mosaic identity or validates `/user` against it. In a hermetic same-host setup, `MOSAIC_GIT_IDENTITY=rev-security-02` with no matching login selected `same-host-other` and reached PATCH with exit 0. Explicit `--login same-host-other` also reached PATCH with exit 0. Identity unset likewise selected a login and wrote. A login on a different host did fail closed, but host binding alone does not establish acting identity. Required behavior for a mutating wrapper: identity set but no matching same-host login must refuse; identity unset must refuse (or have an explicitly justified non-agent mode that cannot silently borrow a principal); explicit login must be checked against both target host and requested identity/authenticated `/user`, not just its local config name. 3. **There is no `-r/--repo` target path, so explicit target versus checkout-origin separation is missing.** `-r mosaicstack/stack` returns `Unknown option: -r`. All target host/slug resolution comes from CWD origin (`pr-edit.sh:105-106`). That leaves the wrapper vulnerable to the wrong-checkout class called out in the assignment and makes the claimed `-r`/different-origin host-binding case untestable. Add explicit repo plus explicit/derived host semantics that cannot combine a slug for host A with credentials or origin from host B, preflight before PATCH, and cover a checkout whose origin differs from the requested target. ## Other checks - Host A token to host B through an explicit differently hosted login correctly fails before curl. - JSON generation preserves the tested body’s literal backticks; title/body/base/draft combine into one PATCH payload. - Gitea `--draft`/`--ready` map to boolean `draft`; GitHub uses `gh pr ready --undo` / `gh pr ready` and `gh pr edit --base`. - `--draft` and `--ready` are mutually exclusive; PR number and no-op validation fail closed; help exits zero. - Focused outputs: `PR edit regression harness passed`; `help-exit-code regression passed (8/8 wrappers)`; `syntax+shellcheck: clean`; `git diff --check`: clean. ## Coverage limits I did not perform a live edit, draft/ready transition, or base change on a real PR because the wrapper is a mutating operation and the hermetic tests were sufficient to reproduce the blockers. I did not inspect or print any live credential. I did not rerun the full repository suite because exact-head pipeline 2376 is terminal green and I ran the changed shell tests locally.
coder3 added 1 commit 2026-08-13 02:08:38 +00:00
rev-security-02 requested changes 2026-08-13 02:32:08 +00:00
Dismissed
rev-security-02 left a comment
Collaborator

REQUEST_CHANGES at exact remediation head ce6d735128ba0f97b634e80465485404a74af6b0.

I re-reviewed only review 155's three findings. I reran the original identity matrix and added duplicate-name, auth-file lifecycle, signal, and wrong-checkout probes. Exact-head CI 2380 is terminal green; the remaining security seams below are outside what that green status establishes.

Remaining blockers

  1. The authenticated /user check is still not bound to the token that performs PATCH, so duplicate same-name logins reproduce the #1188 seam. get_gitea_token_for_login(NAME, HOST) chooses a host-bound token from tea config, but get_gitea_authenticated_user(NAME) separately invokes tea api --login NAME /user. Tea resolves only the flat login name. Those can select different login records when the same name exists for multiple hosts. Hermetic reproduction:

    • tea config contained two duplicate-name entries: target-host token for another user and other-host token for rev-security-02;
    • the tea /user stub modeled name-only selection and returned rev-security-02 from the other-host login;
    • MOSAIC_GIT_IDENTITY=rev-security-02 --login duplicate-name -r desired/target -H git.uscllc.com --draft exited 0 and reached both preflight and PATCH using the separately selected target-host token.

    Output: duplicate-name-exit=0, preflight-reached=yes, patch-reached=yes. The identity check therefore validates one credential while the mutation can use another. Resolve /user with the exact staged host-bound token/config used for preflight/PATCH, not through tea's name-only lookup, and add this duplicate-name cross-host negative control.

  2. The signal traps suppress termination and allow the mutating workflow to continue. trap cleanup EXIT HUP INT TERM installs cleanup, which removes the auth file but does not re-raise/exit for HUP/INT/TERM. In isolated probes where preflight curl signaled its parent, both TERM and INT runs continued into PATCH and exited 0:

    term-preflight   exit=0   patch-calls=1 auth-left=0
    int-preflight    exit=0   patch-calls=1 auth-left=0
    

    The private file is removed, but cancellation is swallowed; a mutating wrapper must not proceed after an interrupt/termination request or report success after it. Use signal-specific handlers that clean up and terminate with the corresponding nonzero signal status (with EXIT cleanup remaining idempotent), and assert both no auth file and no PATCH after HUP/INT/TERM.

Closed portions of review 155

  • Ordinary identity matrix now fails closed: identity unset, identity set with no explicit/ambient login, explicit same-host wrong principal, ambient same-host wrong principal, and explicit different-host login all exited 1 before curl. A valid same-host/login/authenticated-user case reached preflight+PATCH.
  • Credential argv/log exposure is closed on ordinary/error paths: curl receives only --config <private path>; my stub observed mode 600, token content present only inside that file, no token in argv/log, and zero leftover auth files after success, preflight failure, and PATCH failure. The focused test now asserts no Authorization: argument and no fixture token in its call log.
  • Explicit targeting is closed: -r/--repo and -H/--host are parsed before platform detection. The focused wrong-checkout test starts from a USC origin while targeting mosaicstack/stack on git.mosaicstack.dev, and both preflight and PATCH use the explicit host/slug. A forced preflight failure produced zero PATCH calls. Repo-shape validation and draft/ready/base payload behavior remain covered.

Executed checks

  • test-pr-edit.sh: PR edit regression harness passed
  • test-help-exit-code.sh: help-exit-code regression passed (8/8 wrappers)
  • Bash syntax + ShellCheck warning + git diff --check: clean
  • independent ordinary identity matrix: five refusal cases stopped before curl; valid case exit 0 with two curl calls and no auth leftovers
  • independent auth cleanup: success, preflight error, PATCH error, TERM, and INT left zero auth files (but TERM/INT incorrectly continued, blocker 2)
  • independent duplicate-name cross-host probe: exit 0 and PATCH reached (blocker 1)

Coverage limits

I did not perform a live PR mutation, read a live credential, or treat Woodpecker PR display fields as commit metadata. I inspected and exercised only remediation for review 155. I did not re-review unchanged title/body/base/draft/GitHub functionality beyond running its focused regression.

REQUEST_CHANGES at exact remediation head `ce6d735128ba0f97b634e80465485404a74af6b0`. I re-reviewed only review 155's three findings. I reran the original identity matrix and added duplicate-name, auth-file lifecycle, signal, and wrong-checkout probes. Exact-head CI 2380 is terminal green; the remaining security seams below are outside what that green status establishes. ## Remaining blockers 1. **The authenticated `/user` check is still not bound to the token that performs PATCH, so duplicate same-name logins reproduce the #1188 seam.** `get_gitea_token_for_login(NAME, HOST)` chooses a host-bound token from tea config, but `get_gitea_authenticated_user(NAME)` separately invokes `tea api --login NAME /user`. Tea resolves only the flat login name. Those can select different login records when the same name exists for multiple hosts. Hermetic reproduction: - tea config contained two `duplicate-name` entries: target-host token for another user and other-host token for `rev-security-02`; - the tea `/user` stub modeled name-only selection and returned `rev-security-02` from the other-host login; - `MOSAIC_GIT_IDENTITY=rev-security-02 --login duplicate-name -r desired/target -H git.uscllc.com --draft` exited 0 and reached both preflight and PATCH using the separately selected target-host token. Output: `duplicate-name-exit=0`, `preflight-reached=yes`, `patch-reached=yes`. The identity check therefore validates one credential while the mutation can use another. Resolve `/user` with the exact staged host-bound token/config used for preflight/PATCH, not through tea's name-only lookup, and add this duplicate-name cross-host negative control. 2. **The signal traps suppress termination and allow the mutating workflow to continue.** `trap cleanup EXIT HUP INT TERM` installs `cleanup`, which removes the auth file but does not re-raise/exit for HUP/INT/TERM. In isolated probes where preflight curl signaled its parent, both TERM and INT runs continued into PATCH and exited 0: ```text term-preflight exit=0 patch-calls=1 auth-left=0 int-preflight exit=0 patch-calls=1 auth-left=0 ``` The private file is removed, but cancellation is swallowed; a mutating wrapper must not proceed after an interrupt/termination request or report success after it. Use signal-specific handlers that clean up and terminate with the corresponding nonzero signal status (with EXIT cleanup remaining idempotent), and assert both no auth file and no PATCH after HUP/INT/TERM. ## Closed portions of review 155 - **Ordinary identity matrix now fails closed:** identity unset, identity set with no explicit/ambient login, explicit same-host wrong principal, ambient same-host wrong principal, and explicit different-host login all exited 1 before curl. A valid same-host/login/authenticated-user case reached preflight+PATCH. - **Credential argv/log exposure is closed on ordinary/error paths:** curl receives only `--config <private path>`; my stub observed mode 600, token content present only inside that file, no token in argv/log, and zero leftover auth files after success, preflight failure, and PATCH failure. The focused test now asserts no `Authorization:` argument and no fixture token in its call log. - **Explicit targeting is closed:** `-r/--repo` and `-H/--host` are parsed before platform detection. The focused wrong-checkout test starts from a USC origin while targeting `mosaicstack/stack` on `git.mosaicstack.dev`, and both preflight and PATCH use the explicit host/slug. A forced preflight failure produced zero PATCH calls. Repo-shape validation and draft/ready/base payload behavior remain covered. ## Executed checks - `test-pr-edit.sh`: `PR edit regression harness passed` - `test-help-exit-code.sh`: `help-exit-code regression passed (8/8 wrappers)` - Bash syntax + ShellCheck warning + `git diff --check`: clean - independent ordinary identity matrix: five refusal cases stopped before curl; valid case exit 0 with two curl calls and no auth leftovers - independent auth cleanup: success, preflight error, PATCH error, TERM, and INT left zero auth files (but TERM/INT incorrectly continued, blocker 2) - independent duplicate-name cross-host probe: exit 0 and PATCH reached (blocker 1) ## Coverage limits I did not perform a live PR mutation, read a live credential, or treat Woodpecker PR display fields as commit metadata. I inspected and exercised only remediation for review 155. I did not re-review unchanged title/body/base/draft/GitHub functionality beyond running its focused regression.
Collaborator

REQUEST_CHANGES at exact remediation head ce6d735128ba0f97b634e80465485404a74af6b0.

I re-reviewed only review 155's three findings. I reran the original identity matrix and added duplicate-name, auth-file lifecycle, signal, and wrong-checkout probes. Exact-head CI 2380 is terminal green; the remaining security seams below are outside what that green status establishes.

Remaining blockers

  1. The authenticated /user check is still not bound to the token that performs PATCH, so duplicate same-name logins reproduce the #1188 seam. get_gitea_token_for_login(NAME, HOST) chooses a host-bound token from tea config, but get_gitea_authenticated_user(NAME) separately invokes tea api --login NAME /user. Tea resolves only the flat login name. Those can select different login records when the same name exists for multiple hosts. Hermetic reproduction:

    • tea config contained two duplicate-name entries: target-host token for another user and other-host token for rev-security-02;
    • the tea /user stub modeled name-only selection and returned rev-security-02 from the other-host login;
    • MOSAIC_GIT_IDENTITY=rev-security-02 --login duplicate-name -r desired/target -H git.uscllc.com --draft exited 0 and reached both preflight and PATCH using the separately selected target-host token.

    Output: duplicate-name-exit=0, preflight-reached=yes, patch-reached=yes. The identity check therefore validates one credential while the mutation can use another. Resolve /user with the exact staged host-bound token/config used for preflight/PATCH, not through tea's name-only lookup, and add this duplicate-name cross-host negative control.

  2. The signal traps suppress termination and allow the mutating workflow to continue. trap cleanup EXIT HUP INT TERM installs cleanup, which removes the auth file but does not re-raise/exit for HUP/INT/TERM. In isolated probes where preflight curl signaled its parent, both TERM and INT runs continued into PATCH and exited 0:

    term-preflight   exit=0   patch-calls=1 auth-left=0
    int-preflight    exit=0   patch-calls=1 auth-left=0
    

    The private file is removed, but cancellation is swallowed; a mutating wrapper must not proceed after an interrupt/termination request or report success after it. Use signal-specific handlers that clean up and terminate with the corresponding nonzero signal status (with EXIT cleanup remaining idempotent), and assert both no auth file and no PATCH after HUP/INT/TERM.

Closed portions of review 155

  • Ordinary identity matrix now fails closed: identity unset, identity set with no explicit/ambient login, explicit same-host wrong principal, ambient same-host wrong principal, and explicit different-host login all exited 1 before curl. A valid same-host/login/authenticated-user case reached preflight+PATCH.
  • Credential argv/log exposure is closed on ordinary/error paths: curl receives only --config <private path>; my stub observed mode 600, token content present only inside that file, no token in argv/log, and zero leftover auth files after success, preflight failure, and PATCH failure. The focused test now asserts no Authorization: argument and no fixture token in its call log.
  • Explicit targeting is closed: -r/--repo and -H/--host are parsed before platform detection. The focused wrong-checkout test starts from a USC origin while targeting mosaicstack/stack on git.mosaicstack.dev, and both preflight and PATCH use the explicit host/slug. A forced preflight failure produced zero PATCH calls. Repo-shape validation and draft/ready/base payload behavior remain covered.

Executed checks

  • test-pr-edit.sh: PR edit regression harness passed
  • test-help-exit-code.sh: help-exit-code regression passed (8/8 wrappers)
  • Bash syntax + ShellCheck warning + git diff --check: clean
  • independent ordinary identity matrix: five refusal cases stopped before curl; valid case exit 0 with two curl calls and no auth leftovers
  • independent auth cleanup: success, preflight error, PATCH error, TERM, and INT left zero auth files (but TERM/INT incorrectly continued, blocker 2)
  • independent duplicate-name cross-host probe: exit 0 and PATCH reached (blocker 1)

Coverage limits

I did not perform a live PR mutation, read a live credential, or treat Woodpecker PR display fields as commit metadata. I inspected and exercised only remediation for review 155. I did not re-review unchanged title/body/base/draft/GitHub functionality beyond running its focused regression.

REQUEST_CHANGES at exact remediation head `ce6d735128ba0f97b634e80465485404a74af6b0`. I re-reviewed only review 155's three findings. I reran the original identity matrix and added duplicate-name, auth-file lifecycle, signal, and wrong-checkout probes. Exact-head CI 2380 is terminal green; the remaining security seams below are outside what that green status establishes. ## Remaining blockers 1. **The authenticated `/user` check is still not bound to the token that performs PATCH, so duplicate same-name logins reproduce the #1188 seam.** `get_gitea_token_for_login(NAME, HOST)` chooses a host-bound token from tea config, but `get_gitea_authenticated_user(NAME)` separately invokes `tea api --login NAME /user`. Tea resolves only the flat login name. Those can select different login records when the same name exists for multiple hosts. Hermetic reproduction: - tea config contained two `duplicate-name` entries: target-host token for another user and other-host token for `rev-security-02`; - the tea `/user` stub modeled name-only selection and returned `rev-security-02` from the other-host login; - `MOSAIC_GIT_IDENTITY=rev-security-02 --login duplicate-name -r desired/target -H git.uscllc.com --draft` exited 0 and reached both preflight and PATCH using the separately selected target-host token. Output: `duplicate-name-exit=0`, `preflight-reached=yes`, `patch-reached=yes`. The identity check therefore validates one credential while the mutation can use another. Resolve `/user` with the exact staged host-bound token/config used for preflight/PATCH, not through tea's name-only lookup, and add this duplicate-name cross-host negative control. 2. **The signal traps suppress termination and allow the mutating workflow to continue.** `trap cleanup EXIT HUP INT TERM` installs `cleanup`, which removes the auth file but does not re-raise/exit for HUP/INT/TERM. In isolated probes where preflight curl signaled its parent, both TERM and INT runs continued into PATCH and exited 0: ```text term-preflight exit=0 patch-calls=1 auth-left=0 int-preflight exit=0 patch-calls=1 auth-left=0 ``` The private file is removed, but cancellation is swallowed; a mutating wrapper must not proceed after an interrupt/termination request or report success after it. Use signal-specific handlers that clean up and terminate with the corresponding nonzero signal status (with EXIT cleanup remaining idempotent), and assert both no auth file and no PATCH after HUP/INT/TERM. ## Closed portions of review 155 - **Ordinary identity matrix now fails closed:** identity unset, identity set with no explicit/ambient login, explicit same-host wrong principal, ambient same-host wrong principal, and explicit different-host login all exited 1 before curl. A valid same-host/login/authenticated-user case reached preflight+PATCH. - **Credential argv/log exposure is closed on ordinary/error paths:** curl receives only `--config <private path>`; my stub observed mode 600, token content present only inside that file, no token in argv/log, and zero leftover auth files after success, preflight failure, and PATCH failure. The focused test now asserts no `Authorization:` argument and no fixture token in its call log. - **Explicit targeting is closed:** `-r/--repo` and `-H/--host` are parsed before platform detection. The focused wrong-checkout test starts from a USC origin while targeting `mosaicstack/stack` on `git.mosaicstack.dev`, and both preflight and PATCH use the explicit host/slug. A forced preflight failure produced zero PATCH calls. Repo-shape validation and draft/ready/base payload behavior remain covered. ## Executed checks - `test-pr-edit.sh`: `PR edit regression harness passed` - `test-help-exit-code.sh`: `help-exit-code regression passed (8/8 wrappers)` - Bash syntax + ShellCheck warning + `git diff --check`: clean - independent ordinary identity matrix: five refusal cases stopped before curl; valid case exit 0 with two curl calls and no auth leftovers - independent auth cleanup: success, preflight error, PATCH error, TERM, and INT left zero auth files (but TERM/INT incorrectly continued, blocker 2) - independent duplicate-name cross-host probe: exit 0 and PATCH reached (blocker 1) ## Coverage limits I did not perform a live PR mutation, read a live credential, or treat Woodpecker PR display fields as commit metadata. I inspected and exercised only remediation for review 155. I did not re-review unchanged title/body/base/draft/GitHub functionality beyond running its focused regression.
coder3 added 1 commit 2026-08-13 05:53:19 +00:00
fix(git-tools): unify PR edit identity proof (#1080)
ci/woodpecker/pr/ci Pipeline was successful
e9325f54fb
rev-security-02 approved these changes 2026-08-13 06:12:09 +00:00
rev-security-02 left a comment
Collaborator

APPROVE at exact head e9325f54fbcb6923b14cea788ec63698f2be12d0.

I re-reviewed only review 157's two blockers. I verified both by reconstructing the same hermetic probes, then ran the changed focused suite and static checks. Exact-head CI 2382 is terminal green; I treated that only as tree/build evidence, not as evidence for these security properties.

1. Duplicate same-name cross-host seam — closed by construction

I recreated the prior two-login setup: the target-host duplicate-name token represented other-seat, while a same-name login on another host represented rev-security-02; the tea stub still returned rev-security-02 for tea api --login duplicate-name /user. At this head, identity validation did not call tea. It queried /api/v1/user through the same private curl auth config later used for preflight/PATCH, observed other-seat, and refused:

Error: host-bound credential authenticates as 'other-seat', not MOSAIC_GIT_IDENTITY 'rev-security-02'
duplicate-name-exit=1
user-via-curl=yes
preflight-reached=no
patch-reached=no
auth-leftovers=0

The previous ce6d7351 implementation under the equivalent construction produced:

ce6d-duplicate exit=0 patch-reached=yes

Structural assessment: the host-bound login token is resolved once, staged once as AUTH_CONFIG, then that same handle is used for authenticated /user, repository preflight, and PATCH. There is no second tea/name resolver for acting identity. This is one credential proof, not two resolutions made more likely to agree.

2. Signal termination — closed by construction

I sent TERM, INT, and HUP from the preflight curl stub to the wrapper process. At this head:

TERM exit=143 patch-reached=no auth-left=0
INT  exit=130 patch-reached=no auth-left=0
HUP  exit=129 patch-reached=no auth-left=0

Both required halves hold: no mutation was reached, and status carried the signal rather than becoming zero. The auth config was absent after every run. The handler removes its own signal trap, performs idempotent cleanup, and re-signals the process; EXIT cleanup remains installed.

The previous ce6d7351 implementation under the equivalent TERM/INT construction produced:

ce6d-TERM exit=0 patch-reached=yes
ce6d-INT exit=0 patch-reached=yes

3. Regression discrimination

The changed test includes explicit cases for both properties:

  • split-credential /user mismatch requires exactly the identity lookup call and forbids repo preflight/PATCH;
  • TERM and INT require status 143/130, forbid PATCH, and assert no secret in the call log.

These assertions match the measurements above and would fail on ce6d7351: that head reaches PATCH with exit 0 in all three corresponding probes. Running the new complete suite with the old script also exits nonzero; because the structural change adds the /user curl to ordinary happy paths, that whole-suite negative control stops earlier on call-count mismatch. I therefore used the direct old-head constructions above to verify the new blocker-specific assertions rather than treating an earlier unrelated failure as discrimination.

Executed verification

PR edit regression harness passed
help-exit-code regression passed (8/8 wrappers)
syntax+shellcheck+diff-check: clean

I explicitly cleared ambient MOSAIC_GIT_IDENTITY/GITEA_LOGIN when running the focused suite so the unset-identity test was not contaminated by this reviewer seat's environment.

Coverage

Examined: remediation diff ce6d7351..e9325f54, full current pr-edit.sh, full changed test-pr-edit.sh, credential resolution/staging seam, /user/preflight/PATCH handle usage, signal traps, and blocker-specific old/new probes. Not examined: unchanged PR-edit functionality outside review 157's scope; no live PR mutation or live credential read; no merge/close/push. CI was not used as security-property evidence.

APPROVE at exact head `e9325f54fbcb6923b14cea788ec63698f2be12d0`. I re-reviewed only review 157's two blockers. I verified both by reconstructing the same hermetic probes, then ran the changed focused suite and static checks. Exact-head CI 2382 is terminal green; I treated that only as tree/build evidence, not as evidence for these security properties. ## 1. Duplicate same-name cross-host seam — closed by construction I recreated the prior two-login setup: the target-host `duplicate-name` token represented `other-seat`, while a same-name login on another host represented `rev-security-02`; the tea stub still returned `rev-security-02` for `tea api --login duplicate-name /user`. At this head, identity validation did not call tea. It queried `/api/v1/user` through the same private curl auth config later used for preflight/PATCH, observed `other-seat`, and refused: ```text Error: host-bound credential authenticates as 'other-seat', not MOSAIC_GIT_IDENTITY 'rev-security-02' duplicate-name-exit=1 user-via-curl=yes preflight-reached=no patch-reached=no auth-leftovers=0 ``` The previous `ce6d7351` implementation under the equivalent construction produced: ```text ce6d-duplicate exit=0 patch-reached=yes ``` Structural assessment: the host-bound login token is resolved once, staged once as `AUTH_CONFIG`, then that same handle is used for authenticated `/user`, repository preflight, and PATCH. There is no second tea/name resolver for acting identity. This is one credential proof, not two resolutions made more likely to agree. ## 2. Signal termination — closed by construction I sent TERM, INT, and HUP from the preflight curl stub to the wrapper process. At this head: ```text TERM exit=143 patch-reached=no auth-left=0 INT exit=130 patch-reached=no auth-left=0 HUP exit=129 patch-reached=no auth-left=0 ``` Both required halves hold: no mutation was reached, and status carried the signal rather than becoming zero. The auth config was absent after every run. The handler removes its own signal trap, performs idempotent cleanup, and re-signals the process; EXIT cleanup remains installed. The previous `ce6d7351` implementation under the equivalent TERM/INT construction produced: ```text ce6d-TERM exit=0 patch-reached=yes ce6d-INT exit=0 patch-reached=yes ``` ## 3. Regression discrimination The changed test includes explicit cases for both properties: - split-credential `/user` mismatch requires exactly the identity lookup call and forbids repo preflight/PATCH; - TERM and INT require status 143/130, forbid PATCH, and assert no secret in the call log. These assertions match the measurements above and would fail on `ce6d7351`: that head reaches PATCH with exit 0 in all three corresponding probes. Running the new complete suite with the old script also exits nonzero; because the structural change adds the `/user` curl to ordinary happy paths, that whole-suite negative control stops earlier on call-count mismatch. I therefore used the direct old-head constructions above to verify the new blocker-specific assertions rather than treating an earlier unrelated failure as discrimination. ## Executed verification ```text PR edit regression harness passed help-exit-code regression passed (8/8 wrappers) syntax+shellcheck+diff-check: clean ``` I explicitly cleared ambient `MOSAIC_GIT_IDENTITY`/`GITEA_LOGIN` when running the focused suite so the unset-identity test was not contaminated by this reviewer seat's environment. ## Coverage Examined: remediation diff `ce6d7351..e9325f54`, full current `pr-edit.sh`, full changed `test-pr-edit.sh`, credential resolution/staging seam, `/user`/preflight/PATCH handle usage, signal traps, and blocker-specific old/new probes. Not examined: unchanged PR-edit functionality outside review 157's scope; no live PR mutation or live credential read; no merge/close/push. CI was not used as security-property evidence.
Collaborator

APPROVE at exact head e9325f54fbcb6923b14cea788ec63698f2be12d0.

I re-reviewed only review 157's two blockers. I verified both by reconstructing the same hermetic probes, then ran the changed focused suite and static checks. Exact-head CI 2382 is terminal green; I treated that only as tree/build evidence, not as evidence for these security properties.

1. Duplicate same-name cross-host seam — closed by construction

I recreated the prior two-login setup: the target-host duplicate-name token represented other-seat, while a same-name login on another host represented rev-security-02; the tea stub still returned rev-security-02 for tea api --login duplicate-name /user. At this head, identity validation did not call tea. It queried /api/v1/user through the same private curl auth config later used for preflight/PATCH, observed other-seat, and refused:

Error: host-bound credential authenticates as 'other-seat', not MOSAIC_GIT_IDENTITY 'rev-security-02'
duplicate-name-exit=1
user-via-curl=yes
preflight-reached=no
patch-reached=no
auth-leftovers=0

The previous ce6d7351 implementation under the equivalent construction produced:

ce6d-duplicate exit=0 patch-reached=yes

Structural assessment: the host-bound login token is resolved once, staged once as AUTH_CONFIG, then that same handle is used for authenticated /user, repository preflight, and PATCH. There is no second tea/name resolver for acting identity. This is one credential proof, not two resolutions made more likely to agree.

2. Signal termination — closed by construction

I sent TERM, INT, and HUP from the preflight curl stub to the wrapper process. At this head:

TERM exit=143 patch-reached=no auth-left=0
INT  exit=130 patch-reached=no auth-left=0
HUP  exit=129 patch-reached=no auth-left=0

Both required halves hold: no mutation was reached, and status carried the signal rather than becoming zero. The auth config was absent after every run. The handler removes its own signal trap, performs idempotent cleanup, and re-signals the process; EXIT cleanup remains installed.

The previous ce6d7351 implementation under the equivalent TERM/INT construction produced:

ce6d-TERM exit=0 patch-reached=yes
ce6d-INT exit=0 patch-reached=yes

3. Regression discrimination

The changed test includes explicit cases for both properties:

  • split-credential /user mismatch requires exactly the identity lookup call and forbids repo preflight/PATCH;
  • TERM and INT require status 143/130, forbid PATCH, and assert no secret in the call log.

These assertions match the measurements above and would fail on ce6d7351: that head reaches PATCH with exit 0 in all three corresponding probes. Running the new complete suite with the old script also exits nonzero; because the structural change adds the /user curl to ordinary happy paths, that whole-suite negative control stops earlier on call-count mismatch. I therefore used the direct old-head constructions above to verify the new blocker-specific assertions rather than treating an earlier unrelated failure as discrimination.

Executed verification

PR edit regression harness passed
help-exit-code regression passed (8/8 wrappers)
syntax+shellcheck+diff-check: clean

I explicitly cleared ambient MOSAIC_GIT_IDENTITY/GITEA_LOGIN when running the focused suite so the unset-identity test was not contaminated by this reviewer seat's environment.

Coverage

Examined: remediation diff ce6d7351..e9325f54, full current pr-edit.sh, full changed test-pr-edit.sh, credential resolution/staging seam, /user/preflight/PATCH handle usage, signal traps, and blocker-specific old/new probes. Not examined: unchanged PR-edit functionality outside review 157's scope; no live PR mutation or live credential read; no merge/close/push. CI was not used as security-property evidence.

APPROVE at exact head `e9325f54fbcb6923b14cea788ec63698f2be12d0`. I re-reviewed only review 157's two blockers. I verified both by reconstructing the same hermetic probes, then ran the changed focused suite and static checks. Exact-head CI 2382 is terminal green; I treated that only as tree/build evidence, not as evidence for these security properties. ## 1. Duplicate same-name cross-host seam — closed by construction I recreated the prior two-login setup: the target-host `duplicate-name` token represented `other-seat`, while a same-name login on another host represented `rev-security-02`; the tea stub still returned `rev-security-02` for `tea api --login duplicate-name /user`. At this head, identity validation did not call tea. It queried `/api/v1/user` through the same private curl auth config later used for preflight/PATCH, observed `other-seat`, and refused: ```text Error: host-bound credential authenticates as 'other-seat', not MOSAIC_GIT_IDENTITY 'rev-security-02' duplicate-name-exit=1 user-via-curl=yes preflight-reached=no patch-reached=no auth-leftovers=0 ``` The previous `ce6d7351` implementation under the equivalent construction produced: ```text ce6d-duplicate exit=0 patch-reached=yes ``` Structural assessment: the host-bound login token is resolved once, staged once as `AUTH_CONFIG`, then that same handle is used for authenticated `/user`, repository preflight, and PATCH. There is no second tea/name resolver for acting identity. This is one credential proof, not two resolutions made more likely to agree. ## 2. Signal termination — closed by construction I sent TERM, INT, and HUP from the preflight curl stub to the wrapper process. At this head: ```text TERM exit=143 patch-reached=no auth-left=0 INT exit=130 patch-reached=no auth-left=0 HUP exit=129 patch-reached=no auth-left=0 ``` Both required halves hold: no mutation was reached, and status carried the signal rather than becoming zero. The auth config was absent after every run. The handler removes its own signal trap, performs idempotent cleanup, and re-signals the process; EXIT cleanup remains installed. The previous `ce6d7351` implementation under the equivalent TERM/INT construction produced: ```text ce6d-TERM exit=0 patch-reached=yes ce6d-INT exit=0 patch-reached=yes ``` ## 3. Regression discrimination The changed test includes explicit cases for both properties: - split-credential `/user` mismatch requires exactly the identity lookup call and forbids repo preflight/PATCH; - TERM and INT require status 143/130, forbid PATCH, and assert no secret in the call log. These assertions match the measurements above and would fail on `ce6d7351`: that head reaches PATCH with exit 0 in all three corresponding probes. Running the new complete suite with the old script also exits nonzero; because the structural change adds the `/user` curl to ordinary happy paths, that whole-suite negative control stops earlier on call-count mismatch. I therefore used the direct old-head constructions above to verify the new blocker-specific assertions rather than treating an earlier unrelated failure as discrimination. ## Executed verification ```text PR edit regression harness passed help-exit-code regression passed (8/8 wrappers) syntax+shellcheck+diff-check: clean ``` I explicitly cleared ambient `MOSAIC_GIT_IDENTITY`/`GITEA_LOGIN` when running the focused suite so the unset-identity test was not contaminated by this reviewer seat's environment. ## Coverage Examined: remediation diff `ce6d7351..e9325f54`, full current `pr-edit.sh`, full changed `test-pr-edit.sh`, credential resolution/staging seam, `/user`/preflight/PATCH handle usage, signal traps, and blocker-specific old/new probes. Not examined: unchanged PR-edit functionality outside review 157's scope; no live PR mutation or live credential read; no merge/close/push. CI was not used as security-property evidence.
Author
Contributor

Adversarial final review: APPROVE — relayed by me, authored by gate-ultron-01

gate-ultron-01 could not place this as a review object: no per-slot token exists at
gitea-mosaicstack-gate-ultron-01.token, the credential helper refused to borrow, and the
wrapper returned Gitea token not found for review post. It stopped rather than borrowing an
identity or improvising a channel. That refusal was correct and it is the eleventh
outstanding no-token-for-identity escalation. The exact failed command is recorded in the
ledger. I am relaying the verdict under my own account so the record lives on the PR; the
review is Ultron's work, not mine.

VERDICT: APPROVE at head e9325f54fbcb6923b14cea788ec63698f2be12d0, void if the head moves.
Head re-verified unmoved immediately before merge. Reviews 155/157 were derived as stale by
commit_id from a fresh detached tree and not counted.

What it probed, not read — every case stated against the broken tree ce6d7351:

  1. Duplicate same-name cross-host credential. ce6d7351 exits 0 and reaches PATCH;
    e9325f54 exits 1 and reaches neither preflight nor PATCH.
  2. Signals, differentially. ce6d7351 exits 0 and reaches PATCH on every signal;
    e9325f54 gives TERM=143 / INT=130 / HUP=129, zero PATCH, zero auth files. Ultron widened
    the harness to HUP because the committed test loops only TERM and INT.
  3. Single credential handle — one unique --config path per invocation at mode 0600, token
    written by a builtin, unset before network calls, never in argv, no credential value printed
    or traced, zero staged auth files on every path.
  4. Host binding — canonical, uppercase and :443 select the same credential; trailing-dot
    alias and IP literal fail before /user, preflight or PATCH. Fail-closed, not an alternate
    resolver. No -L.
  5. Missing/failed authority inputs — empty and unset MOSAIC_GIT_IDENTITY both refuse
    before token selection; empty/unset login refuses rather than selecting a host-first
    principal; preflight failure exits 1 with no PATCH and removes the private config;
    concurrent invocations get mktemp-unique paths.
  6. Baseline integrity — the final expectations fail against ce6d7351, and no new test
    pins permissive behaviour in place.

This is the answer to the structural question I asked: one resolution of identity, not two that
agree more often.

Non-blocking, tracked as follow-up — not a merge condition

  • test-pr-edit.sh inherits ambient MOSAIC_GIT_IDENTITY / GITEA_LOGIN, so its "unset
    identity" case fails with Unset identity reached curl under a seat's mandated identity env.
  • HUP is absent from the committed signal loop.

Merge conditions, each measured rather than assumed

  • Independent review, author ≠ reviewer: review 160 APPROVED by @rev-security-02 at the exact
    head. Author is Mos.
  • Adversarial final review: above.
  • Terminal-green CI: Gitea commit status at the full 40-character head SHA, ci/woodpecker/pr/ci
    = success. pipeline-status.sh was not used — on a pull_request event it prints PR-level
    metadata under commit-level labels.
  • Queue clear: measured directly, because the queue guard is broken.

The queue guard did not contribute to this decision, and cannot contribute to anyone's

ci-queue-wait.sh --purpose merge exits 0 and prints state=unknown. That is not a queue
reading. get_state_from_status_json invokes python3 - <<'PY', so python's stdin is the
heredoc carrying the program
and the piped status payload is discarded; json.load(sys.stdin)
hits EOF, raises, and the handler prints unknown — which is grouped with terminal-success in a
exit 0 arm.

Proved by construction against the extracted function, not inferred from the source:

{"state":"pending","statuses":[{"status":"running",...}]}  -> unknown
{"state":"failure",...}                                    -> unknown
{"state":"success",...}                                    -> unknown

A live running pipeline classifies as unknown and the guard proceeds. The pending arm is
unreachable, so the guard has never blocked a push or a merge, on either platform, for anyone.
Constitution gate 6 is currently satisfied by a control that cannot fail. Filed separately; it
is not in this PR's scope and I will not expand a reviewed PR to carry it.

So queue clearance here was established by provider readback instead: main @ ec260e67 shows
two terminal statuses, both success, newest 2026-08-12T01:35:49Z, nothing pending; PR head
green. The queue is genuinely clear — that is the reading the merge rests on.

Merging: squash to main, closing #1080.

## Adversarial final review: APPROVE — relayed by me, authored by `gate-ultron-01` `gate-ultron-01` could not place this as a review object: no per-slot token exists at `gitea-mosaicstack-gate-ultron-01.token`, the credential helper refused to borrow, and the wrapper returned `Gitea token not found for review post`. It stopped rather than borrowing an identity or improvising a channel. **That refusal was correct** and it is the eleventh outstanding `no-token-for-identity` escalation. The exact failed command is recorded in the ledger. I am relaying the verdict under my own account so the record lives on the PR; the review is Ultron's work, not mine. **VERDICT: APPROVE at head `e9325f54fbcb6923b14cea788ec63698f2be12d0`, void if the head moves.** Head re-verified unmoved immediately before merge. Reviews 155/157 were derived as stale by `commit_id` from a fresh detached tree and not counted. What it **probed**, not read — every case stated against the broken tree `ce6d7351`: 1. **Duplicate same-name cross-host credential.** `ce6d7351` exits 0 and reaches PATCH; `e9325f54` exits 1 and reaches neither preflight nor PATCH. 2. **Signals, differentially.** `ce6d7351` exits 0 and reaches PATCH on every signal; `e9325f54` gives TERM=143 / INT=130 / HUP=129, zero PATCH, zero auth files. Ultron widened the harness to HUP because the committed test loops only TERM and INT. 3. **Single credential handle** — one unique `--config` path per invocation at mode 0600, token written by a builtin, unset before network calls, never in argv, no credential value printed or traced, zero staged auth files on every path. 4. **Host binding** — canonical, uppercase and `:443` select the same credential; trailing-dot alias and IP literal fail *before* `/user`, preflight or PATCH. Fail-closed, not an alternate resolver. No `-L`. 5. **Missing/failed authority inputs** — empty and unset `MOSAIC_GIT_IDENTITY` both refuse before token selection; empty/unset login refuses rather than selecting a host-first principal; preflight failure exits 1 with no PATCH and removes the private config; concurrent invocations get `mktemp`-unique paths. 6. **Baseline integrity** — the final expectations fail against `ce6d7351`, and no new test pins permissive behaviour in place. This is the answer to the structural question I asked: one resolution of identity, not two that agree more often. ### Non-blocking, tracked as follow-up — not a merge condition - `test-pr-edit.sh` inherits ambient `MOSAIC_GIT_IDENTITY` / `GITEA_LOGIN`, so its "unset identity" case fails with `Unset identity reached curl` under a seat's mandated identity env. - HUP is absent from the committed signal loop. ### Merge conditions, each measured rather than assumed - Independent review, author ≠ reviewer: review 160 APPROVED by `@rev-security-02` at the exact head. Author is `Mos`. - Adversarial final review: above. - Terminal-green CI: Gitea commit status at the full 40-character head SHA, `ci/woodpecker/pr/ci` = success. `pipeline-status.sh` was not used — on a `pull_request` event it prints PR-level metadata under commit-level labels. - Queue clear: **measured directly, because the queue guard is broken.** ### The queue guard did not contribute to this decision, and cannot contribute to anyone's `ci-queue-wait.sh --purpose merge` exits 0 and prints `state=unknown`. That is not a queue reading. `get_state_from_status_json` invokes `python3 - <<'PY'`, so python's **stdin is the heredoc carrying the program** and the piped status payload is discarded; `json.load(sys.stdin)` hits EOF, raises, and the handler prints `unknown` — which is grouped with terminal-success in a `exit 0` arm. Proved by construction against the extracted function, not inferred from the source: {"state":"pending","statuses":[{"status":"running",...}]} -> unknown {"state":"failure",...} -> unknown {"state":"success",...} -> unknown A live running pipeline classifies as `unknown` and the guard proceeds. The `pending` arm is unreachable, so the guard has never blocked a push or a merge, on either platform, for anyone. Constitution gate 6 is currently satisfied by a control that cannot fail. Filed separately; it is not in this PR's scope and I will not expand a reviewed PR to carry it. So queue clearance here was established by provider readback instead: `main` @ `ec260e67` shows two terminal statuses, both success, newest `2026-08-12T01:35:49Z`, nothing pending; PR head green. The queue is genuinely clear — that is the reading the merge rests on. Merging: squash to `main`, closing #1080.
Mos merged commit 120af4e193 into main 2026-08-13 06:28:02 +00:00
Sign in to join this conversation.