GATE C RERUN, 29 July 2026 night. VERDICT: PASS on both surfaces, zero findings, both positive controls proven. POSITIVE CONTROLS FIRST, both surfaces, and both FAILED as they must. authenticated "positive control OK: the planted overflow AND the planted min width regression were both DETECTED". The planted page requires 4000px and the sweep reported HORIZONTAL_OVERFLOW at every viewport plus a shell guard breach of 4000px against the 732px baseline. public same, at 320 and 390 as well. So a clean counted run below is a measurement rather than an absence. COUNTED RUN, AUTHENTICATED. 2 roles, 8 routes, 3 viewports, 48 captures, 0 FINDINGS. Roles: gatec.recruiter and gatec.manager, the fixture accounts recorded in the ledger. Shell guard: the widest route requires 694px against a 732px baseline plus 24px allowance. PASSES, so the Phase 5 phone shell item has not been made worse by anything in Phase 2. 8 transport findings did not reproduce on the confirming reload and were dropped, recorded in transient.json. THE ROLE MATRIX WAS CHANGED, DELIBERATELY, AND IT IS WHAT FOUND THE ONE REAL DEFECT. The previous Gate C ran as a SUPERUSER. A superuser can list users, so the roster request on /admin succeeded and no finding was possible. This run used the recorded fixture accounts instead, a recruiter and a manager, which is both closer to the protocol's "seeded fixture accounts per role" and closer to how the product is actually used. It immediately produced 6 findings, all one cause. THE DEFECT, FOUND AND FIXED RATHER THAN ALLOWED. screens/Admin.tsx issued its roster query unconditionally, so a recruiter or manager who reached /admin by typing the URL sent GET /api/users and the API correctly answered 403. Nothing leaked. The screen simply asked for something it knew it could not have, six times across two roles and three viewports. IT WAS NOT ADDED TO THE SWEEP'S ALLOWED RESPONSE LIST, and that was the important decision. That list is keyed to role, status and exact path together specifically so it cannot grow to cover a 403 on a data endpoint, and its own comment in sweep.js says so. Allowing it would have taught the instrument to expect a pointless failing request instead of removing it. The query is now gated on the same userInvite capability the nav link already uses, and the screen renders a plain explanation rather than a spinner that never resolves. RE RUN AFTER THE FIX: 48 captures, 0 findings. COUNTED RUN, PUBLIC. Anonymous, 5 viewports, 40 captures, 0 FINDINGS. The full matrix, 320 through 1440, because candidates arrive on phones. 40 named expected error responses allowed: the anonymous session probe answering 403, which is correct behaviour for a visitor who is not logged in, keyed to role, status and exact path. THE FIRST PUBLIC RUN REPORTED 1 FINDING and the second reported 0. The finding was net::ERR_NETWORK_CHANGED fetching a woff2 from fonts.gstatic.com, a transport failure reaching a THIRD PARTY host, and it did not reproduce. Reported here rather than quietly rerun, because a flake that is not written down is indistinguishable from a flake that was hidden. ONE OBSERVATION THE FLAKE UNCOVERED, RECORDED NOT FIXED. frontend/index.html loads Inter and JetBrains Mono from fonts.googleapis.com and fonts.gstatic.com on every page load. For a product targeting a federal authorisation that means every visitor's IP and user agent reaches Google, including candidates on the public surface, and the critical render path depends on a host that a government network may block. It also means the only finding this gate produced across two runs came from an external dependency rather than from the product. Both font families are OFL licensed, so self hosting is permitted. Recorded in docs/IMPROVEMENTS.md. WHAT THIS GATE STILL DOES NOT CLAIM. THERE ARE NO PIXEL BASELINES. New or changed screens become baselines only after Joseph approves the contact sheets, and none has been approved, so the pixel regression half of Gate C cannot run. Saying so is worth more than a baseline nobody has looked at. THE SCREENSHOTS ARE NOT COMMITTED, on purpose. 88 full page PNGs across the two surfaces, several megabytes, regenerated by rerunning the sweep. They live on Bubbles at /tmp/sweep-auth3 and /tmp/sweep-pub4. An instrument you can rerun is worth more than an archive you cannot question. TWO INSTRUMENT IMPROVEMENTS MADE DURING THIS RUN MM_SWEEP_ROLES now carries the fixture credentials out of argv. --roles put every password in the process table for the length of a sweep that runs for minutes, which is the same exposure found in mm-identity-sync earlier tonight. The flag is kept for the recorded runbook. cmd/rotate-credential gained MM_ROTATE_PASSWORD for the same reason, and it is how these fixtures were reset. REPRODUCE node sweep.js --base --out DIR --control # must FAIL, both surfaces MM_SWEEP_ROLES=':,:' node sweep.js --base --out DIR node sweep.js --base --surface public --out DIR Fixture passwords are reset with cmd/rotate-credential and are recorded NOWHERE, per finding D4. ============================================================================ ADDENDUM, THE PIXEL REGRESSION HALF, and a coverage limit found by checking it ============================================================================ THE PIXEL HALF DID NOT EXIST. Joseph approved the contact sheets, and the approval unblocked nothing, because the thing it was supposed to unblock had never been written. The protocol asks in as many words for screens to be "pixel diffed against their approved baselines with pixelmatch", and sweep.js contained no pixelmatch, no baseline directory, and no comparison of any kind. Two Gate C write ups had recorded the gap as "no contact sheet has been approved", which reads as waiting on a person while it was waiting on code. That is the seventh time in this build a missing implementation was filed as a pending decision, and it is the most expensive version of that mistake because it moves an engineering task into someone else's queue where nobody works on it. BUILT AND PROVEN BOTH DIRECTIONS. authenticated 48 baselines established from a clean run. repeat run: 48 compared, 0 regressions. control run: 48 of 48 detected, each naming the size change, baseline 768x900 against 4000x912. public 40 baselines established from a clean run. repeat run: 40 compared, 0 regressions. control run: 40 of 40 detected. A size change is treated as a regression rather than skipped, because a full page capture changes height when layout changes and that is exactly the case worth catching. The threshold is a RATIO, 0.5 percent, not a pixel count, because a 1440 capture has many times the pixels of a 320 one and a fixed count would mean something different at every width. THE APPROVAL GUARD EARNED ITSELF IMMEDIATELY. --approve REFUSES to promote a run that has findings, and the first public attempt was refused with 3 transport findings. Approving that run would have made a flake the standard every future run is measured against. The next run was clean and was approved. A COVERAGE LIMIT, FOUND BY CHECKING THE BASELINES RATHER THAN COUNTING THEM. 48 captures contain only 18 DISTINCT IMAGES. Per viewport: 16 captures, 6 distinct. CAUSE, measured not guessed: both fixture accounts hold exactly one tool, slatematch, in the Acme GovCon org. So /command, /screen, /recruit and /compliance all render the SAME "tool not enabled" panel. That is correct product behaviour and it means the authenticated sweep is photographing a denial panel on most routes rather than a screen. SO THE ASSERTION "no screen renders a raw error or an empty state where fixture data should be" IS NOT BEING EXERCISED on those routes, and 48 captures cover fewer screens than the number suggests. THE TENSION IS REAL AND WORTH STATING. The previous Gate C ran as a superuser and saw real screens on every route, which is why its captures were diverse, and it could not surface the /admin RBAC defect this run found because a superuser is permitted everything. Restricted roles surface RBAC and photograph denial panels. Superusers photograph screens and hide RBAC. WHAT A COMPLETE MATRIX NEEDS: both passes. A fixture org holding ALL tools for screen coverage, plus the restricted fixture accounts for RBAC coverage. That is fixture DATA work, not a code defect, and it is recorded rather than quietly accepted. VERDICT, STATED PRECISELY. Gate C PASSES what it asserts: zero horizontal overflow, zero console errors, zero failed requests, the shell guard at 694px against a 732px baseline, correct RBAC denials, and pixel stability proven in both directions on both surfaces. It carries ONE NAMED COVERAGE LIMIT: screen diversity on the authenticated surface is bounded by the fixture org's single tool.