Skip to content

Commit 4616501

Browse files
eastmadcclaude
andcommitted
docs(rules): promote Rule #51 — Rule-#33 conversion mandates rate-limit tier re-evaluation
Rule-of-One mechanical-rigor strength (precedent: Rules #40 + #47 + #50 promoted on same basis). When converting an endpoint from synchronous to 202+polling per Rule #33, the saturation calculus changes from "uvicorn worker held for N minutes" to "background task spawned per ACK" — the original rate-limit tier becomes the wrong shape, usually too restrictive AND keyed to the wrong resource ceiling. Source evidence — 2026-05-18 rate-limit campaign (9 commits): - f6dbc7b: split TIER_A_HEAVY → TIER_A_HEAVY + TIER_A_LIGHT_ACK - 69ed1dd: extractErrorMessage handles SlowAPI body shape - ca5a64f: axios global 429 interceptor + Retry-After cooldown - 616e89d: custom structured 429 handler (tier name + retry_after + hint) - 3d2454b: vuln_scan_status orphan reaper (mirror of cve_match / device_dump reapers) - 58a6f54: bump DB pool 10+20 → 15+25 = 40 for 30/hour burst headroom - 8766710: add TIER_A_HEAVY to undecorated 202 endpoints /firmware/{id}/unpack + /device/dumps - afa23a9: fix tier reverse-map (parsed-form keys) + Retry-After header (caught by live canary) - b24a4d8: dynamic 429 test + Rule #46 META-CANARY trio (proves gate fires) Root cause: the Rule #33 sync→202+polling conversion at commit 8f54a24 (vuln-scan) didn't re-evaluate the rate-limit tier, so the 5/hour limit kept throttling the operator's iterative research workflow on DS1 firmware. Sweep also caught 2 unrelated UNLIMITED 202+polling endpoints with the same shape-mismatch (firmware/unpack + device/dumps). Rule shape: - Mechanical procedure (a)-(h) covering measurement + computation + documentation + test-update + canary discipline at Rule #33 conversion time. - Tier shape by WORK duration (not ack shape): TIER_A_HEAVY for ≥5min event-loop pin OR sync; TIER_A_LIGHT_ACK for ≤2min detached; TIER_B_DOCKER for Docker-spawn. - Companion failure-mode bullets (orphan reaper / frontend 429 handler / structured 429 body) so future Rule-#33 conversions enumerate the dependents explicitly. - Promotable to Rule-of-Two when next Rule-#33 conversion surfaces the same gap. This commit IS itself a cross-stack-alignment commit per Rule #48 Shape 1 (CLAUDE.md learned rule + conventions.md Verify Checklist mirror enforce the same conceptual contract via Rule #21). CLAUDE.md changes: - Rule #51 inserted after Rule #50 (lines 464-466) - "rules 1–50" → "rules 1–51" in Companion scaffold section conventions.md changes: - description: "50 learned rules" → "51 learned rules" - last_updated: amended with Rule #51 promotion line - Verify Checklist: new bullet inserted before Rule #50 entry Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b24a4d8 commit 4616501

2 files changed

Lines changed: 7 additions & 3 deletions

File tree

.mex/context/conventions.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: conventions
3-
description: How code is written in Wairz — naming, file structure, async patterns, MCP handler rules, schema/model discipline, and the verify checklist derived from 50 learned rules. Load when writing new code or reviewing existing code.
3+
description: How code is written in Wairz — naming, file structure, async patterns, MCP handler rules, schema/model discipline, and the verify checklist derived from 51 learned rules. Load when writing new code or reviewing existing code.
44
triggers:
55
- "convention"
66
- "pattern"
@@ -18,7 +18,7 @@ edges:
1818
condition: when the work touches MCP tool handlers, registry, or ToolContext
1919
- target: patterns/INDEX.md
2020
condition: when starting a common task — a pattern likely encodes these conventions
21-
last_updated: 2026-05-18 (Rules #48-50 promoted from hw-firmware-adaptive 2026-05-15 trio of postmortems — cross-stack-alignment-test 5-part shape Rule-of-Nine, forward-prepared-CVE-pin Rule-of-Two Tegra+MediaTek, shared-advisory_id with documented dedup Rule-of-One+ FragAttacks; also bumps Rule #25 single-slice exception #2 evidence chain Rule-of-Eight → Rule-of-Nine via d641f28 Shape-2 regression-canary form)
21+
last_updated: 2026-05-18 (Rule #51 promoted from rate-limit campaign 2026-05-18 — Rule-#33 conversion mandates rate-limit tier re-evaluation; Rule-of-One mechanical-rigor strength; companion failure-mode sweep caught 3 paired gaps (orphan reaper / frontend 429 handler / structured 429 body) + 2 undecorated 202+polling endpoints. Prior 2026-05-18 update: Rules #48-50 promoted from hw-firmware-adaptive 2026-05-15 trio of postmortems — cross-stack-alignment-test 5-part shape Rule-of-Nine, forward-prepared-CVE-pin Rule-of-Two Tegra+MediaTek, shared-advisory_id with documented dedup Rule-of-One+ FragAttacks; also bumps Rule #25 single-slice exception #2 evidence chain Rule-of-Eight → Rule-of-Nine via d641f28 Shape-2 regression-canary form.)
2222
---
2323

2424
# Conventions
@@ -195,4 +195,6 @@ Before presenting any code change:
195195
- [ ] **Canary discipline for any "asserts absence" verification mechanism (Rule #46):** ruff/lint suppressions, Rule #36/#45 test gates, CI workflows, pre-commit hooks, type-checker invocations, deny-list scanners, AST/token visitors, schema-validation assertions — ALL gates that say "no forbidden tokens / no type errors / no failed tests / no policy violations" MUST be paired with a CANARY test in the same file that (a) synthesises a violation IN MEMORY or as a fixture, (b) runs the gate against it, (c) asserts the gate REJECTS it. Without the canary, a passing result is structurally indistinguishable from "the mechanism isn't actually checking" (Learned Rule #46). Rule-of-Four evidence chain: Rule #17 (tsc -b cache short-circuit) + Rule #24 (tsc --noEmit empty-files no-check) + κ.D test-gate tokenize-whitespace gap (regex `\.decrypt\(` failed because tokenize joins with spaces) + κ.E meta-canary (Rule #24 invocation caught a Rule #35a pipe-induced silent exit IN ITSELF). Mechanical authoring: write the synthetic-violation constructor FIRST; ensure the synthetic round-trips through the gate's preprocessing (string-join, tokenize, AST-walk, JSON-load); a synthetic the gate strips out (e.g. f-string under tokenize) is itself a bug — finding it pre-ships saves regressions. Reviewer-level check at PR/commit time: "where's the canary that proves this gate fires on a synthetic?" Companion to Rule #17 (the original CLI-exit instance — Rule #46 generalises), Rule #24 (mandatory-per-session form for tsc), Rule #36 + #45 (no-execute / no-decrypt gates whose canary is the partner discipline).
196196
- [ ] **Cross-stack alignment test discipline — 5-part shape (Rule #48):** N source-of-truth surfaces enforcing the same conceptual contract (DB CHECK + Pydantic Literal + frontend Record map; curated-tier narrowing-field allowlist + banner-pin family-only gate; parser-exposed tuple + loader's private allowlist) require a single-file regression canary with 5 mandatory parts: (1) **paired rejection** — each layer rejects its dialect of the conceptual antipattern; (2) **paired acceptance** — each narrowing dimension parametrized; (3) **size-lock** — both allowlists pinned at current documented sizes (`len(<allowlist>) == N` — drift forces a deliberate test edit); (4) **cross-layer alignment proper** — synthesize antipattern in BOTH dialects in ONE test; assert BOTH reject; (5) **META-CANARY per Rule #46** — confirm gate's WARN/error contains the diagnostic substring operators rely on. **Asymmetry tolerance:** reject MODE may differ per layer (WARN+skip vs raise ValueError) — assert via each layer's idiomatic shape (`_caplog_at(<logger>)` vs `pytest.raises`), NOT a forced common mode. Name-equality across dialects is a FALSE alignment (dialects may legitimately use different vocabulary; contract is SHAPE-equivalence). **Two commit shapes:** Shape 1 (multi-surface change in ONE commit per Rule #25 single-slice exception #2) for ADD-new-entry cases — see Rule #25's Rule-of-Nine evidence table for 8 Shape-1 worked examples; Shape 2 (alignment regression canary on EXISTING surfaces) for already-aligned-surfaces cases, commit-prefix `test(<scope>):`. The 9th instance `d641f28` (2026-05-15 evening) is the canonical Shape-2 case. Mechanical decision: ADDING a new surface or new entries → Shape 1. Otherwise → Shape 2. Recipe: `.mex/patterns/cross-stack-alignment-test.md`. Companions: Rule #25 single-slice exception #2 (commit shape), Rule #46 META-CANARY (load-bearing part 5), Rule #31 width-canary (surface-identification grep run twice), Rule #19 evidence-first (asymmetry documented in module docstring before "normalising" to common-mode), Rule #21 (recipe + this entry + CLAUDE.md Rule #48 in the same commit per the cross-stack-alignment commit shape itself).
197197
- [ ] **Forward-prepared CVE pin pattern (Rule #49 — Rule-of-Two Tegra + MediaTek modem):** when NVD CPE narrows a CVE to a version range / chipset family / OS family / banner identifier that requires extraction infrastructure not yet shipped in the wairz parser, ship the pin TODAY with HARD-REJECT `version_regex`. Matcher's hard-reject contract at `backend/app/services/hardware_firmware/cve_matcher.py:477-491` (comment line 478: *"Stays STRICT — when present, version evidence MUST be found"*) produces ZERO matches on current corpus, eliminating over-attribution risk per Reviewer B 2026-05-15 NVD-CPE discipline. Pin activates the moment the parser ships extraction — **ZERO YAML edits required at activation**. **Required components:** (a) inline YAML comment header citing Reviewer/session source + enumerated narrowing values + hard-reject contract line ref (`cve_matcher.py:480-491`) + activation prerequisite (parser-name + banner-format + target column); (b) boundary-anchored regex `(?i)(?:^|[^a-z0-9])(<val1>|<val2>|...|<valN>)(?:[^a-z0-9]|$)` — prevents whole-substring false-positives; DON'T use `\b` (Python's `\b` treats `_` as word char, fails on underscore-separated banners like `MOLY_NR16_R1`); (c) gate-canary test `test_<cve>_hard_rejects_blob_with_null_version` per Rule #46; (d) activation commit-chain plan documented in postmortem + `.planning/ADAPTIVE_BACKLOG.md`: parser extraction → detection re-run with DELETE-before-redetect (afternoon postmortem Pattern #7 — detector's `on_conflict_do_nothing` skips updates on existing rows) → cve-match with surgical DELETE before re-match (evening postmortem Pattern #5 — `force_rescan=True` skips dedup check but doesn't DELETE; UNIQUE constraint violations on re-insert) → pre/post SQL audit. DON'T apply when narrowing evidence IS extracted today (just ship normally); CVE scope is genuinely vendor+category; narrowing field is `chipset_regex` with `strict_chipset: false` (soft-fallback — different shape). Rule-of-Two: `6bc1c1d` (morning — 6 Tegra/L4T pins activated afternoon via `f54d415`+`0a901f2`+`338f95b`, 4-of-6 fired on DS1) + `e45a74c` (evening — MediaTek CVE-2023-20819 `lr11`/`lr12a`/`lr13`/`nr15`/`nr16`/`nr17` modem-OS families, pending mtk_modem parser shipment). Recipe: `.mex/patterns/forward-prepared-cve-pin.md`. Companions: Rule #19 (NVD WebFetch), Rule #25 per-piece commits, Rule #46 paired-canary (gate-canary REQUIRED), Rule #16 detection roots. Future Rule-of-Three candidate: KRACK/Dragonblood/BroadPwn audit queued as `evening:RvwB-B11`.
198+
- [ ] **Rule #33 (sync→202+polling) conversion mandates rate-limit tier re-evaluation (Rule #51 — Rule-of-One mechanical-rigor):** When converting an endpoint from synchronous to 202+polling, the saturation calculus changes from "uvicorn worker held for N minutes" to "background task spawned per ACK". The original rate-limit tier becomes the wrong shape — usually too restrictive AND keyed to the wrong resource ceiling. **Mechanical procedure at conversion time:** (a) measure new ack latency (sub-second); (b) measure new detached-work latency on representative data; (c) identify the bounding resource (DB pool / subprocess count / container memory / arq worker depth); (d) compute `tier = max(1, headroom_capacity / work_concurrency_per_unit)`, pick nearest tier constant; (e) document derivation INLINE in the constant's docstring; (f) update `test_rate_limit_tiers._EXPECTED_TIERS` in the SAME commit (Rule #25 single-slice exception #2); (g) add Rule #46 META-CANARY for the static decorator test if not present; (h) verify structured 429 handler produces correct tier name via dynamic-flavor test (POST tier+1 times, assert body has `tier: "<NAME>"`). **Tier shape post-conversion** by WORK duration (NOT ack shape — both LIGHT_ACK and HEAVY are 202+polling at the HTTP layer): TIER_A_HEAVY (5/hour) for ≥5min event-loop pin OR sync; TIER_A_LIGHT_ACK (30/hour) for ≤2min detached; TIER_B_DOCKER (20/hour) for Docker-spawn. **Companion failure modes that frequently coexist** (2026-05-18 sweep caught all three): orphan reaper missing for new state-machine column (Firmware.vuln_scan_status lacked one despite cve_match_status / device_dump_status having ones — fix 3d2454b); frontend 429 handler reads `data.detail` but SlowAPI body is `data.error` (fix 69ed1dd); structured 429 body lacks tier/retry_after_seconds/hint (fix 616e89d + afa23a9). All three share root cause with the tier mismatch: Rule #33 conversion changed an invariant other components depended on but the dependents weren't enumerated or migrated. Worked example: 2026-05-18 commit chain `f6dbc7b → 69ed1dd → ca5a64f → 616e89d → 3d2454b → 58a6f54 → 8766710 → afa23a9 → b24a4d8` (9 commits). Companions: Rule #33 (202+polling shape contract — Rule #51 is its rate-limit dual), Rule #29 (timeout discipline — same family of "constraint moves when work shape moves"), Rule #25 single-slice exception #2 (cross-stack-alignment commit shape), Rule #46 (paired META-CANARY for tier-decorator test), Rule #47 (consumer-hook enumeration — same shape generalised).
199+
198200
- [ ] **Shared advisory_id with documented dedup pattern (Rule #50 — Rule-of-One+ FragAttacks):** when N curated YAML entries cover the same SPEC-level CVE cluster across N vendor-fork entries (FragAttacks broadcom + qualcomm WiFi; KRACK multi-vendor WPA; Dragonblood multi-vendor WPA3; BroadPwn multi-Broadcom-variant), set the SAME `advisory_id` across all N entries. Matcher dedupes per `(blob_id, cve_id)` via an in-memory `existing` set at `cve_matcher.py:905` (firmware-scoped initial SELECT) checked at `:989` + `:1042`; `firmware_id` is implicit per-invocation. NO DB UniqueConstraint exists on `sbom_vulnerabilities` (`backend/app/models/sbom.py:65-129` declares only `Index` entries); `force_rescan=True` skips the in-memory check, never DELETEs. Duplicate-advisory_id WARN at load time is **INTENTIONAL** convergence signal (deferred opt-in suppression key `shared_advisory_id: true` will silence WARN when both entries declare convergence — Reviewer A A5 + Reviewer B B6, queued as `evening:RvwA-A5 + RvwB-B6`). Anti-pattern: distinct per-vendor advisory_ids when conceptual scope is identical — loses dedup; doubles operator-facing rows for no gain. **Vendor narrowing fields on advisory-only entries (`cves: []`) remain load-bearing** — despite F-FORENSIC-10 gate's advisory-only bypass not requiring narrowing, the narrowing scope's match boundary (broadcom `category_regex: ^wifi$`; qualcomm `chipset_regex: ^wcn3xxx`) is load-bearing for `_match_curated`; preserves matching shape + prevents future re-conversion-to-CVE-bearing from immediately over-firing (Reviewer A A6). **CVSS aggregate discipline (7 sessions running, durable):** advisory aggregating N CVEs needs NVD primary CVSS for ALL N; advisory's `cvss_score` is **worst-case individual**; severity reflects worst-case category. Implementer-side WebFetch focuses on attribution scope (vendor/version); reviewer-side must independently re-fetch CVSS fields — Reviewer B 2026-05-15 evening caught FragAttacks CVSS drift medium 6.5 → NVD primary LOW 3.5/2.6/3.5 (aggregate 3.5). Rule-of-One: `54a0a32` + `3e12ae5` (2026-05-15 evening — FragAttacks NVD-CPE realignment curated → advisory-only with shared `ADVISORY-FRAGATTACK`; 32 rows post-rebuild on qualcomm wcn3xxx blobs). Promotable to Rule-of-Two on KRACK/Dragonblood/BroadPwn audit. Companions: Rule #25 per-piece commits (advisory_id rename + WARN suppression opt-in deferred as separate commits), Rule #19 NVD-CPE verification.

0 commit comments

Comments
 (0)