Engineering notes

ENGINEERING NOTE 03

From TypeScript Graph to Immutable Curriculum Release

The curriculum is authored as typed relationships, validated as a complete graph, exported as a content-addressed artifact, and only then published to PostgreSQL.

  • 10 / 30 / 420Curriculum graph — Ten modules, thirty lessons, and 420 published questions are required by the release validator.
  • 5Question domains — Four Series 65 blueprint domains plus a separate Virginia-law domain.
  • 2 × 140Mock artifacts — Two deterministic, disjoint simulation templates are generated during export.

SECTION 01

Author relationships, not pages

Modules, lessons, questions, sources, visuals, pathways, and story missions form a typed directed graph whose edges are validated before rendering.

A module owns an ordered lesson list and declares its track and domain. Every question points back to a module, lesson, concept family, revision, difficulty, and source set. The enriched learning layer adds stable section IDs, paragraph structure, takeaways, one case, one renderer-neutral visual, one checkpoint, authority notes, and optional image metadata. Pages are projections of this graph; they are not the source of truth.

That design makes invalid cross-links detectable without a browser. A question cannot quietly claim one domain while referencing a lesson from another. A story mission cannot exist without its lesson, and a pathway stage cannot name an absent module. Stable IDs carry relationships; slugs provide readable routes; order fields define sequence. Titles and summaries can change without forcing a database-key migration or invalidating a completed session's question identity.

Curriculum relationship graphA release owns ordered teaching content and assessment content, while pathways and story mode project the same identifiers.A curriculum release contains modules, modules order lessons, and questions reference both a lesson and its module. Pathways and story mode reuse those same identifiers as alternate presentations. Connections: Curriculum release to Module (contains); Module to Lesson (orders); Lesson to Question revision (grounds); Module to Pathway + story (projects); Lesson to Pathway + story (maps).
  1. Curriculum release

    Version, source hash, and publication status.

  2. Module

    Track, domain, order, and three lessons.

  3. Lesson

    Objectives and four enriched sections.

  4. Question revision

    Concept, options, rationale, explanation, and sources.

  5. Pathway + story

    Alternative sequences over the same module and lesson IDs.

SECTION 02

Turn editorial expectations into release invariants

Export validation checks inventory, reference existence, item completeness, cue balance, and simulation feasibility; tests and admin publication add stricter relationship and authority gates.

The export validator requires exactly ten modules, thirty lessons, and 420 questions, with domain counts of 50 economic, 80 vehicles, 95 recommendations, 95 laws-and-ethics, and 100 Virginia-law items. It rejects duplicate question IDs and normalized stems, unknown module or lesson references, the wrong option count or a missing keyed option, thin rationales and explanations, incomplete basic source fields, invalid Virginia track flags, and severe answer-length cues sampled by concept family. It does not by itself prove that a referenced lesson belongs to the named module, that domains align, that option IDs are unique, or that authority URLs and jurisdictions meet publication policy.

Unit tests and the admin publication validator enforce additional same-module, domain-alignment, unique-option-ID, HTTPS, jurisdiction, and enriched-content rules. Validation also executes the assessment selector rather than assuming the inventory is sufficient. It constructs two seeded forms, checks that the forms are disjoint, requires all 64 authored Series 65 concepts on each, caps close-variant reuse, prevents adjacent identical concepts, and compares difficulty mixes. These are build-time facts about this release—not assurances that a mock form reproduces live exam questions or predicts a candidate's outcome.

Selected release invariants — Across export checks, unit tests, and admin publication validation, structural or assessment violations fail the relevant gate.
LayerInvariantFailure meaning
GraphEvery question resolves to a same-module lessonBroken traceability or domain crossing.
ItemFour unique options, key present, complete rationalesUnusable or weakly explainable assessment item.
AuthorityHTTPS source plus citation, jurisdiction, and datesUnsupported teaching point.
Form140 unique revisions with exact scored quotasMock-form mechanics diverge from the pinned specification.

SECTION 03

Export one reproducible artifact

A seeded selector, asset manifest, and SHA-256 source hash convert the graph into a deterministic database input.

The export command first runs the validator, then constructs two simulation forms with fixed random seeds. It records question IDs and revisions rather than duplicating free-floating answer text. It also reads every required learning image, stores its byte count and SHA-256 digest, serializes modules, questions, release metadata, assets, and templates, and hashes the complete payload. The resulting release ID contains the leading portion of that hash.

Content addressing gives operations a precise question: “Is this the artifact we built?” rather than “Does this folder have the expected name?” Changes to exported modules, lessons, questions, templates, release metadata, or image bytes change the release identity. Pathway and story metadata are not currently part of that hash. Determinism is scoped to the export inputs and seeded selection; runtime practice sets still shuffle so learners do not receive an identical short set every time.

Release identity from serialized content — The identifier changes when the exported curriculum, templates, or asset manifest changes.typescript
const serialized = JSON.stringify(payload);
const sourceHash = createHash("sha256").update(serialized).digest("hex");
const releaseId = `release-${sourceHash.slice(0, 12)}`;

SECTION 04

Separate artifact insertion from active publication

Bootstrap applies migrations transactionally and inserts a new content release atomically; it publishes the first seed automatically, while replacement of an active seed requires an explicit deployment flag.

On container start, bootstrap waits for PostgreSQL, applies unapplied migration files inside transactions, and reads the generated seed. A new seed is inserted with its modules, lessons, questions, templates, learner row, and audit event in one transaction. Bootstrap automatically publishes the first seed when no active release exists. If another release is already active and seed publication was not requested, the new artifact is archived rather than unexpectedly replacing production content.

Once a release is active, deployment deliberately enables seed replacement after taking a backup and before starting the final web service. This bootstrap path does not invoke the database draft validator; its source artifact has passed the export and build checks described above. A table lock serializes competing release transitions, the previous published release becomes archived, and the new release becomes the only active source for curriculum queries and new sessions. Existing sessions do not follow that pointer: their item snapshots and release ID preserve the assessment that was actually delivered. Separately, publication through the admin interface requires a database-validated draft.

REFERENCES

Sources and further reading

  1. Everyday TypesTypeScript

    Language reference for discriminated unions, constrained identifiers, and renderer-neutral content contracts.

  2. TransactionsPostgreSQL Global Development Group

    Database reference for all-or-nothing release changes, session creation, grading, and auditable state transitions.

  3. Series 65 Exam Content OutlineNorth American Securities Administrators Association

    Primary reference for the examination name, current scored-domain specification, timing, and passing-score context represented by this release.