import type { ConstraintStatus, WitnessObservationBasis, WitnessConflict } from '../../types/gateway.js'; import type { ScopeOfClaim } from '../accountability/types/base.js'; import { type IndependenceRelation } from './shares-root.js'; export type { SignerGraph, SignerNode, IndependenceRelation } from './shares-root.js'; export { sharesRoot, allPairwiseIndependence, independentSignerCount } from './shares-root.js'; /** * One mechanical fact: signer `signerId` produced a signature over `claim` * and the verifier checked it. `signatureValid` is the cryptographic * outcome; `tri-state` for an absent signer mirrors verifyBilateralReceipt, * where `null` means "no signature was present to check" (never `false`). * * No assurance level lives here. This is "who signed what, and did it * verify" - nothing more. */ export interface SignerClaim { /** Stable signer identity: Ed25519 public key hex, or a DID. */ signerId: string; /** Self-described role, carried through; never used for independence. */ role?: string; /** The claim this signature covers, named by a stable label * (e.g. 'outcome', 'witness:notary', 'gateway-countersignature'). */ claim: string; /** Cryptographic result. `null` = signer expected but no signature * present (absent-signer tri-state, matching BilateralReceiptVerification). */ signatureValid: boolean | null; /** How the verifier obtained the key behind this check, when the caller * recorded it (src/v2/verification-source). Optional and additive: a * claim without it is shaped exactly as before. One more mechanical * fact; never an input to independence or corroboration. */ verificationSource?: import('../verification-source/types.js').VerificationSource; } /** * One witness's mechanical observation facts. `observationBasis` reuses the * existing five-valued WitnessObservationBasis enum verbatim - the * descriptor does not invent a new strength vocabulary. `divergence` echoes * predictionError.divergence (0 = matched, 1 = fully unexpected) when the * witness reported one. */ export interface WitnessObservationFact { witnessId: string; /** HOW the witness observed. Categorical, not a score. */ observationBasis: WitnessObservationBasis; /** predictionError.divergence (0..1) if the witness reported one. */ divergence?: number; } /** * Evidence Descriptor: a verifier OUTPUT reporting exactly the mechanical * evidence facts present on one receipt. * * Every field is recomputable by the verifier from the receipt, its * signatures, the witness attestations, and the key/DID graph. No field is * read from an issuer-written assurance slot, because none exists. * * `corroborationStatus` is the lattice point: the four-valued Belnap * ConstraintStatus, not a 1..N score. */ export interface EvidenceDescriptor { /** Format version for additive evolution. */ version: 'aps:evidence-descriptor:v1'; /** Receipt this descriptor was computed over (id only; no body copied). */ receiptId: string; /** Every (signer, claim, signatureValid) fact the verifier checked. */ signerClaims: SignerClaim[]; /** Distinct signer identities present, sorted. Convenience view of the * signer set; derivable from signerClaims. */ signerSet: string[]; witnessObservations: WitnessObservationFact[]; /** True iff at least one WitnessConflict was supplied for this receipt. */ hasWitnessConflict: boolean; /** The conflict ids surfaced, sorted. Empty iff hasWitnessConflict false. */ witnessConflictIds: string[]; /** True iff every present signature verified and no signer that was * expected is missing. Generalized from BilateralReceiptVerification.valid. */ allSignaturesValid: boolean; /** Count of signatures that verified. */ validSignatureCount: number; /** Count of signers expected but with no signature present (tri-state null). */ absentSignerCount: number; /** Every pairwise sharesRoot relation, in stable order. */ independenceRelations: IndependenceRelation[]; /** Count of signers independent of every other signer (no shared root). */ independentSignerCount: number; /** True iff at least two signers exist and NO pair shares a root. */ fullyIndependent: boolean; /** Four-valued Belnap corroboration status (pass | fail | * not_applicable | unknown). NOT a scalar ladder. */ corroborationStatus: ConstraintStatus; /** What this descriptor claims and explicitly does NOT claim. */ scope_of_claim: ScopeOfClaim; } /** * A pre-checked signature fact handed to the descriptor builder. The * builder does NOT re-run crypto; it consumes verification results the * caller already produced (e.g. from verifyBilateralReceipt or * verifyWitnessAttestation) and arranges them as facts. This keeps signing * and canonicalization entirely in the existing modules and never touches * canonical-jcs.ts or any receipt preimage. * * `valid: null` means the signer was expected but no signature was present, * mirroring the absent-gateway tri-state of BilateralReceiptVerification. */ export interface CheckedSignature { signerId: string; role?: string; claim: string; /** Cryptographic outcome already computed by the caller. null = absent. */ valid: boolean | null; /** Anchors this signer chains to (issuer DID, gateway root, JWKS origin, * trust-anchor fingerprint). Feeds the independence graph. */ chainsTo?: string[]; /** How the caller obtained the key for this check, when it recorded that * (src/v2/verification-source). Echoed onto the SignerClaim fact; * never consulted by the independence graph or the corroboration * status. */ verificationSource?: import('../verification-source/types.js').VerificationSource; } export interface BuildDescriptorInput { receiptId: string; /** Pre-checked signatures (from verifyBilateralReceipt and friends). */ signatures: CheckedSignature[]; /** Witness observation facts (observationBasis + optional divergence). */ witnessObservations?: WitnessObservationFact[]; /** Any WitnessConflict events the verifier holds for this receipt. */ witnessConflicts?: WitnessConflict[]; /** Anchor equivalences for the independence graph (verifier-supplied). */ anchorEdges?: Array<[string, string]>; } /** * The shape returned by verifyBilateralReceipt. Imported structurally * rather than by type-import to keep this module free of a hard dependency * on the bilateral type module; the fields match exactly. */ export interface BilateralVerificationLike { valid: boolean; requestingAgentSignatureValid: boolean; servingAgentSignatureValid: boolean; /** null = no gateway signature present. */ gatewaySignatureValid: boolean | null; outcomeConsistent: boolean; timingValid: boolean; errors: string[]; } /** * Generalize a bilateral verification into the descriptor's signature * facts. This is the EXTENSION point the task calls for: rather than * writing a new multi-signature checker, the descriptor reads the result of * verifyBilateralReceipt and the receipt's signer identities and reshapes * them as (signer, claim, valid) facts plus their key/DID anchors. * * The two agents both sign the SAME outcome, so both carry claim 'outcome'. * The gateway, when present, countersigns the same body and carries claim * 'gateway-countersignature'; when absent it surfaces as a tri-state `null` * signer so the descriptor can report absence rather than failure. */ export declare function generalizeBilateralVerification(opts: { verification: BilateralVerificationLike; requestingAgentId: string; servingAgentId: string; gatewayId?: string; /** Anchors each party chains to, keyed by signer id. Verifier-supplied. */ anchors?: Record; }): CheckedSignature[]; /** * Build the Evidence Descriptor: a verifier OUTPUT over one receipt's * evidence. Pure over its input - identical input always yields an * identical descriptor, which is what makes the advisory scalar * reproducible. * * Reminder of the absolute rule: this reads no issuer-written assurance * field. Every input is either a cryptographic result the caller already * computed or a fact from the key/DID graph. */ export declare function buildEvidenceDescriptor(input: BuildDescriptorInput): EvidenceDescriptor; /** * Strength weights for the five-valued WitnessObservationBasis enum. These * grade observation STRENGTH using the existing vocabulary verbatim - no * new categories. They are a relying-party-policy default; a relying party * may substitute its own weights. Direct observation and independent * recomputation are the strongest bases; a receipt-only check is the weakest. */ export declare const DEFAULT_OBSERVATION_WEIGHTS: Record; /** * The single verifier-derived advisory scalar. It is computed PURELY from * an EvidenceDescriptor - it reads no receipt and no issuer field. It is a * RELYING-PARTY-POLICY view, not an assertion of truth: a relying party may * ignore it, recompute it from the descriptor, or replace the policy. * * Because it is a deterministic function of the descriptor, two parties * holding the same descriptor and the same weights always get the same * scalar. That reproducibility is the property the tests pin. */ export interface AdvisoryScalar { /** Label, hard: this is policy, not truth. */ kind: 'relying-party-policy'; /** 0..1 advisory corroboration strength. NOT a probability of truth. */ value: number; /** The Belnap status this scalar was computed against (echoed, for audit). */ basis: ConstraintStatus; /** One line naming what went into the scalar. Non-authoritative. */ rationale: string; } /** * Compute the advisory scalar from a descriptor. * * The scalar is grounded in the four-valued status first: * fail -> 0 (contradicted evidence) * not_applicable -> 0 (nothing to corroborate) * unknown -> capped low band (signers present but not independent) * pass -> scaled by independence and observation strength * * Within `pass`/`unknown`, independence dominates (it is the sharp metric) * and witness observation strength modulates. Self-attestation - witnesses * sharing a root - cannot lift the scalar, because those signers never add * an independent corroborator and so never raise independentSignerCount. */ export declare function computeAdvisoryScalar(descriptor: EvidenceDescriptor, weights?: Record): AdvisoryScalar; //# sourceMappingURL=descriptor.d.ts.map