feat: upgrade to Astro 7; harden the content schema; wire a11y linting
Amends D1 to pin the major explicitly (v7.x) rather than inherit it. The ^5.0.0 pin was recalled rather than checked and was two majors stale the day it was written, which meant shipping a framework carrying high-severity XSS advisories. CLAUDE.md now requires every version pin to be verified against the registry, and R11 requires re-checking at each build-order boundary. npm audit now reports 0 vulnerabilities, down from 16. Every Astro advisory is cleared; the residual 10 all traced to @lhci/cli, which is removed — it was the sole source of 7 high-severity findings, 0.15.1 is latest so there was no clean upgrade, and it cannot run without pages or a lighthouserc. Re-added at build step 7 with a freshly verified pin. Content collections migrated to the Content Layer API: src/content.config.ts, loader: glob(), z from astro/zod. Two review passes found seven defects in the fix itself, all now closed: - z.coerce.date() read an unquoted 20260801 as epoch milliseconds and yielded 1970-01-01 silently; the first replacement then accepted 2026-13-45 as an Invalid Date and rolled 2026-02-30 over to 2026-03-02. Dates are now anchored, date-only, parsed as UTC and round-tripped. - The title bound applied the SEO spec's 50-60 to the headline rather than the rendered <title>, which guaranteed 68-78 on every article and rejected all five planned launch headlines. Articles are now the documented exception: the headline is the <title>, no suffix. - An article could ship an image with no alt text, or whitespace-only alt. - Two schema comments asserted controls nothing enforced; both are now real refinements, each tested with a failing and a passing case. - PRACTICE_SLUGS and PRACTICE_AREAS could drift silently; a compile-time check now catches both directions. - eslint.config.js imported globals and @eslint/js undeclared, resolving by hoisting accident. - scripts/deploy-local.sh claimed parity with CI while skipping npm run check and two credential guards — on the only path this site can ship today. Accessibility linting is on (36 jsx-a11y rules) before step 1 writes the layout. An earlier claim in §7 that none was possible was wrong twice, and is corrected in AGENTS.md entry (t) along with the reasoning. Opens Q30 and Q31 for two unregistered claims in src/data/site.ts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012XquaEq4BgWMCwUqLEyNkF
This commit is contained in:
co-authored by
Claude Opus 5
parent
0d8b63380a
commit
7514a49803
@@ -106,7 +106,6 @@ npm run preview # serve ./dist locally
|
||||
npm run check # astro check — type and template errors
|
||||
npm run lint # eslint + prettier check
|
||||
npm run format # prettier — rewrite files in place
|
||||
npm run lighthouse # lighthouse CI — NOT YET WIRED, nothing to measure yet
|
||||
npm run deploy # build + deploy from this machine (see docs/06)
|
||||
```
|
||||
|
||||
@@ -122,20 +121,22 @@ docs/ the specs you build from
|
||||
05-backend-spec.md intake form, Lambda/DynamoDB/SES, booking, PIPEDA
|
||||
06-deployment.md S3/CloudFront, Gitea Actions, IAM, cutover checklist
|
||||
src/
|
||||
content.config.ts content collections — Content Layer API, NOT content/config.ts
|
||||
styles/tokens.css design tokens — the single source of colour and scale
|
||||
styles/global.css reset, base type, utilities
|
||||
layouts/ page shells
|
||||
components/ UI components
|
||||
pages/ routes (file-based)
|
||||
content/ content collections; Insights MDX lives here
|
||||
content/insights/ Insights MDX only; the config sits above, not in here
|
||||
data/site.ts site-wide constants, nav, contact details
|
||||
public/ static assets served as-is
|
||||
```
|
||||
|
||||
## Conventions
|
||||
|
||||
**Framework.** Astro, `output: 'static'`. Never introduce a server runtime
|
||||
without a Change Log entry recording why.
|
||||
**Framework.** Astro **7.x**, `output: 'static'` (D1 as amended). Never introduce
|
||||
a server runtime without a Change Log entry recording why. The major is pinned
|
||||
deliberately — check `npm view astro version` before changing it.
|
||||
|
||||
**JavaScript.** Default to zero. Reach for an Astro island only when a feature
|
||||
genuinely cannot be CSS or progressive HTML. If you add a `client:*` directive,
|
||||
@@ -163,6 +164,17 @@ page that collects legal inquiries.
|
||||
URL, Open Graph and Twitter card tags, and appropriate JSON-LD. See
|
||||
`docs/04-seo-spec.md`. A page without these is not finished.
|
||||
|
||||
**A version pin is verified against the registry, never recalled.** Before you
|
||||
write or change any dependency version, run `npm view <pkg> version` and pin
|
||||
against what it returns. One second of checking; a stale pin costs a migration.
|
||||
This rule exists because `astro: "^5.0.0"` was written from memory and was
|
||||
**two majors stale on the day it was written** — which meant shipping a
|
||||
framework carrying high-severity XSS advisories. The same check applies to
|
||||
every pin in `package.json`, not just the framework.
|
||||
|
||||
Re-check currency at each phase boundary in the build order (`AGENTS.md` R11),
|
||||
not only when something breaks.
|
||||
|
||||
**`AGENTS.md` §7 is the single source of truth for operational facts.** Resource
|
||||
IDs, regions, DNS records, credential state, service status — these live in §7
|
||||
and nowhere else. Specs in `docs/` **cite** §7; they do not restate it. Write
|
||||
|
||||
Reference in New Issue
Block a user