Skip to content

ADR 0006: Backend and Index Contract

ADR 0006: Backend and Index Contract

Status: Accepted for architectural direction.

Date: 2026-05-11.

Context

The backend will not scrape live calendar data.

The backend will load a published runtime index.

The runtime index will initially be SQLite plus metadata files.

The backend will also store anonymous student state.

Student state must be stored outside the index artifact.

The backend must answer course lookup, credential lookup, graph, and solver-style query requests.

The frontend should not need to understand raw scraper outputs.

The backend should not need to understand raw snapshot directory internals.

The backend and index need a narrow, stable contract.

Decision

The backend consumes a published index directory.

The published index directory must contain course-universe.sqlite.

The published index directory must contain build-metadata.json.

The published index directory must contain validation-summary.json.

The published index directory must contain release-decision.json.

The published index directory must contain build-report.md.

The published index directory should contain release-decision.md when a human-readable release record is generated.

The published index directory may contain graph-projection.json.

The backend should receive the index directory path through configuration.

The backend should open the SQLite database read-only.

The backend should validate index metadata at startup.

The backend should validate supported index schema version at startup.

The backend should validate acceptable validation status at startup.

The backend should expose loaded index metadata through an API endpoint.

The backend should not read raw snapshot files during normal operation.

The backend should not read parsed JSONL files during normal operation.

The backend should not apply parser patches during normal operation.

The backend should not rebuild graph projections during normal operation unless a later performance decision allows it.

The backend should treat SQLite as the canonical runtime read model.

The backend may treat graph projection JSON as a cached projection.

The backend should never treat graph projection JSON as more authoritative than SQLite.

Required Runtime Index Capabilities

The index must support course lookup by course code.

The index must support course lookup by source pid.

The index must support course lookup by source item id.

The index must support credential lookup by source pid.

The index must support credential lookup by source item id.

The index must support credential lookup by code.

The index must support listing all catalog versions contained in the artifact.

The index must support retrieving requirement sources for a course.

The index must support retrieving requirement sources for a credential.

The index must support traversing requirement expressions.

The index must support retrieving requirement conditions.

The index must support retrieving unparsed requirements.

The index must support retrieving source references.

The index must support retrieving validation findings.

The index must support retrieving parser warning summaries.

The index must support graph projection loading or graph projection reconstruction.

The index must support subject and level filtering.

The index must support full-text or prefix search later.

Backend Responsibilities

The backend owns API shape.

The backend owns student state persistence.

The backend owns token-based anonymous access.

The backend owns query evaluation.

The backend owns source-reference lookup responses.

The backend owns catalog mismatch responses.

The backend owns request validation.

The backend owns rate limiting for state and query endpoints.

The backend owns runtime logging.

The backend owns health checks.

The backend owns index compatibility checks.

The backend does not own source scraping.

The backend does not own parser patching.

The backend does not own index publication.

The backend does not own visual layout truth.

Index Responsibilities

The index owns catalog facts.

The index owns parsed requirement structures.

The index owns unparsed requirement records.

The index owns source references.

The index owns validation summaries.

The index owns graph projection facts when included.

The index owns relationship tables derived at build time.

The index does not own student state.

The index does not own API authorization.

The index does not own active user sessions.

The index does not own runtime mutations.

Contract Boundary

The backend may depend on documented SQLite tables.

The backend may depend on documented metadata files.

The backend may depend on documented graph projection format.

The backend must not depend on scraper temporary files.

The backend must not depend on raw Kuali response layout.

The backend must not depend on parsed JSONL once the index is built.

The backend must not depend on manual patch file layout.

The backend must not know Kuali endpoint URLs for normal runtime.

The backend may expose source links from source references.

The backend may expose upstream catalog metadata.

The backend may expose build report links in admin or debug views.

Alternatives Considered

Alternative 1: Backend Reads Parsed JSONL Directly

The backend could load parsed JSONL files instead of SQLite.

This would simplify the first index builder.

However, it would move query indexing burden into backend startup.

It would make lookup performance and schema checks harder.

It would blur the line between intermediate and runtime artifacts.

This alternative is rejected for the main backend.

Alternative 2: Backend Reads Raw Snapshot and Parses at Startup

The backend could parse raw data at startup.

This would reduce artifact count.

However, it would make runtime startup slow and fragile.

It would mix parser failures with serving failures.

It would violate the offline pipeline decision.

This alternative is rejected.

Alternative 3: Frontend Loads Index Directly

The frontend could load graph JSON and perform all queries locally.

This could work for demos.

However, private state and exact query explanation are better centralized at the backend.

It would duplicate solver logic in the browser.

It would complicate migration and state persistence.

This alternative is rejected as the primary architecture.

Consequences

Backend architecture can focus on API, state, and query evaluation.

The index builder must produce a complete runtime read model.

Index schema versioning becomes mandatory.

The backend can start without network access to Waterloo or Kuali.

The backend can fail fast on invalid artifacts.

Frontend iteration can proceed against stable backend APIs.

The project can later replace SQLite only by updating this contract.

Follow-Up

Define the concrete SQLite schema in the backend architecture document.

Define the initial backend endpoints.

Define query result aggregation for unparsed requirements.

Define state database schema and token policy.

Release gate and patch governance are defined in ADR 0007 and ADR 0008.