feat(attribution): one verified address for the agent on every forge #964

Merged
coilysiren merged 1 commit from aos/claude/wz68-bot-identity into main 2026-08-27 09:33:52 +00:00
Owner

Agent commits were authored as the GitHub App's noreply alias, built from /github/coilyco-ops-user-id. That address can never receive mail, so it could not be verified on any forge, and the agent rendered as a placeholder everywhere except GitHub.

coilyco-ops@coilysiren.me is now verified on all three forges the estate publishes to:

  • Forgejo - the coilyco-ops user already carried it, verified, as a secondary address. Nothing to do.
  • Tangled - verified against the bot.coilysiren.me handle, via the SES inbound path from coilysiren/inbox#440.
  • GitHub - a machine user now holds it, verified through the same SES path.

One address attributes the agent on all three. The commits already authored under it attributed retroactively on each forge the moment its verification landed, confirmed on GitHub by querying a July commit and seeing author.login = coilyco-ops.

What this removes

  • The /github/coilyco-ops-user-id SSM lookup from the Ansible role.
  • The entire AOSguard resolution block and the -AOSguardPath parameter from the Windows converge script. Both existed solely to feed that lookup, so AOSguard is no longer a dependency of attribution convergence at all.

The task named Build the cross-forge bot author identity is finally accurate rather than being the most GitHub-shaped string in the estate.

What is untouched

The coilyco-ops[bot] GitHub App. It still authenticates and pushes. GitHub links commits to accounts by author email regardless of which credential pushed them, so authentication and attribution are independent and both work. The machine user holds no token, no repo access, and no collaborator grant, so this adds attribution without adding credential surface.

provision_coilyco_ops_bot_helper.py and its test are deliberately unchanged: they provision the App's own noreply alias, which is a separate concern from commit attribution, and the App still exists.

Tests

scripts/agent_git_attribution_test.py needed no change (its fixtures use bot@example.invalid). scripts/windows_git_convergence_test.py asserted the old coilyco-ops[bot] <123+... shape and staged a fake AOSguard to feed the SSM call, both now gone.

18/18 pass in 0.38s.

A trap worth knowing about

Running just agent-git-attribution-test from inside an agent session fails one test, test_hook_and_shim_set_bot_author_and_two_coauthors, and takes ~190s doing it. This is not a defect and predates this branch: it reproduces identically on main at b16da78.

The cause is that the harness pre-exports AGENT_GIT_ATTRIBUTION_COAUTHOR and prepends the real shim directory to PATH. The test does os.environ.copy(), so its staged shim resolves the "real git" back to the ambient shim and recurses until git exits 2. Unset that variable and strip the shim directory from PATH and the same test passes in 0.55s.

Worth a follow-up so the test sanitises its own environment rather than inheriting a hostile one, but out of scope here.

Rollout

This is authored here; the fleet converge is the separate act. No host changes identity until agent-git-attribution runs on it.

Agent commits were authored as the GitHub App's noreply alias, built from `/github/coilyco-ops-user-id`. That address can never receive mail, so it could not be verified on any forge, and the agent rendered as a placeholder everywhere except GitHub. `coilyco-ops@coilysiren.me` is now verified on all three forges the estate publishes to: * **Forgejo** - the `coilyco-ops` user already carried it, verified, as a secondary address. Nothing to do. * **Tangled** - verified against the `bot.coilysiren.me` handle, via the SES inbound path from coilysiren/inbox#440. * **GitHub** - a machine user now holds it, verified through the same SES path. One address attributes the agent on all three. The commits already authored under it attributed **retroactively** on each forge the moment its verification landed, confirmed on GitHub by querying a July commit and seeing `author.login = coilyco-ops`. ## What this removes * The `/github/coilyco-ops-user-id` SSM lookup from the Ansible role. * The entire AOSguard resolution block and the `-AOSguardPath` parameter from the Windows converge script. Both existed solely to feed that lookup, so AOSguard is no longer a dependency of attribution convergence at all. The task named `Build the cross-forge bot author identity` is finally accurate rather than being the most GitHub-shaped string in the estate. ## What is untouched The `coilyco-ops[bot]` GitHub App. It still authenticates and pushes. GitHub links commits to accounts by author email regardless of which credential pushed them, so authentication and attribution are independent and both work. The machine user holds no token, no repo access, and no collaborator grant, so this adds attribution without adding credential surface. `provision_coilyco_ops_bot_helper.py` and its test are deliberately unchanged: they provision the App's own noreply alias, which is a separate concern from commit attribution, and the App still exists. ## Tests `scripts/agent_git_attribution_test.py` needed no change (its fixtures use `bot@example.invalid`). `scripts/windows_git_convergence_test.py` asserted the old `coilyco-ops[bot] <123+...` shape and staged a fake AOSguard to feed the SSM call, both now gone. **18/18 pass in 0.38s.** ### A trap worth knowing about Running `just agent-git-attribution-test` from inside an agent session fails one test, `test_hook_and_shim_set_bot_author_and_two_coauthors`, and takes ~190s doing it. This is **not** a defect and predates this branch: it reproduces identically on `main` at `b16da78`. The cause is that the harness pre-exports `AGENT_GIT_ATTRIBUTION_COAUTHOR` and prepends the real shim directory to `PATH`. The test does `os.environ.copy()`, so its staged shim resolves the "real git" back to the ambient shim and recurses until git exits 2. Unset that variable and strip the shim directory from `PATH` and the same test passes in 0.55s. Worth a follow-up so the test sanitises its own environment rather than inheriting a hostile one, but out of scope here. ## Rollout This is authored here; the fleet converge is the separate act. No host changes identity until `agent-git-attribution` runs on it.
feat(attribution): one verified address for the agent on every forge
All checks were successful
TruffleHog / Scan for secrets (pull_request) Successful in 7m55s
CI / lint (pull_request) Successful in 8m33s
09a4872c7e
Agent commits were authored as the GitHub App's noreply alias, built from
/github/coilyco-ops-user-id. That address can never receive mail, so it
could not be verified anywhere, and the agent showed up unattributed on
every forge except GitHub.

coilyco-ops@coilysiren.me is now verified on all three the estate
publishes to: the Forgejo coilyco-ops user already carried it, Tangled
verified it against the bot.coilysiren.me handle, and a GitHub machine
user now holds it. One address attributes the agent everywhere, and the
commits already authored under it attributed retroactively on all three
the moment each verification landed.

This drops the SSM lookup from the role, and the whole AOSguard
resolution block plus the -AOSguardPath parameter from the Windows
converge script, both of which existed only to feed that lookup. The task
named "Build the cross-forge bot author identity" is finally accurate
rather than GitHub-shaped.

The GitHub App is untouched and still does the pushing. It authenticates,
the machine user attributes, and the two are independent, because GitHub
links commits by author email regardless of which credential pushed.

Refs coilysiren/inbox#440

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Agent-Role: sysadmin
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/infrastructure!964
No description provided.