@rulvar/core 1.57.0 → 1.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1035,6 +1035,90 @@ declare function maskSecrets(text: string): string;
1035
1035
  declare function maskSecretsDeep<T>(value: T): T;
1036
1036
  /** Convenience for hosts: masks a Json value (alias of the deep walk). */
1037
1037
  declare function maskSecretsJson(value: Json): Json;
1038
+ /** A compiled masking policy: text and deep-JSON forms of one pattern set. */
1039
+ interface SecretMasker {
1040
+ maskText(text: string): string;
1041
+ maskDeep<T>(value: T): T;
1042
+ }
1043
+ /**
1044
+ * Compiles the redaction policy: the DEFAULT credential pattern set
1045
+ * plus host-defined patterns (RV-217), for the telemetry boundary
1046
+ * (events and traces; never the journal, where lossless encryption is
1047
+ * the right tool). String patterns compile as global regexes; RegExp
1048
+ * patterns are recompiled with the global flag when it is missing, so
1049
+ * replace-all semantics always hold. An invalid pattern is a typed
1050
+ * ConfigError at compile time, before anything runs under the policy.
1051
+ */
1052
+ declare function compileSecretMasker(patterns?: ReadonlyArray<RegExp | string>, site?: string): SecretMasker;
1053
+ //#endregion
1054
+ //#region src/l0/encryption.d.ts
1055
+ /**
1056
+ * The KMS seam. `keyId` is a stable routing id stamped into every
1057
+ * envelope (a KMS key ARN or alias, or a local rotation label); the
1058
+ * two methods are the exact shape of KMS GenerateDataKey and Decrypt.
1059
+ * Both are called only inside `createEnvelopeEncryption`.
1060
+ */
1061
+ interface DataKeyProvider {
1062
+ readonly keyId: string;
1063
+ generateDataKey(): Promise<{
1064
+ plaintext: Bytes;
1065
+ wrapped: Bytes;
1066
+ }>;
1067
+ unwrapDataKey(wrapped: Bytes): Promise<Bytes>;
1068
+ }
1069
+ /**
1070
+ * The local reference DataKeyProvider: the key-encryption key is
1071
+ * HKDF-SHA256(secret, info), data keys are random 32-byte AES keys,
1072
+ * and wrapping is AES-256-GCM under the KEK. `info` partitions one
1073
+ * master secret into unrelated KEKs (tenant-scoped keys: one provider
1074
+ * per tenant with `info: tenantId`); a provider with different
1075
+ * secret or info CANNOT unwrap this provider's keys. For production
1076
+ * KMS, implement the same interface over GenerateDataKey/Decrypt.
1077
+ */
1078
+ declare function localKeyProvider(options: {
1079
+ secret: string | Bytes; /** Stamped into envelopes; default 'local:v1'. */
1080
+ keyId?: string; /** KEK partition label (e.g. a tenant id); default ''. */
1081
+ info?: string;
1082
+ }): DataKeyProvider;
1083
+ /** The journal envelope marker; a stored entry's whole value is this. */
1084
+ declare const JOURNAL_ENVELOPE_MARKER = "__rulvarEnvelope";
1085
+ interface EnvelopeEncryption {
1086
+ /** Pass as `createEngine({ serialization })`. */
1087
+ hook: SerializationHook;
1088
+ /** The provider's routing id, stamped into every envelope. */
1089
+ keyId: string;
1090
+ /**
1091
+ * The CURRENT wrapped data key. Every write stamps it into the
1092
+ * envelope, so nothing else must be persisted; it is exposed for
1093
+ * hosts that keep a rotation ledger.
1094
+ */
1095
+ wrappedDataKey: Bytes;
1096
+ }
1097
+ interface EnvelopeEncryptionOptions {
1098
+ provider: DataKeyProvider;
1099
+ /**
1100
+ * Wrapped data keys from earlier sessions or rotations that this
1101
+ * process must still read. Unwrapped once at creation; an envelope
1102
+ * carrying an UNREGISTERED wrapped key fails typed at read, naming
1103
+ * this list.
1104
+ */
1105
+ historicalWrappedKeys?: readonly Bytes[];
1106
+ /**
1107
+ * What a NON-enveloped stored entry or blob means at read:
1108
+ * 'reject' (default, fail closed) or 'passthrough' (explicit
1109
+ * migration mode for stores with pre-encryption history).
1110
+ */
1111
+ plaintextReads?: "reject" | "passthrough";
1112
+ }
1113
+ /**
1114
+ * Builds the envelope-encryption SerializationHook. All DataKeyProvider
1115
+ * calls happen HERE (the hook itself is synchronous, on in-memory data
1116
+ * keys): a fresh data key is minted and wrapped for this instance, and
1117
+ * every historical wrapped key is unwrapped for the read path.
1118
+ */
1119
+ declare function createEnvelopeEncryption(options: EnvelopeEncryptionOptions): Promise<EnvelopeEncryption>;
1120
+ /** Guards against non-constant-time comparisons in host key checks. */
1121
+ declare function constantTimeEqual(a: Bytes, b: Bytes): boolean;
1038
1122
  //#endregion
1039
1123
  //#region src/l0/usage.d.ts
1040
1124
  /**
@@ -5446,12 +5530,18 @@ interface CreateEngineOptions {
5446
5530
  */
5447
5531
  serialization?: SerializationHook;
5448
5532
  /**
5449
- * The default key-masking policy at the telemetry boundary. Default
5450
- * ON: key-shaped strings in every
5451
- * emitted WorkflowEvent are masked; never touches the journal.
5533
+ * The masking policy at the telemetry boundary. Default ON:
5534
+ * key-shaped strings in every emitted WorkflowEvent are masked;
5535
+ * never touches the journal (lossless encryption via `serialization`
5536
+ * is the persistence-side tool). `patterns` adds host-defined
5537
+ * redaction on top of the default credential set (RV-217): RegExp or
5538
+ * pattern strings, compiled once at construction, applied to every
5539
+ * string in every emitted event body. Feed the same patterns to the
5540
+ * OTel exporter for trace parity.
5452
5541
  */
5453
5542
  redaction?: {
5454
5543
  maskEvents?: boolean;
5544
+ patterns?: ReadonlyArray<RegExp | string>;
5455
5545
  };
5456
5546
  /**
5457
5547
  * Bare-nondeterminism detection over in-process workflow bodies
@@ -5465,6 +5555,21 @@ interface CreateEngineOptions {
5465
5555
  * runtime frames are classified exempt and stay silent.
5466
5556
  */
5467
5557
  determinism?: DeterminismConfig;
5558
+ /**
5559
+ * Metadata protection knobs (RV-217). `argsHashSalt` switches the
5560
+ * RunMeta.argsHash digest from plain sha256 to HMAC-SHA256 under the
5561
+ * salt: equal args stop correlating across deployments and
5562
+ * low-entropy args stop being recoverable from the digest. The salt
5563
+ * is deployment config, not a per-run secret: every engine (and the
5564
+ * CLI host config) resuming this store's runs must carry the SAME
5565
+ * salt, or the resume args gate refuses matching args. Runs recorded
5566
+ * before the salt keep their unsalted digests; the gate then simply
5567
+ * mismatches until forced, so introduce the salt on a fresh store or
5568
+ * accept --allow-args-change on legacy runs.
5569
+ */
5570
+ security?: {
5571
+ argsHashSalt?: string;
5572
+ };
5468
5573
  }
5469
5574
  interface RunOptions {
5470
5575
  /** Explicit id; otherwise the engine mints a ULID. */
@@ -5590,6 +5695,35 @@ interface Engine {
5590
5695
  pruneRun(runId: string, opts?: {
5591
5696
  lease?: Lease;
5592
5697
  }): Promise<number>;
5698
+ /**
5699
+ * Portable run export (RV-217): the meta record, every journal
5700
+ * entry, and every transcript blob, read through Engine.stores (the
5701
+ * one policy point), so an encrypted deployment exports PLAINTEXT
5702
+ * for a subject-access request or a store migration, without raw
5703
+ * store spelunking. Blobs are materialized in memory; export runs
5704
+ * one at a time, not catalogs.
5705
+ */
5706
+ exportRun(runId: string): Promise<RunExport>;
5707
+ /**
5708
+ * Imports a bundle produced by exportRun, under its ORIGINAL runId
5709
+ * (transcript refs and journal fields embed it; rewriting ids is
5710
+ * deliberately out of scope). Writes through Engine.stores, so an
5711
+ * encrypting target re-encrypts under its own policy. Refuses typed
5712
+ * when the run already exists in the target store, so an import can
5713
+ * never interleave with live history.
5714
+ */
5715
+ importRun(bundle: RunExport): Promise<void>;
5716
+ }
5717
+ /** The portable bundle exportRun produces and importRun consumes (RV-217). */
5718
+ interface RunExport {
5719
+ runId: string;
5720
+ /** Absent when the source store had no meta row for the run. */
5721
+ meta?: RunMeta;
5722
+ entries: JournalEntry[];
5723
+ blobs: Array<{
5724
+ ref: string;
5725
+ data: Bytes;
5726
+ }>;
5593
5727
  }
5594
5728
  /** Content hash of an in-process workflow body (run-to-definition binding). */
5595
5729
  declare function hashWorkflowBody(wf: Workflow<never, never> | Workflow<unknown, unknown>): string;
@@ -5613,7 +5747,9 @@ declare function workflowSourceRef(runId: string): string;
5613
5747
  * sensitive-derived metadata, not a value safe to publish (see the
5614
5748
  * `argsHash` field docs).
5615
5749
  */
5616
- declare function hashRunArgs(args: unknown): string | undefined;
5750
+ declare function hashRunArgs(args: unknown, options?: {
5751
+ salt?: string;
5752
+ }): string | undefined;
5617
5753
  /**
5618
5754
  * sha256 hex over the JCS canonical serialization of a run's result
5619
5755
  * value: the digest the engine records as `outputHash` on the journaled
@@ -7545,6 +7681,37 @@ declare function implementationAgentProfile(options?: AgentProfileTemplateOption
7545
7681
  */
7546
7682
  declare function reviewAgentProfile(options?: AgentProfileTemplateOptions): AgentProfile;
7547
7683
  //#endregion
7684
+ //#region src/engine/audit.d.ts
7685
+ type AuditCategory = "suspension" | "resolution" | "abandon" | "decision" | "termination-denied" | "run-settle";
7686
+ /** One reviewable authority event, in journal order. */
7687
+ interface AuditRecord {
7688
+ /** The journal seq of the entry behind this record. */
7689
+ seq: number;
7690
+ /** The entry's startedAt timestamp. */
7691
+ at: string;
7692
+ scope: string;
7693
+ category: AuditCategory;
7694
+ /**
7695
+ * The finer type: the suspension kind ('external' | 'approval') for
7696
+ * suspensions, the journaled decisionType for decisions.
7697
+ */
7698
+ type?: string;
7699
+ /** Who acted: a ResolutionBy for resolutions, 'engine' for decisions. */
7700
+ by?: string;
7701
+ /** The seq of the entry this record acts on (resolution/abandon target). */
7702
+ target?: number;
7703
+ /** One deterministic reviewable line. */
7704
+ summary: string;
7705
+ /** The journaled payload, verbatim (plaintext through Engine.stores). */
7706
+ value?: Json;
7707
+ }
7708
+ /**
7709
+ * Folds a loaded journal into the audit trail, in seq order. Pass the
7710
+ * FULL entry list (`Engine.stores.journal.load(runId)` or
7711
+ * `exportRun(runId).entries`); filtering is the reducer's job.
7712
+ */
7713
+ declare function reduceAuditTrail(entries: readonly JournalEntry[]): AuditRecord[];
7714
+ //#endregion
7548
7715
  //#region src/journal/scope.d.ts
7549
7716
  /**
7550
7717
  * Scope-path grammar (M1-T04): deterministic structural paths, independent
@@ -8114,7 +8281,7 @@ declare class EventBus {
8114
8281
  private readonly runId;
8115
8282
  private readonly spans;
8116
8283
  private readonly now;
8117
- private readonly maskEvents;
8284
+ private readonly mask;
8118
8285
  private readonly subscribers;
8119
8286
  private readonly listeners;
8120
8287
  private seq;
@@ -8131,6 +8298,12 @@ declare class EventBus {
8131
8298
  */
8132
8299
  maskEvents?: boolean;
8133
8300
  /**
8301
+ * The compiled masking policy applied when maskEvents is on
8302
+ * (RV-217): the default credential set plus host patterns. Absent
8303
+ * falls back to the default maskSecretsDeep.
8304
+ */
8305
+ mask?: (body: WorkflowEventBody) => WorkflowEventBody;
8306
+ /**
8134
8307
  * First seq value (default 0): the resumed-segment base that keeps
8135
8308
  * seq strictly increasing per run across segments (v1.22.0 review
8136
8309
  * P1-2).
@@ -8311,4 +8484,4 @@ interface SandboxBridge {
8311
8484
  declare const SANDBOX_AGENT_OPT_KEYS: readonly string[];
8312
8485
  declare function createSandboxBridge(ctx: Ctx<never>, options: SandboxBridgeOptions): SandboxBridge;
8313
8486
  //#endregion
8314
- export { AWAIT_SCHEMA, AbandonAttempt, AbandonFold, AbandonPayload, AbandonedSpendView, AbortClass, type AdaptiveEvents, AdmissionController, AdmissionDecision, AdmissionRejectedError, AdmissionStatsBefore, AdmitLineage, AdmitRejectReason, AdmitSpec, AdmitVerdict, AgentCallError, AgentError, type AgentEvents, AgentIdentityInput, type AgentInvocationRow, AgentOpts, AgentProfile, AgentProfilePermissions, AgentProfileTemplateOptions, AgentResult, AgentResultMeta, AgentStatus, ApproachSignatureInputs, ApprovalDecision, ApprovalIdentityInput, Artifact, AttemptOutcomeClass, AuditRunsOptions, BUDGET_ABORT_REASON, BaseAppend, BriefOpts, BudgetAccountView, BudgetDefaults, BudgetExhaustedError, BudgetExhaustionDiagnostics, BudgetHooks, BudgetReserve, type Bytes, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, CacheHint, CacheTtl, CanUseTool, CanonicalId, CanonicalIdentity, CanonicalLadderSpec, CanonicalModelSpec, ChatEvent, ChatRequest, CheckpointState, ChildArtifactPage, ChildIdentityInput, ChildResultPage, type ClaimClass, type ClaimOp, type ClaimStatus, ClaimValidationOptions, CollectOpts, CollectedTurn, CompactionConfig, CompiledPermissionChain, CompiledWorkflow, ConfigError, type CoreEvents, CostAttribution, CostAttributionFacts, CostReport, CreateEngineOptions, type CriticalPath, Ctx, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DEFAULT_SYNTHESIS_NOTE_MAX_TURNS, DebitResult, DeclaredLadder, DedupIndex, DedupNote, DedupedClaims, DerivedKey, DeriverRegistry, type DeterminismConfig, DeterminismError, type DeterminismEvents, type DeterminismMode, DispositionRule, DispositionTable, DonorCandidate, DonorRef, DroppedItem, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EffectiveUsageLimits, Effort, Engine, EngineDefaults, EngineQuotaConfig, EngineQuotaRuntime, EntryKind, EntryRef, EntryStatus, ErrorClass, ErrorCode, ErrorPolicy, EscalatedResult, EscalationDecision, EscalationDecisionAbortedError, EscalationDigest, EscalationKind, EscalationLimits, EscalationOptions, EscalationReport, EscalationRequest, EventBus, type EvidenceRef, type ExplorationSummary, ExtensionAppendInput, ExtensionDispatchSpec, ExternalIdentityInput, ExternalRegistry, ExtractNecessityInput, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailRunError, FailoverTarget, FailoverTrigger, FallbackField, FallbackTrigger, FileModelKnowledgeStore, FileModelKnowledgeStoreOptions, FileTranscriptStore, FinishInfo, FinishValidationChild, FinishValidationInput, FinishValidationSpec, FinishValidationVerdict, FinishValidator, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, Gate, GateAudit, type GateRecord, GitWorktreeProvider, GitWorktreeProviderOptions, GraftBoot, HashVersion, HookVerdict, IMPLEMENTATION_PROFILE_LIMITS, INBOX_PROPOSAL_TTL_DAYS, IdentityInput, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, IncrementalSynthesisResult, InvalidResolutionError, InvocationRole, type InvocationTable, type IsolationProvider, type IsolationSpec, Issue$1 as Issue, JournalCompatSubCode, JournalCompatibilityError, JournalEntry, JournalMatcher, JournalMissError, JournalOperation, JournalOrderViolation, JournalSerializationHook, type JournalStore, type Json, JsonSchema, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, type KbProposal, type KbProposalTrigger, KeyDeriver, KeyRing, KeyedLimiter, KnowledgeCasError, type KnowledgeSnapshot, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LadderSpec, type LeasableStore, type Lease, LeaseHeldError, Ledger, LineageCounters, LineageIndex, LineageRef, LineageRelation, LineageStats, LogicalTaskId, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_DEPTH_CEILING, MatchResult, McpConfig, McpToolSource, MechanicalGateProfile, MechanicalGateVerdict, MemoryQuotaLimiter, type MetaLookupStore, type ModelCaps, ModelChoice, type ModelClaim, ModelEpochInputs, type ModelKnowledgeHandle, type ModelKnowledgeStore, ModelListConstraint, ModelRef, ModelRetry, ModelSpec, Msg, NoProgressDetector, NodeId, NodeLinkValue, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OnEscalation, OperationDisposition, OrchestrateAcceptance, OrchestrateOptions, OrchestrateSynthesis, OrchestratorBudgetSpec, OrchestratorCapConfigError, OrchestratorExtension, OrchestratorExtensionIO, OrchestratorRuntime, Out, PARALLEL_AGENTS_SCHEMA, PROGRESS_REPORT_TOOL_NAME, ParallelSiteCounter, Part, PendingExternal, PendingToolTurn, PermissionConfig, PermissionGate, PermissionHook, PermissionPreset, PermissionRule, PermissionVerdict, type PhaseRow, PhaseTarget, PipelineCollected, PipelineOpts, PlanInvariantError, PriceTable, PricedUsage, type Pricing, type PricingTier, ProgressReport, type ProviderAdapter, QUOTA_WINDOW_MS, QualityFloors, QuotaCounters, type QuotaDecision, type QuotaEstimate, type QuotaLimiter, type QuotaReservationRequest, QuotaRule, QuotaWindowSnapshot, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, RESEARCH_PROFILE_LIMITS, REVIEW_PROFILE_LIMITS, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, RandIdentityInput, RandPayload, ReconcileOptions, ReconcileResult, RefEntryAppender, RefEntryClassification, RefusalInfo, RepeatedClaim, ReplayDisposition, ReplayMode, ReplayPlanHashMismatch, Replayer, RepositoryResearchToolset, RepositoryResearchToolsetOptions, ResearchAgentProfileOptions, ResearchAgentProfileResult, ResearchEvidenceEntry, ResolutionArbiter, ResolutionAttempt, ResolutionBy, ResolutionFold, ResolutionLayer, ResolutionOutcome, ResolutionPayload, ResolvedInvocation, ResolvedToolset, ResumeHandle, ResumeOptions, ResumePreview, ResumeReport, RetryClass, RetryPolicy, ReuseConfig, RiskRuleValue, Role, RulvarError, RulvarErrorCode, RunAgentOptions, RunAuditVerdict, RunBudget, RunEventSink, type RunFilter, RunHandle, RunInternals, type RunMeta, RunOptions, RunOutcome, RunProfile, RunStateAudit, RunStatus, RuntimeEventSink, SANDBOX_AGENT_OPT_KEYS, SPAWN_AGENT_SCHEMA, SandboxBridge, SandboxBridgeOptions, SandboxError, SandboxHostToWorker, SandboxMethod, SandboxWorkerToHost, SchemaPair, SchemaSpec, SchemaValidationResult, ScopeSegment, ScriptRejected, ScriptRunner, ScrubNote, Semaphore, SerializationHook, Settled, ShellPatternRules, ShellSegment, ShellVerdict, SinglePhaseAppend, SpanMinter, SpanRegistry, SpawnAdmissionValue, SpawnAgentParams, SpawnKey, SpawnLineage, SpawnLineageOpt, SpawnOrigin, SpawnRecord, Spend, Stage, type StandardJSONSchemaV1, type StandardSchemaV1, StepIdentityInput, StructuredOutputTier, SuspendedAppend, SuspensionState, TOOL_NAME_PATTERN, type TaskClass, TaskDigest, TaskSpec, TerminalPatch, TerminationAccount, TerminationAccountSnapshot, TerminationDeniedValue, TerminationDeniedWriter, TerminationInitValue, TerminationLimits, TerminationResource, ToolCallRequest, ToolChoice, type ToolContext, ToolContextSeed, ToolContract, type ToolDef, type ToolEvents, type ToolExecutor, ToolInit, type ToolRisk, ToolRuntime, type ToolSource, type ToolSourceSession, ToolsOption, TranscriptSerializationHook, type TranscriptStore, TriggerClass, TtlState, Usage, UsageLimits, UsageSlice, VerifiedRecommendation, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, WakeBudgetBlock, WakeDigest, WakeTrigger, WireError, Workflow, WorkflowCallOpts, type WorkflowEvent, type WorkflowEventBody, WorkflowRegistry, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, atCompactionThreshold, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, dedupeRepeatedClaims, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidencePreservedValidator, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, identityJcs, implementationAgentProfile, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, latestProgressReport, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, memoryQuotaLimiter, mergeQuotaDenial, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, progressReportTool, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, quotaActualTokens, quotaEstimateTokens, quotaRuleAdmission, quotaRuleMatches, readRunMeta, readTerminationInit, reconcileRunMeta, reduceCriticalPath, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, repositoryResearchToolset, requiredFieldsValidator, requiredSectionsValidator, researchAgentProfile, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, reviewAgentProfile, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, snapshotUsage, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, usageViolations, validateEditorialCommit, validateEngineQuotaConfig, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateQuotaRules, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateUsageLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
8487
+ export { AWAIT_SCHEMA, AbandonAttempt, AbandonFold, AbandonPayload, AbandonedSpendView, AbortClass, type AdaptiveEvents, AdmissionController, AdmissionDecision, AdmissionRejectedError, AdmissionStatsBefore, AdmitLineage, AdmitRejectReason, AdmitSpec, AdmitVerdict, AgentCallError, AgentError, type AgentEvents, AgentIdentityInput, type AgentInvocationRow, AgentOpts, AgentProfile, AgentProfilePermissions, AgentProfileTemplateOptions, AgentResult, AgentResultMeta, AgentStatus, ApproachSignatureInputs, ApprovalDecision, ApprovalIdentityInput, Artifact, AttemptOutcomeClass, AuditCategory, AuditRecord, AuditRunsOptions, BUDGET_ABORT_REASON, BaseAppend, BriefOpts, BudgetAccountView, BudgetDefaults, BudgetExhaustedError, BudgetExhaustionDiagnostics, BudgetHooks, BudgetReserve, type Bytes, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, CacheHint, CacheTtl, CanUseTool, CanonicalId, CanonicalIdentity, CanonicalLadderSpec, CanonicalModelSpec, ChatEvent, ChatRequest, CheckpointState, ChildArtifactPage, ChildIdentityInput, ChildResultPage, type ClaimClass, type ClaimOp, type ClaimStatus, ClaimValidationOptions, CollectOpts, CollectedTurn, CompactionConfig, CompiledPermissionChain, CompiledWorkflow, ConfigError, type CoreEvents, CostAttribution, CostAttributionFacts, CostReport, CreateEngineOptions, type CriticalPath, Ctx, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DEFAULT_SYNTHESIS_NOTE_MAX_TURNS, DataKeyProvider, DebitResult, DeclaredLadder, DedupIndex, DedupNote, DedupedClaims, DerivedKey, DeriverRegistry, type DeterminismConfig, DeterminismError, type DeterminismEvents, type DeterminismMode, DispositionRule, DispositionTable, DonorCandidate, DonorRef, DroppedItem, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EffectiveUsageLimits, Effort, Engine, EngineDefaults, EngineQuotaConfig, EngineQuotaRuntime, EntryKind, EntryRef, EntryStatus, EnvelopeEncryption, EnvelopeEncryptionOptions, ErrorClass, ErrorCode, ErrorPolicy, EscalatedResult, EscalationDecision, EscalationDecisionAbortedError, EscalationDigest, EscalationKind, EscalationLimits, EscalationOptions, EscalationReport, EscalationRequest, EventBus, type EvidenceRef, type ExplorationSummary, ExtensionAppendInput, ExtensionDispatchSpec, ExternalIdentityInput, ExternalRegistry, ExtractNecessityInput, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailRunError, FailoverTarget, FailoverTrigger, FallbackField, FallbackTrigger, FileModelKnowledgeStore, FileModelKnowledgeStoreOptions, FileTranscriptStore, FinishInfo, FinishValidationChild, FinishValidationInput, FinishValidationSpec, FinishValidationVerdict, FinishValidator, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, Gate, GateAudit, type GateRecord, GitWorktreeProvider, GitWorktreeProviderOptions, GraftBoot, HashVersion, HookVerdict, IMPLEMENTATION_PROFILE_LIMITS, INBOX_PROPOSAL_TTL_DAYS, IdentityInput, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, IncrementalSynthesisResult, InvalidResolutionError, InvocationRole, type InvocationTable, type IsolationProvider, type IsolationSpec, Issue$1 as Issue, JOURNAL_ENVELOPE_MARKER, JournalCompatSubCode, JournalCompatibilityError, JournalEntry, JournalMatcher, JournalMissError, JournalOperation, JournalOrderViolation, JournalSerializationHook, type JournalStore, type Json, JsonSchema, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, type KbProposal, type KbProposalTrigger, KeyDeriver, KeyRing, KeyedLimiter, KnowledgeCasError, type KnowledgeSnapshot, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LadderSpec, type LeasableStore, type Lease, LeaseHeldError, Ledger, LineageCounters, LineageIndex, LineageRef, LineageRelation, LineageStats, LogicalTaskId, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_DEPTH_CEILING, MatchResult, McpConfig, McpToolSource, MechanicalGateProfile, MechanicalGateVerdict, MemoryQuotaLimiter, type MetaLookupStore, type ModelCaps, ModelChoice, type ModelClaim, ModelEpochInputs, type ModelKnowledgeHandle, type ModelKnowledgeStore, ModelListConstraint, ModelRef, ModelRetry, ModelSpec, Msg, NoProgressDetector, NodeId, NodeLinkValue, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OnEscalation, OperationDisposition, OrchestrateAcceptance, OrchestrateOptions, OrchestrateSynthesis, OrchestratorBudgetSpec, OrchestratorCapConfigError, OrchestratorExtension, OrchestratorExtensionIO, OrchestratorRuntime, Out, PARALLEL_AGENTS_SCHEMA, PROGRESS_REPORT_TOOL_NAME, ParallelSiteCounter, Part, PendingExternal, PendingToolTurn, PermissionConfig, PermissionGate, PermissionHook, PermissionPreset, PermissionRule, PermissionVerdict, type PhaseRow, PhaseTarget, PipelineCollected, PipelineOpts, PlanInvariantError, PriceTable, PricedUsage, type Pricing, type PricingTier, ProgressReport, type ProviderAdapter, QUOTA_WINDOW_MS, QualityFloors, QuotaCounters, type QuotaDecision, type QuotaEstimate, type QuotaLimiter, type QuotaReservationRequest, QuotaRule, QuotaWindowSnapshot, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, RESEARCH_PROFILE_LIMITS, REVIEW_PROFILE_LIMITS, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, RandIdentityInput, RandPayload, ReconcileOptions, ReconcileResult, RefEntryAppender, RefEntryClassification, RefusalInfo, RepeatedClaim, ReplayDisposition, ReplayMode, ReplayPlanHashMismatch, Replayer, RepositoryResearchToolset, RepositoryResearchToolsetOptions, ResearchAgentProfileOptions, ResearchAgentProfileResult, ResearchEvidenceEntry, ResolutionArbiter, ResolutionAttempt, ResolutionBy, ResolutionFold, ResolutionLayer, ResolutionOutcome, ResolutionPayload, ResolvedInvocation, ResolvedToolset, ResumeHandle, ResumeOptions, ResumePreview, ResumeReport, RetryClass, RetryPolicy, ReuseConfig, RiskRuleValue, Role, RulvarError, RulvarErrorCode, RunAgentOptions, RunAuditVerdict, RunBudget, RunEventSink, RunExport, type RunFilter, RunHandle, RunInternals, type RunMeta, RunOptions, RunOutcome, RunProfile, RunStateAudit, RunStatus, RuntimeEventSink, SANDBOX_AGENT_OPT_KEYS, SPAWN_AGENT_SCHEMA, SandboxBridge, SandboxBridgeOptions, SandboxError, SandboxHostToWorker, SandboxMethod, SandboxWorkerToHost, SchemaPair, SchemaSpec, SchemaValidationResult, ScopeSegment, ScriptRejected, ScriptRunner, ScrubNote, SecretMasker, Semaphore, SerializationHook, Settled, ShellPatternRules, ShellSegment, ShellVerdict, SinglePhaseAppend, SpanMinter, SpanRegistry, SpawnAdmissionValue, SpawnAgentParams, SpawnKey, SpawnLineage, SpawnLineageOpt, SpawnOrigin, SpawnRecord, Spend, Stage, type StandardJSONSchemaV1, type StandardSchemaV1, StepIdentityInput, StructuredOutputTier, SuspendedAppend, SuspensionState, TOOL_NAME_PATTERN, type TaskClass, TaskDigest, TaskSpec, TerminalPatch, TerminationAccount, TerminationAccountSnapshot, TerminationDeniedValue, TerminationDeniedWriter, TerminationInitValue, TerminationLimits, TerminationResource, ToolCallRequest, ToolChoice, type ToolContext, ToolContextSeed, ToolContract, type ToolDef, type ToolEvents, type ToolExecutor, ToolInit, type ToolRisk, ToolRuntime, type ToolSource, type ToolSourceSession, ToolsOption, TranscriptSerializationHook, type TranscriptStore, TriggerClass, TtlState, Usage, UsageLimits, UsageSlice, VerifiedRecommendation, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, WakeBudgetBlock, WakeDigest, WakeTrigger, WireError, Workflow, WorkflowCallOpts, type WorkflowEvent, type WorkflowEventBody, WorkflowRegistry, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, atCompactionThreshold, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileSecretMasker, compileVerifiedLayer, constantTimeEqual, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createEnvelopeEncryption, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, dedupeRepeatedClaims, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidencePreservedValidator, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, identityJcs, implementationAgentProfile, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, latestProgressReport, lexShellCommand, liftRetainedParts, lineageWeightOf, localKeyProvider, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, memoryQuotaLimiter, mergeQuotaDenial, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, progressReportTool, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, quotaActualTokens, quotaEstimateTokens, quotaRuleAdmission, quotaRuleMatches, readRunMeta, readTerminationInit, reconcileRunMeta, reduceAuditTrail, reduceCriticalPath, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, repositoryResearchToolset, requiredFieldsValidator, requiredSectionsValidator, researchAgentProfile, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, reviewAgentProfile, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, snapshotUsage, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, usageViolations, validateEditorialCommit, validateEngineQuotaConfig, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateQuotaRules, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateUsageLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createHash, getRandomValues, randomUUID } from "node:crypto";
1
+ import { createCipheriv, createDecipheriv, createHash, createHmac, getRandomValues, hkdfSync, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
2
2
  import { appendFileSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
3
3
  import path, { dirname, join, resolve, sep } from "node:path";
4
4
  import { Client } from "@modelcontextprotocol/sdk/client";
@@ -491,6 +491,338 @@ function maskSecretsDeep(value) {
491
491
  function maskSecretsJson(value) {
492
492
  return maskSecretsDeep(value);
493
493
  }
494
+ /**
495
+ * Compiles the redaction policy: the DEFAULT credential pattern set
496
+ * plus host-defined patterns (RV-217), for the telemetry boundary
497
+ * (events and traces; never the journal, where lossless encryption is
498
+ * the right tool). String patterns compile as global regexes; RegExp
499
+ * patterns are recompiled with the global flag when it is missing, so
500
+ * replace-all semantics always hold. An invalid pattern is a typed
501
+ * ConfigError at compile time, before anything runs under the policy.
502
+ */
503
+ function compileSecretMasker(patterns = [], site = "redaction.patterns") {
504
+ const raw = patterns;
505
+ if (!Array.isArray(raw)) throw new ConfigError(`${site} must be an array of RegExp or string patterns`);
506
+ const compiled = raw.map((pattern, index) => {
507
+ const at = `${site}[${String(index)}]`;
508
+ if (pattern instanceof RegExp) return pattern.flags.includes("g") ? pattern : new RegExp(pattern.source, `${pattern.flags}g`);
509
+ if (typeof pattern !== "string" || pattern === "") throw new ConfigError(`${at} must be a RegExp or a nonempty pattern string`);
510
+ try {
511
+ return new RegExp(pattern, "g");
512
+ } catch (thrown) {
513
+ throw new ConfigError(`${at} is not a valid regular expression: ${thrown instanceof Error ? thrown.message : String(thrown)}`);
514
+ }
515
+ });
516
+ const maskText = (text) => {
517
+ let masked = maskSecrets(text);
518
+ for (const pattern of compiled) masked = masked.replace(pattern, MASKED_SECRET);
519
+ return masked;
520
+ };
521
+ const maskDeep = (value) => deepMap(value, maskText);
522
+ return {
523
+ maskText,
524
+ maskDeep
525
+ };
526
+ }
527
+ /** Shared deep string walk preserving identity when nothing changed. */
528
+ function deepMap(value, mapText) {
529
+ if (typeof value === "string") {
530
+ const masked = mapText(value);
531
+ return masked === value ? value : masked;
532
+ }
533
+ if (Array.isArray(value)) {
534
+ let changed = false;
535
+ const next = value.map((item) => {
536
+ const masked = deepMap(item, mapText);
537
+ if (masked !== item) changed = true;
538
+ return masked;
539
+ });
540
+ return changed ? next : value;
541
+ }
542
+ if (value !== null && typeof value === "object") {
543
+ let changed = false;
544
+ const next = {};
545
+ for (const [key, item] of Object.entries(value)) {
546
+ const masked = deepMap(item, mapText);
547
+ if (masked !== item) changed = true;
548
+ next[key] = masked;
549
+ }
550
+ return changed ? next : value;
551
+ }
552
+ return value;
553
+ }
554
+ //#endregion
555
+ //#region src/l0/encryption.ts
556
+ /**
557
+ * Envelope encryption over the serialization hook (RV-217): the
558
+ * reference implementation of "PII never persists in plaintext". The
559
+ * hook seam (l0/serialization.ts) is the single policy point between
560
+ * the engine and persistence; this module puts real cryptography on
561
+ * it, KMS-shaped.
562
+ *
563
+ * The envelope pattern, exactly as cloud KMS services frame it:
564
+ *
565
+ * - A DataKeyProvider is the KMS seam. It mints a fresh DATA key and
566
+ * returns it in two forms (plaintext for this process's memory,
567
+ * wrapped for storage), and it unwraps previously wrapped keys. The
568
+ * shipped `localKeyProvider` derives its key-encryption key from a
569
+ * host secret via HKDF-SHA256; an AWS KMS provider maps 1:1 onto
570
+ * GenerateDataKey and Decrypt (the guide shows the sketch), and
571
+ * tenant-scoped keys are providers constructed per tenant (the
572
+ * `info` input partitions one master secret into unrelated KEKs).
573
+ * - All provider calls are ASYNC and happen ONCE, in
574
+ * `createEnvelopeEncryption`, never per entry: the hook contract is
575
+ * synchronous, so the factory unwraps everything up front and the
576
+ * hooks run on in-memory data keys. Entries carry the WRAPPED key in
577
+ * every envelope, so decrypt needs only the provider registration,
578
+ * not a live KMS on the read path.
579
+ * - Payload encryption is AES-256-GCM with a random IV per write and
580
+ * the entry identity as ASSOCIATED DATA (`seq` and `key` for journal
581
+ * entries, the ref for transcript blobs), so a ciphertext moved to a
582
+ * different entry fails authentication instead of decrypting into
583
+ * the wrong place.
584
+ * - Journal entries keep the kernel ordering/identity fields plus the
585
+ * operational timestamps and spanId in plaintext (stores index and
586
+ * humans operate on them; none carry payload content); EVERYTHING
587
+ * else (value, error, usage, servedBy, cost attribution, refs) is
588
+ * inside the ciphertext. `fromStored(toStored(e))` reproduces the
589
+ * entry, so replay, content keys, and the folds are untouched.
590
+ * - Reads of NON-enveloped stored data fail closed by default
591
+ * (`plaintextReads: 'reject'`); `'passthrough'` is the explicit
592
+ * migration mode for stores with pre-encryption history.
593
+ *
594
+ * Docs: https://docs.rulvar.com/guide/data-protection
595
+ */
596
+ const HKDF_SALT = "rulvar-envelope-kek-v1";
597
+ const GCM_IV_BYTES = 12;
598
+ const GCM_TAG_BYTES = 16;
599
+ const DATA_KEY_BYTES = 32;
600
+ /**
601
+ * The local reference DataKeyProvider: the key-encryption key is
602
+ * HKDF-SHA256(secret, info), data keys are random 32-byte AES keys,
603
+ * and wrapping is AES-256-GCM under the KEK. `info` partitions one
604
+ * master secret into unrelated KEKs (tenant-scoped keys: one provider
605
+ * per tenant with `info: tenantId`); a provider with different
606
+ * secret or info CANNOT unwrap this provider's keys. For production
607
+ * KMS, implement the same interface over GenerateDataKey/Decrypt.
608
+ */
609
+ function localKeyProvider(options) {
610
+ const raw = options.secret;
611
+ if ((typeof raw !== "string" || raw === "") && !(raw instanceof Uint8Array)) throw new ConfigError("localKeyProvider secret must be a nonempty string or bytes");
612
+ if (raw instanceof Uint8Array && raw.length < 16) throw new ConfigError("localKeyProvider secret bytes must be at least 16 bytes");
613
+ const keyId = options.keyId ?? "local:v1";
614
+ if (typeof keyId !== "string" || keyId === "") throw new ConfigError("localKeyProvider keyId must be a nonempty string when given");
615
+ const kek = Buffer.from(hkdfSync("sha256", typeof raw === "string" ? Buffer.from(raw, "utf8") : Buffer.from(raw), Buffer.from(HKDF_SALT, "utf8"), Buffer.from(options.info ?? "", "utf8"), DATA_KEY_BYTES));
616
+ return {
617
+ keyId,
618
+ async generateDataKey() {
619
+ const plaintext = randomBytes(DATA_KEY_BYTES);
620
+ const iv = randomBytes(GCM_IV_BYTES);
621
+ const cipher = createCipheriv("aes-256-gcm", kek, iv);
622
+ const ct = Buffer.concat([cipher.update(plaintext), cipher.final()]);
623
+ const wrapped = Buffer.concat([
624
+ iv,
625
+ cipher.getAuthTag(),
626
+ ct
627
+ ]);
628
+ return {
629
+ plaintext: new Uint8Array(plaintext),
630
+ wrapped: new Uint8Array(wrapped)
631
+ };
632
+ },
633
+ async unwrapDataKey(wrapped) {
634
+ const buffer = Buffer.from(wrapped);
635
+ if (buffer.length <= 28) throw new ConfigError("localKeyProvider: the wrapped data key is truncated");
636
+ const iv = buffer.subarray(0, GCM_IV_BYTES);
637
+ const tag = buffer.subarray(GCM_IV_BYTES, 28);
638
+ const ct = buffer.subarray(28);
639
+ const decipher = createDecipheriv("aes-256-gcm", kek, iv);
640
+ decipher.setAuthTag(tag);
641
+ try {
642
+ const plaintext = Buffer.concat([decipher.update(ct), decipher.final()]);
643
+ return new Uint8Array(plaintext);
644
+ } catch {
645
+ throw new ConfigError(`localKeyProvider '${keyId}': cannot unwrap the data key (wrong secret, wrong info partition, or a corrupted wrapped key)`);
646
+ }
647
+ }
648
+ };
649
+ }
650
+ /** The journal envelope marker; a stored entry's whole value is this. */
651
+ const JOURNAL_ENVELOPE_MARKER = "__rulvarEnvelope";
652
+ /** The transcript blob envelope magic (version 1). */
653
+ const BLOB_MAGIC = Buffer.from("RVE1", "utf8");
654
+ /**
655
+ * Plaintext fields of a stored journal entry: the kernel
656
+ * ordering/identity fields the hook contract pins, plus the
657
+ * operational metadata stores index and operators read (timestamps,
658
+ * spanId). None carry payload content.
659
+ */
660
+ const CLEAR_FIELDS = [
661
+ "hashVersion",
662
+ "seq",
663
+ "ref",
664
+ "scope",
665
+ "key",
666
+ "ordinal",
667
+ "kind",
668
+ "status",
669
+ "spanId",
670
+ "startedAt",
671
+ "endedAt"
672
+ ];
673
+ function b64(bytes) {
674
+ return Buffer.from(bytes).toString("base64");
675
+ }
676
+ function isEnvelope(value) {
677
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
678
+ const keys = Object.keys(value);
679
+ if (keys.length !== 1 || keys[0] !== "__rulvarEnvelope") return false;
680
+ const env = value[JOURNAL_ENVELOPE_MARKER];
681
+ return typeof env === "object" && env !== null && env.v === 1 && typeof env.keyId === "string" && typeof env.wrapped === "string" && typeof env.iv === "string" && typeof env.tag === "string" && typeof env.data === "string";
682
+ }
683
+ /**
684
+ * Builds the envelope-encryption SerializationHook. All DataKeyProvider
685
+ * calls happen HERE (the hook itself is synchronous, on in-memory data
686
+ * keys): a fresh data key is minted and wrapped for this instance, and
687
+ * every historical wrapped key is unwrapped for the read path.
688
+ */
689
+ async function createEnvelopeEncryption(options) {
690
+ const provider = options.provider;
691
+ if (typeof provider !== "object" || provider === null || typeof provider.keyId !== "string" || provider.keyId === "" || typeof provider.generateDataKey !== "function" || typeof provider.unwrapDataKey !== "function") throw new ConfigError("createEnvelopeEncryption: provider must implement DataKeyProvider (keyId, generateDataKey, unwrapDataKey)");
692
+ const plaintextReads = options.plaintextReads ?? "reject";
693
+ if (plaintextReads !== "reject" && plaintextReads !== "passthrough") throw new ConfigError("createEnvelopeEncryption: plaintextReads must be 'reject' or 'passthrough'");
694
+ const realProvider = options.provider;
695
+ const current = await realProvider.generateDataKey();
696
+ if (current.plaintext.length !== DATA_KEY_BYTES) throw new ConfigError(`createEnvelopeEncryption: the provider returned a ${String(current.plaintext.length)}-byte data key; AES-256-GCM needs exactly ${String(DATA_KEY_BYTES)}`);
697
+ const ring = /* @__PURE__ */ new Map();
698
+ ring.set(b64(current.wrapped), Buffer.from(current.plaintext));
699
+ for (const wrapped of options.historicalWrappedKeys ?? []) {
700
+ const plaintext = await realProvider.unwrapDataKey(wrapped);
701
+ if (plaintext.length !== DATA_KEY_BYTES) throw new ConfigError(`createEnvelopeEncryption: a historical wrapped key unwrapped to ${String(plaintext.length)} bytes; AES-256-GCM needs exactly ${String(DATA_KEY_BYTES)}`);
702
+ ring.set(b64(wrapped), Buffer.from(plaintext));
703
+ }
704
+ const keyId = realProvider.keyId;
705
+ const currentWrappedB64 = b64(current.wrapped);
706
+ const currentKey = ring.get(currentWrappedB64);
707
+ const keyFor = (envelopeKeyId, wrappedB64, site) => {
708
+ const key = ring.get(wrappedB64);
709
+ if (key === void 0) throw new ConfigError(`${site}: the stored envelope carries a data key (keyId '${envelopeKeyId}') that this process has not registered; pass it in historicalWrappedKeys so the factory can unwrap it, and check the provider secret and info match the writing deployment`);
710
+ return key;
711
+ };
712
+ const encrypt = (key, aad, plaintext) => {
713
+ const iv = randomBytes(GCM_IV_BYTES);
714
+ const cipher = createCipheriv("aes-256-gcm", key, iv);
715
+ cipher.setAAD(aad);
716
+ const ct = Buffer.concat([cipher.update(plaintext), cipher.final()]);
717
+ return {
718
+ v: 1,
719
+ keyId,
720
+ wrapped: currentWrappedB64,
721
+ iv: iv.toString("base64"),
722
+ tag: cipher.getAuthTag().toString("base64"),
723
+ data: ct.toString("base64")
724
+ };
725
+ };
726
+ const decrypt = (key, aad, env, site) => {
727
+ const decipher = createDecipheriv("aes-256-gcm", key, Buffer.from(env.iv, "base64"));
728
+ decipher.setAAD(aad);
729
+ decipher.setAuthTag(Buffer.from(env.tag, "base64"));
730
+ try {
731
+ return Buffer.concat([decipher.update(Buffer.from(env.data, "base64")), decipher.final()]);
732
+ } catch {
733
+ throw new ConfigError(`${site}: envelope authentication failed (a tampered ciphertext, or a ciphertext moved to a different entry; the entry identity is associated data)`);
734
+ }
735
+ };
736
+ return {
737
+ hook: {
738
+ journal: {
739
+ toStored(e) {
740
+ const clear = {};
741
+ const rest = {};
742
+ for (const [field, fieldValue] of Object.entries(e)) if (CLEAR_FIELDS.includes(field)) clear[field] = fieldValue;
743
+ else rest[field] = fieldValue;
744
+ const aad = Buffer.from(`journal:${String(e.seq)}:${e.key}`, "utf8");
745
+ const envelope = encrypt(currentKey, aad, Buffer.from(JSON.stringify(rest), "utf8"));
746
+ return {
747
+ ...clear,
748
+ value: { [JOURNAL_ENVELOPE_MARKER]: envelope }
749
+ };
750
+ },
751
+ fromStored(e) {
752
+ if (!isEnvelope(e.value)) {
753
+ if (plaintextReads === "passthrough") return e;
754
+ throw new ConfigError(`envelope encryption: stored entry seq ${String(e.seq)} is not enveloped and plaintextReads is 'reject'; enable 'passthrough' only for a deliberate migration of pre-encryption history`);
755
+ }
756
+ const env = e.value[JOURNAL_ENVELOPE_MARKER];
757
+ const key = keyFor(env.keyId, env.wrapped, "envelope encryption (journal read)");
758
+ const aad = Buffer.from(`journal:${String(e.seq)}:${e.key}`, "utf8");
759
+ const rest = JSON.parse(decrypt(key, aad, env, "envelope encryption (journal read)").toString("utf8"));
760
+ const clear = {};
761
+ for (const field of CLEAR_FIELDS) if (e[field] !== void 0) clear[field] = e[field];
762
+ return {
763
+ ...clear,
764
+ ...rest
765
+ };
766
+ }
767
+ },
768
+ transcripts: {
769
+ toStored(ref, blob) {
770
+ const iv = randomBytes(GCM_IV_BYTES);
771
+ const cipher = createCipheriv("aes-256-gcm", currentKey, iv);
772
+ cipher.setAAD(Buffer.from(`blob:${ref}`, "utf8"));
773
+ const ct = Buffer.concat([cipher.update(Buffer.from(blob)), cipher.final()]);
774
+ const keyIdBytes = Buffer.from(keyId, "utf8");
775
+ const wrappedBytes = Buffer.from(currentWrappedB64, "base64");
776
+ const header = Buffer.alloc(4);
777
+ header.writeUInt16BE(keyIdBytes.length, 0);
778
+ header.writeUInt16BE(wrappedBytes.length, 2);
779
+ return new Uint8Array(Buffer.concat([
780
+ BLOB_MAGIC,
781
+ header,
782
+ keyIdBytes,
783
+ wrappedBytes,
784
+ iv,
785
+ cipher.getAuthTag(),
786
+ ct
787
+ ]));
788
+ },
789
+ fromStored(ref, blob) {
790
+ const buffer = Buffer.from(blob);
791
+ if (buffer.length < BLOB_MAGIC.length || !buffer.subarray(0, 4).equals(BLOB_MAGIC)) {
792
+ if (plaintextReads === "passthrough") return blob;
793
+ throw new ConfigError(`envelope encryption: stored blob '${ref}' is not enveloped and plaintextReads is 'reject'; enable 'passthrough' only for a deliberate migration`);
794
+ }
795
+ let offset = BLOB_MAGIC.length;
796
+ const keyIdLen = buffer.readUInt16BE(offset);
797
+ const wrappedLen = buffer.readUInt16BE(offset + 2);
798
+ offset += 4;
799
+ const envelopeKeyId = buffer.subarray(offset, offset + keyIdLen).toString("utf8");
800
+ offset += keyIdLen;
801
+ const wrappedB64 = buffer.subarray(offset, offset + wrappedLen).toString("base64");
802
+ offset += wrappedLen;
803
+ const iv = buffer.subarray(offset, offset + GCM_IV_BYTES);
804
+ const tag = buffer.subarray(offset + GCM_IV_BYTES, offset + GCM_IV_BYTES + GCM_TAG_BYTES);
805
+ const ct = buffer.subarray(offset + GCM_IV_BYTES + GCM_TAG_BYTES);
806
+ const decipher = createDecipheriv("aes-256-gcm", keyFor(envelopeKeyId, wrappedB64, `envelope encryption (blob '${ref}')`), iv);
807
+ decipher.setAAD(Buffer.from(`blob:${ref}`, "utf8"));
808
+ decipher.setAuthTag(tag);
809
+ try {
810
+ return new Uint8Array(Buffer.concat([decipher.update(ct), decipher.final()]));
811
+ } catch {
812
+ throw new ConfigError(`envelope encryption: blob '${ref}' authentication failed (tampered ciphertext or a ciphertext moved between refs; the ref is associated data)`);
813
+ }
814
+ }
815
+ }
816
+ },
817
+ keyId,
818
+ wrappedDataKey: new Uint8Array(current.wrapped)
819
+ };
820
+ }
821
+ /** Guards against non-constant-time comparisons in host key checks. */
822
+ function constantTimeEqual(a, b) {
823
+ if (a.length !== b.length) return false;
824
+ return timingSafeEqual(Buffer.from(a), Buffer.from(b));
825
+ }
494
826
  //#endregion
495
827
  //#region src/vendor/ulid.ts
496
828
  /**
@@ -3941,6 +4273,90 @@ function reviewAgentProfile(options = {}) {
3941
4273
  };
3942
4274
  }
3943
4275
  //#endregion
4276
+ //#region src/engine/audit.ts
4277
+ function record(entry, fields) {
4278
+ return {
4279
+ seq: entry.seq,
4280
+ at: entry.startedAt,
4281
+ scope: entry.scope,
4282
+ ...fields
4283
+ };
4284
+ }
4285
+ /**
4286
+ * Folds a loaded journal into the audit trail, in seq order. Pass the
4287
+ * FULL entry list (`Engine.stores.journal.load(runId)` or
4288
+ * `exportRun(runId).entries`); filtering is the reducer's job.
4289
+ */
4290
+ function reduceAuditTrail(entries) {
4291
+ const trail = [];
4292
+ for (const entry of entries) {
4293
+ if ((entry.kind === "external" || entry.kind === "approval") && entry.status === "suspended") {
4294
+ trail.push(record(entry, {
4295
+ category: "suspension",
4296
+ type: entry.kind,
4297
+ summary: `${entry.kind} suspension opened` + (entry.deadlineAt === void 0 ? "" : ` (deadline ${entry.deadlineAt})`),
4298
+ ...entry.value === void 0 ? {} : { value: entry.value }
4299
+ }));
4300
+ continue;
4301
+ }
4302
+ if (entry.kind === "resolution") {
4303
+ const payload = entry.resolution;
4304
+ if (payload === void 0) continue;
4305
+ trail.push(record(entry, {
4306
+ category: "resolution",
4307
+ by: payload.by,
4308
+ target: payload.target,
4309
+ summary: `suspension #${String(payload.target)} resolved by ${payload.by}` + (payload.decisionRef === void 0 ? "" : ` (class decision #${String(payload.decisionRef)})`),
4310
+ value: payload.value
4311
+ }));
4312
+ continue;
4313
+ }
4314
+ if (entry.kind === "abandon") {
4315
+ const payload = entry.abandon;
4316
+ if (payload === void 0) continue;
4317
+ trail.push(record(entry, {
4318
+ category: "abandon",
4319
+ target: payload.target,
4320
+ by: `decision #${String(payload.authorizedBy)}`,
4321
+ summary: `#${String(payload.target)} abandoned: ${payload.reason}`
4322
+ }));
4323
+ continue;
4324
+ }
4325
+ if (entry.kind === "termination.denied") {
4326
+ trail.push(record(entry, {
4327
+ category: "termination-denied",
4328
+ by: "engine",
4329
+ summary: "a termination-limit action was denied",
4330
+ ...entry.value === void 0 ? {} : { value: entry.value }
4331
+ }));
4332
+ continue;
4333
+ }
4334
+ if (entry.kind === "decision") {
4335
+ const value = entry.value;
4336
+ const decisionType = typeof value?.decisionType === "string" ? value.decisionType : void 0;
4337
+ if (decisionType === void 0) continue;
4338
+ if (decisionType === "run_settle") {
4339
+ trail.push(record(entry, {
4340
+ category: "run-settle",
4341
+ by: "engine",
4342
+ type: decisionType,
4343
+ summary: `run settled ${typeof value?.runStatus === "string" ? value.runStatus : "unknown"}`,
4344
+ ...entry.value === void 0 ? {} : { value: entry.value }
4345
+ }));
4346
+ continue;
4347
+ }
4348
+ trail.push(record(entry, {
4349
+ category: "decision",
4350
+ by: "engine",
4351
+ type: decisionType,
4352
+ summary: `engine decision ${decisionType}`,
4353
+ ...entry.value === void 0 ? {} : { value: entry.value }
4354
+ }));
4355
+ }
4356
+ }
4357
+ return trail;
4358
+ }
4359
+ //#endregion
3944
4360
  //#region src/journal/identity.ts
3945
4361
  /**
3946
4362
  * Content-addressed entry identity (M1-T04): IdentityInput records per
@@ -15949,7 +16365,7 @@ var EventBus = class {
15949
16365
  runId;
15950
16366
  spans;
15951
16367
  now;
15952
- maskEvents;
16368
+ mask;
15953
16369
  subscribers = /* @__PURE__ */ new Set();
15954
16370
  listeners = /* @__PURE__ */ new Set();
15955
16371
  seq;
@@ -15959,12 +16375,12 @@ var EventBus = class {
15959
16375
  this.runId = options.runId;
15960
16376
  this.spans = options.spans;
15961
16377
  this.now = options.now ?? realNow;
15962
- this.maskEvents = options.maskEvents ?? true;
16378
+ this.mask = options.maskEvents ?? true ? options.mask ?? maskSecretsDeep : void 0;
15963
16379
  this.seq = options.firstSeq ?? 0;
15964
16380
  }
15965
16381
  emit(body, spanId, replayed) {
15966
16382
  const parentSpanId = this.spans.parentOf(spanId);
15967
- const safeBody = this.maskEvents ? maskSecretsDeep(body) : body;
16383
+ const safeBody = this.mask === void 0 ? body : this.mask(body);
15968
16384
  const event = {
15969
16385
  runId: this.runId,
15970
16386
  seq: this.seq++,
@@ -16564,9 +16980,12 @@ function liftRunCompletion(candidate) {
16564
16980
  * sensitive-derived metadata, not a value safe to publish (see the
16565
16981
  * `argsHash` field docs).
16566
16982
  */
16567
- function hashRunArgs(args) {
16983
+ function hashRunArgs(args, options) {
16568
16984
  if (args === void 0) return;
16569
- return createHash("sha256").update(jcsSerialize(args), "utf8").digest("hex");
16985
+ const canonical = jcsSerialize(args);
16986
+ const salt = options?.salt;
16987
+ if (salt === void 0) return createHash("sha256").update(canonical, "utf8").digest("hex");
16988
+ return createHmac("sha256", Buffer.from(salt, "utf8")).update(canonical, "utf8").digest("hex");
16570
16989
  }
16571
16990
  /**
16572
16991
  * sha256 hex over the JCS canonical serialization of a run's result
@@ -16595,6 +17014,7 @@ function createEngine(options) {
16595
17014
  const journal = options.serialization?.journal === void 0 ? rawJournal : wrapJournalStore(rawJournal, options.serialization.journal);
16596
17015
  const transcripts = options.serialization?.transcripts === void 0 ? rawTranscripts : wrapTranscriptStore(rawTranscripts, options.serialization.transcripts);
16597
17016
  const maskEvents = options.redaction?.maskEvents ?? true;
17017
+ const eventMasker = options.redaction?.patterns === void 0 ? void 0 : compileSecretMasker(options.redaction.patterns, "createEngine redaction.patterns");
16598
17018
  const defaults = options.defaults ?? {};
16599
17019
  if (defaults.retry !== void 0) validateRetryPolicy(defaults.retry, "createEngine defaults.retry");
16600
17020
  if (options.concurrency?.perRun !== void 0) requirePositiveInteger(options.concurrency.perRun, "createEngine concurrency.perRun");
@@ -16618,6 +17038,8 @@ function createEngine(options) {
16618
17038
  }
16619
17039
  validateDeterminismConfig(options.determinism);
16620
17040
  validateEngineQuotaConfig(options.quota);
17041
+ if (options.security?.argsHashSalt !== void 0 && (typeof options.security.argsHashSalt !== "string" || options.security.argsHashSalt === "")) throw new ConfigError("createEngine security.argsHashSalt must be a nonempty string when given");
17042
+ const argsHashSalt = options.security?.argsHashSalt;
16621
17043
  const quotaRuntime = options.quota === void 0 ? void 0 : {
16622
17044
  limiter: options.quota.limiter,
16623
17045
  ...options.quota.tenant === void 0 ? {} : { tenant: options.quota.tenant },
@@ -16657,6 +17079,7 @@ function createEngine(options) {
16657
17079
  spans,
16658
17080
  now: realNow,
16659
17081
  maskEvents,
17082
+ ...eventMasker === void 0 ? {} : { mask: (body) => eventMasker.maskDeep(body) },
16660
17083
  firstSeq: telemetryBase
16661
17084
  });
16662
17085
  const rootSpanId = spans.mint();
@@ -16783,7 +17206,7 @@ function createEngine(options) {
16783
17206
  if (resumeCtx === void 0) {
16784
17207
  argsBinding.argsProvided = args !== void 0;
16785
17208
  try {
16786
- const argsHash = hashRunArgs(args);
17209
+ const argsHash = hashRunArgs(args, argsHashSalt === void 0 ? void 0 : { salt: argsHashSalt });
16787
17210
  if (argsHash !== void 0) argsBinding.argsHash = argsHash;
16788
17211
  } catch {}
16789
17212
  } else {
@@ -17044,6 +17467,42 @@ function createEngine(options) {
17044
17467
  preview
17045
17468
  };
17046
17469
  }
17470
+ /** Portable export through the policy point (RV-217). */
17471
+ async function exportRun(runId) {
17472
+ const entries = await journal.load(runId);
17473
+ const meta = await readRunMeta(journal, runId);
17474
+ const blobs = [];
17475
+ for (const ref of await transcripts.list(runId)) {
17476
+ const data = await transcripts.get(ref);
17477
+ if (data !== null) blobs.push({
17478
+ ref,
17479
+ data
17480
+ });
17481
+ }
17482
+ if (entries.length === 0 && meta === void 0 && blobs.length === 0) throw new ConfigError(`exportRun: run '${runId}' does not exist in this engine's stores`);
17483
+ return {
17484
+ runId,
17485
+ ...meta === void 0 ? {} : { meta },
17486
+ entries,
17487
+ blobs
17488
+ };
17489
+ }
17490
+ /** Import under the original runId; refuses an existing run (RV-217). */
17491
+ async function importRun(bundle) {
17492
+ const raw = bundle;
17493
+ if (typeof raw !== "object" || raw === null || typeof raw.runId !== "string" || raw.runId === "" || !Array.isArray(raw.entries) || !Array.isArray(raw.blobs)) throw new ConfigError("importRun: the bundle must be a RunExport (runId, entries, blobs)");
17494
+ const runId = bundle.runId;
17495
+ const existingMeta = await readRunMeta(journal, runId);
17496
+ const existingEntries = await journal.load(runId);
17497
+ const existingBlobs = await transcripts.list(runId);
17498
+ if (existingMeta !== void 0 || existingEntries.length > 0 || existingBlobs.length > 0) throw new ConfigError(`importRun: run '${runId}' already exists in the target stores; an import never interleaves with live history (delete the run first if replacement is intended)`);
17499
+ for (const entry of bundle.entries) await journal.append(runId, entry);
17500
+ for (const blob of bundle.blobs) await transcripts.put(blob.ref, blob.data);
17501
+ if (bundle.meta !== void 0) await journal.putMeta({
17502
+ ...bundle.meta,
17503
+ runId
17504
+ });
17505
+ }
17047
17506
  /** Retention cascade (OQ-20 executed at M8-T04): blobs, then journal. */
17048
17507
  async function deleteRun(runId, opts) {
17049
17508
  const refs = await transcripts.list(runId);
@@ -17108,6 +17567,8 @@ function createEngine(options) {
17108
17567
  },
17109
17568
  deleteRun,
17110
17569
  pruneRun,
17570
+ exportRun,
17571
+ importRun,
17111
17572
  profileCard: (names) => {
17112
17573
  const registered = defaults.profiles ?? {};
17113
17574
  if (names === void 0) return profileCard(registered, defaults.toolsets);
@@ -17405,4 +17866,4 @@ function createSandboxBridge(ctx, options) {
17405
17866
  };
17406
17867
  }
17407
17868
  //#endregion
17408
- export { AWAIT_SCHEMA, AdmissionController, AdmissionRejectedError, AgentCallError, BUDGET_ABORT_REASON, BudgetExhaustedError, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, ConfigError, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DEFAULT_SYNTHESIS_NOTE_MAX_TURNS, DedupIndex, DeterminismError, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EscalationDecisionAbortedError, EventBus, ExternalRegistry, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailRunError, FileModelKnowledgeStore, FileTranscriptStore, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, GitWorktreeProvider, IMPLEMENTATION_PROFILE_LIMITS, INBOX_PROPOSAL_TTL_DAYS, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, JournalCompatibilityError, JournalMatcher, JournalMissError, JournalOrderViolation, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, KeyedLimiter, KnowledgeCasError, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LeaseHeldError, LineageIndex, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_DEPTH_CEILING, ModelRetry, NoProgressDetector, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OrchestratorCapConfigError, PARALLEL_AGENTS_SCHEMA, PROGRESS_REPORT_TOOL_NAME, ParallelSiteCounter, PlanInvariantError, QUOTA_WINDOW_MS, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, RESEARCH_PROFILE_LIMITS, REVIEW_PROFILE_LIMITS, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionFold, RulvarError, RunBudget, SANDBOX_AGENT_OPT_KEYS, SPAWN_AGENT_SCHEMA, SandboxError, ScriptRejected, Semaphore, SpanRegistry, TOOL_NAME_PATTERN, TerminationAccount, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, atCompactionThreshold, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, dedupeRepeatedClaims, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidencePreservedValidator, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, identityJcs, implementationAgentProfile, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, latestProgressReport, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, memoryQuotaLimiter, mergeQuotaDenial, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, progressReportTool, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, quotaActualTokens, quotaEstimateTokens, quotaRuleAdmission, quotaRuleMatches, readRunMeta, readTerminationInit, reconcileRunMeta, reduceCriticalPath, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, repositoryResearchToolset, requiredFieldsValidator, requiredSectionsValidator, researchAgentProfile, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, reviewAgentProfile, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, snapshotUsage, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, usageViolations, validateEditorialCommit, validateEngineQuotaConfig, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateQuotaRules, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateUsageLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
17869
+ export { AWAIT_SCHEMA, AdmissionController, AdmissionRejectedError, AgentCallError, BUDGET_ABORT_REASON, BudgetExhaustedError, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, ConfigError, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DEFAULT_SYNTHESIS_NOTE_MAX_TURNS, DedupIndex, DeterminismError, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EscalationDecisionAbortedError, EventBus, ExternalRegistry, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailRunError, FileModelKnowledgeStore, FileTranscriptStore, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, GitWorktreeProvider, IMPLEMENTATION_PROFILE_LIMITS, INBOX_PROPOSAL_TTL_DAYS, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, JOURNAL_ENVELOPE_MARKER, JournalCompatibilityError, JournalMatcher, JournalMissError, JournalOrderViolation, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, KeyedLimiter, KnowledgeCasError, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LeaseHeldError, LineageIndex, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_DEPTH_CEILING, ModelRetry, NoProgressDetector, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OrchestratorCapConfigError, PARALLEL_AGENTS_SCHEMA, PROGRESS_REPORT_TOOL_NAME, ParallelSiteCounter, PlanInvariantError, QUOTA_WINDOW_MS, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, RESEARCH_PROFILE_LIMITS, REVIEW_PROFILE_LIMITS, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionFold, RulvarError, RunBudget, SANDBOX_AGENT_OPT_KEYS, SPAWN_AGENT_SCHEMA, SandboxError, ScriptRejected, Semaphore, SpanRegistry, TOOL_NAME_PATTERN, TerminationAccount, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, atCompactionThreshold, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileSecretMasker, compileVerifiedLayer, constantTimeEqual, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createEnvelopeEncryption, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, dedupeRepeatedClaims, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidencePreservedValidator, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, identityJcs, implementationAgentProfile, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, latestProgressReport, lexShellCommand, liftRetainedParts, lineageWeightOf, localKeyProvider, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, memoryQuotaLimiter, mergeQuotaDenial, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, progressReportTool, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, quotaActualTokens, quotaEstimateTokens, quotaRuleAdmission, quotaRuleMatches, readRunMeta, readTerminationInit, reconcileRunMeta, reduceAuditTrail, reduceCriticalPath, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, repositoryResearchToolset, requiredFieldsValidator, requiredSectionsValidator, researchAgentProfile, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, reviewAgentProfile, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, snapshotUsage, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, usageViolations, validateEditorialCommit, validateEngineQuotaConfig, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateQuotaRules, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateUsageLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/core",
3
- "version": "1.57.0",
3
+ "version": "1.58.0",
4
4
  "description": "Rulvar core: L0 contracts, journal kernel, ctx primitives, agent runtime, model router, tool system, dynamic orchestrator, InMemory and JSONL stores, event stream.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",