fix: refute (ar)'s intake finding; fix the D20 gloss class; add X-Robots-Tag on *.pdf
Build and deploy / build-and-deploy (push) Failing after 4s

Pouya's rulings of 2026-09-03, in five parts.

1. THE INTAKE FORM IS NOT BROKEN. (ar) was wrong. docs/09 §7.1 verbatim —
POST /api/intake with an Origin header — returns 303 to /contact/could-not-send/
with access-control-allow-origin echoed; the same probe without Origin returns
403. A bare POST 403s BY DESIGN and §7.1 says so three lines below the probe it
prescribes: "403 means the Origin header did not arrive". The earlier finding
read a status code without reading the document that defines it. Second time in
two days. CLAUDE.md's instrument list goes eight to nine. D20 findings 12 and 19
fall with it; §7.2 (that both emails arrive) is still owed.

The correction is APPENDED as entry (as); (ar) stands unedited.

2. The privacy retention comment was stale, not a defect — superseded by his
decision to publish and confirm after launch, reading from 2026-09-04. Reworded;
the TODO(pouya) came off with the gate it enforced. The mechanism finding
survives: it was a JSX comment, stripped by Astro, so no build or deploy path
could see it. A publication gate that lives only in a stripped comment is not a
gate. §9 Q60 corrected.

3. The gloss class is fixed — 15 of the 20 D20 findings, 14 distinct edits across
9 files, under the rule "the gloss may say no more than the extract says; no new
claims, no new sources". Swept three unpublished insights drafts too, and
corrected the wrong CAA attribution at its source in docs/reference/, which is
where a fixed page re-seeds. /bio/ changed, so the committed PDF is regenerated
(89,549 B, 1 page asserted). Three findings outstanding: 10 needs a ruling, 11 is
ruled and owed via Q60, 13 needs him to have said it. R1 is not one of the twenty.

4. X-Robots-Tag cannot be done with S3 object metadata — --metadata writes user
metadata, returned as x-amz-meta-x-robots-tag, which no crawler reads. Built as
the CloudFront response-headers policy docs/06 has specified all along:
configure.mjs section 4. It needs a --apply run, not a deploy. The policy is
cloned from whatever is attached at run time and reconciled on every run, because
a response-headers policy replaces rather than merges.

5. Headshot deferred as an open non-defect. The master and the srcset ladder are
both fine; Astro passes no quality, so AVIF encodes at sharp's default 50 and is
served first.

Two review rounds, 29 findings, all resolved, none declined; stopped at two per
D19. NINE of round 2's fourteen were defects in round 1's own repairs — including
a fix that harmonised both /fees/ rows onto wording that was itself unregistered,
publishing an unsourced fee term twice where it had been once.

Gates, exit status read for each: check 0 (0 errors, 0 warnings, 0 hints),
build 0 (23 pages), check:claims 0, check:intake 0, og:proof 0, lint 0, minifier
grep exit 1, router.test.mjs 30/30. Lighthouse NOT run. Nothing deployed and
nothing applied to the distribution.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
This commit is contained in:
Pouya Lajevardi
2026-09-03 17:23:20 -04:00
co-authored by Claude Opus 5
parent b9523817e2
commit 02739adac9
18 changed files with 764 additions and 101 deletions
+136 -29
View File
@@ -408,12 +408,26 @@ Then invalidate `/*`.
> `67847d9`** — SHA-256 compared page by page, 22 same / 0 differ / 0 errors. The
> five `noindex` surfaces and the 17-URL sitemap are correct.
>
> 🛑 **BUT THIS LIST WAS NOT CLEAN WHEN THE SITE PUBLISHED, AND THAT IS THE
> RECORD, NOT A REPROACH. THREE BLOCKING ITEMS WERE OPEN AT THE MOMENT OF
> CUTOVER AND TWO STILL ARE.** D11 is a single shot and the checklist exists
> because of it; a launch that crosses its own gates should be legible as one
> afterwards rather than smoothed over. **What follows is the state as at
> 2026-09-02, after the D20 pass ran against the shipped bytes.**
> 🛑 **THIS LIST WAS NOT CLEAN WHEN THE SITE PUBLISHED, AND THAT IS THE RECORD,
> NOT A REPROACH. TWO BLOCKING ITEMS WERE GENUINELY OPEN AT CUTOVER; BOTH ARE
> NOW NARROWED RATHER THAN CLOSED.** D11 is a single shot and the checklist
> exists because of it; a launch that crosses its own gates should be legible as
> one afterwards rather than smoothed over.
>
> ⚠️ **THE COUNT SAID THREE FOR ONE DAY AND THREE WAS WRONG — corrected
> 2026-09-03.** The third, *"the intake form is live and broken"*, was **a false
> alarm from a malformed probe** and is refuted in item 2 below. It is corrected
> here rather than deleted because a blocker that was never real, asserted on the
> most-read part of this page, is the same failure as a real one that goes
> unrecorded — and because **this is the first time the count moved for a reason
> the earlier notes did not anticipate: not closed, not deleted, not moot, but
> WRONG.** That is a fourth way off this list, and it looks identical to the
> other three in a tally.
>
> **The state as at 2026-09-03:** **Q60** is owed rather than pending — Pouya
> ruled the page publishes and the deletion is confirmed after launch, reading
> from **2026-09-04**. **The D20 pass** returned 20 confirmed findings, of which
> **15 are fixed, 2 refuted and 3 need a ruling from him** rather than an edit.
>
> ✅ **THE READ-THROUGH IS COMPLETE — Pouya, 2026-09-02, and it returned ONE
> FINDING WHICH WAS NOT COPY.** `public/favicon.ico` shipped with no
@@ -455,27 +469,73 @@ Then invalidate `/*`.
> period. `docs/09` Part 10 is the test; earliest useful reading **48 hours**
> after the record is written, failure not called before **7 days** — Pouya
> started the window 2026-09-02, so **check from 2026-09-04**.
> ⚠️ **THE PAGE CARRIED ITS OWN INSTRUCTION NOT TO DO THIS AND IT WAS
> INVISIBLE AT DEPLOY TIME.** `src/pages/legal/privacy.astro:229` holds a live
> `TODO(pouya)` ending, in terms: *"This page must not go public until a
> deletion has actually been seen."* It is a **JSX comment**, so Astro strips
> it and it never reaches `dist/` — which is exactly why `check:claims`, the
> build and both deploy paths were all green over it. **A publication gate
> that lives only in a stripped comment is not a gate.** The checklist item
> *"No `TODO(pouya)` remains in any shipped page"* below is the control that
> would have caught it and it was never ticked.
> 2. 🛑 **THE INTAKE FORM IS LIVE AND BROKEN — a submitter gets a blank page.**
> `/contact/` ships `<form method="post" action="/api/intake">`; **`POST
> /api/intake` returns HTTP 403 with `content-length: 0`** and an
> `apigw-requestid` header, so the request reaches API Gateway and is rejected
> because the only route is `POST /submissions` (§7). No styled error, no
> message, no fallback. Measured against production 2026-09-02. `docs/09`
> Part 6 is the fix; Pouya has the end-to-end test in progress.
> ⚠️ **AND `/legal/privacy/` AND `/contact/received/` BOTH DESCRIBE THAT
> MECHANISM AS RUNNING** — *"Two emails are sent when you submit the form"* and
> *"A confirmation goes to the email address you gave"*. Nothing is sent,
> because nothing can be submitted. Found by the D20 pass; see item 3.
> 3. 🛑 **THE D20 CLAIMS PASS HAS NOW RUN AGAINST THE SHIPPED BYTES AND RETURNED
> ⚠️ **THE PAGE CARRIED ITS OWN INSTRUCTION NOT TO DO THIS — RULED STALE BY
> POUYA 2026-09-03 AND REWORDED.** `src/pages/legal/privacy.astro` held a
> `TODO(pouya)` ending *"This page must not go public until a deletion has
> actually been seen."* **His decision supersedes it: publish, then confirm the
> deletion after launch.** The comment now states that decision and its date,
> and the `TODO(pouya)` marker is gone, which also clears the checklist item
> *"No `TODO(pouya)` remains in any shipped page"* below.
> **What stays true is the mechanism finding, and it is worth keeping:** that
> instruction was a **JSX comment**, so Astro strips it and it never reached
> `dist/` — which is why `check:claims`, the build and both deploy paths were
> green over it. **A publication gate that lives only in a stripped comment is
> not a gate**, whatever the gate happens to say. Q60 itself is unchanged and
> the confirmation is now *owed* rather than *pending*.
> 2. ✅ **REFUTED BY MEASUREMENT 2026-09-03 — THE INTAKE FORM IS NOT BROKEN, AND
> THIS ENTRY IS THE CORRECTION.** Pouya's probe, reproduced here in both
> directions: `docs/09` §7.1 verbatim — `POST /api/intake` with
> `Origin: https://adr.smlcompany.ca` and
> `Content-Type: application/x-www-form-urlencoded` — returns **HTTP/2 303**,
> `location: https://adr.smlcompany.ca/contact/could-not-send/`, with
> `access-control-allow-origin` echoed and an `apigw-requestid` present. **The
> handler answered as designed**: it validated, found an empty submission and
> redirected to the failure page before any write and any email. The **same
> probe with the `Origin` header removed returns 403**, which is the control.
> ⚠️ **A BARE POST TO `/api/intake` RETURNS 403 BY DESIGN, AND §7.1 SAYS SO
> THREE LINES BELOW THE PROBE** — *"403 means the `Origin` header did not
> arrive"*. The earlier finding read a status code without reading the document
> that defines what that code means on that route. **This false alarm has now
> fired twice in two days** — Pouya's own probe tripped it 2026-09-02 — and it
> is recorded in `CLAUDE.md`'s instrument list, which stands at nine.
> **The only valid route probe is `docs/09` §7.1 verbatim, `Origin` included.**
>
> ⚠️ **AND THE TWO "BACKEND NOT DEPLOYED" CLAIMS FINDINGS FALL WITH IT.**
> `/legal/privacy/` §Where it is stored (*"Two emails are sent when you submit
> the form"*) and `/contact/received/` (*"A confirmation goes to the email
> address you gave"*) were both premised on the route not existing. It exists.
> **What is NOT settled by this probe is that both emails actually arrive** —
> §7.1 stops before any write and any email by design, and that is `docs/09`
> §7.2, the real-submission test Pouya has in progress. The disclosures are
> unblocked; the end-to-end confirmation is still owed.
> 3. ⚠️ **THE D20 CLAIMS PASS RETURNED FAIL WITH 20 CONFIRMED FINDINGS; 15 ARE
> NOW FIXED, 2 REFUTED, 3 OUTSTANDING — updated 2026-09-03, and the three
> numbers partition the twenty.** Fixed under Pouya's rule *"the gloss may say
> no more than the extract says; no new claims, no new sources"*: findings
> 19, 1418 and 20 — the whole gloss class, plus `/bio/`'s role verb.
> ⚠️ **15 FINDINGS, 14 DISTINCT EDITS: findings 4 and 15 quote the same
> sentence** on `/practice/energy/`, so one edit closed both. **REFUTED:**
> findings 12 and 19, the two backend disclosures, with item 2 above.
> **OUTSTANDING — findings 10, 11 and 13, and each is outstanding for a
> different reason:**
> **(10) NEEDS A RULING.** `/fees/`'s *"Every figure is on this page"* against
> §4's **Med-Arb** offering, which `docs/07-fees.md` prices nowhere. Either a
> med-arb fee term or a scoped promise; it cannot be closed by narrowing.
> **(11) IS RULED, AND THE CONFIRMATION IS OWED.** The retention *mechanism*
> sentence on `/legal/privacy/` is unchanged and still ships, deliberately —
> that is blocker 1 above and §9 Q60, reading from 2026-09-04. It is listed so
> the twenty account for themselves, not because it is unresolved.
> **(13) NEEDS HIM TO HAVE SAID IT.** `/legal/privacy/`'s *"if a conflicts
> check has already been run I will tell you what its outcome was"* is an
> **undertaking**, and §4's gate for that class is one line: Pouya must have
> made it **in terms**. It is not in `CONDUCT_UNDERTAKINGS`.
> ⚠️ **§12 R1 IS NOT ONE OF THE TWENTY.** An earlier form of this item named it
> as the third outstanding finding and dropped 11 to make room — a tally that
> did not partition its own set. R1 is a standing reminder on licensure that a
> completeness critic reached independently from the copy; it is live, and it
> is counted nowhere. The original entry follows.
>
> 🛑 **THE D20 CLAIMS PASS HAS NOW RUN AGAINST THE SHIPPED BYTES AND RETURNED
> FAIL — 20 CONFIRMED FINDINGS ON LIVE PAGES.** Run 2026-09-02 at `67847d9`,
> after cutover, over all 23 built pages: 13 auditors (8 page groups + 5
> cross-cutting lenses) → 41 raw findings → 31 distinct → each adversarially
@@ -1081,8 +1141,25 @@ the decision is re-readable rather than re-litigated.
byte-reproducible** — Chrome stamps a `/CreationDate`, so two runs of
identical content differ in digest and every re-render is a binary diff.
Re-commit it when something actually changed, and say what in the message
- [ ] **`X-Robots-Tag: noindex` on `*.pdf`**, via a CloudFront response-headers
policy. **This is the PDF half of a decision already taken for the page.**
- [ ] **`X-Robots-Tag: noindex` on `*.pdf`** — ⚠️ **WRITTEN 2026-09-03, NOT YET
APPLIED. It needs a `configure.mjs --apply` run, not a deploy.**
`infra/cloudfront/configure.mjs` §4 creates a response-headers policy
`adr-sml-pdf-noindex` and a `*.pdf` cache behaviour carrying it. ⚠️ **S3
OBJECT METADATA CANNOT DO THIS, which is the natural first reach and was
the instruction this was implemented against.** `aws s3 sync --metadata`
writes USER metadata, which S3 returns as `x-amz-meta-x-robots-tag` — a
header no crawler reads. Only a literal `X-Robots-Tag` counts and S3's REST
endpoint will not emit one, so the mechanism is the response-headers policy
this line has specified from the start. ⚠️ **THE POLICY CLONES THE
SECURITY HEADERS AT RUN TIME RATHER THAN RETYPING THEM** — a
response-headers policy REPLACES rather than merges, and all five
(`strict-transport-security`, `x-content-type-options`, `x-frame-options`,
`x-xss-protection`, `referrer-policy`) were measured arriving on the live
PDF 2026-09-03, so a hand-written policy would have silently dropped them.
Verify after applying with `docs/09` Part 3's header block, which counts
each of the six separately — an alternation `grep` exits 0 on any one match
and would call a partial clone a pass. **This is the PDF half of a decision
already taken for the page.**
`/bio/` is `noindex` and excluded from the sitemap because it is a condensed
duplicate of `/about/` and `/fees/`, and *"two URLs competing on the same
content is the one thing `docs/04` is most concerned with."* The committed
@@ -1092,6 +1169,36 @@ the decision is re-readable rather than re-litigated.
instead. A `Disallow` will not do it: a blocked URL can still be listed.
Found by `adversarial-reviewer`, 2026-08-31
- [ ] Booking link works, including the no-JavaScript fallback — **conditional on R6**; booking is parked and `CONTACT.bookingUrl` is `null`, so nothing renders and this passes vacuously until a tool is chosen. **Nothing on `/contact/` mentions booking**, deliberately
- [x] ⚠️ **THE HEADSHOT SHIPS SOFT, AND IT IS A DEFERRED DECISION RATHER THAN A
DEFECT — Pouya, 2026-09-03. NO CHANGE.** ✅ **Ticked because the decision is
taken, not because anything was done** — an item recording a decision *not*
to act can never be ticked on completion, and leaving it open would stop
this checklist ever reading clean. He raised it on the live site;
measured 2026-09-03 and the cause is not the master and not the delivery.
**The master is fine** (1600×1600, 4:4:4, real detail at full size — a
1/2-scale round trip is visibly softer than it is) and **the srcset ladder
is correct** (9 device profiles in Chrome: ratios **1.001.21, no
upscaling anywhere**, `sizes` 476 px matching the measured rendered width
exactly). **The cause is that Astro passes no `quality`, so sharp's
per-format defaults apply — AVIF 50, WebP 80, JPEG 80 — and
`formats={['avif','webp']}` puts AVIF first, so every modern browser gets
the quality-50 encode.** At 960 px it retains **55%** of the reference's
high-frequency energy; WebP retains 85% and JPEG 95%, and neither is
served. Sweep at 960 px: q60 → 76% at 33 KB, q65 → 80% at 39 KB, **q70 →
90% at 51 KB**, q80 → 94% at 77 KB, against today's **21 KB**.
⚠️ **IT IS DEFERRED BECAUSE IT IS A REAL TRADE, NOT BECAUSE IT IS SMALL:**
the portrait is the LCP element from 768 px up, and **§7's Lighthouse row
records `/` at LCP 2.03 s** `[verified 2026-08-31 — lcp-breakdown-insight]`,
so +30 KB needs a fresh `npm run lighthouse` before it ships.
⚠️ **THAT IS NOT A MEASUREMENT AGAINST `docs/04`'s BUDGET AND MUST NOT BE
READ AS ONE.** `docs/04`'s < 2.0 s is a **Slow 4G field** figure; 2.03 s is
a local run under loopback throttling, which is why `npm run lighthouse`
*reports* LCP and does not assert it (§7). The two are close enough to look
comparable and are not the same measurement — so this is a reason to
re-measure before adding bytes, not a recorded budget breach. **Three call sites would be affected
and none sets `quality`** — `src/pages/index.astro`, `src/pages/about.astro`
and `src/components/InfinityMark.astro`; the mark is line art and would
want a different number from the portrait, so this is not one edit.
- [x] ✅ **Favicon set complete, and REGENERATED 2026-09-02 — it had shipped with
no transparency at all.** Pouya's read-through finding. All three frames
(16/32/48) declared a 32-bit alpha channel and then carried `alpha = 255`