/** * ClaimDefinition compiler — v1 slice (inv.18): a pure, total, FAIL-CLOSED * completeness/consistency VALIDATOR for the generic `ClaimDefinition` shape. * * It does NOT yet GENERATE kernel artifacts (the DSL/codegen + the `Proof` * brand are the larger v2, out of scope). What it DOES is take the THREE today- * unenforced alignment CONVENTIONS of the claims runtime and make them ONE * load-time mechanism that REJECTS an incomplete/inconsistent definition set: * * (a) every render-template PROPOSITION slot is backed by a value projection / * binding to a `requiredEvidence` key — INV-1, INV-7 * (b) every `falsifierComplete: true` type enumerates falsifiers — INV-2 * (folds in the existing §R `assertFalsifierDeclaration` hard-throw) * (c) every render-template entry has a registered claim definition — INV-3 * (this is what makes a dangling template state IMPOSSIBLE) * * …plus every Triad-scoped type appears in some decomposition closure (INV-4), * provenance is default-deny (INV-5), and the §5 structural conjuncts that * already exist as RUNTIME checks (C0 non-vacuity, the cacheable-requires-ttl * shape) are lifted to DEFINITION-LOAD time (INV-6, INV-8). * * SOURCES CONSOLIDATED (the scattered facets this unifies; see the per-invariant * doc comments for exact file:line in the ibatexas + adjudicate trees): * - `requiredEvidence` / `minSourceIntegrity` / `kind` ← `EvidenceRequirement` * (`./evidence-requirement.ts`) + the soundness §5 predicate (`./soundness.ts`). * - falsifier declaration ← `FalsifierDeclaration` + `assertFalsifierDeclaration` * (`./evidence-requirement.ts`). * - value binding ← `ValueBinding` + the C6 binding-key gate (`./soundness.ts`). * - render template / value projections / decomposition closure ← the ibatexas * `slot-grammar.ts` / `claim-registry.ts` / `required-claim-decomposer.ts` * artifacts, modelled here as GENERIC shapes so the validator is testable * IN-REPO without the ibatexas registry or any link. * * PURITY: every invariant is DEFINITION-LOAD-TIME — no clock, no RNG, no IO — so * the whole module is a pure function of its inputs and is exhaustively testable * against synthetic fixtures. The validator is TOTAL: it never throws on a * malformed input; it returns a `{ ok: false, code, reason }` instead (the * underlying `parseEvidenceRequirement` / `assertFalsifierDeclaration` throws are * caught and converted). No kernel-downstream import (§R kernel purity). */ import { type EvidenceRequirement, type FalsifierDeclaration, type SourceIntegrity } from "./evidence-requirement.js"; import type { ClaimKind, ValueBinding } from "./soundness.js"; /** * One render-template slot. Mirrors the ibatexas `TemplateSlot` (slot-grammar.ts * `LITERAL | PROPOSITION`): * * - `LITERAL` — fixed prose; imposes NO evidence requirement. * - `PROPOSITION` — a value slot filled from a claim of `claimType`, reading its * `field`. INV-1 requires this slot to be backed by a value * projection bound to a `requiredEvidence` key. */ export type TemplateSlot = { readonly kind: "LITERAL"; readonly text: string; } | { readonly kind: "PROPOSITION"; readonly claimType: string; readonly field: string; }; /** A render template = an ordered list of slots (ibatexas `Template`). */ export interface RenderTemplate { readonly slots: readonly TemplateSlot[]; } /** * A value projection: the slot↔ledger binding that backs ONE rendered proposition * field with a `requiredEvidence` key (and an optional `path` projection into that * evidence value). Mirrors the ibatexas `RegistryClaimSpec.valueBinding {key, * path?}` generalized to multiple fields, and is what the adjudicate C6 * value-binding gate compares at runtime. INV-1 requires every PROPOSITION slot's * `field` to have a matching projection; INV-1/INV-7 require `key` to be a member * of `requiredEvidence` keys (so presence/freshness/provenance/integrity are * already §5-gated before a rendered value can be sourced from it). */ export interface ValueProjection { readonly field: string; readonly key: string; readonly path?: readonly (string | number)[]; } /** * The generic, registry-agnostic `ClaimDefinition` — the single shape onto which * the today-scattered per-type facets are consolidated. Keyed by `type` (a claim * type name). A `Record` plus the cross-tables * (render-template keys, decomposition closures, registry enum) is what the * validator consumes. * * Extends `FalsifierDeclaration`, so `falsifierComplete?` / `falsifiers?` are * carried verbatim (INV-2 reuses the existing §R guard over them). */ export interface ClaimDefinition extends FalsifierDeclaration { /** The claim type name (the registry key + the VALIDATED_TEMPLATES key). */ readonly type: string; /** `read_claim | action_claim` — the §5 `c.kind` (drives C4 at runtime). */ readonly kind: ClaimKind; /** The `∀ e ∈ requiredEvidence` set §5 quantifies over (C0 demands non-empty). */ readonly requiredEvidence: readonly EvidenceRequirement[]; /** The C2 source-integrity floor each evidence must meet-or-exceed. */ readonly minSourceIntegrity: SourceIntegrity; /** OPTIONAL C6 kernel value-binding; if present its `key` must be §5-gated (INV-7). */ readonly valueBinding?: ValueBinding; /** OPTIONAL slot↔ledger projections backing the render template's slots (INV-1). */ readonly valueProjections?: readonly ValueProjection[]; /** OPTIONAL render template; every PROPOSITION slot must be backed (INV-1). */ readonly renderTemplate?: RenderTemplate; /** * Whether this type is Triad-scoped. A Triad-scoped type MUST appear in some * decomposition closure (INV-4) so the P4 required-set completeness check can * never leave it unreachable. Absent ⟹ not Triad-scoped (no closure obligation). */ readonly triadScoped?: boolean; } /** * The stable failure code identifying WHICH invariant rejected a definition set. * Each maps 1:1 to one of the inv.18 invariants so the mutation harness can * assert the SPECIFIC reason for each removed/corrupted facet. */ export type ValidationFailureCode = /** INV-6 — `requiredEvidence` empty (C0 vacuity). */ "EMPTY_REQUIRED_EVIDENCE" /** INV-8 — an `EvidenceRequirement` / falsifier is structurally ill-formed. */ | "MALFORMED_EVIDENCE" /** INV-5 — an evidence/falsifier has absent/invalid provenancePolicy (default-deny). */ | "PROVENANCE_DENY" /** INV-2 — `falsifierComplete: true` with an empty/missing `falsifiers[]`. */ | "FALSIFIER_INCOMPLETE" /** INV-7 — `valueBinding.key` is not a member of `requiredEvidence` keys. */ | "BINDING_KEY_UNGATED" /** INV-1 — a PROPOSITION slot / projection is not backed by a §5-gated key. */ | "SLOT_UNBACKED" /** INV-3 — a render-template entry has no registered ClaimDefinition. */ | "TEMPLATE_UNREGISTERED" /** INV-4 — a Triad type is absent from every closure, or a closure type is unregistered. */ | "DECOMPOSITION_UNREACHABLE" /** Totality — the value is not a structurally-shaped ClaimDefinition / defs map. */ | "MALFORMED_DEFINITION"; /** * The validator result. `{ ok: true }` on a complete+consistent definition (set); * `{ ok: false, code, reason }` otherwise. FAIL-CLOSED: anything not provably * complete is REJECTED. The `reason` is a human-legible message; `code` is the * stable machine-checkable invariant identity. */ export type ValidationResult = { readonly ok: true; } | { readonly ok: false; readonly code: ValidationFailureCode; readonly reason: string; }; /** * INV-1 (the slot↔projection static check, exported as a reusable predicate): * every PROPOSITION slot in `def.renderTemplate` MUST be backed by a * `valueProjection` (on the slot's `claimType` owner) whose `field` matches the * slot's `field` AND whose `key` is a member of that owner's `requiredEvidence` * keys. A LITERAL slot imposes nothing; a def with no render template imposes * nothing. * * `lookup` resolves a slot's `claimType` to its owning `ClaimDefinition` for the * cross-type composition case. When `lookup` is omitted, only SELF-type slots * (`slot.claimType === def.type`) are checked and cross-type slots are deferred * (the aggregate `validateClaimDefinitions` always supplies a lookup, so an * unresolved cross-type slot is rejected there). TOTAL: guards every field. */ export declare function checkSlotProjectionAlignment(def: ClaimDefinition, lookup?: (type: string) => ClaimDefinition | undefined): ValidationResult; /** * Validate ONE `ClaimDefinition`, fail-closed and TOTAL. Enforces the per-def * invariants: * * - INV-6 — `requiredEvidence` non-empty (C0 non-vacuity). * - INV-8 — every `requiredEvidence` + falsifier is structurally valid. * - INV-5 — every `requiredEvidence` + falsifier has an explicit provenancePolicy * (default-deny). * - INV-2 — `falsifierComplete: true` ⟹ a non-empty, valid `falsifiers[]`. * - INV-7 — `valueBinding.key` ∈ `requiredEvidence` keys (the load-time form of * the runtime C6 guard). * - INV-1 — every render-template PROPOSITION slot is backed by a §5-gated * value projection (cross-type via the optional `lookup`). * * The cross-table invariants INV-3 (template→registered) and INV-4 (decomposition * closure) are SET-level — see `validateClaimDefinitions`. * * @param lookup resolves a cross-type slot's `claimType` to its owning definition. */ export declare function validateClaimDefinition(def: ClaimDefinition, lookup?: (type: string) => ClaimDefinition | undefined): ValidationResult; /** * The cross-tables the set-level invariants quantify over. All OPTIONAL: an * absent table skips its invariant (so a caller can validate only the per-def * invariants by passing `{}`), but a PRESENT table is enforced fail-closed. */ export interface ValidationContext { /** * The render-template registry keyed by claim type (ibatexas VALIDATED_TEMPLATES). * INV-3: every key MUST resolve to a registered ClaimDefinition. The values are * not inspected here (slot backing is INV-1 on the def's own `renderTemplate`). */ readonly templates?: Readonly>; /** * The decomposition closures keyed by span class (ibatexas REQUIRED_CLAIM_CLOSURE: * SpanClass → claim type[]). INV-4: every Triad-scoped def must appear in some * value; every referenced type must be registered. */ readonly closures?: Readonly>; /** * The set of registered claim types (the CLAIM_REGISTRY enum). Defaults to * `Object.keys(defs)` when omitted. INV-3/INV-4 resolve "registered" against this. */ readonly registryEnum?: readonly string[]; } /** * Validate a WHOLE definition set + its cross-tables, fail-closed and TOTAL. Runs * `validateClaimDefinition` on each member (with a cross-type lookup) and then the * SET-level invariants: * * - INV-3 (TEMPLATE → REGISTERED-DEFINITION; mechanizes convention (c)): every * `context.templates` key MUST have a registered ClaimDefinition. This is the * check that makes a dangling template (a render template keyed to a type with * no definition) IMPOSSIBLE at load — it REJECTS rather than booting. * - INV-4 (DECOMPOSITION-CLOSURE membership): every Triad-scoped def type MUST * appear in some `context.closures` value, and every closure-referenced type * MUST be registered. * * Also enforces def-key↔`def.type` agreement (a mismatch is a malformed map). */ export declare function validateClaimDefinitions(defs: Readonly>, context?: ValidationContext): ValidationResult; //# sourceMappingURL=claim-definition.d.ts.map