deploy / deploy (push) Successful in 5m34s
Reverses the org team added an hour ago. It was solving the wrong problem. Measured on the bare account, with no team and no collaborator role: pushing to its own fork works, opening a cross-repo pull request works, commenting works, creating an issue works. Pushing to a lair repo is denied and so is deleting it. Exactly one §2.2 capability is out of reach — applying a label — and that is the one that must not be bought by granting code write. So the runner gets nothing at all, which is a better property than a carefully scoped grant: there is no permission to review, no team to audit, and no rule to forget on the next repo added. Adding a repo to its remit is now one step, a fork, rather than three. Labelling moves to a separate identity, which lines up with the split the two units already have. The runner records state in Postgres — already the authority per §2.2 — and the poller reconciles labels onto the forge under its own account with issue write and no code access. The token that can touch issues is held by the process that never runs an agent; the token held by the process running unattended agents can only push to a repository nobody depends on. That also removes a silent failure I found while testing this. Creating an issue *with* labels as an unprivileged user returns 201 and drops the labels — no error, an issue that never gets picked up. A Plan job stamping inherited admission on its children would have failed precisely that way and looked fine. Children are now created bare, with their intended labels recorded in Postgres for the poller to apply. The second identity is provisioned with stage 2, when the first label is written. Nothing before then needs it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013TxK1CWPkFXqdcXMJ4hVe6