Skip to content

0.9.0 — the first ten minutes: init sets up CI and a baseline, errors say what to type, redirects and sign-in walls, five more templates - #28

Merged
likeBloodMoon merged 5 commits into
masterfrom
claude/release-roadmap-0-8-0-v79592
Sep 24, 2026
Merged

likeBloodMoon merged 5 commits into
masterfrom
claude/release-roadmap-0-8-0-v79592

Conversation

@likeBloodMoon

@likeBloodMoon likeBloodMoon commented Sep 23, 2026 •

Copy link
Copy Markdown
Owner

The plan for 0.9.0 is in ROADMAP.md, and this PR carries it out. The version number is not bumped: like 0.8.0, it waits on the citation check below.

What's in it

init sets up the project, not just the config

  • After writing the config, it offers:
    • A baseline, when a built site is already there (it never runs a build). The config's audit.baseline points at it, so eaa-kit audit uses it without flags.
    • A GitHub Actions workflow at .github/workflows/accessibility.yml, when inside a git repo. It is written for the project:
      • package manager from the lockfile, with pnpm/bun setup steps;
      • the build script;
      • the build directory, or '' to let the action detect it;
      • working-directory in a monorepo;
      • the baseline, the current branch, and the action pinned to this release.
  • An existing workflow is never overwritten. --no-ci and --no-baseline turn the offers off. --yes takes the defaults (a workflow only in a repo, a baseline only when a build exists).

Errors say what to type next

  • Every exit-2 path a new user is likely to hit ends with a copyable command:
    error No config file found in /tmp or its parent directories
      → eaa-kit init  write one, filled in from what the site already states
    
  • Covered:
    • no config → eaa-kit init;
    • missing language → --lang with one the country has;
    • invalid --country → eaa-kit countries;
    • missing or outdated report, baseline or review record → the command that writes it;
    • mistyped flag → that command's --help;
    • existing config → init --force;
    • --watch --url → a directory watch.
  • Errors carry the fix as a next field (src/next.ts), so the message itself only says what went wrong. Unknown commands keep commander's own "did you mean".

Redirects and sign-in walls, found before the crawl (src/audit/entry.ts)

  • The entry URL is followed one hop at a time before anything is crawled. Credentials are only sent while the chain stays on the entry's origin.
  • Redirect to another site (e.g. www.gtainside.de → 301 → www.gtainside.com):
    • Previously every page failed as "redirected off" and the run ended on "Could not fetch".
    • Now the new --redirects ask|follow|stop decides:
      • ask (default) prompts in a terminal and stops when nobody is there to ask (CI);
      • follow goes on;
      • stop never does.
    • Stopping names both ways on: audit the destination, or --redirects follow.
    • A same-site redirect (www., http→https) is followed without a question. The destination must pass the same --allow-remote gate.
  • A followed redirect is in every report:
    • console: both addresses above the counts;
    • HTML: a Redirected row;
    • JSON: completeness.entryRedirect;
    • SARIF: an entryRedirect run property.
  • It can also be set with the redirects config key and the redirects Action input.
  • Sign-in walls stop the run (exit 2) instead of the login form being audited as the site.
    • Caught from a 401/403, a redirect to an identity provider (Google, Microsoft, Okta, Auth0, Cognito…), a sign-in path, or a page with a password field.
    • The message names the credentials flag to use, and says so when credentials were sent but not accepted.
    • The weaker during-crawl signal (many pages landing on one address) is now called a sign-in page when that page has a password field, and "looks like one" otherwise.

Five more templates

  • be.de (Belgium in German).
  • cz.cs/en: zákon č. 424/2023 Sb.; ČOI.
  • dk.da/en: lov nr. 801 af 7. juni 2022; Sikkerhedsstyrelsen, supervision split.
  • fi.fi/en: 306/2019 as amended; Traficom.
  • se.sv/en: lag (2023:254); PTS.
  • Fifteen countries, 31 templates. cs/da/fi/sv are new --lang values, and init maps sv/da/cs to their countries.

⚠️ Release blocker: citations from secondary sources

As agreed, the five new templates were written from secondary sources (regulators' pages, government portals, law firms). The official gazettes are still unreachable from this environment. They're marked unverified in the registry, in eaa-kit countries and in the docs, and cite no article numbers or fines.

Before tagging, check against the primary text:

  • CZ: 424/2023 Sb. and ČOI as supervisor.
  • DK: lov nr. 801 af 7/6/2022; Sikkerhedsstyrelsen for e-commerce; Finanstilsynet for financial services.
  • FI: that e-commerce accessibility sits in 306/2019 as amended; Traficom as supervisor.
  • SE: SFS 2023:254; PTS for e-commerce.
  • BE (de): German names for the law and FÖD Wirtschaft / Generaldirektion Wirtschaftsinspektion.

The 0.8.0 four (BE, IE, PL, PT) still need the same check. The Czech, Danish, Finnish and Swedish texts are my own writing; a native-speaker review is worth it.

Testing

  • pnpm lint, pnpm typecheck: clean.
  • pnpm test, with and without FORCE_COLOR=1 (CI forces colour): 1403 passed. The only failure is tests/audit/runners/playwright.test.ts: this environment's Chromium doesn't match the pinned Playwright. It fails identically on master, and CI's Chromium is fine.
  • pnpm smoke: green. pnpm examples: no drift. test:packaged: only the same 3 Chromium checks fail.
  • New tests:
    • tests/cli/next.test.ts: each error path's next step.
    • tests/cli/setup.test.ts: the workflow generator and init's new steps.
    • tests/cli/redirects.test.ts (14 tests):
      • cross-site redirect stops / asks / follows on yes / follows under --redirects follow;
      • local→remote refused;
      • same-site followed and recorded; stop refuses it;
      • four kinds of sign-in wall;
      • credentials not sent off-origin;
      • all four report formats record the redirect;
      • collapsed pages on a password page.
    • Snapshots for all five new templates, plus authority, review-sentence and split-supervision tests.
  • By hand, with the built CLI against local servers:
    • A cross-origin 301 stops with both next steps, and --redirects follow audits the destination and prints it above the counts.
    • A 401 stops with the --basic-auth next step.
    • init --yes in a scratch git repo wrote the baseline, the config and a tailored workflow.

🤖 Generated with Claude Code

https://claude.ai/code/session_013BXnvSeRtgZoTXe4j753gM

Every exit-2 path a new user is likely to meet now ends with the command
that fixes it, on a line of its own under the message:

  error No config file found in /tmp or its parent directories
    → eaa-kit init  write one, filled in from what the site already states

No config points at init; a statement in a language the country does not
have points at --lang with one it does; an unknown country at `eaa-kit
countries`; a missing or outdated report, baseline or review record at the
command that writes one; a mistyped flag at that command's --help; an
existing config at init --force; --watch with --url at a watch of the
build directory.

The errors carry it as `next` (src/next.ts), rather than folding it into
the message, so the message still says only what went wrong and the command
can be copied as it is. Where the fix is an edit rather than a command, an
invalid config field, there is no next step: the issues already name the
field. An unknown command gets none either, because commander already
suggests the nearest one.

Also writes the plan for 0.9.0 into ROADMAP.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BXnvSeRtgZoTXe4j753gM
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BXnvSeRtgZoTXe4j753gM
…nfig

A config is one of three things a project needs before the tool is doing
its job. After writing it, init now offers the other two:

- A baseline, when there is a built site to record it from (init never
  runs a build to get one). The config's audit block points at it, so a
  local `eaa-kit audit` reads it without being told.
- A GitHub Actions workflow at .github/workflows/accessibility.yml, when
  the project is in a git repository. It is written for the project: the
  package manager from the lockfile (with pnpm's and bun's setup steps),
  the build script, the build directory init found or '' to let the action
  work it out, working-directory for a package below the repository root,
  the baseline, the branch HEAD is on, and the action pinned to this exact
  release.

An existing workflow is never overwritten, --no-ci and --no-baseline keep
init from offering either, and --yes takes the defaults: a workflow only
inside a repository, a baseline only when a build is already there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BXnvSeRtgZoTXe4j753gM
Five more statement templates, each written under its own country's law:
be.de, cz.cs/en, dk.da/en, fi.fi/en, se.sv/en. cs, da, fi and sv are new
--lang values; fifteen countries and thirty-one templates in all.

- CZ: zákon č. 424/2023 Sb.; Česká obchodní inspekce.
- DK: lov nr. 801 af 7. juni 2022; Sikkerhedsstyrelsen for e-commerce,
  and the template says supervision is split.
- FI: laki digitaalisten palvelujen tarjoamisesta (306/2019) as amended;
  Traficom.
- SE: lag (2023:254); Post- och telestyrelsen.
- BE in German: the 0.8.0 citations, FÖD Wirtschaft, split supervision.

As agreed, these come from secondary sources, because the gazettes are
still unreachable from here. They are marked unverified in the registry,
in `eaa-kit countries` and in the docs, and cite no article numbers and
no fines. Finland has no Swedish rendering yet.

init's language-to-country lookup now reads sv, da and cs, which are not
spelled like their countries: a language only one listed country is
written in stands for it, English excepted.

The review-record test now reads its fix from the error's next step, as the
baseline one does, and the docs, README, package description and changelog
say fifteen countries and describe init's new steps and the next-step lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BXnvSeRtgZoTXe4j753gM
Two things put a crawl somewhere other than where it was sent. The entry
URL is now followed one hop at a time before anything is crawled, with
credentials sent only while the chain stays on the entry's origin, and
the run decides what to do with what it finds.

A redirect to another site -- www.gtainside.de answering 301 to
www.gtainside.com -- used to fail every page as "redirected off" and end
on "Could not fetch". It now stops before crawling, says where the site
went, and names the two commands that go on: audit the destination, or
pass the new --redirects follow. --redirects ask, the default, asks at the
terminal and stops when there is nobody to ask; stop never goes on. A
redirect within the same site (www., http to https) is followed without a
question. The destination passes the same --allow-remote gate as the
entry. A followed redirect is recorded in every report: console lines
above the counts, a Redirected row in HTML, completeness.entryRedirect in
JSON and an entryRedirect run property in SARIF. There is a redirects
config key and a redirects input on the Action.

A sign-in wall is caught from what the site says: 401, 403, a redirect to
an identity provider, to a sign-in path, or to a page with a password
field. The run exits 2 with the credentials flag to use, instead of
auditing the login form as the site. Pages that all land on one address
during a crawl are called a sign-in page when that page has a password
field, and "looks like one" otherwise.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013BXnvSeRtgZoTXe4j753gM
@likeBloodMoon likeBloodMoon changed the title 0.9.0 — the first ten minutes: init sets up CI and a baseline, errors say what to type, five more templates 0.9.0 — the first ten minutes: init sets up CI and a baseline, errors say what to type, redirects and sign-in walls, five more templates Sep 23, 2026

Copy link
Copy Markdown
Owner Author

github-advanced-security is red on this PR, and the cause isn't in the diff. It fails inside GitHub's Copilot code-scanning service with CAPIError: 400 The requested model is not supported, before it reads any code. It was the same on every commit of #27, and GitHub refuses a re-run of it (403). Nothing in this repository can fix it: it needs a fix on GitHub's side, or a change to the code-scanning setup in the repo's security settings.

The check matrix is what tests this PR. It was green on the previous head (f668b58), and I'm watching it on the current one.


Generated by Claude Code

@likeBloodMoon
likeBloodMoon marked this pull request as ready for review September 24, 2026 11:03
@likeBloodMoon
likeBloodMoon merged commit ca7e535 into master Sep 24, 2026
5 of 6 checks passed
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants