/** * Celilo Module Contract Registry * * Maps contract version strings to their canonical hook signatures. The * manifest's `celilo_contract` field selects which contract applies; the * registry is the single source of truth for what each version promises. * * To mint a new contract version: add a new file (e.g. `./v2.ts`), import its * contract object here, and register it in `CONTRACTS`. Old contracts stay * registered indefinitely so legacy modules continue to validate. */ import { V1_CONTRACT } from './v1'; import type { ContractHookSignature, ContractHooks } from './v1'; export type { ContractHooks, ContractHookSignature }; /** * Look up a hook signature by an UNTRUSTED name. * * `ContractHooks` is keyed by `HookName` (celilo#821), which is what makes a * missing or unknown entry a compile error. The executor's `hookName` is a * plain `string` on purpose — it comes from a module manifest, and deciding * whether it names a real hook is precisely what the caller is asking. This * helper is the one place that crossing is expressed, so every other use of * `ContractHooks` stays exact. * * Returns `undefined` for a name the contract does not define; the caller * turns that into "Hook 'x' is not part of celilo_contract 1.0". */ export function contractHookSignature( hooks: ContractHooks, name: string, ): ContractHookSignature | undefined { return (hooks as Record)[name]; } /** * The shape of a registered contract. */ export interface Contract { /** Semver-style version string (e.g. "1.0"). */ version: string; /** Canonical hook signatures for this version. */ hooks: ContractHooks; } /** * Registry of every contract version Celilo knows about. * The keys are the strings users write in `celilo_contract`. * * When minting a new version, also add its string literal to * `SUPPORTED_CONTRACT_VERSIONS` below so Zod's enum picks it up. */ export const CONTRACTS: Record = { '1.0': V1_CONTRACT, }; /** * Const tuple of supported contract version strings, used to drive the Zod * enum that validates the manifest's `celilo_contract` field. */ export const SUPPORTED_CONTRACT_VERSIONS = ['1.0'] as const; export type SupportedContractVersion = (typeof SUPPORTED_CONTRACT_VERSIONS)[number]; /** * Look up a contract by version string. * * @returns The contract, or `undefined` if the version is not registered. */ export function resolveContract(version: string): Contract | undefined { return CONTRACTS[version]; } /** * List of all registered contract version strings, used for error messages * and for validating the `celilo_contract` field's enum. */ export function supportedContractVersions(): string[] { return Object.keys(CONTRACTS); }