/** * PEAC Interaction Evidence Types (v0.10.7+) * * Interaction evidence captures what happened during agent execution. * This is an extension type - stored at evidence.extensions["org.peacprotocol/interaction@0.1"] * * Design principles: * - Wire-stable: Uses extensions mechanism (NOT a top-level evidence field) * - Hash-only by default: Privacy-preserving content digests * - Open kind registry: Not a closed enum, converges through convention * - 1 receipt = 1 interaction: No batching (use bundles for that) * * @see docs/specs/INTERACTION-EVIDENCE.md */ import { z } from 'zod'; import type { JsonValue } from '@peac/kernel'; import type { PEACEnvelope } from './envelope.js'; import type { WorkflowContext } from './workflow.js'; /** * Extension key for interaction evidence * Used in evidence.extensions['org.peacprotocol/interaction@0.1'] */ export declare const INTERACTION_EXTENSION_KEY = "org.peacprotocol/interaction@0.1"; /** * Canonical digest algorithms (NORMATIVE) * * k = 1024 bytes (binary), m = 1024*1024 bytes (binary) * NO case-insensitivity, NO regex matching - strict canonical set only. */ export declare const CANONICAL_DIGEST_ALGS: readonly ["sha-256", "sha-256:trunc-64k", "sha-256:trunc-1m"]; /** * Size constants for digest truncation (NORMATIVE) */ export declare const DIGEST_SIZE_CONSTANTS: { readonly k: 1024; readonly m: number; readonly 'trunc-64k': 65536; readonly 'trunc-1m': 1048576; }; /** * Result status values for interaction outcomes */ export declare const RESULT_STATUSES: readonly ["ok", "error", "timeout", "canceled"]; /** * Redaction modes for payload references */ export declare const REDACTION_MODES: readonly ["hash_only", "redacted", "plaintext_allowlisted"]; /** * Policy decision values */ export declare const POLICY_DECISIONS: readonly ["allow", "deny", "constrained"]; /** * Well-known interaction kinds (informational, not normative) * * The kind field accepts any string matching the kind grammar. * These well-known values are listed in the PEAC registries for interop. * New kinds do NOT require protocol updates - just use the name. * * Custom kinds: use "custom:" or ":" */ export declare const WELL_KNOWN_KINDS: readonly ["tool.call", "http.request", "fs.read", "fs.write", "message", "inference.chat_completion"]; /** * Reserved kind prefixes (NORMATIVE) * * Kinds starting with these prefixes that are NOT in WELL_KNOWN_KINDS * MUST be rejected to prevent namespace pollution. */ export declare const RESERVED_KIND_PREFIXES: readonly ["peac.", "org.peacprotocol."]; /** * Interaction evidence limits (DoS protection) */ export declare const INTERACTION_LIMITS: { /** Maximum interaction ID length */ readonly maxInteractionIdLength: 256; /** Maximum kind length */ readonly maxKindLength: 128; /** Maximum platform name length */ readonly maxPlatformLength: 64; /** Maximum version string length */ readonly maxVersionLength: 64; /** Maximum plugin ID length */ readonly maxPluginIdLength: 128; /** Maximum tool name length */ readonly maxToolNameLength: 256; /** Maximum provider length */ readonly maxProviderLength: 128; /** Maximum URI length */ readonly maxUriLength: 2048; /** Maximum method length */ readonly maxMethodLength: 16; /** Maximum error code length */ readonly maxErrorCodeLength: 128; /** Maximum payment reference length */ readonly maxPaymentReferenceLength: 256; /** Maximum receipt RID length */ readonly maxReceiptRidLength: 128; }; /** * Kind format pattern * * Lowercase letters, digits, dots, underscores, colons, hyphens. * Must start with a letter, end with letter or digit. * Min 2 chars, max 128 chars. * * Examples: "tool.call", "http.request", "custom:com.example.foo" */ export declare const KIND_FORMAT_PATTERN: RegExp; /** * Extension key format pattern (NORMATIVE) * * Reverse-DNS domain + '/' + key name + optional version * Pattern: ^([a-z0-9-]+\.)+[a-z0-9-]+\/[a-z][a-z0-9._:-]{0,126}[a-z0-9](?:@[0-9]+(?:\.[0-9]+)*)?$ * * Examples: * - "com.example/foo" * - "org.peacprotocol/interaction@0.1" * - "io.vendor/custom-data" */ export declare const EXTENSION_KEY_PATTERN: RegExp; /** * Digest value format (64 lowercase hex chars) */ export declare const DIGEST_VALUE_PATTERN: RegExp; /** * Digest algorithm schema - strict canonical set */ export declare const DigestAlgSchema: z.ZodEnum<{ "sha-256": "sha-256"; "sha-256:trunc-64k": "sha-256:trunc-64k"; "sha-256:trunc-1m": "sha-256:trunc-1m"; }>; /** * Digest schema for privacy-preserving content hashing */ export declare const DigestSchema: z.ZodObject<{ alg: z.ZodEnum<{ "sha-256": "sha-256"; "sha-256:trunc-64k": "sha-256:trunc-64k"; "sha-256:trunc-1m": "sha-256:trunc-1m"; }>; value: z.ZodString; bytes: z.ZodNumber; }, z.core.$strict>; /** * Payload reference schema (on-wire, portable) */ export declare const PayloadRefSchema: z.ZodObject<{ digest: z.ZodObject<{ alg: z.ZodEnum<{ "sha-256": "sha-256"; "sha-256:trunc-64k": "sha-256:trunc-64k"; "sha-256:trunc-1m": "sha-256:trunc-1m"; }>; value: z.ZodString; bytes: z.ZodNumber; }, z.core.$strict>; redaction: z.ZodEnum<{ redacted: "redacted"; hash_only: "hash_only"; plaintext_allowlisted: "plaintext_allowlisted"; }>; }, z.core.$strict>; /** * Executor identity schema (who ran this) */ export declare const ExecutorSchema: z.ZodObject<{ platform: z.ZodString; version: z.ZodOptional; plugin_id: z.ZodOptional; plugin_digest: z.ZodOptional; value: z.ZodString; bytes: z.ZodNumber; }, z.core.$strict>>; }, z.core.$strict>; /** * Tool target schema (for tool.call kind) */ export declare const ToolTargetSchema: z.ZodObject<{ name: z.ZodString; provider: z.ZodOptional; version: z.ZodOptional; }, z.core.$strict>; /** * Resource target schema (for http/fs kinds) */ export declare const ResourceTargetSchema: z.ZodObject<{ uri: z.ZodOptional; method: z.ZodOptional; }, z.core.$strict>; /** * Execution result schema */ export declare const ResultSchema: z.ZodObject<{ status: z.ZodEnum<{ error: "error"; ok: "ok"; timeout: "timeout"; canceled: "canceled"; }>; error_code: z.ZodOptional; retryable: z.ZodOptional; }, z.core.$strict>; /** * Policy context schema (policy state at execution time) */ export declare const PolicyContextSchema: z.ZodObject<{ decision: z.ZodEnum<{ allow: "allow"; deny: "deny"; constrained: "constrained"; }>; sandbox_enabled: z.ZodOptional; elevated: z.ZodOptional; effective_policy_digest: z.ZodOptional; value: z.ZodString; bytes: z.ZodNumber; }, z.core.$strict>>; }, z.core.$strict>; /** * References schema (links to related evidence) */ export declare const RefsSchema: z.ZodObject<{ payment_reference: z.ZodOptional; related_receipt_rid: z.ZodOptional; }, z.core.$strict>; /** * Kind schema with format validation */ export declare const KindSchema: z.ZodString; /** * Interaction evidence schema with invariant refinements * * ALL REJECT invariants are enforced here. This ensures that * both direct schema validation and ordered validation produce * consistent results. */ export declare const InteractionEvidenceV01Schema: z.ZodObject<{ interaction_id: z.ZodString; kind: z.ZodString; executor: z.ZodObject<{ platform: z.ZodString; version: z.ZodOptional; plugin_id: z.ZodOptional; plugin_digest: z.ZodOptional; value: z.ZodString; bytes: z.ZodNumber; }, z.core.$strict>>; }, z.core.$strict>; tool: z.ZodOptional; version: z.ZodOptional; }, z.core.$strict>>; resource: z.ZodOptional; method: z.ZodOptional; }, z.core.$strict>>; input: z.ZodOptional; value: z.ZodString; bytes: z.ZodNumber; }, z.core.$strict>; redaction: z.ZodEnum<{ redacted: "redacted"; hash_only: "hash_only"; plaintext_allowlisted: "plaintext_allowlisted"; }>; }, z.core.$strict>>; output: z.ZodOptional; value: z.ZodString; bytes: z.ZodNumber; }, z.core.$strict>; redaction: z.ZodEnum<{ redacted: "redacted"; hash_only: "hash_only"; plaintext_allowlisted: "plaintext_allowlisted"; }>; }, z.core.$strict>>; started_at: z.ZodString; completed_at: z.ZodOptional; duration_ms: z.ZodOptional; result: z.ZodOptional; error_code: z.ZodOptional; retryable: z.ZodOptional; }, z.core.$strict>>; policy: z.ZodOptional; sandbox_enabled: z.ZodOptional; elevated: z.ZodOptional; effective_policy_digest: z.ZodOptional; value: z.ZodString; bytes: z.ZodNumber; }, z.core.$strict>>; }, z.core.$strict>>; refs: z.ZodOptional; related_receipt_rid: z.ZodOptional; }, z.core.$strict>>; extensions: z.ZodOptional>; }, z.core.$strict>; export type DigestAlg = z.infer; export type Digest = z.infer; export type PayloadRef = z.infer; export type Executor = z.infer; export type ToolTarget = z.infer; export type ResourceTarget = z.infer; export type ResultStatus = z.infer['status']; export type Result = z.infer; export type PolicyDecision = z.infer['decision']; export type PolicyContext = z.infer; export type Refs = z.infer; export type InteractionEvidenceV01 = z.infer; /** * Validation error with code and optional field path */ export interface ValidationError { /** Machine-readable error code (E_INTERACTION_*) */ code: string; /** Human-readable message */ message: string; /** JSON path to the problematic field */ field?: string; } /** * Validation warning with code and optional field path */ export interface ValidationWarning { /** Machine-readable warning code (W_INTERACTION_*) */ code: string; /** Human-readable message */ message: string; /** JSON path to the problematic field */ field?: string; } /** * Result of interaction evidence validation. * * Warning-capable API: returns both errors (fatal) and warnings (non-fatal). * This enables conformance testing with warning fixtures. */ export type InteractionValidationResult = { valid: true; value: InteractionEvidenceV01; warnings: ValidationWarning[]; } | { valid: false; errors: ValidationError[]; warnings: ValidationWarning[]; }; /** * Validate interaction evidence with explicit evaluation ordering. * * Returns canonical error codes per validation ordering. * This function does NOT depend on Zod's internal validation ordering. * Cross-language implementations MUST produce identical error_code values * for the same invalid input. * * Validation order: * 1. Required field presence * 2. Required field format (interaction_id, kind, started_at) * 3. Kind format and reserved prefix check * 4. Executor field validation * 5. Optional field format (completed_at, digests, etc.) * 6. Cross-field invariants (timing, output-result, error-detail) * 7. Extension key namespacing * 8. Target consistency (kind prefix -> target field) * * @param input - Raw input to validate * @returns Validation result with canonical error codes on failure */ export declare function validateInteractionOrdered(input: unknown): InteractionValidationResult; /** * Simple validation result for conformance harness compatibility. * * This matches the pattern used by other PEAC validators (workflow, etc.) * and allows conformance fixtures to test without needing to handle the * full warning-capable API shape. */ export interface SimpleValidationResult { /** Whether the input is valid */ valid: boolean; /** Error code on failure */ error_code?: string; /** Field path on failure */ error_field?: string; } /** * Validate interaction evidence (simple API for conformance harness) * * This is the recommended entry point for conformance testing. * Returns a simple result matching the existing harness contract. * * ## Warnings Contract * * This compat API intentionally **omits warnings** from the result. * Warnings are available via validateInteractionOrdered() for consumers * who explicitly opt in. Stable consumers should: * - Use this function for pass/fail validation * - Use validateInteractionOrdered() only when warnings are needed * * This prevents breaking changes if warning codes are added/modified. * * @param input - Raw input to validate * @returns Simple validation result with error_code on failure (no warnings) */ export declare function validateInteraction(input: unknown): SimpleValidationResult; /** * Validate interaction evidence (throwing) * * @param evidence - Object to validate * @returns Validated InteractionEvidenceV01 * @throws ZodError if validation fails */ export declare function validateInteractionEvidence(evidence: unknown): InteractionEvidenceV01; /** * Check if an object is valid interaction evidence (non-throwing) * * @param evidence - Object to check * @returns True if valid InteractionEvidenceV01 */ export declare function isValidInteractionEvidence(evidence: unknown): evidence is InteractionEvidenceV01; /** * Check if a kind is in the well-known registry * * @param kind - Kind string to check * @returns True if well-known */ export declare function isWellKnownKind(kind: string): kind is (typeof WELL_KNOWN_KINDS)[number]; /** * Check if a kind uses a reserved prefix * * @param kind - Kind string to check * @returns True if uses reserved prefix */ export declare function isReservedKindPrefix(kind: string): boolean; /** * Check if a digest uses truncation * * @param digest - Digest to check * @returns True if truncated */ export declare function isDigestTruncated(digest: Digest): boolean; /** * Get interaction evidence from a PEAC envelope * * @param receipt - PEAC envelope to read from * @returns Interaction evidence if present, undefined otherwise */ export declare function getInteraction(receipt: PEACEnvelope): InteractionEvidenceV01 | undefined; /** * Set interaction evidence on a PEAC envelope (mutates) * * @param receipt - PEAC envelope to modify * @param interaction - Interaction evidence to set */ export declare function setInteraction(receipt: PEACEnvelope, interaction: InteractionEvidenceV01): void; /** * Check if a PEAC envelope has interaction evidence * * @param receipt - PEAC envelope to check * @returns True if interaction evidence is present */ export declare function hasInteraction(receipt: PEACEnvelope): boolean; /** * ReceiptView - pure view layer that makes extensions feel like top-level fields * * Does NOT modify the underlying envelope; just provides convenient access. * This projection allows code to work with interaction evidence as if it were * a first-class field while maintaining wire format stability. */ export interface ReceiptView { /** The underlying envelope (unchanged) */ readonly envelope: PEACEnvelope; /** Interaction evidence (from extension) - feels like top-level */ readonly interaction?: InteractionEvidenceV01; /** Array form for uniform pipeline processing */ readonly interactions: readonly InteractionEvidenceV01[]; /** Workflow context (from auth.extensions) */ readonly workflow?: WorkflowContext; } /** * Create a view over a PEAC envelope that provides first-class access * to extension data without modifying the wire format. * * @param envelope - PEAC envelope to create view for * @returns ReceiptView with convenient accessors * * @example * const view = createReceiptView(envelope); * if (view.interaction) { * console.log(view.interaction.kind); * } */ export declare function createReceiptView(envelope: PEACEnvelope): ReceiptView; /** * Parameters for creating interaction evidence */ export interface CreateInteractionParams { interaction_id: string; kind: string; executor: { platform: string; version?: string; plugin_id?: string; plugin_digest?: Digest; }; tool?: { name: string; provider?: string; version?: string; }; resource?: { uri?: string; method?: string; }; input?: { digest: Digest; redaction: (typeof REDACTION_MODES)[number]; }; output?: { digest: Digest; redaction: (typeof REDACTION_MODES)[number]; }; started_at: string; completed_at?: string; duration_ms?: number; result?: { status: (typeof RESULT_STATUSES)[number]; error_code?: string; retryable?: boolean; }; policy?: { decision: (typeof POLICY_DECISIONS)[number]; sandbox_enabled?: boolean; elevated?: boolean; effective_policy_digest?: Digest; }; refs?: { payment_reference?: string; related_receipt_rid?: string; }; extensions?: Record; } /** * Create validated interaction evidence * * @param params - Interaction parameters * @returns Validated InteractionEvidenceV01 * @throws ZodError if validation fails */ export declare function createInteractionEvidence(params: CreateInteractionParams): InteractionEvidenceV01; //# sourceMappingURL=interaction.d.ts.map