DOM-IDEN-006: Canonical Context Resolution
| Reference Number | Version | Effective Date | Supersedes | Authority Level |
|---|---|---|---|---|
| DOM-IDEN-006 | 1.3 | 2026-07-10 | 1.2 | Constitutional |
I. Purpose
This document defines the Canonical Context Resolution within Classroom Token Hub. It governs how the system determines the active class context for a given user, ensuring that all actions are performed within the correct classroom boundaries. It also defines how missing or malformed context is handled.
II. Scope
This document applies to all code that requires authenticated runtime context. All business logic and page-load requests MUST validate and resolve a canonical class context before performing class-scoped reads or writes. It serves as the authoritative reference for this critical cross-cutting capability.
This document is about how the backend constructs the canonicalContext object and how the program consumes the object. It does not govern user account lifecycle, authentication, or identity display aliases.
III. Authority Level
Tier 1 - Constitutional. This document defines the sole valid method for constructing canonicalContext objects and when those objects are constructed and consumed. All other documents that reference canonicalContext objects MUST defer to this document. It is subordinate to INV-CORE-000, INV-CORE-001, and INV-ARC-008.
IV. Dependencies
INV-CORE-000_CORE_INVARIANTS.mdINV-CORE-001_CAPABILITY_BASED_ARCHITECTURE_AND_AUTHORITY_MODEL.mdINV-ARC-008_IDENTITY_RESOLUTION_AND_SEAT_SCOPE.md
V. Schema Authority Declaration
Canonical Context Resolution SHALL NOT own or mutate any table. Its scope is limited to how canonicalContext objects are constructed and consumed.
VI. Owned Tables
Canonical Context Resolution is prohibited from owning any table.
VII. Canonical Context Object
A canonicalContext object is the sole runtime authority for authenticated class-scoped execution. Downstream code MUST either receive a valid canonicalContext object or fail closed immediately.
A valid canonicalContext object MUST contain:
user_id: the authenticatedusers.idprincipal.class_id: the activeclasses.class_iduniverse.seat_id: the activeseats.idactor within the active class universe.actor_role: the resolved authority role for the selected seat in the selected class.
canonicalContext is request-scoped. It SHALL be constructed once at the authenticated request boundary and then passed downward to business logic, route helpers, services, and policy checks.
No downstream code may reconstruct, infer, mutate, or re-resolve canonicalContext.
VIII. Resolution Algorithm
The backend SHALL construct canonicalContext using the following algorithm and no other algorithm.
- Read the authenticated
user_idfrom the authenticated user session. - Read
last_active_class_idfor the authenticated user. - If
last_active_class_idis missing, route the user to the class-selection screen. No class-scoped business logic may run. - Use
last_active_class_idas the candidateclass_id. - Scope all seat resolution to the candidate
class_id. - Read
last_active_seat_idfor the authenticated user. - If
last_active_seat_idis missing, queryseatswithin the candidateclass_idwhereseats.user_id == users.id. - If no matching seat exists, fail closed.
- If exactly one matching seat exists, use that seat as the candidate
seat_id. - If more than one matching seat exists within the same class scope, fail closed unless an authoritative class-selection or seat-selection boundary resolves the ambiguity.
- If
last_active_seat_idis present, verify that the referenced seat belongs to the candidateclass_id. - If the referenced seat is outside the candidate
class_id, fail closed. - Verify that the selected seat’s
user_idequals the authenticatedusers.id. - If the selected seat’s
user_iddoes not equal the authenticatedusers.id, fail closed. - Read the actor role from the selected seat and class-scoped authority rules.
- Construct the
canonicalContextobject containinguser_id,class_id,seat_id, andactor_role. - Attach the constructed
canonicalContextto the request boundary for downstream consumption.
The resolver SHALL NOT use join_code as runtime authority. join_code may only be used at explicit boundary-ingress workflows that resolve a class before authenticated class-scoped runtime begins.
IX. Boundary Rules
canonicalContext resolution is a boundary concern.
The system SHALL:
- construct
canonicalContextexactly once per authenticated request; - construct
canonicalContextonly through the canonical context resolver; - fail closed when class, seat, user, or role validation fails;
- treat missing active class context as a class-selection requirement, not as authorization to guess or infer context;
- treat missing or mismatched seat context as an authorization failure unless an explicit selection boundary resolves it.
The system SHALL NOT:
- construct identity from downstream route logic;
- re-resolve context inside helper functions;
- derive runtime authority from
join_code; - derive runtime authority from URL parameters;
- derive runtime authority from request payload fields;
- derive runtime authority from legacy identity tables;
- trust
last_active_seat_idwithout checking that it belongs tolast_active_class_id; - trust
last_active_seat_idwithout checking that the seat belongs to the authenticateduser_id.
X. Consumption Rules
All class-scoped business logic SHALL consume canonicalContext as an explicit input.
Helpers, services, and policy checks that require class-scoped authority SHALL accept canonicalContext or the specific fields derived from it. They SHALL NOT call the canonical context resolver themselves, and they SHALL NOT resolve class scope from globals after the authenticated request boundary.
A function below the request boundary that needs class context MUST receive one of the following from its caller:
- the full
canonicalContextobject; or - an explicit
class_id,seat_id, anduser_idderived fromcanonicalContext.
No function below the request boundary may perform independent session reads to determine class, seat, user, or role authority.
XI. Failure Semantics
Canonical context resolution MUST fail closed.
The resolver SHALL NOT silently repair, infer, or switch context when validation fails.
The following conditions MUST fail closed:
- authenticated
user_idis missing; last_active_class_idreferences a deleted or inaccessible class;last_active_seat_idreferences a deleted seat;last_active_seat_idreferences a seat outsidelast_active_class_id;last_active_seat_idreferences a seat whoseuser_iddoes not match the authenticatedusers.id;- no seat exists for the authenticated user in the selected class;
- multiple candidate seats exist and no explicit boundary selection resolves the ambiguity;
- actor role cannot be resolved.
Missing last_active_class_id is not a failure condition by itself. It requires routing to class selection before class-scoped runtime proceeds.
XII. Explicit Prohibitions
The following patterns are prohibited in authenticated runtime code:
- helper-level calls to the canonical context resolver;
- direct session reads for class, seat, or role authority below the request boundary;
- runtime authorization using
join_code; - runtime authorization using legacy identifiers such as
admin_id,student_id, orsysadmin_id; - runtime identity construction from legacy tables;
- alternate constructors for
canonicalContext; - compatibility bridges that reconstruct context from non-canonical state.
XIII. Relationship to Identity Lifecycle
This document governs runtime context resolution only.
It does not govern roster provisioning, account claim, credential setup, account recovery, identity display, or class binding lifecycle. Those workflows are governed by the Identity domain documents.
Identity lifecycle documents may define how last_active_class_id and last_active_seat_id are initialized or updated. However, once an authenticated request begins, this document is the sole authority for resolving and validating runtime class context.
XIV. Amendment
Revisions to this document must:
- Increment the version number.
- Update the Effective Date.
- Maintain consistency with
INV-CORE-000andINV-CORE-001. - Maintain consistency with
INV-ARC-008for identity resolution and seat scope. - Preserve the rule that
canonicalContextis resolved exactly once at the authenticated request boundary and consumed downstream without re-resolution.
Last updated: 2026-07-11