Skip to content

Frontend Backend Contract Specification

Frontend Backend Contract Specification

Status: draft

Last updated: 2026-05-11

Audience: frontend implementers, backend implementers, API reviewers, and state/security reviewers.

Related documents:

Primary external references:

1. Purpose

This document defines how the SvelteKit frontend consumes the Go backend API.

It defines client behavior, validation expectations, caching posture, token handling, proxy constraints, request metadata, and error rendering.

It does not redefine backend endpoint payloads.

It does not introduce OpenAPI.

It does not choose a mandatory client-state library.

It does not permit the SvelteKit server to become a second backend.

2. Contract Thesis

The frontend consumes /api/v1.

The backend owns academic meaning.

The frontend validates transport shape before rendering.

The frontend preserves backend academic statuses exactly.

The frontend may proxy requests for same-origin deployment.

The frontend must not read the published index directly.

The frontend must not run backend solver logic.

The frontend must not store raw state_token values server-side.

The frontend must not reinterpret academic results.

3. API Origin Modes

Version 1 supports two origin modes.

Mode one is same-origin proxy mode.

In same-origin proxy mode, browser requests go to the SvelteKit server and are proxied to the Go backend.

Mode two is split-origin mode.

In split-origin mode, browser requests go directly to the Go backend origin.

Same-origin proxy mode is the primary v1 production shape because ADR 0020 chooses a SvelteKit Node server.

Split-origin mode remains useful for local development and deployments that separate frontend and API infrastructure.

Both modes must use the same /api/v1 backend contract.

4. SvelteKit Server Role

The SvelteKit server may:

  • serve frontend routes;
  • serve built frontend assets;
  • run route load functions;
  • set frontend-only response headers;
  • proxy /api/v1 requests to the Go backend;
  • attach request ids;
  • redact logs;
  • report frontend observability metrics;
  • serve non-secret frontend configuration.

The SvelteKit server must not:

  • open the SQLite index;
  • open the SQLite state store;
  • read raw scraper snapshots;
  • run parser patches;
  • evaluate prerequisites;
  • evaluate credential requirements;
  • run Datalog, SAT, SMT, CP, package-resolution, or direct academic evaluation;
  • store raw state_token;
  • mint backend state tokens;
  • mutate state without calling the backend.

5. Backend API Authority

The Go backend is authoritative for:

  • catalog metadata;
  • course lookup;
  • credential lookup;
  • source references;
  • student state persistence;
  • state migration;
  • state export;
  • state deletion;
  • query evaluation;
  • graph view projections;
  • unknown propagation;
  • conflict reporting;
  • explanation trees.

The frontend may cache and display these results.

The frontend may not strengthen them.

The frontend may not remove warning, unknown, or conflict information before presentation.

6. API Client

The frontend should use a narrow API client module.

The API client module must be the only normal path for calling backend endpoints.

The API client module must attach Authorization: Bearer <state_token> only when a token is present and the endpoint requires or benefits from state.

The API client module must attach Accept: application/json.

The API client module must attach Content-Type: application/json for JSON request bodies.

The API client module should attach a request id or correlation id when available.

The API client module must parse and validate response envelopes before returning data to UI components.

The API client module must redact tokens from thrown errors.

The API client module must expose cancellation support through AbortSignal.

The API client module must distinguish transport failure from successful academic unknown.

7. Runtime Validation

Frontend TypeScript types are not enough at the network boundary.

The API client must validate backend response envelopes at runtime.

Zod is the preferred schema-validation library for the first implementation because it provides TypeScript-first runtime validation and static type inference.

Zod requires TypeScript strict mode according to its documentation.

If Zod is replaced later, the replacement must provide equivalent runtime validation.

Validation failures must be treated as client-side contract errors.

Validation failures must not be rendered as academic unknowns.

Validation failures must include enough redacted diagnostics for developers to fix the contract.

8. Envelope Handling

The backend API spec defines response envelopes.

The frontend must preserve:

  • data;
  • meta;
  • warnings;
  • unknowns;
  • error;
  • source_references;
  • academic status fields;
  • result completeness fields.

The frontend must not drop warnings because data exists.

The frontend must not treat an empty warnings array as proof that the academic claim is complete.

The frontend must respect backend-provided omitted counts and graph bounds.

The frontend must show semantic unknowns from successful 200 query results as academic states, not transport errors.

9. Status Mapping

Academic statuses are:

  • satisfied;
  • not_satisfied;
  • partial;
  • unknown;
  • conflict;
  • not_applicable.

The frontend must render these statuses consistently.

The frontend must not rename statuses in data structures.

The frontend may translate statuses into user-facing text.

The frontend may map statuses to colors, icons, labels, and ordering.

The frontend must not collapse unknown into not_satisfied.

The frontend must not collapse conflict into not_satisfied.

The frontend must not collapse partial into satisfied.

10. Server-State Strategy

The app may use SvelteKit load functions for route-level data.

The app may use a Svelte-compatible server-state library for interactive browser data.

TanStack Query for Svelte is an acceptable candidate because it provides a Svelte API for query and mutation state.

The project does not mandate TanStack Query in this spec.

If a library is used, it must not hide backend warnings, unknowns, or conflicts.

If a library is used, query keys must include catalog/index identity when cached data depends on the active catalog.

If a library is not used, the app must still implement cache invalidation, cancellation, stale state handling, and validation explicitly.

11. Cache Policy

The frontend must respect backend cache headers.

Catalog and graph data may be cacheable when the backend marks them cacheable.

State and query responses that depend on Authorization should be treated as private.

The frontend must avoid sharing state-dependent cached data across tokens.

The frontend must clear state-dependent caches when the active token changes.

The frontend must clear state-dependent caches after deletion.

The frontend must invalidate relevant query and graph overlays after state mutation.

The frontend must not use HTTP cache behavior to override backend no-store semantics.

12. Token Handling

The raw state_token is a bearer secret.

The frontend must never put it in a URL.

The frontend must never log it.

The frontend must never send it to third-party telemetry.

The frontend must never persist it on the SvelteKit server.

The frontend must send it to the backend through the Authorization header.

The frontend may keep it in browser memory for the active session.

The frontend may offer explicit local-device persistence only as a later product decision or clearly marked option.

Cookie sessions are not part of v1.

HttpOnly, Secure, and SameSite cookie settings remain a future extension.

13. Proxy Rules

If the SvelteKit server proxies /api/v1, it must preserve HTTP method, path, query, relevant headers, and request body.

It must forward Authorization only to the Go backend.

It must not log raw Authorization values.

It must not rewrite successful academic unknowns into errors.

It must not rewrite backend source_reference payloads.

It must not cache state-dependent responses unless the backend explicitly allows it.

It must map backend unavailability to a transport/system error UI state.

It must not mask unsupported index or release-gate startup failures as frontend problems.

14. Request IDs

The frontend should attach a request id for developer diagnostics.

The request id must not include tokens, course histories, grades, or user notes.

If the backend returns a request id, the frontend should preserve it in error diagnostics.

If the SvelteKit proxy creates a request id, it should forward it to the backend.

User-facing error messages may include a short request id when useful for bug reports.

15. Cancellation

Interactive atlas operations can produce many requests.

The frontend must support cancellation for superseded requests.

Search requests should cancel when the query changes.

Graph expansion requests should cancel when the selected target changes.

Overlay requests should cancel when state changes before the response returns.

Cancellation must be rendered differently from backend failure.

Cancellation must not create an academic unknown.

16. Catalog Metadata

The frontend must load active catalog metadata early.

The frontend must display enough metadata for trust and debugging.

Important fields include:

  • catalog id;
  • calendar version;
  • index schema version;
  • release decision;
  • release status;
  • generated timestamp when provided.

The frontend must treat unsupported schema or missing catalog metadata as startup-blocking for academic screens.

The frontend may still render an informational error page.

17. Catalog Mismatch

Student state is anchored to a catalog version.

The frontend must display catalog mismatch information returned by the backend.

The frontend must not silently migrate state locally.

The frontend must call backend migration preview or import/migration endpoints when available.

The frontend must allow read-only inspection when the backend permits it.

The frontend must preserve user-entered unresolved references through mismatch and migration flows.

18. Source References

The frontend must preserve source references in query, graph, course, credential, and explanation payloads.

The frontend may fetch full source reference details from backend source endpoints.

The frontend must prefer backend-provided stable source URLs, source ids, hashes, and short snippets.

The frontend must not generate its own authoritative source ids.

The frontend must not broadly republish raw extracted source content.

The frontend must make source references reachable from academic claims.

19. Graph View Consumption

The frontend consumes typed graph view endpoints.

The frontend must preserve node ids and edge ids.

The frontend must not infer semantic type from id string formatting.

The frontend must use explicit node and edge types.

The frontend may derive local layout ids for rendering, but those ids must not replace backend ids in academic interactions.

The frontend must preserve graph bounds, omitted counts, source references, and state overlays.

The frontend may request expansions through graph view endpoints.

The frontend must not synthesize academic edges that the backend did not provide except as visually marked local previews.

20. Query Result Consumption

Course unlock, credential progress, what-if, advisory, course impact, and credential gap summary results must be rendered from backend query responses.

The frontend must not compute these results as academic truth.

The frontend may use advisory course_signals and bounded course-impact relationship evidence to highlight course-library rows and Canva nodes.

Those highlights must remain display signals.

They must not become frontend-computed prerequisite, unlock, progress, or feasibility claims.

The frontend may prepare request bodies from current UI state.

The frontend may show optimistic local editing state before save.

The frontend must label optimistic or local-only states when they could affect interpretation.

The frontend must preserve explanation trees.

The frontend must preserve unknown and conflict reasons.

21. Error Taxonomy

The frontend must distinguish:

  • validation failure;
  • network failure;
  • backend unavailable;
  • backend timeout;
  • unauthorized or invalid token;
  • deleted or missing state;
  • catalog mismatch;
  • unsupported index schema;
  • request too large;
  • graph bounds exceeded;
  • academic unknown;
  • academic conflict.

Only academic unknown and academic conflict are semantic academic results.

The rest are transport, contract, state, or operational conditions.

22. HTTP Methods

The frontend must respect method semantics from the backend specs.

Safe read operations must use GET where the backend defines GET.

State creation and mutation must use backend-defined write methods.

The frontend must not introduce a mutating side effect around GET /api/v1/state/current/export.

Export auditing, if added later, must be a separate backend decision.

23. Request Body Limits

The backend runtime spec defines request size limits.

The frontend should enforce user-friendly limits before sending large payloads when feasible.

The frontend must still handle backend request_too_large errors.

The frontend must not split a single academic mutation into multiple hidden mutations unless the backend contract supports that behavior.

24. Versioning

The frontend must display or log API contract version when provided.

The frontend must include index/catalog identity in state-dependent cache keys.

The frontend must not assume index_schema_version is 1.0.0.

The first index schema version remains 0.1.0 unless ADR 0003 changes.

Frontend package versions are implementation concerns and do not change backend API versions.

25. Security Headers

The SvelteKit server may set frontend security headers.

Content security policy must account for WASM workers and renderer assets.

Worker scripts should be served from trusted same-origin paths.

The app should avoid unsafe inline scripts where practical.

Security headers must not interfere with backend API semantics.

26. Environment Configuration

The frontend should use explicit environment variables for:

  • public frontend origin;
  • backend API origin for proxy mode;
  • backend API origin for direct mode;
  • build-time feature flags;
  • optional telemetry endpoint;
  • debug logging mode.

Public environment variables must not contain secrets.

Private server-side environment variables must not be exposed to the browser.

The SvelteKit Node adapter documents ORIGIN, HOST, PORT, and related deployment variables; deployments must configure them according to their reverse proxy topology.

27. Observability

The frontend should measure:

  • route load time;
  • API duration;
  • validation failures;
  • cancellation count;
  • graph response sizes;
  • atlas worker duration;
  • renderer backend selected;
  • fallback path selected.

Metrics must not include raw tokens.

Metrics must not include full course histories or grades.

Metrics must distinguish backend semantic unknowns from system errors.

28. Contract Test Fixtures

Frontend tests should use fixture backend responses derived from docs/spec examples.

Fixtures must include:

  • successful catalog metadata;
  • course detail with prerequisites;
  • credential detail with nested requirements;
  • query result with unknown;
  • query result with conflict;
  • graph view with omitted counts;
  • invalid token response;
  • catalog mismatch response;
  • response envelope validation failure.

Fixtures must not contain raw real student tokens.

29. Acceptance Criteria

The frontend can call catalog endpoints and render catalog metadata.

The frontend can call state endpoints with Authorization and render state.

The frontend can call query endpoints and render explanation trees.

The frontend can call graph view endpoints and pass graph data to the atlas engine.

The frontend can handle academic unknown as a successful query result.

The frontend can handle transport failure as a system error.

The SvelteKit server can proxy API requests without storing raw tokens.

The app can operate in split-origin local development mode with explicit allowed origins.

30. Review Checklist

No UI component calls backend fetch directly except through the API client or route-load wrapper.

No SvelteKit server code opens backend storage artifacts.

No logs include raw state_token.

No cache key omits catalog identity where it matters.

No validation failure is presented as an academic result.

No academic unknown is presented as a transport failure.

No source reference is discarded before rendering.

No backend warning is silently hidden.