Files
adr-sml/eslint.config.js
T
Pouya LajevardiandClaude Opus 5 3c3ba5dc6e
Build and deploy / build-and-deploy (push) Failing after 4s
feat: price med-arb by phase, attest the conflicts undertaking, and answer the first real spam
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
2026-09-04 10:06:37 -04:00

117 lines
5.1 KiB
JavaScript

// ESLint 10 flat config. Scope is deliberately small: this project targets zero
// client JavaScript (CLAUDE.md, AGENTS.md §7), so the only JS/TS here is build
// configuration, site data, and the occasional island. Rules exist to catch
// mistakes, not to impose style — Prettier owns formatting.
//
// `typescript-eslint` is here because .astro frontmatter IS TypeScript, so the
// plugin cannot parse a single component without it. It runs unconfigured for
// type-awareness on purpose: `astro check` already does the type checking, and
// duplicating it here would be slower and would disagree at the edges.
import js from '@eslint/js';
import globals from 'globals';
import tseslint from 'typescript-eslint';
import astro from 'eslint-plugin-astro';
export default [
{ ignores: ['dist/**', 'node_modules/**', '.astro/**', 'docs/reference/**'] },
js.configs.recommended,
...tseslint.configs.recommended,
...astro.configs.recommended,
...astro.configs['flat/jsx-a11y-recommended'],
// `no-undef` off for TYPESCRIPT ONLY, on typescript-eslint's own advice: it
// has no type information, so every ambient global is a false positive —
// Astro declares `ImageMetadata`, `astroHTML.JSX` and friends globally, and
// .astro frontmatter IS TypeScript. tsc catches a real undefined reference,
// which is what `npm run check` is for.
//
// NOT applied to .js/.mjs. `tsconfig.json` sets `allowJs` without `checkJs`,
// so plain JS is not type-checked by anything — turning the rule off there
// meant a typo like `procss.env.X` in astro.config.mjs passed lint silently.
{
files: ['**/*.ts', '**/*.astro'],
rules: { 'no-undef': 'off' },
},
{
files: ['**/*.{js,mjs,ts}', '**/*.astro'],
languageOptions: {
ecmaVersion: 2023,
sourceType: 'module',
globals: { ...globals.browser, ...globals.node },
},
rules: {
// A stray console.log in a static build is dead weight shipped to nobody.
'no-console': ['warn', { allow: ['warn', 'error'] }],
// `role="list"` on a <ul> is redundant to a spec reader and load-bearing
// in a browser: Safari drops list semantics from any list styled
// `list-style: none`, so VoiceOver stops announcing "list, 6 items".
// src/styles/global.css keys its own reset off `ul[role='list']` for
// exactly this reason. The rule is right in general; this is the one
// documented exception, and it is scoped to that single pairing.
'astro/jsx-a11y/no-redundant-roles': [
'error',
{ ul: ['list'], ol: ['list'] },
],
eqeqeq: ['error', 'always'],
'prefer-const': 'error',
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_' },
],
},
},
// `scripts/` ARE CLI TOOLS, AND PRINTING IS THEIR OUTPUT. The `no-console`
// rule above is justified in this config as "a stray console.log in a static
// build is dead weight shipped to nobody" — which is a statement about the
// shipped bundle, and nothing in `scripts/` reaches it. `check-claims.mjs`
// exists to print what it matched: CLAUDE.md's rule is that a grep is not a
// finding until you read what it matched, so suppressing its output would
// defeat the tool. Scoped to this directory rather than disabled globally.
//
// ⚠️ IT MUST SIT AFTER THE BLOCK IT OVERRIDES. Flat config applies matching
// blocks in order, last one wins — placed above, this had no effect at all
// and `npm run lint` still reported all six warnings. Measured, not assumed.
{
files: ['scripts/**/*.{js,mjs}'],
rules: { 'no-console': 'off' },
},
/* `infra/cloudfront/` IS NOT A NODE MODULE AND NOT A BROWSER SCRIPT. A
CloudFront Function's entry point is a bare `function handler(event)` that
the runtime calls **by name** — it has no `export` (the runtime rejects
module syntax) and nothing in the file references it, so
`no-unused-vars` fires on the one declaration that is the whole point of
the file. `argsIgnorePattern` cannot reach a function declaration, so the
rule is scoped off here rather than silenced with a comment at the
declaration, which would read as though the name were incidental.
The test beside it is a CLI tool and prints, exactly as `scripts/` does.
⚠️ LIKE THE BLOCK ABOVE, THIS MUST STAY LAST. Flat config applies matching
blocks in order and the last one wins. */
{
files: ['infra/cloudfront/**/*.{js,mjs}'],
rules: {
'@typescript-eslint/no-unused-vars': 'off',
'no-console': 'off',
},
},
/* THE BACKEND TEST FILE ONLY — NOT `backend/intake/**`. `handler.mjs` runs in
Lambda, where `console.log` is a line in CloudWatch that nobody reads and
`console.warn`/`console.error` are the two that signal, so the rule stays on
for it deliberately. The test beside it is a CLI tool and prints its verdict,
exactly as `scripts/` and the router test do.
⚠️ LAST, LIKE THE TWO ABOVE. Flat config applies matching blocks in order
and the last one wins. */
{
files: ['backend/**/*.test.mjs'],
rules: { 'no-console': 'off' },
},
];