Skip to content

ADR 0004: Student State Catalog Version and Migration Policy

ADR 0004: Student State Catalog Version and Migration Policy

Status: Accepted for architectural direction.

Date: 2026-05-11.

Context

UWScrape will allow students to save anonymous planning state.

Student state may include completed courses, grades, planned courses, academic progress, academic standing, declared credentials, and desired credentials.

The runtime index is tied to a Waterloo catalog version.

Course records and program requirements can change between catalog versions.

Students may follow different requirement terms.

The backend must not silently reinterpret a student record under a different catalog without telling the user.

The anonymous state system does not use email accounts.

The initial state access mechanism is a generated secret token.

The state store must remain separate from published index artifacts.

Decision

Every student state record must store its catalog_version_id.

Every completed course entry must store the course code provided by the user.

Every completed course entry should store the resolved CourseListing id when known.

Every planned course entry must store the course code provided by the user.

Every planned course entry should store the resolved CourseListing id when known.

Every declared or desired credential entry must store the credential id when known.

Every declared or desired credential entry should preserve user-entered display text when needed.

The backend must evaluate state against its own recorded catalog version when that index is available.

If the active backend index differs from the state catalog version, the backend must report a catalog mismatch.

The backend may offer a migration preview.

The backend must not silently overwrite the state catalog version.

The backend must not silently replace course or credential references.

Migration from one catalog version to another must be explicit.

The first migration mode should be advisory.

Advisory migration means the backend computes a proposed mapping and warnings.

The user chooses whether to accept the migrated state.

The original state should remain recoverable until migration is confirmed.

Migration Semantics

Migration should match courses by exact course code first.

Migration should then consider known cross-listing or former-number relationships.

Migration should preserve unresolved courses as user-entered records.

Migration should match credentials by source pid when stable.

Migration should match credentials by code when source pid changes.

Migration should match credentials by title only with low confidence.

Migration should flag removed courses.

Migration should flag changed units.

Migration should flag changed requisites.

Migration should flag changed credential requirements.

Migration should flag credentials that no longer exist.

Migration should flag course codes that now resolve ambiguously.

Migration should preserve grades exactly as entered.

Migration should preserve academic progress exactly as entered.

Migration should preserve academic standing exactly as entered.

Migration should preserve user notes and UI preferences when present.

Catalog Availability

The backend may initially load only one active index.

If a state record references an unavailable catalog version, the backend should still return the raw state.

If a state record references an unavailable catalog version, exact requirement evaluation should be unavailable.

The backend should return a clear catalog_unavailable status.

Later backends may load multiple catalog versions.

Multi-catalog loading should be a separate backend architecture decision.

Alternatives Considered

Alternative 1: Always Evaluate Against Latest Catalog

The backend could always use the current catalog.

This is simple.

However, it can produce misleading answers for students following older requirement terms.

It can also make saved states change meaning after a deploy.

This alternative is rejected.

Alternative 2: Clone State Per Catalog Automatically

The backend could automatically create a migrated copy whenever a new index appears.

This reduces user friction.

However, it risks hiding ambiguous mapping decisions.

It can multiply state records unexpectedly.

This alternative is rejected for the initial architecture.

Alternative 3: Refuse Old State

The backend could reject state from older catalogs.

This is safe but hostile.

Students need continuity across visits.

This alternative is rejected.

Consequences

Student state remains meaningful across index updates.

Backend query responses must include catalog mismatch information.

The state schema must include catalog version references from day one.

Migration tooling can be added later without corrupting early records.

The frontend must handle mismatch and migration-preview states.

The backend must preserve unresolved user-entered course data.

Follow-Up

Define the state database schema in backend architecture.

Define token hashing and access semantics separately.

Define migration preview API after backend/index contract.

Define catalog mismatch response shape in the query API spec.