fix(auth): re-enable real GET /v1/auth/memberships call (MAPPS-379) #441

Merged
nrupard merged 1 commit from fix/mapps-379-memberships into main 2026-07-24 17:52:53 +02:00
Owner

What

Re-enable the real GET /v1/auth/memberships call in use_memberships_loader so AuthContext reflects the user's actual bunyip memberships, replacing the locally synthesized single membership (MAPPS-379).

Why

The synthetic membership was introduced because bunyip's AuthenticatedUser extractor only validated legacy HS256 access tokens, so the SPA's EdDSA at+jwt 401'd. BUNYIP-55 removed that blocker: the extractor now routes typ == "at+jwt" tokens to the OidcProvider verifier (signature + iss + exp + typ, with validate_aud = false), so the SPA's Mokosh-audience at+jwt is accepted at bunyip's /v1/* endpoints. The inline comment claiming bunyip rejects the EdDSA at+jwt was therefore stale, and the MembershipView deserialize struct was dead code.

Changes

  • src/hooks/auth.rs: use_memberships_loader now calls issuer_get_authed::<Body>(&cfg, "/v1/auth/memberships") and, on a non-empty response, stores the deserialized MembershipView rows and adopts the response's active_tenant_id.
  • Added a graceful fallback: on error or an empty response it seeds the synthetic single membership, extracted into a private synthesize_single_membership helper. This keeps the switcher UI working (correct today under single-tenant-per-user, PMS-447) and prevents the effect from re-firing forever on a persistently empty membership list.
  • Replaced the stale doc comment (which claimed bunyip rejects the EdDSA at+jwt with a 401) with the accurate BUNYIP-55 rationale.

Tests

  • just pre-commit in the CI-matching rust-builder-glibc image: cargo fmt --all --check, cargo clippy --all-targets -- -D warnings, cargo check --target wasm32-unknown-unknown, and cargo test --lib all pass (see PR checks for the recorded run).
  • Runtime verification against a live bunyip is pending: this cannot be exercised end to end here, only compile/lint/build/test. The BUNYIP-55 acceptance path and the response deserialization still need a live check against bunyip's /v1/auth/memberships.
## What Re-enable the real `GET /v1/auth/memberships` call in `use_memberships_loader` so AuthContext reflects the user's actual bunyip memberships, replacing the locally synthesized single membership (MAPPS-379). ## Why The synthetic membership was introduced because bunyip's `AuthenticatedUser` extractor only validated legacy HS256 access tokens, so the SPA's EdDSA `at+jwt` 401'd. BUNYIP-55 removed that blocker: the extractor now routes `typ == "at+jwt"` tokens to the OidcProvider verifier (signature + `iss` + `exp` + `typ`, with `validate_aud = false`), so the SPA's Mokosh-audience `at+jwt` is accepted at bunyip's `/v1/*` endpoints. The inline comment claiming bunyip rejects the EdDSA `at+jwt` was therefore stale, and the `MembershipView` deserialize struct was dead code. ## Changes - `src/hooks/auth.rs`: `use_memberships_loader` now calls `issuer_get_authed::<Body>(&cfg, "/v1/auth/memberships")` and, on a non-empty response, stores the deserialized `MembershipView` rows and adopts the response's `active_tenant_id`. - Added a graceful fallback: on error or an empty response it seeds the synthetic single membership, extracted into a private `synthesize_single_membership` helper. This keeps the switcher UI working (correct today under single-tenant-per-user, PMS-447) and prevents the effect from re-firing forever on a persistently empty membership list. - Replaced the stale doc comment (which claimed bunyip rejects the EdDSA `at+jwt` with a 401) with the accurate BUNYIP-55 rationale. ## Tests - `just pre-commit` in the CI-matching `rust-builder-glibc` image: `cargo fmt --all --check`, `cargo clippy --all-targets -- -D warnings`, `cargo check --target wasm32-unknown-unknown`, and `cargo test --lib` all pass (see PR checks for the recorded run). - Runtime verification against a live bunyip is pending: this cannot be exercised end to end here, only compile/lint/build/test. The BUNYIP-55 acceptance path and the response deserialization still need a live check against bunyip's `/v1/auth/memberships`.
fix(auth): re-enable real GET /v1/auth/memberships call
All checks were successful
Check / fmt + clippy + tests (pull_request) Successful in 13m4s
Create release / Create release from merged PR (pull_request) Has been skipped
134d2b5fed
BUNYIP-55 extended bunyip's AuthenticatedUser extractor to route typ == "at+jwt" tokens to the OidcProvider verifier (signature + iss + exp + typ, with validate_aud = false), so the SPA's Mokosh-audience EdDSA at+jwt is now accepted at bunyip's own /v1/* endpoints. The prior rationale that bunyip rejects the EdDSA at+jwt with a 401 is stale, and the MembershipView deserialize struct was dead code.

use_memberships_loader now issues the real GET /v1/auth/memberships via issuer_get_authed and uses the deserialized MembershipView rows plus the response's active_tenant_id. When the call errors or returns no rows it falls back to a synthetic single membership (extracted into synthesize_single_membership), which is correct today given single-tenant-per-user (PMS-447) and also stops the effect re-firing on a persistently empty list.

Runtime verification against a live bunyip is pending; verified via cargo fmt, clippy -D warnings, the wasm32 build, and cargo test --lib.

#MAPPS-379

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nrupard deleted branch fix/mapps-379-memberships 2026-07-24 17:52:53 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-apps!441
No description provided.