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
- A contract is frozen when it has a published schema in the registry + approved architectural sign-off + a versioning rule documented.
- After freeze, only additive changes allowed within the current version.
- Breaking changes require a new
vNand a documented migration window (migration-backward-compatibility.md). - Freezes are audited in CI — a PR that modifies a frozen schema without version bump is blocked.
- Every freeze has a owner team and a ratification record in the architecture decision log (ADR).
2. Freeze Timeline
| # | Contract | Frozen before | Owner | Evolution rule |
|---|---|---|---|---|
| F01 | EventEnvelope | M0 end | Platform | Additive only; schemaUri content-hash required; breaking → new envelope version (never needed) |
| F02 | Outbox/inbox schema | M0 end | Platform | Extended by columns only |
| F03 | TenantId, UserId, DeviceId, CourseId, CourseVersionId, EnrollmentId, BundleId, MediaAssetId, OrgUnitId, AssignmentId, ListingId, LicenseId, OrderId, PlaySessionId, AttemptId, StatementId, CompletionId, EmbeddingId, CertificateId (branded string VOs) | M0 end | Platform | Never change shape |
| F04 | AIProvenance VO | M0 end | AI Services | Additive optional fields only; never rename or remove existing |
| F05 | LicenseEnvelope VO | M1 start | Content-Packaging + Security | Additive only; signature algorithm pinned; changes → new envelope version |
| F06 | VectorClock shape + Lamport cursor semantics | M0 end | Sync | Never change semantics; additive-only |
| F07 | Sync protocol: /sync/v1/pull, /sync/v1/push, /sync/v1/resolve, conflict codes | M0 end | Sync | Additive only within v1; breaking → /sync/v2/ with long overlap |
| F08 | Conflict-resolution matrix (02 §7) | M0 end | Sync + DDD | Adding aggregates: always allowed; changing policy: requires ADR + migration plan |
| F09 | AIClient port contract (methods, streaming shape, error codes) | M0 end | AI Services | Additive methods allowed; existing method signatures never change |
| F10 | Prompt registry format (fields, semver, eval set ref, safety policy) | M0 end | AI Services | Additive only |
| F11 | Error code registry /openapi/errors.json | M1 end | Platform | Codes never renamed or remapped; new codes additive |
| F12 | Problem+JSON shape (05 §5) | M1 end | Platform | Extended fields allowed; existing fields never change type |
| F13 | Cursor format (base64url JSON with v, k, d, f) | M1 end | Platform | New cursor versions (v2) for shape changes; stale detection via f filter fingerprint |
| F14 | Idempotency key semantics | M1 end | Platform | Algorithm frozen; TTL 24 h; scope (tenant, user, route, key) |
| F15 | PlayPackage manifest schema | M1 start | Content-Packaging | Additive only; breaking → PlayPackage v2 (never used in practice) |
| F16 | Navigation state machine (11 Player) | M1 start | Delivery | Additive states/transitions; existing transitions stable |
| F17 | Block registry schema + BlockBase shape | M2 start | Authoring | New kind values: additive; existing kind data shapes: stable per kind-version |
| F18 | Authoring publish saga steps + compensations (04 §8.2) | M2 start | Authoring + Content + Catalog | Additive steps allowed; step semantics stable |
| F19 | SCORM 1.2 export manifest mapping | M2 start | Content-Packaging | ADL conformance is the contract |
| F20 | Purchase saga (04 §8.1) | M2 start | Marketplace + Billing + Enrollment | Steps + compensations frozen |
| F21 | Webhook signature format (HMAC-SHA256 + nonce + 5-min window) | M2 start | Notification | Never changed |
| F22 | AI prompt semver + evaluation rules | M2 start | AI Services | Versions append-only; deprecation per tenant |
| F23 | SSE frame format (event names, id: resume, terminal types) | M2 start | Platform | Additive event names; terminal done/error never change |
| F24 | Cert proof format (JWS + JSON-LD + verification token grammar) | M3 start | Certification | Additive fields; signing algorithm stable |
| F25 | RRULE engine semantics (RFC 5545 subset + platform caps) | M3 start | Assignment | RFC 5545 is the contract; platform caps documented |
| F26 | ComplianceWindow state machine | M3 start | Assignment | Frozen; transitions never renamed |
| F27 | SCORM 2004 + xAPI + cmi5 export/import | M3 start | Content-Packaging + Progress | ADL + xAPI 1.0.3 + cmi5 are the contracts |
| F28 | SAML + OIDC attribute mapping rules | M3 start | Identity | Additive mappings; mapping DSL frozen |
| F29 | Role + ABAC predicate DSL | M3 start | Tenant | DSL frozen; additive operators only |
| F30 | DynamicGroup query DSL | M3 start | Tenant | Frozen; additive operators only |
| F31 | GDPR + erasure saga contract | M3 start | Platform + all services | Participating services frozen; new services declare participation |
| F32 | Yjs doc model (Y.Array of Y.Map) + field-level CRDT split | M4 start | Authoring | Frozen; additions per-field mapped at design time |
| F33 | Offline authoring conflict UI contract (diff shape) | M4 start | Authoring + Sync | Frozen |
| F34 | LTI 1.3 launch + deep-link + AGS shape | M4 start | Tenant + Delivery | LTI standard |
| F35 | Open Badges v3 shape | M4 start | Certification | OB v3 standard |
| F36 | Residency migration saga contract | M5 start | Platform + all services | Frozen; adding participating services allowed |
| F37 | HIPAA-tier AI provider allowlist | M5 start | AI Services + Compliance | Append-only; removal requires deprecation window |
| F38 | White-label branding contract (CSS vars, CSP scoping) | M5 start | Platform + Design | Frozen |
| F39 | Developer SDK v1 API surface | M5 start | DevEx | Frozen; 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.