feat: price med-arb by phase, attest the conflicts undertaking, and answer the first real spam
Build and deploy / build-and-deploy (push) Failing after 4s
Build and deploy / build-and-deploy (push) Failing after 4s
Pouya's rulings of 2026-09-03 (the last two D20 findings) and 2026-09-04 (the spam observation and four mitigations), in one change set. D20 finding 10 — med-arb is billed BY PHASE, each phase at the rates already published, so /fees/'s "Every figure is on this page" is true as written rather than narrowed. FEES.medArb is the single source; docs/07 §Med-arb carries the rule INTERIM against R5, and R5 now carries it back, because a derived price moves silently when a rate moves. D20 finding 13 — conduct undertaking (g), attested 2026-09-03, published as his wording verbatim on /legal/privacy/ and /contact/. The clause that raised the finding promised to DISCLOSE a conflicts check's outcome, which the attestation does not cover; it is struck. D20 now partitions 17 fixed / 2 refuted / 1 owed. Spam, 2026-09-04 — recorded in docs/05 §Observed abuse with the date and signature. A second honeypot (a decoy checkbox, own class, `hidden`, a label that tells a human not to tick it) and scoring that LABELS and never rejects: nothing is dropped, nothing new is stored, and only the operator notification changes. Q65 opens the WAF cost call. The timing floor could not be built: there is no timing check and never has been. docs/05 carries it struck, and every mechanism that would give a real per-visitor clock breaks zero-JS, handler-and-form-only, or D1. Q66. configure.mjs gains section 5 — a custom origin request policy forwarding CloudFront-Viewer-Address on /api/*. Written, dry-run against the live distribution, NOT applied. It reads the handler's own header reads and refuses to run if the whitelist omits one. And reading the live account to do it found four AGENTS.md §7 rows saying the intake backend was undeployed, two days after it went live — corrected against get-function-configuration, get-routes, get-stage, get-policy and the deployed zip, which was downloaded and read. Review: adversarial-reviewer only (claims-auditor is D20's cutover pass and has run). Round 1 five lenses, 56 findings, 7 blocking, 4 refuted by an independent refuter; round 2 four lenses, 36 findings, 33 of them defects in round 1's own repairs. Stopped at two per D19. Gates, exit status read for each: check 0 · build 0 (23 pages) · check:claims 0 · check:intake 0 · og:proof 0 · lint 0 · spam-score.test 39/39 with 6/6 mutations killed · router.test 30/30 · minifier grep 1 (clean) · lighthouse 0, no category below 95 · configure.mjs dry run 0, nothing written. Nothing deployed and nothing applied. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Md3GndFqWPzK78xAoebsg5
This commit is contained in:
co-authored by
Claude Opus 5
parent
02739adac9
commit
3c3ba5dc6e
+64
-7
@@ -38,15 +38,21 @@
|
||||
*/
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import Button from '../components/Button.astro';
|
||||
import Undertaking from '../components/Undertaking.astro';
|
||||
import ContactBand from '../components/ContactBand.astro';
|
||||
import Eyebrow from '../components/Eyebrow.astro';
|
||||
import SectionHeading from '../components/SectionHeading.astro';
|
||||
import { getImage } from 'astro:assets';
|
||||
import ogDefault from '../assets/og-portrait.jpg';
|
||||
import { pageGraph } from '../data/schema';
|
||||
import { CONTACT, NO_RETAINER_NOTICE } from '../data/site';
|
||||
import {
|
||||
CONDUCT_UNDERTAKINGS,
|
||||
CONTACT,
|
||||
NO_RETAINER_NOTICE,
|
||||
} from '../data/site';
|
||||
import {
|
||||
CONSENT_TEXT,
|
||||
DECOY_CHECKBOX_FIELD,
|
||||
HONEYPOT_FIELD,
|
||||
INTAKE_ACTION,
|
||||
INTAKE_FIELDS,
|
||||
@@ -117,11 +123,20 @@ const hintId = (name: string) => `${name}-hint`;
|
||||
</div>
|
||||
<div class="prose">
|
||||
<p class="statement">{NO_RETAINER_NOTICE}</p>
|
||||
<p>I ask for the other parties and their counsel for one reason.</p>
|
||||
{
|
||||
/* RENDERED FROM `CONDUCT_UNDERTAKINGS`, NEVER TYPED — undertaking (g).
|
||||
⚠️ THIS PAGE HAND-TYPED THE SAME PROPOSITION AS *"I cannot accept an
|
||||
appointment before conflicts are checked"* UNTIL 2026-09-04, and it
|
||||
survived the change set that struck the identical sentence from
|
||||
`/legal/privacy/` — one file swept, its sibling missed, which is the
|
||||
shape R8 exists for. §4 row (g) lists BOTH surfaces. */
|
||||
}
|
||||
<Undertaking>{CONDUCT_UNDERTAKINGS.conflictsCheck}</Undertaking>
|
||||
<p>
|
||||
I ask for the other parties and their counsel because I cannot accept
|
||||
an appointment before conflicts are checked, and that check needs
|
||||
names. Please keep the summary short and leave privileged or
|
||||
confidential detail out of it — the call is for that.
|
||||
That check needs names, and the call above is where it happens. Please
|
||||
keep the summary short and leave privileged or confidential detail out
|
||||
of it — the call is for that.
|
||||
</p>
|
||||
<p>
|
||||
What is collected, where it is stored, how long it is kept, and how to
|
||||
@@ -248,7 +263,13 @@ const hintId = (name: string) => `${name}-hint`;
|
||||
the form: a browser that helpfully fills a plausible-looking field
|
||||
would make a human look like a bot. */
|
||||
}
|
||||
<div class="honeypot" aria-hidden="true">
|
||||
{
|
||||
/* `hidden` ADDED 2026-09-04, for the reason spelled out on the decoy
|
||||
below: a class-only rule leaves this field on screen wherever author
|
||||
styles do not apply, and a visitor who fills it loses their inquiry
|
||||
behind a success page. */
|
||||
}
|
||||
<div class="honeypot" hidden aria-hidden="true">
|
||||
<label for={HONEYPOT_FIELD}>Company website</label>
|
||||
<input
|
||||
type="text"
|
||||
@@ -287,6 +308,41 @@ const hintId = (name: string) => `${name}-hint`;
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{
|
||||
/* THE SECOND HONEYPOT — a decoy CHECKBOX. The mechanism, and the
|
||||
limits of what the observed spam supports, are in `src/data/intake.ts`
|
||||
and are not restated here. Four properties of the MARKUP, each of
|
||||
which is what stops this field costing a real inquiry:
|
||||
|
||||
· its own CLASS NAME, not `.honeypot` — one selector must not
|
||||
match both traps. They share a declaration block below, which is
|
||||
presentation; what matters is that `.honeypot` does not select
|
||||
this one;
|
||||
· placed after the consent block, not beside the other honeypot;
|
||||
· `hidden` as well as the CSS rule, so it stays hidden where
|
||||
author styles do not apply;
|
||||
· a label that tells a human not to tick it. With `hidden` in
|
||||
place a human essentially cannot see it, so this is the last
|
||||
line rather than the first — and it costs almost nothing,
|
||||
because the PLAUSIBLE NAME is what a bot matches on and the name
|
||||
is unchanged.
|
||||
|
||||
⚠️ NO `required`, AND NO `checked`. An unchecked box sends nothing,
|
||||
so absence is the pass — and the handler tests for a NON-EMPTY value,
|
||||
so an empty one passes too. */
|
||||
}
|
||||
<div class="optin-decoy" hidden aria-hidden="true">
|
||||
<label for={DECOY_CHECKBOX_FIELD}>Leave this box unticked.</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
id={DECOY_CHECKBOX_FIELD}
|
||||
name={DECOY_CHECKBOX_FIELD}
|
||||
value="on"
|
||||
tabindex="-1"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{
|
||||
/* ⚠️ `<Button type="submit">`, NOT a hand-written `<button class="btn">`.
|
||||
`.btn` and `.btn-primary` are SCOPED TO `Button.astro`, so a raw
|
||||
@@ -505,7 +561,8 @@ const hintId = (name: string) => `${name}-hint`;
|
||||
the input are belt and braces for the case where a future stylesheet
|
||||
un-hides it. Do not swap this for `visibility` or an off-screen position:
|
||||
an off-screen input is still focusable and still announced. */
|
||||
.honeypot {
|
||||
.honeypot,
|
||||
.optin-decoy {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user