Skip to content

chore(codeowners): add third independent reviewer - #138

Merged
waterbro-8 merged 4 commits into
mainfrom
codex/chore-124-clean-codeowners
Sep 3, 2026
Merged

waterbro-8 merged 4 commits into
mainfrom
codex/chore-124-clean-codeowners

Conversation

@PeterGuy326

@PeterGuy326 PeterGuy326 commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Tracking record

Refs #124

Bounded change

The exact diff against main changes one global CODEOWNERS line:

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

No collaborator role, branch-protection setting, required-review count, administrator bypass, tag ruleset, tag permission, release, or repository setting changes.

Requirement trace

Requirement / acceptance Evidence
REQ-001; AC-001 Exact one-line .github/CODEOWNERS diff from base cc727db to head 474fb33.
REQ-002; AC-002 Before-state GitHub protection readback confirms strict checks, code-owner review, stale-review dismissal, last-push approval, linear history, admin enforcement, force-push prohibition, and deletion prohibition remain enabled. Exact-head CI is required.
REQ-003; AC-003 Diff contains no tag or collaborator configuration; an independent current-head CODEOWNER review remains required.

Validation

  • git diff --check: passed.
  • git diff --name-only origin/main...HEAD: only .github/CODEOWNERS.
  • Git author and committer: PeterGuy326 using 47820304+PeterGuy326@users.noreply.github.com.
  • Sensitive-content scan: no credentials or private data introduced.

Review and delivery gates

This clean candidate supersedes #132 because that branch has public commits with non-noreply personal metadata. #132 is left unchanged for audit and is not force-pushed or merged.

@Bindy-lbb must provide a current-head independent CODEOWNER approval after all required CI is green. The author and last pusher will not self-approve. Normal merge authorization, merge-SHA push/main checks, verification ledger, and product acceptance still apply.

@waterbro-8

Copy link
Copy Markdown
Collaborator

One caveat that decides whether this PR can do its own job

The diff is one line: * @PeterGuy326 @Bindy-lbb* @PeterGuy326 @Bindy-lbb @waterbro-8.

Worth recording explicitly, because #124 is precisely about believing a stated gate that is not mechanically enforced: GitHub resolves required code-owner reviews from the CODEOWNERS as it exists when the check runs, so on this PR's own run the candidate third owner is not yet an established reviewer. Practically that means #138 cannot be unblocked by the reviewer it adds — it needs @PeterGuy326 or @Bindy-lbb to approve, and only PRs opened after it merges can use the new owner.

That also changes how the three currently-green-but-BLOCKED PRs should be sequenced. #137, #140 and this one all report every check SUCCESS and are held only by REVIEW_REQUIRED. If the intent is "a third reviewer exists so the queue can drain", #138 has to land first and the other two get re-evaluated after. If instead one of @Bindy-lbb / @PeterGuy326 reviews #137 and #140 directly, #138 stops being urgent and #124's "self-merge bypass" concern should be addressed by branch protection instead — which is the part of #124 this file cannot fix on its own.

The header comment above the pattern is also worth a second look once the third owner is live: it says review is satisfiable "by the organization administrator or the designated independent reviewer" (singular). After this change there are three owners, and the sentence no longer describes the rule in force.

No review submitted here — this PR's whole purpose is who is qualified to review, so the answer has to be a human decision.

@Bindy-lbb Bindy-lbb left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent CODEOWNER review (Bindy-lbb) at exact head 7a532f2.

Context: issue #124 (R4) tracks adding @waterbro-8 as a third CODEOWNER. The implementation candidate was behind main, and a duplicate PR (#145) had appeared via an unusual path — a fork PR from a 2-day-old, read-only account (sun-970) carrying a commit claiming author "PeterGuy326" but committer "liyuanyang" (not an org member), unsigned, with CI stuck in action_required. Rather than approve-and-run Actions for that unverified external account, I brought this PR (#138, which already had a single self-consistent PeterGuy326-authored commit) up to date with main via the standard update-branch API (merge commit 7a532f2, authored under my own identity since I initiated it — no new content), then re-verified.

Diff is still exactly the single approved line: adding @waterbro-8 to .github/CODEOWNERS, nothing else. CI 15/15 green on the exact head above. No admin bypass, no self-approval (I am not the subject being added, and I am not the branch's last content-pusher). No P0/P1. Approving.

Recommend closing #145 as superseded by this PR once merged, and recording the resolution on #124.

@sun-970

sun-970 commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Thanks for the clean, minimal diff. Two suggestions before merge:

1. Update the header comment

The comment above the pattern currently reads:

# Changes require review from the organization administrator or the designated
# independent reviewer, so code-owner review is satisfiable without admin bypass.

After this change there are three CODEOWNERS, not a single "designated independent reviewer". Suggest updating to something like:

# Changes require review from at least one CODEOWNER, so code-owner review
# is satisfiable without admin bypass.

This can be part of the same commit or a follow-up — but leaving the comment inaccurate after merge would be confusing for future readers.

2. Clarify merge sequencing with blocked PRs

As @waterbro-8 noted, #137 and #140 are also green but blocked on REVIEW_REQUIRED. It would help to record the intended order: does #138 land first and unblock the others via the new third reviewer, or should the existing two owners review #137/#140 directly? A note on #124 tracking the decision would close the loop.

@waterbro-8

Copy link
Copy Markdown
Collaborator

Mechanical steps run; the merge is not, and the reason is one failing required check that this PR cannot fix

Doing what was asked, in order:

step result
update branch onto main done -- head bb9415d6, base now 1332bf46, and the reviewed diff is still exactly +1/-1 on .github/CODEOWNERS
re-run CI on the new head 8 of 9 jobs pass in the CI run -- Go, Worker, Deployment profiles, npm wrapper, npm wrapper compatibility (node18-linux / node20-linux / node24-windows), Offline recall benchmark. The two other workflows on that head, PR Policy and Validate Agent memory, are green
squash merge not executed
close #124 not executed -- it depends on the merge

reviewDecision on the current head is APPROVED (Bindy-lbb, review 5075216652) and mergeable is MERGEABLE. The only thing holding mergeable_state at blocked is one required check: Web → step 5 Audit dependencies, run 33713664506, job 100518235354.

That check is red on main, not red because of this PR

> npm audit --omit=dev --audit-level=moderate && npm audit --audit-level=high
found 0 vulnerabilities            # the shipped dependency set is clean

# npm audit report
browserslist  <=4.28.6
Severity: high
Browserslist: Unbounded memory growth (no cache eviction) via distinct query results, leading to eventual OOM - GHSA-c83g-rgw3-j3cx
Browserslist: Uncaught crash / prototype write via untrusted browserslist-stats.json custom stats (normalizeStats) - GHSA-73wf-gq98-2v4g
fix available via `npm audit fix`
2 vulnerabilities (1 low, 1 high)
##[error]Process completed with exit code 1.

This is a devDependency of web/ (the --omit=dev half reports 0), the advisory is new against an unchanged tree, and the failure predates this PR:

  • CI on push 1332bf46 (current main) -- run 33656751024: failure, and Web → Audit dependencies is the only failing step in the whole run.
  • CI on push 10d4bf7a (previous main) -- run 33475103688: success.

Merging into a red main is the wrong way to fix a red main, and an admin bypass or --no-verify path is not available to me here in any case -- waterbro-8 is not an administrator on this repository. I am also not adding an exception for this PR: #161 and #162 are blocked on the same single leg, so this is one blocker with three victims, all of them green everywhere else.

The one action that unblocks it

#159 (build(deps-dev): bump browserslist from 4.28.2 to 4.28.8 in /web, dependabot, one file web/package-lock.json, +27/-24). Its Web leg is green on its own head 046342fd, i.e. the bump is sufficient for this gate. Two further checks I ran so that green reading can be trusted against today's main rather than against the base it branched from:

I did not merge #159 and did not approve it. It is a dependency bump landing on main, no dependabot PR in this repository has ever been merged (every closed one is unmerged, so there is no convention for me to follow), and I am not a code owner in the base CODEOWNERS -- which is precisely the thing this PR is trying to change. My approval would not count even if governance allowed it.

Sequence to finish the merge, once #159 is in main

  1. Code-owner approval + merge of build(deps-dev): bump browserslist from 4.28.2 to 4.28.8 in /web #159.
  2. I re-run update branch on this PR, so CI re-measures against the fixed lockfile. Content-wise this is a no-op for the reviewed diff -- chore(codeowners): add third independent reviewer #138 touches only .github/CODEOWNERS, which build(deps-dev): bump browserslist from 4.28.2 to 4.28.8 in /web #159 does not touch.
  3. On a green rollup, squash-merge with the (#138) suffix and close Release governance gap: admin self-merge bypass and v0.1.0 tag churn (follow-up to #81) #124 with the merge-SHA evidence, which is what Release governance gap: admin self-merge bypass and v0.1.0 tag churn (follow-up to #81) #124's R4 asks for and what this PR body already declines to do on its own.

Nothing about the review state of #138 is disputed by any of the above: it is approved, MERGEABLE, one line, and waiting on a dependency bump that is already green in the queue.

@waterbro-8
waterbro-8 merged commit 4cf4452 into main Sep 3, 2026
15 checks passed
@waterbro-8
waterbro-8 deleted the codex/chore-124-clean-codeowners branch September 3, 2026 06:32
waterbro-8 added a commit to waterbro-8/mem that referenced this pull request Sep 3, 2026
Refs bytefolk#124

The charter previously asserted a two-owner CODEOWNERS roster and a single tag
ruleset. A third owner reached main through bytefolk#138 under the bytefolk#124 R3 decision, and
refs/tags/v* is covered by a second active ruleset that also blocks creation.
De-duplicate the roster against .github/CODEOWNERS, record both rulesets and what
a gated tag creation means for the runbook, replace the exhaustive required-check
claim with an observed-jobs enumeration, and refresh the R2 attribution to R4.
PeterGuy326 pushed a commit that referenced this pull request Sep 3, 2026
… headers (#161)

## What this changes

Implements the security-header split decided for this repository on
2026-09-03: **nginx is the single authority for
`X-Content-Type-Options`, `X-Frame-Options` and `Referrer-Policy`,
uniformly `no-referrer`, with the proxied path de-duplicated by
`proxy_hide_header`; the API keeps `Content-Security-Policy`,
`X-XSS-Protection` and `Content-Disposition`.**

Closes #135 (the two live proxy defects) and Closes #136 (the ownership
question that defect raised).

This is the in-repo redo of #144, which came from a fork and is being
closed under the fork-policy decision. It is not a cherry-pick of that
commit — no commit from it is imported here.

### The two defects, as measured

Both were real on `main@1332bf4` and neither is visible by reading the
config, which is why the test starts an nginx rather than grepping one.

1. **`/assets/` lost all three headers.** An `add_header` inside a
location replaces the inherited set instead of adding to it, and that
block has always had `add_header Cache-Control`. Every cached bundle
shipped with no `nosniff`, no `X-Frame-Options` and no `Referrer-Policy`
at all.
2. **`/v1/` sent two conflicting `Referrer-Policy` values on one
response.** The proxy said `same-origin`, the API says `no-referrer`,
and nginx's `add_header` appends rather than replaces, so a client
received both and the effective policy depended on which one the browser
kept. `X-Content-Type-Options` and `X-Frame-Options` were also
duplicated (same value twice).

### Why the API keeps sending the three it no longer owns

`proxy_hide_header` makes the wire value nginx's, which is what "nginx
独占" requires, without deleting `nosniff`/`DENY`/`no-referrer` from
`securityHeadersMiddleware`. A `memd` reached directly — the Helm path
exposes the Service, and `docs/DEPLOYMENT.md` only makes the nginx
guarantee for the container — keeps its defense in depth. If the
intended reading was instead that the Go middleware should stop setting
them, that is a one-line change here and it should be said before merge,
because the alternative silently weakens the no-proxy deployment.

## Test evidence

`scripts/test_nginx_security_headers.sh` renders the shipped template
with the same `envsubst` filter and variables the container entrypoint
uses, runs a fake upstream that answers exactly like
`securityHeadersMiddleware` does, starts nginx against the config, and
reads headers off the wire across five surfaces (`/`, `/assets/`, a 404
under `/assets/`, `/v1/`, `/healthz`).

| run | result |
| --- | --- |
| template as shipped on `main` | **11 of 28 assertions fail** — 6
missing across the two `/assets/` surfaces, `same-origin` on `/` and
`/healthz`, 3 duplicated on `/v1/` |
| this branch | **28 of 28 pass** |
| drop the `/assets/` restatement | 3 fail (`/assets/` 200) |
| drop `always` from the `/assets/` restatement | 3 fail (`/assets/` 404
only) |
| drop `proxy_hide_header` | 3 fail (`/v1/` duplicates) |

Each of the three fix sites is therefore individually load-bearing, and
the 404 surface earns its place: it is the only one that tests `always`.

The harness also refuses to report success on a partial run (the
assertion count is pinned), hard-fails when a caller names an
`NGINX_BIN` that is not executable, and only reports `SKIP` when no
nginx was found at all — so the CI leg cannot go green by measuring
nothing.

Executed locally against nginx **1.27.4**, the same minor the
`web/Dockerfile` pins (`nginxinc/nginx-unprivileged:1.27.4-alpine3.21`).

**Measured in CI on the built image, and it did go red there first.**
The first run of the new step failed exactly where this paragraph
expected the risk to be: `web/Dockerfile:17` ends on
`nginxinc/nginx-unprivileged`, whose own build stops at `USER 101`, so
`apk add` could not write the package database -- `ERROR: Unable to lock
database: Permission denied`, `exit code: 99`. Commit `1c917f96`
installs the four tools in a throwaway child image that returns to uid
101 afterwards, so the harness still runs unprivileged, as the shipped
container does. On that head `Deployment profiles` is green and its job
log carries `all 28 security-header assertions passed`, so the leg
executed the contract against the nginx that ships rather than printing
`SKIP`. The harness content measured above is unchanged by that commit;
it touches only the workflow step.

## Not in scope here, and worth a decision

Nothing in this repository sets a `Content-Security-Policy` for the SPA
itself — `default-src 'none'` is an API-only value and would break the
web app if applied to it. The decided split covers the three shared
headers and leaves HTML/SPA CSP unowned. This PR deliberately does not
invent one.

## Links and state

- `Refs` the decided split; `Closes #135` / `Closes #136` on merge.
- No Go code changed, so the existing `security_headers_test.go` and
`content_*` tests are unaffected.
- `Web` is red on this head and identically red on `main` itself (`Audit
dependencies`, `browserslist <=4.28.6`, GHSA-73wf-gq98-2v4g). That is a
pre-existing repository condition rather than something this branch
introduced, and the queued fix is #159; the readback is on #138.
- Opening this PR is not a claim that it should be merged. Independent
review is the reviewers'; I have not requested or recorded one.

---------

Co-authored-by: waterbro-8 <318569545+waterbro-8@users.noreply.github.com>
waterbro-8 added a commit to waterbro-8/mem that referenced this pull request Sep 3, 2026
Refs bytefolk#124

The charter previously asserted a two-owner CODEOWNERS roster and a single tag
ruleset. A third owner reached main through bytefolk#138 under the bytefolk#124 R3 decision, and
refs/tags/v* is covered by a second active ruleset that also blocks creation.
De-duplicate the roster against .github/CODEOWNERS, record both rulesets and what
a gated tag creation means for the runbook, replace the exhaustive required-check
claim with an observed-jobs enumeration, and refresh the R2 attribution to R4.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

4 participants