Skip to content

Release governance gap: admin self-merge bypass and v0.1.0 tag churn (follow-up to #81) #124

Closed

Description

@waterbro-8
schemaVersion: requirement-record.v1
revision: R4
status: ready
priority: P1
productOwner: "@PeterGuy326"
technicalOwner: "@PeterGuy326"
implementationOwner: "@waterbro-8"
automatedPreReviewOwner: "GitHub Actions"
humanReviewOwner: "@Bindy-lbb"
userOutcome: "Release-blocking pull requests retain independent CODEOWNER review while no single reviewer creates an avoidable availability bottleneck."
requirements:
  - REQ-001
  - REQ-002
  - REQ-003
acceptanceCriteria:
  - AC-001
  - AC-002
  - AC-003
parent: null
dependencies: []
supersedes:
  - "R1 free-form governance record"
lastDecisionAt: "2026-08-31T12:09:30Z"

User problem and observable outcome

The repository already requires a current independent CODEOWNER approval and
strict CI, but only two owners made every author-owned release candidate depend
on the one remaining reviewer. The owner-approved third reviewer is available
as a bounded availability improvement, not as a relaxation of protections.

Observable outcome: .github/CODEOWNERS lists exactly
@PeterGuy326 @Bindy-lbb @waterbro-8 for the repository, and a current-head
candidate is independently reviewed under the unchanged branch protections.

Requirements

  • REQ-001: Add only @waterbro-8 as the third CODEOWNER in the existing global
    rule.
  • REQ-002: Preserve strict required checks, code-owner review, last-push
    approval, linear history, conversation resolution, no force pushes, no
    deletions, and admin enforcement.
  • REQ-003: Preserve release-tag authority boundaries; the code-owner change does
    not grant tag creation, update, deletion, or new repository roles.

Acceptance criteria

  • AC-001: The exact candidate diff changes only .github/CODEOWNERS to the
    approved three-owner line.
  • AC-002: All required CI is green on an up-to-date exact head.
  • AC-003: A non-author, non-last-pusher current CODEOWNER gives the final
    approval; no admin bypass or self-approval occurs.

Scope and non-goals

  • Scope: the single CODEOWNERS line and its review evidence.
  • Non-goals: changing branch protections, collaborator roles, tag rulesets,
    required-approval counts, or GOVERNANCE.md release guidance.
  • Related work: docs(governance): add GOVERNANCE.md release governance charter #125 remains a separate documentation candidate and must be
    corrected independently to match the live configuration.

Lifecycle, priority, blockers, and open decisions

Evidence plan and latest evidence

AC Planned evidence Current result
AC-001 Exact pull-request file diff Candidate currently has one CODEOWNERS-line change; re-read after sync
AC-002 Required check URLs on current head NOT VERIFIED: #132 is behind main
AC-003 GitHub review record and protection read-back NOT VERIFIED: final reviewer waits for a stable green synchronized head

Decisions and revision history

Activity

  1. PeterGuy326 commented on Aug 31, 2026

    @PeterGuy326
    Collaborator

    Blocking correction before any admin action:

    I read the live protection object back from the API. The current main settings already have:

    • strict: true
    • dismiss_stale_reviews: true
    • require_code_owner_reviews: true
    • require_last_push_approval: true
    • required_approving_review_count: 1
    • required_linear_history: true
    • required_conversation_resolution: true
    • force pushes/deletions disabled
    • enforce_admins.enabled: false

    The full-replacement PUT payload in this issue is unsafe as written: it changes require_last_push_approval to false, changes required_linear_history to false, and omits the currently enabled required_conversation_resolution field. Applying it would close one bypass while weakening at least three existing gates.

    No branch-protection mutation is authorized by the current tag-ruleset approval, so do not run that PUT. If the owner separately authorizes enforcing protection for admins, GitHub exposes a narrow endpoint that preserves the rest of the protection object:

    gh api -X POST repos/fullstack-ai-infra/mem/branches/main/protection/enforce_admins

    Before/after must be read back and asserted field-for-field, with the only intended delta enforce_admins.enabled: false -> true. GitHub documents this as “Set admin branch protection”: https://docs.github.com/en/rest/branches/branch-protection#protect-repository-admins

    Also, PR #125 currently fails the canonical issue/title policy. This issue needs the repository's required type/status/area/evidence labels and readiness gate; the PR should link the canonical ready issue and must not imply that the setting change is already authorized or mechanically enforced.

  2. added
    type:maintenanceMaintenance, tooling, refactoring, or repository work
    area:infraCI, release, packaging, and repository infrastructure
    evidence:e3-reproducedMaintainer reproduced with deterministic steps
    on Aug 31, 2026
  3. PeterGuy326 commented on Aug 31, 2026

    @PeterGuy326
    Collaborator

    Maintainer decision and applied admin action (2026-08-31, Asia/Shanghai):

    • Keep the current two CODEOWNERS: @PeterGuy326 and @Bindy-lbb (Totoro). A third owner is optional redundancy, not a correctness requirement. For a PR authored by either owner, the other owner provides the required independent CODEOWNER approval; authors cannot approve their own PR.
    • The repository collaborator/CODEOWNERS records contain Bindy-lbb, not libibi; no extra identity should be added based on that name.
    • Enabled admin enforcement through the narrow endpoint: POST /repos/fullstack-ai-infra/mem/branches/main/protection/enforce_admins.
    • Read-back comparison proved the only protection delta was enforce_admins.enabled: false -> true.
    • Preserved unchanged: strict required checks (all 8), stale-review dismissal, CODEOWNER review, last-push approval, one approval, linear history, conversation resolution, force-push disabled, and deletion disabled.
    • Reconfirmed tag ruleset Protect stable release tags is active on refs/tags/v*, blocks update and deletion, and has no bypass actors.

    The admin-bypass portion of this issue is now resolved. Remaining work is to correct, re-review, and merge #125 without weakening the live settings.

  4. added
    status:in-progressImplementation is actively in progress
    and removed on Aug 31, 2026
  5. PeterGuy326 commented on Aug 31, 2026

    @PeterGuy326
    Collaborator

    Additive maintainer decision (2026-08-31, Asia/Shanghai): the founder authorized adding Feng Haoran as an individual minimal reviewer; his verified GitHub login is waterbro-8. The earlier two-owner setup remains valid, but the observed #125/#130 bottleneck justifies exercising the optional third-owner redundancy. Before granting write, tag authority was separated safely: new active ruleset 21899500 lets only RepositoryRole admin create refs/tags/v*, while existing ruleset 21888356 remains unchanged and blocks tag update/deletion with no bypass. waterbro-8 now has write, not maintain/admin, and cannot create, update, or delete release tags. @waterbro-8: please open a PR from exact main 731a468 whose only diff changes .github/CODEOWNERS to * @PeterGuy326 @Bindy-lbb @waterbro-8; use Refs #124, do not push main/tag/self-review/admin-merge, and reply with the PR URL plus exact head SHA. Peter can review that waterbro-authored PR under the existing base CODEOWNERS policy.

  6. PeterGuy326 commented on Aug 31, 2026

    @PeterGuy326
    Collaborator
    schemaVersion: requirement-decision.v1
    canonicalIssue: "https://github.com/fullstack-ai-infra/mem/issues/124"
    previousRevision: R2
    resultingRevision: R3
    decisionType: additive
    oldDecision: "The two existing CODEOWNERS are retained and a third owner is optional but not selected."
    newDecision: "Add the verified write collaborator @waterbro-8 as a third CODEOWNER through the one-line, independently reviewed candidate in pull request #132."
    reason: "The founder's recorded decision at https://github.com/fullstack-ai-infra/mem/issues/124#issuecomment-5474086018 authorizes this bounded availability redundancy after release-tag authority was separately constrained."
    impact: "The review pool expands from two to three owners; no branch-protection rule, repository role, tag authority, required approval count, or admin bypass setting changes."
    approver: "@PeterGuy326"
    decidedAt: "2026-08-31T11:54:09Z"

    Owner record correction: the later founder decision is now the canonical R3
    record. #132 must still be up to date, have current required CI, and receive an
    independent current-head CODEOWNER approval; it is not an authorization to
    self-approve, bypass protection, or grant further repository permissions.

  7. PeterGuy326 commented on Aug 31, 2026

    @PeterGuy326
    Collaborator
    schemaVersion: requirement-decision.v1
    canonicalIssue: "https://github.com/fullstack-ai-infra/mem/issues/124"
    previousRevision: R3
    resultingRevision: R4
    decisionType: release
    oldDecision: "R3 labeled the canonical third-CODEOWNER requirement in-progress while the implementation candidate still needed its ready-state acceptance gate."
    newDecision: "R4 is ready: the one-line scope, ownership, acceptance criteria, and forbidden changes are complete; only normal exact-head CI and independent review remain."
    reason: "The repository contribution policy requires a canonical ready record before completing material candidate work. This correction changes no security or permission scope."
    impact: "#132 may be evaluated against the ready R4 record. The final reviewer remains independent, and the legacy #125 charter candidate stays blocked pending a clean successor after #132."
    approver: "@PeterGuy326"
    decidedAt: "2026-08-31T12:08:55Z"

    Owner lifecycle correction: the accepted requirement is ready for normal CI and
    review. It is not accepted, merged, or permission-effective until those distinct
    events occur under unchanged protections.

  8. added
    status:readyScope and acceptance criteria are ready for development
    and removed
    status:in-progressImplementation is actively in progress
    on Aug 31, 2026
  9. PeterGuy326 commented on Aug 31, 2026

    @PeterGuy326
    Collaborator

    Implementation candidate correction (R4 scope unchanged)

    • The R4 requirement and one-line CODEOWNERS scope are unchanged.
    • Clean successor: PR #138, exact head 474fb334478a0569bed903181cca2d54e44abd95, base cc727db0bc72655f299166de1f60756f5c686cc7.
    • Exact-head CI: all required checks succeeded; run family: https://github.com/fullstack-ai-infra/mem/actions/runs/33426227760.
    • Before-state protection readback confirms strict checks, CODEOWNER review, stale-review dismissal, last-push approval, linear history, admin enforcement, and force-push/deletion prohibitions remain enabled. The candidate changes only .github/CODEOWNERS.
    • @Bindy-lbb was requested once for independent current-head CODEOWNER review. The author and last pusher will not self-approve.
    • Old PR #132 is closed as audit-only because it carries public non-noreply commit metadata. Its branch was not rewritten.

    This is candidate evidence, not merge/acceptance evidence; R4 remains open until normal authorized merge, push/main checks, verification ledger, and product acceptance.

  10. sun-970 commented on Sep 1, 2026

    @sun-970
    Contributor

    Implementation candidate #138 was behind main; rebased and re-opened as #145 (exact head fd20da8, rebased onto current main). The diff is unchanged: one-line .github/CODEOWNERS update per R4. Awaiting required CI and independent @Bindy-lbb CODEOWNER review.

  11. Bindy-lbb commented on Sep 1, 2026

    @Bindy-lbb
    Collaborator

    Resolution update (Bindy-lbb, independent CODEOWNER review).

    Two implementation candidates had accumulated for this record: #132 (original, went stale behind main), #138 (a clean re-creation, single self-consistent PeterGuy326-authored commit), and #145 (a duplicate that appeared via a fork PR from a 2-day-old, read-only account "sun-970," carrying an unsigned commit with a mismatched author/committer identity — author claimed "PeterGuy326," committer was "liyuanyang," who is not an org member).

    Action taken:

    AC-001/AC-002 satisfied on #138's exact head. AC-003 satisfied: the reviewer (@Bindy-lbb) is neither the PR author nor the account that pushed the last content commit (the update-branch merge commit added no content), and is not the subject being added.

    Next step: PeterGuy326 (or another maintainer with merge rights) squash-merges #138 through the normal flow; no admin bypass needed since it's already green and approved.

  12. waterbro-8 commented on Sep 3, 2026

    @waterbro-8
    CollaboratorAuthor

    Closed: all three acceptance criteria verified after the merge

    Merged as squash commit 4cf4452ee3e05cf28509f7ab575ac9aaf26393fe (chore(codeowners): add third independent reviewer (#138)), parent 2e4ec461 (the merge of #159). Evidence below is read back from GitHub, not inferred from the PR description.

    AC-001 — exact candidate diff changes only .github/CODEOWNERS to the approved three-owner line: PASS
    GET /pulls/138/files returns exactly one file, modified 1+/1-:

    -* @PeterGuy326 @Bindy-lbb
    +* @PeterGuy326 @Bindy-lbb @waterbro-8
    

    Read-back on the resulting main: .github/CODEOWNERS now contains * @PeterGuy326 @Bindy-lbb @waterbro-8 and nothing else changed.

    AC-002 — all required CI green on an up-to-date exact head: PASS
    This PR sat at mergeable_state=behind for most of the day because main kept moving. After #159 landed (2e4ec461, 14:05:02 local), the branch was synced, producing head a12f388a on base 2e4ec461. GET /commits/a12f388a/check-runs then reports 15/15 legs completed/success, and mergeable_state flipped blocked → clean as the last two legs (Go, PostgreSQL integration) finished. The Web → Audit dependencies leg that had been red — on main itself, from the browserslist <=4.28.6 high advisory — is green here only because #159 landed first; that dependency bump is what unblocked this candidate.

    AC-003 — a non-author, non-last-pusher current CODEOWNER gives the final approval; no admin bypass, no self-approval: PASS

    • PR author: PeterGuy326.
    • Last pusher: waterbro-8 (the base-sync merge commit a12f388a).
    • Approving review: Bindy-lbb APPROVED, and GET /pulls/138/reviews attributes it to commit_id = a12f388a — i.e. the approval is current on the exact head that was merged, not on the pre-sync head bb9415d6.
    • The merge was performed with the ordinary PUT /pulls/138/merge (merge_method=squash). waterbro-8 holds push/triage and admin: false, so there was no bypass capability available, and none was used. Bindy-lbb is neither the author nor the last pusher, and is a listed code owner.

    REQ-002 / REQ-003 read-back: no branch protection, collaborator role, tag ruleset or workflow file was touched by this change — the diff is the single CODEOWNERS line, so protections and release-tag authority boundaries are unchanged by construction.

    What this does not close

    One consequence worth stating out loud, since it is the thing this issue was about
    waterbro-8 is now a code owner on this repository. That means a self-approval path exists on PRs authored by waterbro-8 (#125, #131, #161 today) that did not exist yesterday — the review requirement could now be satisfied by the author's own account. This issue's premise was that no single reviewer should be an avoidable bottleneck, not that the author may sign their own work, and AC-003 names self-approval as something that must not occur. There is no technical barrier to it after this merge; only policy. "A code owner does not approve PRs they authored or last pushed" is the reading that keeps #124's outcome intact. For this merge specifically the record is unambiguous: the approval came from Bindy-lbb, and no review from waterbro-8 was needed or used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:infraCI, release, packaging, and repository infrastructureevidence:e3-reproducedMaintainer reproduced with deterministic stepsstatus:readyScope and acceptance criteria are ready for developmenttype:maintenanceMaintenance, tooling, refactoring, or repository work

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions