Skip to main content

Architectural Freeze Points

:::info Source Sourced from docs/roadmap/architectural-freeze-points.md in the documentation repo. :::

Execution-layer companion to ROADMAP.md and the foundational specs (02 DDD, 04 EDA, 05 API Design).

This document enumerates every contract that must freeze (stop evolving in a breaking way) before the code that depends on it begins. Freezing early is how we avoid the most expensive category of rework: changing shared schemas after multiple services have coded against them.

1. Freeze Rules

  1. A contract is frozen when it has a published schema in the registry + approved architectural sign-off + a versioning rule documented.
  2. After freeze, only additive changes allowed within the current version.
  3. Breaking changes require a new vN and a documented migration window (migration-backward-compatibility.md).
  4. Freezes are audited in CI — a PR that modifies a frozen schema without version bump is blocked.
  5. Every freeze has a owner team and a ratification record in the architecture decision log (ADR).

2. Freeze Timeline

#ContractFrozen beforeOwnerEvolution rule
F01EventEnvelopeM0 endPlatformAdditive only; schemaUri content-hash required; breaking → new envelope version (never needed)
F02Outbox/inbox schemaM0 endPlatformExtended by columns only
F03TenantId, UserId, DeviceId, CourseId, CourseVersionId, EnrollmentId, BundleId, MediaAssetId, OrgUnitId, AssignmentId, ListingId, LicenseId, OrderId, PlaySessionId, AttemptId, StatementId, CompletionId, EmbeddingId, CertificateId (branded string VOs)M0 endPlatformNever change shape
F04AIProvenance VOM0 endAI ServicesAdditive optional fields only; never rename or remove existing
F05LicenseEnvelope VOM1 startContent-Packaging + SecurityAdditive only; signature algorithm pinned; changes → new envelope version
F06VectorClock shape + Lamport cursor semanticsM0 endSyncNever change semantics; additive-only
F07Sync protocol: /sync/v1/pull, /sync/v1/push, /sync/v1/resolve, conflict codesM0 endSyncAdditive only within v1; breaking → /sync/v2/ with long overlap
F08Conflict-resolution matrix (02 §7)M0 endSync + DDDAdding aggregates: always allowed; changing policy: requires ADR + migration plan
F09AIClient port contract (methods, streaming shape, error codes)M0 endAI ServicesAdditive methods allowed; existing method signatures never change
F10Prompt registry format (fields, semver, eval set ref, safety policy)M0 endAI ServicesAdditive only
F11Error code registry /openapi/errors.jsonM1 endPlatformCodes never renamed or remapped; new codes additive
F12Problem+JSON shape (05 §5)M1 endPlatformExtended fields allowed; existing fields never change type
F13Cursor format (base64url JSON with v, k, d, f)M1 endPlatformNew cursor versions (v2) for shape changes; stale detection via f filter fingerprint
F14Idempotency key semanticsM1 endPlatformAlgorithm frozen; TTL 24 h; scope (tenant, user, route, key)
F15PlayPackage manifest schemaM1 startContent-PackagingAdditive only; breaking → PlayPackage v2 (never used in practice)
F16Navigation state machine (11 Player)M1 startDeliveryAdditive states/transitions; existing transitions stable
F17Block registry schema + BlockBase shapeM2 startAuthoringNew kind values: additive; existing kind data shapes: stable per kind-version
F18Authoring publish saga steps + compensations (04 §8.2)M2 startAuthoring + Content + CatalogAdditive steps allowed; step semantics stable
F19SCORM 1.2 export manifest mappingM2 startContent-PackagingADL conformance is the contract
F20Purchase saga (04 §8.1)M2 startMarketplace + Billing + EnrollmentSteps + compensations frozen
F21Webhook signature format (HMAC-SHA256 + nonce + 5-min window)M2 startNotificationNever changed
F22AI prompt semver + evaluation rulesM2 startAI ServicesVersions append-only; deprecation per tenant
F23SSE frame format (event names, id: resume, terminal types)M2 startPlatformAdditive event names; terminal done/error never change
F24Cert proof format (JWS + JSON-LD + verification token grammar)M3 startCertificationAdditive fields; signing algorithm stable
F25RRULE engine semantics (RFC 5545 subset + platform caps)M3 startAssignmentRFC 5545 is the contract; platform caps documented
F26ComplianceWindow state machineM3 startAssignmentFrozen; transitions never renamed
F27SCORM 2004 + xAPI + cmi5 export/importM3 startContent-Packaging + ProgressADL + xAPI 1.0.3 + cmi5 are the contracts
F28SAML + OIDC attribute mapping rulesM3 startIdentityAdditive mappings; mapping DSL frozen
F29Role + ABAC predicate DSLM3 startTenantDSL frozen; additive operators only
F30DynamicGroup query DSLM3 startTenantFrozen; additive operators only
F31GDPR + erasure saga contractM3 startPlatform + all servicesParticipating services frozen; new services declare participation
F32Yjs doc model (Y.Array of Y.Map) + field-level CRDT splitM4 startAuthoringFrozen; additions per-field mapped at design time
F33Offline authoring conflict UI contract (diff shape)M4 startAuthoring + SyncFrozen
F34LTI 1.3 launch + deep-link + AGS shapeM4 startTenant + DeliveryLTI standard
F35Open Badges v3 shapeM4 startCertificationOB v3 standard
F36Residency migration saga contractM5 startPlatform + all servicesFrozen; adding participating services allowed
F37HIPAA-tier AI provider allowlistM5 startAI Services + ComplianceAppend-only; removal requires deprecation window
F38White-label branding contract (CSS vars, CSP scoping)M5 startPlatform + DesignFrozen
F39Developer SDK v1 API surfaceM5 startDevExFrozen; additions per semver

3. Freeze-Point Details

F01–F04 — Envelope & VO family (M0)

These are the atomic types used in every event, every aggregate, every API response. Change them after M0 and every service touches again.

Enforcement: source-of-truth in /packages/platform-primitives/ shared package; CI blocks any PR that changes exported types without a version bump and ADR.

F05 — LicenseEnvelope (M1)

Encoded in every offline bundle forever. Changing it forces every device to re-download every bundle.

Enforcement: envelope signature includes an envVersion. Clients accept current + N-1 versions.

F07 — Sync protocol (M0)

Touched by every offline client build + every replicable service. A breaking change would require client updates in lockstep with server.

Enforcement: /sync/v1/ is the long-term promise; any breaking change would be /sync/v2/ with months of overlap.

F08 — Conflict matrix (M0)

Policies are chosen per aggregate and drive client UX (conflict UI vs silent merge vs reject). Changing a policy for an existing aggregate causes surprising behavior and must be rare.

Enforcement: policy changes require ADR + risk-register entry + migration plan (typically a client-visible deprecation).

F09–F10 — AIClient + Prompt registry (M0)

Every service that calls AI does it through AIClient. If the contract changes, every consumer refactors.

Enforcement: port defined in /packages/ai-client/; adapter in ai-gateway-service. Methods add, never change.

F15 — PlayPackage manifest (M1)

The Player + Content-Packaging contract. Changing breaks both.

Enforcement: manifest.version: "1.0" baked into every built package; player tolerant to additive fields.

F17 — Block registry (M2)

Authoring, Player runtime, exports (SCORM/HTML/xAPI), and AI prompts all depend on block shapes.

Enforcement: new block kinds add freely; existing kinds have kindVersion in data with coded migrations if a kind ever needs a shape change (rare).

F19 — SCORM 1.2 export (M2)

External LMSs consume these zips. Non-conformance is a market-access blocker.

Enforcement: SCORM Cloud conformance suite in CI on every export.

F20 — Purchase saga (M2)

Revenue path. Any shape change risks half-completed transactions.

Enforcement: steps + compensations frozen; additive steps only; saga state machine version pinned.

F21 — Webhook signature (M2)

External consumers integrate once and rely on the format forever.

Enforcement: signature + nonce + window documented; never change.

F22 — Prompt semver (M2)

Each prompt version is immutable after promotion. Tenants may pin versions and expect stability.

Enforcement: prompts append-only; deprecation windows per tenant; eval suites required to promote.

F24 — Certificate proof (M3)

Public-facing verifiability depends on the JWS + JSON-LD shape. Cannot change after customers start issuing.

Enforcement: Open-Badges-compatible shape; signing algorithm pinned (EdDSA Ed25519).

F25–F26 — RRULE + ComplianceWindow (M3)

Recurrence math is notoriously edge-case-heavy. Freeze before any customer data is produced against it.

Enforcement: RFC 5545 subset doc published; platform caps documented; DST + leap-day fixtures in CI.

F27 — SCORM 2004 + xAPI + cmi5 (M3)

Regulated markets consume these. Non-conformance blocks sales.

Enforcement: ADL conformance suites in CI.

F31 — GDPR erasure saga (M3)

Every service participates. Changing participation set or signatures after launch is risky.

Enforcement: participating services declared in code; CI test verifies each service handles gdpr.subject_request.received.v1.

F34 — LTI 1.3 (M4)

External standard; our implementation freezes against the current LTI version.

F36 — Residency saga (M5)

Multi-service migration; schema drift during migration would corrupt tenant data.

Enforcement: saga contract versioned; each participating service acks the current version.

4. Freeze-Point Sequence Diagram

M0 start M5
┌───┬─────────────────────────────────────────────────────────────────────────────────┐
│F01│ F02 F03 F04 F06 F07 F08 F09 F10 │
│ │ │
│M0 │ │
│end│ F05 F11 F12 F13 F14 F15 F16 │
│M1 │ │
│start │
│ │ F17 F18 F19 F20 F21 F22 F23 │
│M2 │ │
│start │
│ │ F24 F25 F26 F27 F28 F29 F30 F31 │
│M3 │ │
│start │
│ │ F32 F33 F34 F35 │
│M4 │ │
│start │
│ │ F36 F37 F38 F39 │
│M5 │ │
│start │
└───┴─────────────────────────────────────────────────────────────────────────────────┘

Each column represents contracts that must freeze before the listed milestone starts. A freeze before M1 end means it has the full M0 cycle to settle.

5. Review Cadence

  • Architecture Decision Log (ADL) is the source of truth for each freeze.
  • Freeze candidates reviewed in the weekly architecture sync.
  • Post-freeze changes require ADL entry + security-review sign-off (if the contract is security-sensitive).
  • Every freeze has a "guardrail" CI check that blocks silent drift.

6. Operational Guidance

  • When unsure if a change breaks a contract: assume it does. Open an ADR. Ask the architecture sync.
  • When a breaking change is unavoidable: plan vN+1 + dual-publish window + consumer migration tracker.
  • Never: delete a published event subject, rename an error code, change a signature algorithm without a formal migration.
  • Always: emit metrics on the adoption curve of new versions so deprecation can be timed.