From c2b80b36916cec0fa0afddc1e47df9af2697ba9b Mon Sep 17 00:00:00 2001 From: James Ross Date: Thu, 15 Oct 2026 22:13:00 -0700 Subject: [PATCH] Import: fail closed instead of staging against the default worldline (#892) dispatch_intent routed every witnessed-suffix import intent to the kernel's default worldline, ignoring the request's receiving worldline, and the import rule recorded Staged without the bundle and basis checks import_suffix performs. Evidence was produced under the wrong causal coordinate. Until comparable-basis transport exists (flyingrobots/continuum#80) and the import is dispatched to its named receiving worldline, dispatch refuses import intents with NOT_SUPPORTED after validating the envelope. Nothing is ingested, staged or attributed; a malformed envelope is still INVALID_INTENT. Witness import_suffix_dispatch_fails_closed_until_transport_exists fails on main (the import was accepted and staged) and passes now. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 7 ++ crates/warp-wasm/src/warp_kernel.rs | 107 +++++++++-------------- docs/architecture/continuum-transport.md | 8 ++ 3 files changed, 56 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 700dfb50a..2dd3c2610 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -232,6 +232,13 @@ ### Fixed +- `dispatch_intent` no longer stages a witnessed suffix import against the + kernel's default worldline (#892). It ignored the request's receiving + worldline and recorded `Staged` without the bundle and basis checks the + library performs. Until comparable-basis transport exists, import intents + are refused with `NOT_SUPPORTED` and nothing is admitted, staged or + attributed. + - A tick that decides a submission no rule matched now commits and recovers under the WAL (#873). The WAL tick decision gains `NoMatchingRule` (code 4), recovery maps it to `RecoveredSubmissionPosture::DecidedNoMatchingRule`, and diff --git a/crates/warp-wasm/src/warp_kernel.rs b/crates/warp-wasm/src/warp_kernel.rs index 4c38a8fea..9c39600f5 100644 --- a/crates/warp-wasm/src/warp_kernel.rs +++ b/crates/warp-wasm/src/warp_kernel.rs @@ -987,6 +987,16 @@ impl KernelPort for WarpKernel { code: error_codes::INVALID_INTENT, message: "invalid import suffix intent envelope".into(), })?; + // Import must be judged at the request's receiving worldline and a + // comparable basis that transport establishes. Until that exists + // (flyingrobots/continuum#80), refuse instead of staging the + // import against this kernel's default worldline. + return Err(AbiError { + code: error_codes::NOT_SUPPORTED, + message: "witnessed suffix import is not supported until comparable-basis \ + transport exists; nothing was admitted" + .into(), + }); } let envelope = IngressEnvelope::local_intent( @@ -1166,13 +1176,12 @@ impl TrustedKernelControlPort for WarpKernel { mod tests { use super::*; use echo_wasm_abi::{ - decode_cbor, kernel_port::{ BuiltinObserverPlan as AbiBuiltinObserverPlan, CausalSuffixBundle as AbiCausalSuffixBundle, ControlIntentV1, GlobalTick as AbiGlobalTick, HeadEligibility as AbiHeadEligibility, HeadId as AbiHeadId, ImportSuffixRequest as AbiImportSuffixRequest, - ImportSuffixResult as AbiImportSuffixResult, ObservationAt as AbiObservationAt, + ObservationAt as AbiObservationAt, ObservationBasisPosture as AbiObservationBasisPosture, ObservationCoordinate as AbiObservationCoordinate, ObservationFrame as AbiObservationFrame, ObservationPayload as AbiObservationPayload, @@ -1187,7 +1196,6 @@ mod tests { SettlementOverlapRevalidation as AbiSettlementOverlapRevalidation, SettlementParentRevalidation as AbiSettlementParentRevalidation, SettlementRequest as AbiSettlementRequest, - WitnessedSuffixAdmissionOutcome as AbiWitnessedSuffixAdmissionOutcome, WitnessedSuffixShell as AbiWitnessedSuffixShell, WorkState, WorldlineId as AbiWorldlineId, WorldlineTick as AbiWorldlineTick, WriterHeadKey as AbiWriterHeadKey, @@ -1933,82 +1941,49 @@ mod tests { } #[test] - fn import_suffix_intent_enters_ingress_and_scheduler() { + fn import_suffix_dispatch_fails_closed_until_transport_exists() { let mut kernel = WarpKernel::new().unwrap(); let request = sample_import_suffix_request(&kernel); let intent = pack_import_suffix_intent_v1(&request).unwrap(); + let head_before = kernel.current_head().unwrap(); - let dispatch = kernel.dispatch_intent(&intent).unwrap(); - assert!(dispatch.accepted); - assert_eq!(dispatch.intent_id.len(), 32); + let refusal = kernel.dispatch_intent(&intent).unwrap_err(); + assert_eq!(refusal.code, error_codes::NOT_SUPPORTED); - let response = start_until_idle(&mut kernel, Some(1)); - let head = kernel.current_head().unwrap(); + // Nothing was admitted: no ingress to run, no tick, no staged result. + start_until_idle(&mut kernel, Some(1)); assert_eq!( - response.scheduler_status.last_run_completion, - Some(RunCompletion::Quiesced) + kernel.current_head().unwrap().worldline_tick, + head_before.worldline_tick + ); + let event_id = NodeId( + IngressEnvelope::local_intent( + IngressTarget::DefaultWriter { + worldline_id: kernel.default_worldline, + }, + make_intent_kind("echo.intent/eint-v1"), + intent.clone(), + ) + .ingress_id(), ); - assert_eq!(head.worldline_tick, AbiWorldlineTick(1)); - - let event_id = NodeId(dispatch.intent_id.as_slice().try_into().unwrap()); - let result_id = warp_core::import_suffix_result_node_id(&event_id); let frontier = kernel .runtime .worldlines() .get(&kernel.default_worldline) .unwrap(); - let frontier_state = frontier.state(); - let root_warp = frontier_state.root().warp_id; - let store = frontier_state.store(&root_warp).unwrap(); - let result_node = store.node(&result_id); - assert!(result_node.is_some()); - - let result_attachment = store - .node_attachment(&result_id) - .expect("import suffix result attachment should be recorded"); - let warp_core::AttachmentValue::Atom(atom) = result_attachment else { - panic!("import suffix result must be a typed atom"); - }; - assert_eq!( - atom.type_id, - make_type_id(warp_core::IMPORT_SUFFIX_RESULT_ATTACHMENT_TYPE) - ); - - let result: AbiImportSuffixResult = decode_cbor(atom.bytes.as_ref()).unwrap(); - assert_eq!(result.bundle_digest, request.bundle.bundle_digest); - assert_eq!( - result.admission.source_shell_digest, - request.bundle.source_suffix.witness_digest - ); - assert_eq!(result.admission.target_basis, request.target_basis); - match result.admission.outcome { - AbiWitnessedSuffixAdmissionOutcome::Staged { staged_refs, .. } => { - assert_eq!(staged_refs, request.bundle.source_suffix.source_entries); - } - other => panic!("expected staged import result, got {other:?}"), - } - - let entry = kernel - .provenance - .entry(kernel.default_worldline, WorldlineTick::ZERO) + let store = frontier + .state() + .store(&frontier.state().root().warp_id) .unwrap(); - let patch = entry.patch.expect("import tick should record a patch"); - assert!(patch.ops.iter().any(|op| { - matches!( - op, - WarpOp::UpsertNode { node, .. } if node.local_id == result_id - ) - })); - assert!(patch.ops.iter().any(|op| { - matches!( - op, - WarpOp::SetAttachment { key, .. } - if *key == AttachmentKey::node_alpha(NodeKey { - warp_id: root_warp, - local_id: result_id, - }) - ) - })); + assert!(store + .node(&warp_core::import_suffix_result_node_id(&event_id)) + .is_none()); + assert!(store.node(&event_id).is_none()); + + // A malformed import envelope is still reported as malformed. + let mut malformed = intent; + malformed.truncate(malformed.len() - 1); + assert!(kernel.dispatch_intent(&malformed).is_err()); } #[test] diff --git a/docs/architecture/continuum-transport.md b/docs/architecture/continuum-transport.md index 35f519b69..43b4249e3 100644 --- a/docs/architecture/continuum-transport.md +++ b/docs/architecture/continuum-transport.md @@ -83,6 +83,14 @@ transport adapter receives bytes -> tick + receipt / witness ``` +**Current status (#892).** This flow is not wired. Until comparable-basis +transport is specified ([continuum#80](https://github.com/flyingrobots/continuum/issues/80)) +and the import is dispatched to its explicitly named receiving worldline, +`dispatch_intent` refuses import intents with `NOT_SUPPORTED` and admits, +stages and attributes nothing. It never substitutes the kernel's default +worldline. The library evaluator (`import_suffix`) is unaffected and is not +reachable from dispatch. + The runtime must: 1. Verify the source shell and bundle identities.