Lewati ke isi

T0-A1 Active-Role Session / Concurrency Decision

Item Value
Mode Server development
Workspace /home/scola/odoo
Status CLOSED for V1 architecture — DEC-002 approved: session-scoped active role
Related STAB-007, AUTH-001, DEC-002

Decision (approved)

B — Session-scoped acting role is the Scola V1 authorization architecture.

Implemented in T0-B1 via scola_core/services/session_active_role.py (scola_active_role on Odoo HTTP session). res.users.scola_role is preferred/default for new sessions only.

Current behavior

  • Acting role is stored on res.users.scola_role (user-global field).
  • action_switch_active_scola_role validates assignment/authority groups, then write({'scola_role': role_code}).
  • compute_permissions (post T0-A) derives capabilities from active role only, not group-union.
  • HTTP session cookie does not own a separate acting-role slot; every request re-reads the user record.

Scenario analysis

Scenario Observed / reasoned behavior
Two tabs, same browser session Share cookie → same DB user. Last successful switch wins for both tabs. Tab A can suddenly lose capabilities mid-flight after Tab B switches.
Two independent browser sessions (same login) Still same res.users row. Switch in session 1 updates global acting role for session 2.
Desktop + mobile Same as independent sessions — last write wins globally.
Role switch during in-progress mutation Next request after write uses new role. In-flight JSON call already past gate may complete under old snapshot; subsequent calls use new role. No request-scoped freeze.
Stale frontend permissions FE holds permission list until refresh/switch payload. Backend is authoritative; stale FE UX can show buttons that API will 403.
Logout / login Logout clears session; login rebuilds payload from current scola_role. Global field persists across sessions until switched again.
Concurrent switch requests Last committed write wins; no optimistic concurrency / etag on scola_role.

Options

A. User-global acting role (current)

  • Security: Simple single source of truth; hard to “forget” a privileged persona on one device while another retains it — but also means privilege changes are instantly cross-device.
  • UX: Surprising across tabs/devices (last-write-wins).
  • Audit: Acting role at request time equals user field; attribution clear if sampled per request.
  • Complexity: Lowest.
  • Revocation: Changing role revokes previous persona everywhere immediately.
  • Testability: Easy unit tests; concurrency tests must assert global last-write.

B. Session-scoped acting role

  • Store acting role on server session (or signed session claim), not (only) on res.users.
  • Security: Better isolation between devices; must define which field remains for defaults/provisioning.
  • UX: Predictable per tab/session family; multi-device can diverge intentionally.
  • Audit: Must log session id + acting role; user field alone insufficient.
  • Complexity: Medium–high (session store, migration, FE refresh contract, revoke-all-sessions).
  • Revocation: Need explicit session kill / role-invalidate broadcast.
  • Testability: Requires multi-session fixtures in T0-B.

C. Other server-owned context

  • e.g. short-lived acting-role token / request header bound to session id with server validation.
  • Highest flexibility; highest implementation and abuse surface unless tightly designed.

Recommendation

Recommend B (session-scoped acting role) as the long-term security/UX target for multi-device schools.

For T0-A.1 / immediate T0-B entry: do not silently change semantics. Keep A (user-global) as the documented interim contract until Product + Security approve DEC-002 / this record.

Rationale for interim A:

  • Matches shipped code and T0-A unit evidence.
  • Changing to B mid-certification would invalidate prior tests and require session redesign out of T0-A.1 scope.

Decision status

Field Value
Chosen interim for code (T0-A.1) A — user-global acting role (historical)
Approved / implemented (T0-B1) B — session-scoped acting role
Product/Security sign-off DEC-002 APPROVED
Silent semantic change in T0-A.1 No (correct)
Semantic change in T0-B1 Yes — intentional per DEC-002

Migration impact (if B approved later)

  1. Introduce session key scola_active_role (name TBD) set on login + switch.
  2. compute_permissions / gates read session role with fallback to user default.
  3. Decide whether res.users.scola_role remains “last preferred” only.
  4. FE: treat permissions as session-bound; refresh on focus if conflict detected.
  5. Audit: persist session id + acting role on sensitive denials/mutations.
  6. Revocation: logout clears session role; admin kill-sessions clears all.

Required T0-B tests (entry gate)

Until DEC is closed, T0-B must explicitly test interim A and mark B as future:

  1. Two tabs same session: switch in tab B → tab A API uses new role (document expected).
  2. Two independent sessions: switch in one → other observes new role (A) or isolation (B once implemented).
  3. Switch mid mutation: completed call vs follow-up call authority.
  4. Stale FE: UI capability cache vs API 403 after switch.
  5. Logout/login restores documented default/active role.
  6. Concurrent switch: last-write-wins + audit both attempts.
  7. Forged role / unauthorized switch still denied (STAB-007).

T0-B must not assume session isolation until B is implemented and this decision is CLOSED.