Files
meshcore-analyzer/package.json
T
Kpa-clawbot d954ea7444 feat(#1668): axe-core CI gate for WCAG AA color-contrast (M5) (#1696)
Partial fix for #1668 (M5 of 6).

After M1 (audit), M2 (color tokens, #1676), M3 (typography floor,
#1679), and M4 (per-route polish, #1681) cleared ~95% of
contrast/typography violations, M5 **locks in the wins** by adding an
axe-core CI gate that fails the build on any new WCAG AA color-contrast
regression.

## What's in the box

- `test-a11y-axe-1668.js` — Playwright + `@axe-core/playwright`. Runs
every major CoreScope route × `{dark, light}` at 1200×900 desktop,
injects axe, runs only the `color-contrast` rule, asserts net violations
=== 0.
- `test-a11y-axe-1668-selftest.js` — fast, deterministic, browser-free
unit test that exercises the YAML allowlist parser, the
`violationAllowed` matcher, and the route/theme metadata. Runs in the JS
unit block (no browser needed).
- `tests/a11y-allowlist.yaml` — operator-flagged false-positive
allowlist. **0 entries at M5 baseline.**

## Allowlist format

Each entry MUST cite a GH issue # and an `expires_at` date. Missing
fields = refused. Expired `expires_at` = refused (warning logged). This
**forces a periodic revisit** — no permanent suppressions.

```yaml
- route: /analytics?tab=channels
  selector: ".some-known-stale-element"
  rule: color-contrast
  issue: 1234
  expires_at: 2026-09-01
```

## Routes covered (19 × 2 themes = 38 cells)

`/`, `/packets`, `/nodes`, `/channels`, `/live`, `/map`, `/observers`,
`/compare`,
`/analytics?tab={overview,rf,topology,channels,hashsizes,collisions,roles,airtime}`,
`/audio-lab`, `/customize`, `/replay`.

## TDD red→green

- **RED** (`08adafdb`) — adds the gate + deliberately regresses
`--text-muted` from `palette-gray-700` (~10:1) to `#9ca3af` (~2.4:1).
axe-core fails on every light-theme cell.
- **GREEN** (`f62fb1e0`) — restores the M2 token. Net violations = 0
across all 38 cells.

## Scope discipline

- Only `color-contrast` (matches M2/M3/M4 scope). M6 owns `image-alt`,
`aria-required-attr`, `label`, mobile viewports, and letsmesh A/B.
- No new design tokens.
- M2-M4 tokens untouched.

## CI wiring

- `.github/workflows/deploy.yml:155` — selftest in JS unit block.
- `.github/workflows/deploy.yml:367` — real axe browser run in the
Playwright E2E block after the fixture server is up.

## Deps

`@axe-core/playwright@4.11.3` + `axe-core@4.12.1` added to
`devDependencies`. Pinned versions.

---------

Co-authored-by: openclaw-bot <bot@openclaw.local>
Co-authored-by: clawbot <clawbot@users.noreply.github.com>
2026-06-12 20:00:35 -07:00

30 lines
1000 B
JSON

{
"name": "meshcore-analyzer",
"version": "0.0.0-use-git-tags",
"description": "Community-run alternative to the closed-source `analyzer.letsmesh.net`. MQTT packet collection + open-source web analyzer for the Bay Area MeshCore mesh.",
"main": "index.js",
"scripts": {
"test": "npx c8 --reporter=text --reporter=text-summary sh test-all.sh",
"test:unit": "node test-packet-filter.js && node test-aging.js && node test-frontend-helpers.js",
"test:coverage": "npx c8 --reporter=text --reporter=html sh test-all.sh",
"test:full-coverage": "sh scripts/combined-coverage.sh"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@michaelhart/meshcore-decoder": "^0.2.7",
"better-sqlite3": "^12.8.0",
"express": "^5.2.1",
"mqtt": "^5.15.0",
"ws": "^8.19.0"
},
"devDependencies": {
"@axe-core/playwright": "^4.11.3",
"axe-core": "^4.12.1",
"nyc": "^18.0.0",
"playwright": "^1.58.2",
"supertest": "^7.2.2"
}
}