This repository defines the wire contract. It does not define server behavior.
It defines API response shapes only for Majestic. Response shapes are versioned here so that majestic-server and clients share a single contract. Silent drift becomes impossible; CI can enforce parity.
Shapes only. This package exports:
- Types and discriminated unions
- JSON schemas
- Versioning rules
This repository must NOT include:
- Database logic
- Streaming logic
- ffmpeg logic
- Prewarm orchestration
- Business logic
- HTTP handlers
Only types, schemas, discriminated unions, and versioning rules.
| Module | Contents |
|---|---|
version |
CONTRACT_VERSION, API_CONTRACT_VERSION |
playbackPrediction |
PlaybackPrediction union |
incompatibility |
Incompatibility, IncompatibilityType |
prewarm |
PrewarmGetResponse, PrewarmDeleteResponse |
apiError |
ApiError discriminated union |
responseEnvelope |
ApiSuccessEnvelope, ApiErrorEnvelope |
No URL versioning. Server and client move together. contract_version exists for visibility and guardrails only.
| Change | Bump |
|---|---|
| Major | Field removed, field renamed, type changed incompatibly, enum value removed, additionalProperties tightened |
| Minor | New optional field added, new enum value added |
| Patch | Description changes, documentation-only changes |
- Removing a field → breaking
- Renaming a field → breaking
- Changing a discriminant value → breaking
- Adding a new optional field → allowed (minor)
- Adding a new required field → breaking
- Removed fields require a major version bump.
- Renamed fields require a major version bump.
- Discriminant changes (e.g. adding/removing union members, changing
statusortypevalues) require a major version bump. - New required fields require a major version bump.
- Optional new fields are allowed in minor versions.
CI enforces that schema changes require a version bump. No exceptions.
pnpm run generateproducesdist/contract.bundle.json— a canonical, deterministic aggregate of all schemas (sorted keys, no whitespace variance).pnpm run check:hashcomputes SHA-256 of the bundle and compares againstcontract-hashes.json.- If
CONTRACT_VERSIONexists in the hash map and the computed hash differs → CI fails. - If
CONTRACT_VERSIONdoes not exist in the hash map → CI fails (add the new version and hash manually).
- Update
CONTRACT_VERSIONinsrc/version.ts. - Run
pnpm run generate. - Run
pnpm run check:hash— it will fail and print the hash to add. - Add the entry to
contract-hashes.json:"1.1.0": "sha256-<hash-from-output>"
CONTRACT_VERSION is no longer ceremonial. It is enforced identity.
Contract-critical: scripts/generate.mjs canonicalization logic is part of contract identity. Changes to key ordering, array handling, or determinism rules will change the hash. Review changes carefully. tests/canonicalization.test.ts enforces determinism in CI.
A husky pre-commit hook runs check:hash, stages generated/, contract.json, and contract.bundle.json, then runs check and test. This ensures generated artifacts are always fresh before commit. Runs automatically after pnpm install (via prepare script).
generate also produces contract.json (version, hash, schema index, endpoint map) and copies contract.bundle.json to root. These power the contract authority site at majesticcore.dev, which surfaces identity, endpoint mapping, schema descriptions, and bundle download.
Endpoint map is derived from x-endpoints in each schema. Add "x-endpoints": ["GET /path", "DELETE /path"] to a schema to declare which endpoints return that shape. No manual manifest maintenance.
Do not add logic to this package. It defines shapes only. If you need to:
- Validate at runtime → use the JSON schemas in your consumer.
- Compute playback prediction → implement in majestic-server.
- Evaluate compatibility → implement in majestic-server.
This package is consumed; it does not orchestrate.
- majestic-server implements the API and returns responses that conform to these shapes.
- Server consumes this package; it does not define shapes inline.
- When extracting new shapes from server, reconstruct shapes manually by inspecting server code. Do not import server code into this package.
- majestic-appletv, majestic-roku, majestic-tizen, etc. consume these types for type-safe API handling.
- Clients must consume from this package; no ad-hoc types.
- All clients and server share the same contract version.
majestic-api-contracts/
├── src/
│ ├── version.ts
│ ├── playbackPrediction.ts
│ ├── incompatibility.ts
│ ├── prewarm.ts
│ ├── apiError.ts
│ ├── responseEnvelope.ts
│ ├── index.ts
├── schemas/
│ ├── incompatibility.schema.json
│ ├── prewarm.schema.json
│ ├── apiError.schema.json
│ └── ...
├── scripts/
│ ├── generate.mjs
│ └── check-hash.mjs
├── .husky/
│ └── pre-commit
├── contract-hashes.json # SHA-256 per CONTRACT_VERSION (CI enforcement)
├── contract.json # Manifest for site (version, hash, schemas, endpoint map)
├── contract.bundle.json # Canonical bundle for site download
├── index.html # Contract authority site
├── package.json
├── tsconfig.json
└── README.md
None (leaf contract package). Dev dependencies: TypeScript, Vitest, Ajv.
import {
CONTRACT_VERSION,
type PlaybackPrediction,
type Incompatibility,
type PrewarmGetResponse,
type ApiError
} from 'majestic-api-contracts';-
API v1 stabilization
- Maintain strict backward compatibility
- Expand schema coverage tests
- Improve cross-client validation
-
Schema completeness
- JSON schema coverage for all exported types
- Validation parity between TypeScript and JSON schema
- Formal compatibility test suite growth
-
Versioning discipline
- Major version for breaking shape changes
- Minor version for additive optional fields
- Explicit deprecation strategy for future changes
-
Cross-platform contract enforcement
- Client-side validation (Apple TV, future Roku/Tizen)
- Tooling to validate responses against schema in CI
-
Future API v2 considerations (non-committal)
- Optional response envelope standardization
- Formalized error taxonomy expansion
- Explicit capability negotiation versioning