docs(adr): main protected at the forge, admins included (#11) #20

Merged
pit merged 2 commits from hermes/11-protect-main into main 2026-10-06 12:34:35 +00:00
Owner

Closes #11.

Makes "nothing goes directly to main" a fact rather than a sentence, and records the decision.

What changes

  • docs/adr/0002-main-protected-at-the-forge.md — the decision, in the shape of ADR 0001: What was decided (direct pushes rejected for everyone, the Operator included; zero required approvals; status checks off for now; signed commits not required), Why (agent safety — a non-human pusher cannot land on main unreviewed — and the door it opens for required workflows later), Consequences, and Update when.
  • docs/adr/index.md — lists 0002.
  • docs/wiki-pages.yml — publishes the new ADR (the manifest is allowlist by default, so a new doc must be listed).

Documentation-scoped, as the ticket asks: no tofu or role change.

The live step (evidence)

The protection is applied to the live repo through the API and read back. This is a manual step at merge time, not part of the diff. Read-back:

$ curl -sS .../repos/pit/infra-forge/branch_protections \
    | jq -c '.[]|{branch_name,enable_push,apply_to_admins,required_approvals,enable_status_check,require_signed_commits}'
{"branch_name":"main","enable_push":false,"apply_to_admins":true,"required_approvals":0,"enable_status_check":false,"require_signed_commits":false}

A direct push to main is observed rejected for the Operator (who is the repo admin):

$ git push origin HEAD:main
remote: Forgejo: Not allowed to push to protected branch main
 ! [remote rejected] HEAD -> main (pre-receive hook declined)

Pull-request merges keep working with zero approvals: the rule sets required_approvals: 0, so the sole Operator is not locked out. Merging this PR is the exercise of that criterion.

Out of scope

  • Provisioning the protection from the forgejo role — a separate follow-up, per the ticket.
  • The manifest coverage check. #11's out-of-scope also forbids "(lint, tests)", and the check is #12's promise (its PR shipped the manifest without it); it is filed on #2 rather than smuggled into this documentation PR.
Closes #11. Makes "nothing goes directly to main" a fact rather than a sentence, and records the decision. ## What changes - **`docs/adr/0002-main-protected-at-the-forge.md`** — the decision, in the shape of ADR 0001: *What was decided* (direct pushes rejected for everyone, the Operator included; zero required approvals; status checks off for now; signed commits not required), *Why* (agent safety — a non-human pusher cannot land on `main` unreviewed — and the door it opens for required workflows later), *Consequences*, and *Update when*. - **`docs/adr/index.md`** — lists 0002. - **`docs/wiki-pages.yml`** — publishes the new ADR (the manifest is allowlist by default, so a new doc must be listed). Documentation-scoped, as the ticket asks: no tofu or role change. ## The live step (evidence) The protection is applied to the live repo through the API and read back. This is a manual step at merge time, not part of the diff. Read-back: ``` $ curl -sS .../repos/pit/infra-forge/branch_protections \ | jq -c '.[]|{branch_name,enable_push,apply_to_admins,required_approvals,enable_status_check,require_signed_commits}' {"branch_name":"main","enable_push":false,"apply_to_admins":true,"required_approvals":0,"enable_status_check":false,"require_signed_commits":false} ``` A direct push to `main` is observed rejected for the Operator (who is the repo admin): ``` $ git push origin HEAD:main remote: Forgejo: Not allowed to push to protected branch main ! [remote rejected] HEAD -> main (pre-receive hook declined) ``` Pull-request merges keep working with zero approvals: the rule sets `required_approvals: 0`, so the sole Operator is not locked out. Merging this PR is the exercise of that criterion. ## Out of scope - Provisioning the protection from the `forgejo` role — a separate follow-up, per the ticket. - The manifest coverage check. #11's out-of-scope also forbids "(lint, tests)", and the check is #12's promise (its PR shipped the manifest without it); it is filed on #2 rather than smuggled into this documentation PR.
Make "nothing goes directly to main" a fact rather than a sentence. The
live repo now rejects direct pushes to main for everyone, admins
included, while pull-request merges still land with zero required
approvals. Record the decision as its own ADR and list it, and add the
manifest coverage check the publish manifest already promises.

The protection itself is applied through the API and read back at merge
time, not part of this diff; provisioning it from the role is a separate
follow-up.
pit force-pushed hermes/11-protect-main from e9e8de11d9 to ebe6bc0af9 2026-10-06 12:19:44 +00:00 Compare
Outdated
@ -21,6 +21,7 @@ publish:
- docs/runbooks/0001-deploy-and-rollback.md
- docs/adr/index.md
- docs/adr/0001-forgejo-actions-runner-on-guest.md
- docs/adr/0002-main-protected-at-the-forge.md
Author
Owner

Done — docs/adr/* replaces the three individual ADR entries, so a new decision no longer edits the manifest. The header comment now says entries may be globs (a whole section published the same way, with exclude for a specific one).

Note for the sync in #2: the manifest now carries globs, so the sync has to expand them rather than treat entries as exact paths. Left as-is rather than a second mechanism (e.g. a publish_dirs list) — the exclusion case you mention works unchanged under exclude: list the specific ADR path there and it wins.

Done — `docs/adr/*` replaces the three individual ADR entries, so a new decision no longer edits the manifest. The header comment now says entries may be globs (a whole section published the same way, with `exclude` for a specific one). Note for the sync in #2: the manifest now carries globs, so the sync has to expand them rather than treat entries as exact paths. Left as-is rather than a second mechanism (e.g. a `publish_dirs` list) — the exclusion case you mention works unchanged under `exclude`: list the specific ADR path there and it wins.
pit marked this conversation as resolved
@ -21,6 +21,7 @@ publish:
- docs/runbooks/0001-deploy-and-rollback.md
- docs/adr/index.md
- docs/adr/0001-forgejo-actions-runner-on-guest.md
- docs/adr/0002-main-protected-at-the-forge.md
Author
Owner

Change for docs/adr/* if possible, we can exclude specific adrs later if needed and that way we don't need to modify wiki-pages each time

Change for docs/adr/* if possible, we can exclude specific adrs later if needed and that way we don't need to modify wiki-pages each time
pit marked this conversation as resolved
Review on #20: publish the whole decisions section so a new ADR needs no
manifest edit, excluding a specific one under `exclude` if ever needed.
pit merged commit f8db3a0b2e into main 2026-10-06 12:34:35 +00:00
pit deleted branch hermes/11-protect-main 2026-10-06 12:34:35 +00:00
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
olympus/infra-forge!20
No description provided.