test(security): access-control regression gate for the dioxus example
#8 in tonybierman/arium — merged 2026-05-25
What
Commits the inventory-driven access-control probe and wires it into CI as a blocking gate, so a future refactor that silently un-gates an endpoint turns the build red. This is the durable artifact behind the access-control review we did against dioxus-fullstack-example.
The probe — examples/dioxus-fullstack-example/access-control-probe.sh
Generated from the live route_map / openapi_spec / project_index inventory (not guessed), it checks three axes against a running instance:
| Phase | Property |
|---|---|
| 1 | Every protected endpoint denies an anonymous caller; public endpoints stay reachable (catches inventory drift); anon-tolerant endpoints (profile, logout, mfa-status) return a benign default, never real state. |
| 2 | Every /api/admin/* refuses a logged-in non-admin — vertical privilege escalation. |
| 3 | One user cannot reach another's object by id — horizontal / IDOR: B cannot revoke A's API token, with a control that proves the id was real. |
Design notes baked in from the investigation:
- Tolerates Dioxus-fullstack's wire-
500-on-ServerFnErrorconvention by asserting "denied" via the body marker, and distinguishes a confirmed auth-gate hit from a weaker non-2xx. - Rides the
tower_governorrate limiter (burst 30 / 1·s⁻¹) with 429-aware retries so every request actually reaches its gate.
Verified locally end-to-end: 38/38 PASS against a running instance, including Phase 2 (all 9 admin endpoints refuse a non-admin) and Phase 3 (IDOR isolation holds).
CI — access-control job in ci.yml
- Builds the example server-only (
--no-default-features --features server) to skip the web/wasm devtools stack — the reason thetestjob excludes this example. - Boots it headless. Two non-obvious bits discovered while wiring this: the server bind reads plain
IP/PORT(notDIOXUS_DEVSERVER_PORT), and dioxus-server needs a<bin>/publicdir that a rawcargo build(unlikedx build) doesn't create — an empty dir satisfies it. - Waits for readiness, runs the probe with a seeded non-admin, dumps the server log on failure.
This PR is intentionally the validation vehicle: watch the new access-control job go green here before merging, since it can't be exercised on GitHub runners until it runs.
Not included
ffuf-discover.sh (ad-hoc recon helper) is left untracked — this PR is scoped to the regression gate.
🤖 Generated with Claude Code
Last updated 2026-05-26
Links to this note
Merged pull requests, newest first.