Skip to content

OneRoster milestone — starting brief (v1)

Status: implemented (2026-06-12/13) — the design and build live in oneroster-consumer-v1.md (CSV + REST-delta consumer) and oneroster-provider-v1.md (REST rostering provider, CSV export, gradebook + resource services, round-trip CI gate, deferred-items campaign). This file is the original starting brief, retained for provenance. Decisions this builds on: ADR-0012 (OneRoster is a projection, not the roster core), ADR-0013 (person-rooted identity), ADR-0014 (erasure is anonymization) Design groundwork: person-auth-decoupling-v1.md (implemented — the FK blocker named in ADR-0012’s consequences is resolved; persons can exist without auth)

This brief is the handoff into the design session. It records what is already in place, what the milestone must decide, and the commitments the ADRs have already made so the session starts from alignment rather than archaeology.

  • person is the identity root; identity_binding (provider / issuer / subject, effective window) is the only resolution path. OneRoster sourcedIds are bindings, never identities (ADR-0013).
  • Trigger v2 resolve-or-mint with claim stamping; no-fallback deny posture.
  • identity_merge_review — the receiving structure for correlation review (pending/merged/dismissed, cascade from either side, erasure-classified). It has no producers yet.
  • Issuer strings are environment-owned via public.identity_issuer() (docs/runbooks/identity-issuer.md).
  • Erasure registry CI gate: any new person-linked table fails CI until it declares its erasure class (packages/db/src/erasure-registry.ts).
  • The NRPS consumer pattern to mirror: lti_tool_platform / lti_tool_context_mapping / lti_tool_nrps_*_snapshot — retained source snapshots, explicit mapping tables, identity resolution through bindings.

Prerequisites inside this milestone (ordered)

Section titled “Prerequisites inside this milestone (ordered)”

Designed 2026-06-12: all three prerequisites are specified in identity-linking-v1.md — decisions settled there: person_contact_point as the evidence home, a pristine-guard rebind primitive shared by both linking paths, authenticated claim-token redemption, the evidence-class principle, and NRPS email-match alignment pulled into this milestone. Revised the same day: review structures split in two (merge review for signup paths, correlation review for consumer paths) — the SIS consumer inherits hold-and-correlate on ambiguity, not mint-and-merge. Implemented 2026-06-12 (validation and integration gates green); dev-database replay pending.

  1. Pre-provisioned linking paths (rows 3–4 of the decoupling doc’s linking table): claim-token resolve and verified-email-match resolve. Note the email-match path needs an email_confirmed_at UPDATE trigger — confirmation happens after the auth-user INSERT that trigger v2 sees. Hard rules carry over verbatim: never link on an unverified email; binding rows only from service-role paths; post-session linking requires token refresh.
  2. Person-side contact/roster evidence. Persons deliberately carry no email today; the consumer must decide where correlation evidence lives (roster snapshot tables vs. person profile fields) — this decision gates both the email-match path and merge-review producers.
  3. Merge-review producers: the email-match fall-through and SIS correlation review enqueue into identity_merge_review. The admin-console panel follows real queue traffic.

The milestone proper (ADR-0012 commitments)

Section titled “The milestone proper (ADR-0012 commitments)”

Consumer designed 2026-06-12: oneroster-consumer-v1.md — CSV-first shared ingest core, Course → Learning Container, academic sessions enter the core as Learning Period (junction to offerings), identity rules inherited from identity-linking-v1, demographics boundary-only, guardian links deferred. Provider + round-trip gate remain outlined there, designed after the consumer.

  • Consumer (SIS sync): NRPS-style retained snapshots + mapping tables; membership lifecycle mapping per docs/integration/roster-and-grade-exchange.md.
  • Provider (REST/CSV): projection over the neutral core, emitted only for school-shaped contexts; deterministic Course synthesized per Offering; conformance = service behavior (filtering, paging, dateLastModified deltas, stable sourcedIds).
  • Round-trip CI gate: school-context core data must survive emergent → OneRoster → emergent losslessly (mirrors the QTI gate, ADR-0001). This is the invariant ADR-0012 names; nothing exists yet.

Vocabulary checklist items (enter the core as need arrives, never as wire shapes)

Section titled “Vocabulary checklist items (enter the core as need arrives, never as wire shapes)”

Academic sessions (naming still open), guardian links (guardians are Persons — ADR-0013), course templates, org hierarchy, grade/subject vocabularies.

  • One-vocabulary rule: OneRoster terms (User, Org, Course, Class, Enrollment) appear only at the @conform-ed/contracts boundary — never in code, schema, or UI.
  • status: tobedeleted semantics stay at the boundary; they must not leak into pgxsinkit-synced tables’ lifecycle.
  • Zod contracts for OneRoster 1.2 already exist in @conform-ed/contracts.