feat(examples): per-resource membership authz examples (Dioxus + Leptos)

feat(examples): per-resource membership authz examples (Dioxus + Leptos)

#15 in tonybierman/arium — merged 2026-05-27

What

Two minimal, parallel examples demonstrating arium's per-resource membership authorization axis — kept apart from everything else (no OAuth/MFA/mail/tokens) so the membership story stands alone:

  • examples/dioxus-authz-example
  • examples/leptos-authz-example

Each shows the same three pieces:

  1. DemoAuthority — an in-memory ResourceAuthority (role per doc id, registered via AuthConfigBuilder::resource_authority). arium stores no memberships; it calls this on every check.
  2. ResourceGate — a cosmetic UI gate that shows/hides the rename field.
  3. rename_doc — the resource-scoped mutation, enforced by require_resource_{dioxus,leptos} (the real boundary). An "Attempt edit anyway" button on the view-only docs proves the server rejects it, gate or no gate.
Document Role Field shown? Server fn (require ≥ Editor)
Team roadmap Owner shown accepted
Design notes Editor shown accepted
Company handbook Viewer hidden rejected
Q3 board minutes (none) hidden rejected

Bug fix surfaced by these examples

These are the first server/ssr builds without mail, which exposed a latent bug in both adapters: the no-mail register_with_password returned LoginOutcome::LoggedIn but never called complete_login/mark_email_verified — so signup left the caller anonymous and a later sign-in failed as Unverified (UI: "Unexpected sign-in outcome"). Fixed in both arium-dioxus and arium-leptos.

Supporting test/infra changes:

  • Added a round-trip assertion that register itself establishes the session (the harness previously only checked a separate login did).
  • Made each tests/common/spawn_app mail-agnostic so the round-trip runs under --no-default-features (verified the fix on the no-mail path; proved the assertion catches the regression by reverting complete_login).
  • Retightened the dead skip_email_verification gate to all(server/ssr, mail).
  • Hardened the harness temp-DB suffix with a monotonic counter (was pid+nanos, collided under parallel tests → spurious "duplicate column" migration errors).

CI note

The no-mail examples can't be unified into one workspace build alongside the mail-on fullstack examples (AuthConfig::builder arity differs by feature), so they're --excluded from the workspace cargo test/doc/clippy commands and built in isolation — same treatment as the existing dioxus fullstack example.

Verification

  • Both examples build: server/SSR + wasm/hydrate; clippy clean.
  • arium-{dioxus,leptos} clippy clean in both mail-on and no-mail configs.
  • Full default test suites green (round-trip + access_control); no-mail round-trips green.
  • cargo-machete clean.

🤖 Generated with Claude Code

Last updated 2026-05-28