{"version":3,"file":"trusted-context.d.ts","sourceRoot":"","sources":["../../../src/core/long-horizon/trusted-context.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Trusted Ledger Mutation & Validation Contexts.\n *\n * Implements the structural in-process capability boundary for the\n * Mission Contract and Requirement Ledger system, plus a trusted\n * validation registry for authoritative ledger replay.\n *\n * Mutation context: OPAQUE, BRANDED, SEPARATE — not serializable, not reconstructible.\n * Validation context: contains a trust registry for replay verification.\n *\n * This is NOT a cryptographic identity system. It is a structural boundary\n * that prevents serialized payloads from inventing authority, and prevents\n * stored provenance from self-authenticating.\n */\n\nimport { computeMissionContractDigest } from \"./contract-digest.js\";\nimport { validateMissionContract } from \"./mission-contract-schema.js\";\nimport type { EvidenceAuthorityClassification, EvidenceCollectorType, MissionContractV1 } from \"./types.js\";\n\n// =============================================================================\n// Opaque brands — private, unexported\n// =============================================================================\n\nconst _trustedMutationContextBrand = Symbol(\"trustedMutationContextBrand\");\nconst _trustedValidationContextBrand = Symbol(\"trustedValidationContextBrand\");\n\n// =============================================================================\n// Module-private WeakSets as side-channel runtime brands\n// =============================================================================\n\n// Only objects registered here pass isTrustedMutationContext.\n// No plain object, JSON round-trip, or Object.create can enter this set\n// except through the internal trusted factory.\nconst _trustedMutationContextSet = new WeakSet<object>();\n\nconst _trustedValidationContextSet = new WeakSet<object>();\n\n// Contract digest binding — only genuine trusted validation contexts\n// are bound to their originating Mission Contract digest.\nconst _contractDigestMap = new WeakMap<object, string>();\n\n// =============================================================================\n// Principal kinds — attribution only, not authorization\n// =============================================================================\n\n/**\n * Verifiable principal identity classification.\n *\n * These are stored as provenance in the ledger for auditing.\n * They do NOT directly grant capabilities — capability sets are\n * assigned by the trusted factory separately.\n */\nexport type TrustedPrincipalKind = \"agent\" | \"operator\" | \"trusted-collector\" | \"automated-review\" | \"system\";\n\n// =============================================================================\n// Typed ledger capabilities — explicit authorization\n// =============================================================================\n\nexport type LedgerCapability =\n\t| \"evidence:repository-observation\"\n\t| \"evidence:command-result\"\n\t| \"evidence:test-result\"\n\t| \"evidence:runtime-observation\"\n\t| \"evidence:operator-confirmation\"\n\t| \"evidence:trusted-collector\"\n\t| \"transition:satisfy\"\n\t| \"transition:not-applicable\"\n\t| \"transition:operator-override\"\n\t| \"execution:complete\";\n\nexport type EvidenceLedgerCapability = Extract<\n\tLedgerCapability,\n\t| \"evidence:repository-observation\"\n\t| \"evidence:command-result\"\n\t| \"evidence:test-result\"\n\t| \"evidence:runtime-observation\"\n\t| \"evidence:operator-confirmation\"\n\t| \"evidence:trusted-collector\"\n>;\n\nconst ALL_CAPABILITIES: ReadonlySet<string> = new Set([\n\t\"evidence:repository-observation\",\n\t\"evidence:command-result\",\n\t\"evidence:test-result\",\n\t\"evidence:runtime-observation\",\n\t\"evidence:operator-confirmation\",\n\t\"evidence:trusted-collector\",\n\t\"transition:satisfy\",\n\t\"transition:not-applicable\",\n\t\"transition:operator-override\",\n\t\"execution:complete\",\n]);\n\nconst EVIDENCE_CAPABILITIES: ReadonlySet<string> = new Set([\n\t\"evidence:repository-observation\",\n\t\"evidence:command-result\",\n\t\"evidence:test-result\",\n\t\"evidence:runtime-observation\",\n\t\"evidence:operator-confirmation\",\n\t\"evidence:trusted-collector\",\n]);\n\nexport function isEvidenceCapability(cap: string): cap is EvidenceLedgerCapability {\n\treturn EVIDENCE_CAPABILITIES.has(cap);\n}\n\nconst VALID_PRINCIPAL_KINDS: ReadonlySet<string> = new Set([\n\t\"agent\",\n\t\"operator\",\n\t\"trusted-collector\",\n\t\"automated-review\",\n\t\"system\",\n]);\n\n// =============================================================================\n// Trusted Evidence Source Grants\n// =============================================================================\n\n/**\n * A trusted evidence-source grant binds a source identifier to:\n *   - An exact principal tuple (principalId + principalKind)\n *   - An evidence capability\n *   - Optional constraints on evidence type, collector class,\n *     requirement IDs, and criterion IDs.\n *\n * Sources are explicit grants, not derived from principal IDs.\n * A registered principal is NOT automatically a source.\n */\nexport interface TrustedEvidenceSourceGrant {\n\treadonly sourceId: string;\n\n\t/** The exact principal tuple that may use this source. */\n\treadonly principalId: string;\n\treadonly principalKind: TrustedPrincipalKind;\n\n\t/** The evidence capability this source is authorized under. */\n\treadonly capability: EvidenceLedgerCapability;\n\n\t/** Allowed evidence types. Must be non-empty. */\n\treadonly allowedEvidenceTypes: readonly string[];\n\n\t/** Optional collector class restrictions. */\n\treadonly allowedCollectorClasses?: readonly string[];\n\n\t/** Optional requirement ID restrictions. */\n\treadonly allowedRequirementIds?: readonly string[];\n\n\t/** Optional criterion ID restrictions. */\n\treadonly allowedCriterionIds?: readonly string[];\n}\n\n// =============================================================================\n// Trusted Mutation Context\n// =============================================================================\n\nexport interface TrustedLedgerMutationContext {\n\treadonly principalId: string;\n\treadonly principalKind: TrustedPrincipalKind;\n\treadonly capabilities: ReadonlySet<LedgerCapability>;\n}\n\n// =============================================================================\n// Trusted Validation Context — separate from mutation context\n// =============================================================================\n\n/**\n * Source verification request carrying all available dimensions.\n */\nexport interface EvidenceSourceVerificationRequest {\n\treadonly sourceId: string;\n\treadonly principalId: string;\n\treadonly principalKind: TrustedPrincipalKind;\n\treadonly capability: string;\n\treadonly evidenceType: string;\n\treadonly collectorClass?: EvidenceCollectorType;\n\treadonly requirementIds: readonly string[];\n\treadonly criterionIds: readonly string[];\n}\n\n/**\n * Trusted validation context for authoritative ledger replay.\n *\n * Contains a registry of known principals and their capabilities,\n * plus explicit trusted evidence-source grants.\n * During validation, every stored verifiedPrincipalId, verifiedPrincipalKind,\n * and verifiedCapability is checked against this registry.\n * Stored provenance is NOT self-authenticating.\n *\n * This context is not serializable, not reconstructible from ledger JSON,\n * and not derivable from stored verified fields.\n */\nexport interface TrustedValidationContext {\n\t/**\n\t * Verify that a principal exists and has the claimed kind.\n\t */\n\tverifyPrincipal(principalId: string, principalKind: string): boolean;\n\n\t/**\n\t * Verify that a principal was granted a specific capability.\n\t * Requires exact (principalId, principalKind) match.\n\t */\n\tverifyCapability(principalId: string, principalKind: string, capability: string): boolean;\n\n\t/**\n\t * Verify an evidence source against its trusted grant.\n\t * Checks source existence, principal binding, capability, evidence type,\n\t * and optional collector/requirement/criterion constraints.\n\t */\n\tverifyEvidenceSource(request: EvidenceSourceVerificationRequest): boolean;\n}\n\n// =============================================================================\n// Untrusted mutation context — explicitly empty\n// =============================================================================\n\nconst _untrustedMutation: TrustedLedgerMutationContext = (() => {\n\tconst ctx: TrustedLedgerMutationContext = Object.freeze({\n\t\tprincipalId: \"untrusted\",\n\t\tprincipalKind: \"agent\" as const,\n\t\tcapabilities: new Set<LedgerCapability>(),\n\t});\n\t_trustedMutationContextSet.add(ctx);\n\treturn ctx;\n})();\n\n/**\n * The default untrusted context used by the generic CLI and\n * any caller that does not hold a trusted capability grant.\n */\nexport function getUntrustedContext(): TrustedLedgerMutationContext {\n\treturn _untrustedMutation;\n}\n\n// =============================================================================\n// Untrusted validation context — explicitly NOT a trusted context\n// =============================================================================\n\n/**\n * Structural inspection object — NOT a TrustedValidationContext.\n *\n * This object is structurally compatible with the TrustedValidationContext\n * interface for migration purposes, but is deliberately NOT added to the\n * trusted WeakSet. It does NOT pass isTrustedValidationContext() and\n * CANNOT be passed to authoritative validation APIs.\n *\n * Used only for structural ledger introspection (inspectRequirementLedgerStructure,\n * inspectLedgerStructure). Trusted validation requires a genuine\n * TrustedValidationContext from _internalCreateTrustedValidationContext.\n *\n * @deprecated Use inspectRequirementLedgerStructure or inspectLedgerStructure\n * for structural inspection. Remove once all callers have migrated to the\n * structural inspection API.\n */\nconst _untrustedValidation = Object.freeze({\n\tverifyPrincipal: () => true,\n\tverifyCapability: () => true,\n\tverifyEvidenceSource: () => true,\n});\n\n// Deliberately NOT added to _trustedValidationContextSet.\n// isTrustedValidationContext() will return false for this object.\n\n/**\n * @deprecated Use inspectRequirementLedgerStructure() or inspectLedgerStructure()\n * for structural inspection. This function returns a structural-only object that\n * does NOT implement TrustedValidationContext and cannot be passed to\n * authoritative validation APIs.\n *\n * Will be removed when all callers have migrated to the structural API.\n */\nexport function getUntrustedValidationContext(): TrustedValidationContext {\n\t// Cast through unknown: this object is deliberately NOT a real\n\t// TrustedValidationContext (not in the WeakSet). The return type\n\t// is preserved for migration compatibility only.\n\treturn _untrustedValidation as unknown as TrustedValidationContext;\n}\n\n// =============================================================================\n// Type guards — check both Symbol AND WeakSet\n// =============================================================================\n\n/**\n * Returns true when the value was created by _internalCreateTrustedContext\n * or getUntrustedContext. Plain objects, JSON round-trips, and Object.assign\n * copies will always return false.\n */\nexport function isTrustedMutationContext(ctx: unknown): ctx is TrustedLedgerMutationContext {\n\tif (typeof ctx !== \"object\" || ctx === null) return false;\n\treturn _trustedMutationContextSet.has(ctx);\n}\n\n/**\n * Returns true when the value was created by the internal validation\n * context factory or getUntrustedValidationContext.\n */\nexport function isTrustedValidationContext(ctx: unknown): ctx is TrustedValidationContext {\n\tif (typeof ctx !== \"object\" || ctx === null) return false;\n\treturn _trustedValidationContextSet.has(ctx);\n}\n\n// =============================================================================\n// Internal trusted mutation factory\n// =============================================================================\n\nexport function _internalCreateTrustedContext(params: {\n\tprincipalId: string;\n\tprincipalKind: TrustedPrincipalKind;\n\tcapabilities: LedgerCapability[];\n}): TrustedLedgerMutationContext {\n\tconst { principalId, principalKind, capabilities } = params;\n\n\tif (!principalId || principalId.trim().length === 0) {\n\t\tthrow new Error(\"INVALID_TRUSTED_PRINCIPAL: principalId must be non-empty\");\n\t}\n\n\tif (!VALID_PRINCIPAL_KINDS.has(principalKind)) {\n\t\tthrow new Error(`INVALID_TRUSTED_PRINCIPAL: unknown principal kind \"${principalKind}\"`);\n\t}\n\n\tfor (const cap of capabilities) {\n\t\tif (!ALL_CAPABILITIES.has(cap)) {\n\t\t\tthrow new Error(`INVALID_TRUSTED_CAPABILITY: unknown capability \"${cap}\"`);\n\t\t}\n\t}\n\n\tconst ctx: TrustedLedgerMutationContext = Object.freeze({\n\t\tprincipalId,\n\t\tprincipalKind,\n\t\tcapabilities: new Set(capabilities),\n\t});\n\n\t_trustedMutationContextSet.add(ctx);\n\treturn ctx;\n}\n\n// =============================================================================\n// Trusted validation context — principal registry\n// =============================================================================\n\n/**\n * Create a trusted validation context from a set of known principals\n * and explicit trusted evidence-source grants, bound to one validated Mission Contract.\n *\n * THIS IS THE TRUST-MINTING BOUNDARY: every genuine TrustedValidationContext\n * is bound to exactly one Mission Contract digest. The factory itself:\n *   1. Validates the Mission Contract.\n *   2. Derives the authoritative canonical contract digest.\n *   3. Builds immutable requirement and criterion registries from the validated contract.\n *   4. Validates every source-grant requirement and criterion reference.\n *   5. Rejects invalid or ambiguous grants.\n *   6. Binds the resulting genuine validation context to that exact contract digest.\n *   7. Returns no usable trusted context on failure.\n *\n * Principals are identified by exact (id, kind) tuples with associated capabilities.\n * During replay, stored provenance is verified against this registry.\n *\n * Duplicate exact principal tuples are REJECTED.\n *\n * Same textual ID with different kinds is PERMITTED, but each tuple is treated\n * as completely independent. No capability sharing across kinds.\n *\n * Source IDs require explicit TrustedEvidenceSourceGrant entries.\n * Registered principals are NOT automatically sources.\n *\n * Standalone validators (validateSourceGrantCriterionIds) are diagnostic\n * conveniences. This factory is the mandatory enforcement boundary.\n *\n * @deprecated The legacy two-argument form (principals, sourceGrants) is no\n * longer supported for trusted context creation. Use the params-object form\n * with a contract parameter instead.\n */\nexport function _internalCreateTrustedValidationContext(\n\tparamsOrContract:\n\t\t| {\n\t\t\t\tcontract: MissionContractV1;\n\t\t\t\tprincipals: Array<{\n\t\t\t\t\tprincipalId: string;\n\t\t\t\t\tprincipalKind: TrustedPrincipalKind;\n\t\t\t\t\tcapabilities: LedgerCapability[];\n\t\t\t\t}>;\n\t\t\t\tsourceGrants?: TrustedEvidenceSourceGrant[];\n\t\t  }\n\t\t| Array<{\n\t\t\t\tprincipalId: string;\n\t\t\t\tprincipalKind: TrustedPrincipalKind;\n\t\t\t\tcapabilities: LedgerCapability[];\n\t\t  }>,\n): TrustedValidationContext;\nexport function _internalCreateTrustedValidationContext(\n\tprincipals: Array<{\n\t\tprincipalId: string;\n\t\tprincipalKind: TrustedPrincipalKind;\n\t\tcapabilities: LedgerCapability[];\n\t}>,\n\tsourceGrants?: TrustedEvidenceSourceGrant[],\n): TrustedValidationContext;\nexport function _internalCreateTrustedValidationContext(\n\tparamsOrContract:\n\t\t| {\n\t\t\t\tcontract: MissionContractV1;\n\t\t\t\tprincipals: Array<{\n\t\t\t\t\tprincipalId: string;\n\t\t\t\t\tprincipalKind: TrustedPrincipalKind;\n\t\t\t\t\tcapabilities: LedgerCapability[];\n\t\t\t\t}>;\n\t\t\t\tsourceGrants?: TrustedEvidenceSourceGrant[];\n\t\t  }\n\t\t| Array<{\n\t\t\t\tprincipalId: string;\n\t\t\t\tprincipalKind: TrustedPrincipalKind;\n\t\t\t\tcapabilities: LedgerCapability[];\n\t\t  }>,\n): TrustedValidationContext {\n\t// Legacy call detection: if the first argument is an array, it's the old form.\n\tif (Array.isArray(paramsOrContract)) {\n\t\tthrow new Error(\n\t\t\t\"DEPRECATED: _internalCreateTrustedValidationContext(principals, sourceGrants) is no longer supported. \" +\n\t\t\t\t\"Use the params-object form: _internalCreateTrustedValidationContext({ contract, principals, sourceGrants }). \" +\n\t\t\t\t\"Every trusted validation context must be bound to a validated Mission Contract.\",\n\t\t);\n\t}\n\tconst { contract, principals, sourceGrants = [] } = paramsOrContract;\n\n\t// =========================================================================\n\t// Phase 0: Validate the Mission Contract itself\n\t// =========================================================================\n\n\tconst contractValidation = validateMissionContract(contract);\n\tif (!contractValidation.valid) {\n\t\tthrow new Error(`INVALID_MISSION_CONTRACT: ${contractValidation.errors.map((e) => e.message).join(\"; \")}`);\n\t}\n\n\t// =========================================================================\n\t// Phase 0b: Derive canonical contract digest\n\t// =========================================================================\n\n\tconst contractDigest = computeMissionContractDigest(contract);\n\n\t// =========================================================================\n\t// Phase 0c: Build requirement and global criterion registries\n\t// =========================================================================\n\n\tconst requirementIds = new Set<string>();\n\tconst globalCriterionIds = new Set<string>();\n\t// Criterion-to-requirement mapping for cross-scope coherence\n\tconst criterionToRequirement = new Map<string, string>();\n\n\tfor (const req of contract.requirements) {\n\t\trequirementIds.add(req.id);\n\t\tfor (const crit of req.acceptanceCriteria) {\n\t\t\tglobalCriterionIds.add(crit.id);\n\t\t\tcriterionToRequirement.set(crit.id, req.id);\n\t\t}\n\t}\n\n\t// =========================================================================\n\t// Validate and build principal lookup maps\n\t// =========================================================================\n\n\tconst principalMap = new Map<string, { kind: string; caps: ReadonlySet<string> }>();\n\n\tfor (const p of principals) {\n\t\t// Reject empty/whitespace IDs\n\t\tif (!p.principalId || p.principalId.trim().length === 0) {\n\t\t\tthrow new Error(`INVALID_TRUSTED_PRINCIPAL: empty principalId`);\n\t\t}\n\n\t\t// Reject unknown kinds\n\t\tif (!VALID_PRINCIPAL_KINDS.has(p.principalKind)) {\n\t\t\tthrow new Error(`INVALID_TRUSTED_PRINCIPAL: unknown kind \"${p.principalKind}\" for \"${p.principalId}\"`);\n\t\t}\n\n\t\t// Reject unknown capabilities\n\t\tfor (const cap of p.capabilities) {\n\t\t\tif (!ALL_CAPABILITIES.has(cap)) {\n\t\t\t\tthrow new Error(`INVALID_TRUSTED_CAPABILITY: unknown capability \"${cap}\" for \"${p.principalId}\"`);\n\t\t\t}\n\t\t}\n\n\t\tconst key = `${p.principalId}:${p.principalKind}`;\n\n\t\t// Reject duplicate exact tuples\n\t\tif (principalMap.has(key)) {\n\t\t\tthrow new Error(`DUPLICATE_TRUSTED_PRINCIPAL: \"${key}\" registered more than once`);\n\t\t}\n\n\t\t// Store immutable capability snapshot\n\t\tprincipalMap.set(\n\t\t\tkey,\n\t\t\tObject.freeze({\n\t\t\t\tkind: p.principalKind,\n\t\t\t\tcaps: new Set(p.capabilities),\n\t\t\t}),\n\t\t);\n\t}\n\n\t// =========================================================================\n\t// Validate and build source grant lookup\n\t// =========================================================================\n\n\tconst sourceGrantMap = new Map<string, TrustedEvidenceSourceGrant>();\n\n\tfor (let gi = 0; gi < sourceGrants.length; gi++) {\n\t\tconst grant = sourceGrants[gi];\n\n\t\t// Reject empty source IDs\n\t\tif (!grant.sourceId || grant.sourceId.trim().length === 0) {\n\t\t\tthrow new Error(\"INVALID_SOURCE_GRANT: empty sourceId\");\n\t\t}\n\n\t\t// Reject duplicate source IDs (preferred: one source ID → one grant)\n\t\tif (sourceGrantMap.has(grant.sourceId)) {\n\t\t\tthrow new Error(`DUPLICATE_SOURCE_GRANT: source \"${grant.sourceId}\" has conflicting grants`);\n\t\t}\n\n\t\t// Reject unknown principal tuple references\n\t\tconst principalKey = `${grant.principalId}:${grant.principalKind}`;\n\t\tconst principal = principalMap.get(principalKey);\n\t\tif (!principal) {\n\t\t\tthrow new Error(\n\t\t\t\t`INVALID_SOURCE_GRANT: source \"${grant.sourceId}\" references unknown principal \"${principalKey}\"`,\n\t\t\t);\n\t\t}\n\n\t\t// Reject non-evidence capabilities on sources\n\t\tif (!EVIDENCE_CAPABILITIES.has(grant.capability)) {\n\t\t\tthrow new Error(\n\t\t\t\t`INVALID_SOURCE_GRANT: source \"${grant.sourceId}\" has non-evidence capability \"${grant.capability}\"`,\n\t\t\t);\n\t\t}\n\n\t\t// Reject empty allowedEvidenceTypes\n\t\tif (!grant.allowedEvidenceTypes || grant.allowedEvidenceTypes.length === 0) {\n\t\t\tthrow new Error(`INVALID_SOURCE_GRANT: source \"${grant.sourceId}\" has empty allowedEvidenceTypes`);\n\t\t}\n\n\t\t// Reject duplicate values inside arrays\n\t\tconst evidenceTypes = new Set(grant.allowedEvidenceTypes);\n\t\tif (evidenceTypes.size !== grant.allowedEvidenceTypes.length) {\n\t\t\tthrow new Error(`INVALID_SOURCE_GRANT: source \"${grant.sourceId}\" has duplicate evidence types`);\n\t\t}\n\n\t\tif (grant.allowedCollectorClasses) {\n\t\t\tconst collectorSet = new Set(grant.allowedCollectorClasses);\n\t\t\tif (collectorSet.size !== grant.allowedCollectorClasses.length) {\n\t\t\t\tthrow new Error(`INVALID_SOURCE_GRANT: source \"${grant.sourceId}\" has duplicate collector classes`);\n\t\t\t}\n\t\t}\n\n\t\t// =====================================================================\n\t\t// Validate allowedRequirementIds against the contract\n\t\t// =====================================================================\n\t\tif (grant.allowedRequirementIds) {\n\t\t\tconst reqSeen = new Set<string>();\n\t\t\tfor (let rj = 0; rj < grant.allowedRequirementIds.length; rj++) {\n\t\t\t\tconst reqId = grant.allowedRequirementIds[rj];\n\n\t\t\t\t// Reject empty/whitespace\n\t\t\t\tif (!reqId || reqId.trim().length === 0) {\n\t\t\t\t\tthrow new Error(`sourceGrants[${gi}].allowedRequirementIds[${rj}]: empty requirement ID reference`);\n\t\t\t\t}\n\n\t\t\t\t// Reject leading/trailing whitespace\n\t\t\t\tif (reqId !== reqId.trim()) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`sourceGrants[${gi}].allowedRequirementIds[${rj}]: requirement ID has leading/trailing whitespace: \"${reqId}\"`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Reject unknown references\n\t\t\t\tif (!requirementIds.has(reqId)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`sourceGrants[${gi}].allowedRequirementIds[${rj}]: Unknown requirement id reference: ${reqId}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Reject duplicates\n\t\t\t\tif (reqSeen.has(reqId)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`sourceGrants[${gi}].allowedRequirementIds[${rj}]: duplicate requirement ID reference: ${reqId}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treqSeen.add(reqId);\n\t\t\t}\n\n\t\t\t// Additional: reject duplicate requirement IDs via Set check (handled above)\n\t\t}\n\n\t\t// =====================================================================\n\t\t// Validate allowedCriterionIds against the global criterion registry\n\t\t// =====================================================================\n\t\tif (grant.allowedCriterionIds) {\n\t\t\tconst critSeen = new Set<string>();\n\t\t\tfor (let cj = 0; cj < grant.allowedCriterionIds.length; cj++) {\n\t\t\t\tconst critId = grant.allowedCriterionIds[cj];\n\n\t\t\t\t// Reject empty criterion IDs\n\t\t\t\tif (critId.length === 0) {\n\t\t\t\t\tthrow new Error(`sourceGrants[${gi}].allowedCriterionIds[${cj}]: empty criterion ID reference`);\n\t\t\t\t}\n\n\t\t\t\t// Reject whitespace-only criterion IDs\n\t\t\t\tif (critId.trim().length === 0) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`sourceGrants[${gi}].allowedCriterionIds[${cj}]: whitespace-only criterion ID reference`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Reject leading/trailing whitespace\n\t\t\t\tif (critId !== critId.trim()) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`sourceGrants[${gi}].allowedCriterionIds[${cj}]: criterion ID has leading/trailing whitespace: \"${critId}\"`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Reject unknown criterion references\n\t\t\t\tif (!globalCriterionIds.has(critId)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`sourceGrants[${gi}].allowedCriterionIds[${cj}]: Unknown acceptance criterion id reference: ${critId}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Reject duplicates\n\t\t\t\tif (critSeen.has(critId)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`sourceGrants[${gi}].allowedCriterionIds[${cj}]: duplicate criterion ID reference: ${critId}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcritSeen.add(critId);\n\t\t\t}\n\n\t\t\t// =================================================================\n\t\t\t// Cross-scope coherence: when both allowedRequirementIds and\n\t\t\t// allowedCriterionIds are declared, every criterion must belong\n\t\t\t// to one of the allowed requirements.\n\t\t\t// =================================================================\n\t\t\tif (grant.allowedRequirementIds && grant.allowedRequirementIds.length > 0) {\n\t\t\t\tconst allowedReqSet = new Set(grant.allowedRequirementIds);\n\t\t\t\tfor (const critId of grant.allowedCriterionIds) {\n\t\t\t\t\tconst owningReq = criterionToRequirement.get(critId);\n\t\t\t\t\tif (owningReq && !allowedReqSet.has(owningReq)) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`sourceGrants[${gi}]: criterion \"${critId}\" belongs to requirement \"${owningReq}\" which is not in the allowedRequirementIds`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst frozenGrant: TrustedEvidenceSourceGrant = Object.freeze({\n\t\t\t...grant,\n\t\t\tallowedEvidenceTypes: Object.freeze([...grant.allowedEvidenceTypes]),\n\t\t\tallowedCollectorClasses:\n\t\t\t\tgrant.allowedCollectorClasses === undefined ? undefined : Object.freeze([...grant.allowedCollectorClasses]),\n\t\t\tallowedRequirementIds:\n\t\t\t\tgrant.allowedRequirementIds === undefined ? undefined : Object.freeze([...grant.allowedRequirementIds]),\n\t\t\tallowedCriterionIds:\n\t\t\t\tgrant.allowedCriterionIds === undefined ? undefined : Object.freeze([...grant.allowedCriterionIds]),\n\t\t});\n\t\tsourceGrantMap.set(frozenGrant.sourceId, frozenGrant);\n\t}\n\n\t// =========================================================================\n\t// Build frozen context\n\t// =========================================================================\n\n\tconst ctx: TrustedValidationContext = Object.freeze({\n\t\tverifyPrincipal(principalId: string, principalKind: string): boolean {\n\t\t\tconst key = `${principalId}:${principalKind}`;\n\t\t\treturn principalMap.has(key);\n\t\t},\n\n\t\tverifyCapability(principalId: string, principalKind: string, capability: string): boolean {\n\t\t\t// Exact tuple match only — no cross-kind borrowing\n\t\t\tconst key = `${principalId}:${principalKind}`;\n\t\t\tconst entry = principalMap.get(key);\n\t\t\tif (!entry) return false;\n\t\t\treturn entry.caps.has(capability);\n\t\t},\n\n\t\tverifyEvidenceSource(request: EvidenceSourceVerificationRequest): boolean {\n\t\t\t// Source must exist\n\t\t\tconst grant = sourceGrantMap.get(request.sourceId);\n\t\t\tif (!grant) return false;\n\n\t\t\t// Source must belong to the acting principal tuple\n\t\t\tif (grant.principalId !== request.principalId) return false;\n\t\t\tif (grant.principalKind !== request.principalKind) return false;\n\n\t\t\t// Source grant capability must match\n\t\t\tif (grant.capability !== request.capability) return false;\n\n\t\t\t// Evidence type must be allowed\n\t\t\tif (!grant.allowedEvidenceTypes.includes(request.evidenceType)) return false;\n\n\t\t\t// Collector class must be allowed when constrained\n\t\t\tif (\n\t\t\t\tgrant.allowedCollectorClasses &&\n\t\t\t\trequest.collectorClass &&\n\t\t\t\t!grant.allowedCollectorClasses.includes(request.collectorClass)\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Requirement restrictions when declared\n\t\t\tif (grant.allowedRequirementIds && request.requirementIds.length > 0) {\n\t\t\t\tfor (const reqId of request.requirementIds) {\n\t\t\t\t\tif (!grant.allowedRequirementIds.includes(reqId)) return false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Criterion restrictions when declared\n\t\t\tif (grant.allowedCriterionIds && request.criterionIds.length > 0) {\n\t\t\t\tfor (const critId of request.criterionIds) {\n\t\t\t\t\tif (!grant.allowedCriterionIds.includes(critId)) return false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn true;\n\t\t},\n\t});\n\n\t// =========================================================================\n\t// Phase final: Brand context AND bind to contract digest\n\t// Only after every validation gate passes.\n\t// =========================================================================\n\n\t_contractDigestMap.set(ctx, contractDigest);\n\t_trustedValidationContextSet.add(ctx);\n\treturn ctx;\n}\n\n/**\n * Retrieve the contract digest bound to a TrustedValidationContext.\n *\n * Returns undefined when the object is not a genuine trusted context.\n * This is an internal function — not exposed through the public API index.\n */\nexport function _getBoundContractDigest(ctx: TrustedValidationContext): string | undefined {\n\treturn _contractDigestMap.get(ctx);\n}\n\n// =============================================================================\n// Capability check helpers\n// =============================================================================\n\nexport function contextHasCapability(ctx: TrustedLedgerMutationContext, capability: LedgerCapability): boolean {\n\treturn ctx.capabilities.has(capability);\n}\n\nexport function contextHasAnyCapability(ctx: TrustedLedgerMutationContext, capabilities: LedgerCapability[]): boolean {\n\treturn capabilities.some((c) => ctx.capabilities.has(c));\n}\n\n// =============================================================================\n// Evidence capability to authority classification mapping\n// =============================================================================\n\nexport function capabilityToAuthority(capability: LedgerCapability): EvidenceAuthorityClassification | undefined {\n\tswitch (capability) {\n\t\tcase \"evidence:repository-observation\":\n\t\t\treturn \"repository-observation\";\n\t\tcase \"evidence:command-result\":\n\t\t\treturn \"command-result\";\n\t\tcase \"evidence:test-result\":\n\t\t\treturn \"test-result\";\n\t\tcase \"evidence:runtime-observation\":\n\t\t\treturn \"runtime-observation\";\n\t\tcase \"evidence:operator-confirmation\":\n\t\t\treturn \"operator-confirmation\";\n\t\tcase \"evidence:trusted-collector\":\n\t\t\treturn \"trusted-collector\";\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nexport function deriveEffectiveAuthority(\n\tctx: TrustedLedgerMutationContext,\n\tevidenceType: string,\n): EvidenceAuthorityClassification {\n\tconst hasEvidenceCap =\n\t\tctx.capabilities.has(\"evidence:test-result\") ||\n\t\tctx.capabilities.has(\"evidence:command-result\") ||\n\t\tctx.capabilities.has(\"evidence:repository-observation\") ||\n\t\tctx.capabilities.has(\"evidence:runtime-observation\") ||\n\t\tctx.capabilities.has(\"evidence:operator-confirmation\") ||\n\t\tctx.capabilities.has(\"evidence:trusted-collector\");\n\n\tif (!hasEvidenceCap) {\n\t\treturn \"agent-claim\";\n\t}\n\n\tconst typeMap: Record<string, { cap: LedgerCapability; authority: EvidenceAuthorityClassification }> = {\n\t\t\"test-result\": { cap: \"evidence:test-result\", authority: \"test-result\" },\n\t\t\"build-result\": { cap: \"evidence:command-result\", authority: \"command-result\" },\n\t\t\"command-result\": { cap: \"evidence:command-result\", authority: \"command-result\" },\n\t\t\"file-change\": { cap: \"evidence:repository-observation\", authority: \"repository-observation\" },\n\t\tcommit: { cap: \"evidence:repository-observation\", authority: \"repository-observation\" },\n\t\t\"repository-state\": { cap: \"evidence:repository-observation\", authority: \"repository-observation\" },\n\t\t\"runtime-observation\": { cap: \"evidence:runtime-observation\", authority: \"runtime-observation\" },\n\t\t\"operator-confirmation\": { cap: \"evidence:operator-confirmation\", authority: \"operator-confirmation\" },\n\t\tartifact: { cap: \"evidence:trusted-collector\", authority: \"trusted-collector\" },\n\t};\n\n\tconst mapping = typeMap[evidenceType];\n\tif (mapping && ctx.capabilities.has(mapping.cap)) {\n\t\treturn mapping.authority;\n\t}\n\n\tif (ctx.capabilities.has(\"evidence:trusted-collector\")) {\n\t\treturn \"trusted-collector\";\n\t}\n\n\treturn \"agent-claim\";\n}\n\n// =============================================================================\n// Source requirement helper — determines if a source is required\n// =============================================================================\n\n/**\n * Returns true when a non-empty source is required for the given evidence\n * and authority context. A missing/empty source must fail closed.\n */\nexport function isSourceRequiredForEvidence(params: {\n\teffectiveAuthority: EvidenceAuthorityClassification;\n\tcontractAuthoritativeSources?: readonly EvidenceAuthorityClassification[];\n\tcriterionRequiredEvidence?: {\n\t\tallowedTypes?: string[];\n\t\tminAuthority?: EvidenceAuthorityClassification;\n\t\trequiredCollectorClass?: string;\n\t\tminPassingStatus?: \"pass\";\n\t};\n}): boolean {\n\t// Source is required when effective authority is a non-agent-claim type\n\tif (params.effectiveAuthority !== \"agent-claim\") return true;\n\n\t// Source is required when contract declares authoritative sources\n\tif (params.contractAuthoritativeSources && params.contractAuthoritativeSources.length > 0) {\n\t\t// The contract requires authoritative evidence types — if the evidence\n\t\t// type matches one of these, a source is required\n\t\tif (params.contractAuthoritativeSources.includes(params.effectiveAuthority)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Source is required when criterion demands it (minAuthority, collector class)\n\tif (params.criterionRequiredEvidence) {\n\t\tif (\n\t\t\tparams.criterionRequiredEvidence.minAuthority &&\n\t\t\tparams.criterionRequiredEvidence.minAuthority !== \"agent-claim\"\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t\tif (params.criterionRequiredEvidence.requiredCollectorClass) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n"]}