From b9a165d0db29aecb23428cca6439c8e19d9f6ea3 Mon Sep 17 00:00:00 2001 From: James Ross Date: Tue, 12 May 2026 10:43:24 -0700 Subject: [PATCH 1/3] feat(core): add optic invocation admission skeleton --- CHANGELOG.md | 4 + crates/warp-core/src/lib.rs | 6 +- crates/warp-core/src/optic_artifact.rs | 94 ++++++++++++++++ .../tests/optic_invocation_admission_tests.rs | 100 ++++++++++++++++++ 4 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 crates/warp-core/tests/optic_invocation_admission_tests.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 73025fd4..4373993a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ artifact hash, schema id, operation id, and requirements digest before storing admission requirements internally and returning an opaque `OpticArtifactHandle`. +- `warp-core` now has an optic invocation admission skeleton that resolves + registered artifact handles internally and obstructs unknown handles, + operation mismatches, and registered-handle invocations without capability + presentation. - Echo-owned WASM package boundary tooling: `scripts/build-warp-wasm-package.sh` now builds `crates/warp-wasm/pkg` with the bundler target and the package export smoke test imports `crates/warp-wasm/pkg/rmg_wasm.js` to verify the diff --git a/crates/warp-core/src/lib.rs b/crates/warp-core/src/lib.rs index 87e051f3..c92b7d90 100644 --- a/crates/warp-core/src/lib.rs +++ b/crates/warp-core/src/lib.rs @@ -248,8 +248,10 @@ pub use optic::{ StagedIntent, StagedIntentReason, WitnessBasis, WorldlineHeadOptic, }; pub use optic_artifact::{ - OpticAdmissionRequirements, OpticArtifact, OpticArtifactHandle, OpticArtifactOperation, - OpticArtifactRegistrationError, OpticArtifactRegistry, OpticRegistrationDescriptor, + OpticAdmissionRequirements, OpticApertureRequest, OpticArtifact, OpticArtifactHandle, + OpticArtifactOperation, OpticArtifactRegistrationError, OpticArtifactRegistry, + OpticBasisRequest, OpticCapabilityPresentation, OpticInvocation, + OpticInvocationAdmissionOutcome, OpticInvocationObstruction, OpticRegistrationDescriptor, RegisteredOpticArtifact, OPTIC_ARTIFACT_HANDLE_KIND, }; pub use playback::{CursorReceipt, TruthFrame, TruthSink}; diff --git a/crates/warp-core/src/optic_artifact.rs b/crates/warp-core/src/optic_artifact.rs index 02e34565..6f97528d 100644 --- a/crates/warp-core/src/optic_artifact.rs +++ b/crates/warp-core/src/optic_artifact.rs @@ -103,6 +103,69 @@ pub struct RegisteredOpticArtifact { pub requirements: OpticAdmissionRequirements, } +/// Opaque basis request bytes supplied at optic invocation time. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct OpticBasisRequest { + /// Request bytes interpreted only below Echo's runtime admission boundary. + pub bytes: Vec, +} + +/// Opaque aperture request bytes supplied at optic invocation time. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct OpticApertureRequest { + /// Request bytes interpreted only below Echo's runtime admission boundary. + pub bytes: Vec, +} + +/// Placeholder capability presentation supplied at optic invocation time. +/// +/// This v0 shape is intentionally not sufficient to authorize invocation. It +/// exists only so the admission skeleton can name the future presentation slot +/// without inventing grant validation semantics. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct OpticCapabilityPresentation { + /// Presentation identity supplied by the caller. + pub presentation_id: String, +} + +/// Runtime invocation request against a registered optic artifact. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct OpticInvocation { + /// Echo-owned runtime-local artifact handle. + pub artifact_handle: OpticArtifactHandle, + /// Operation id the caller intends to invoke. + pub operation_id: String, + /// Digest of canonical invocation variable bytes. + pub canonical_variables_digest: Vec, + /// Requested causal basis for the invocation. + pub basis_request: OpticBasisRequest, + /// Requested aperture for the invocation. + pub aperture_request: OpticApertureRequest, + /// Caller authority presentation. Registration alone is not authority. + pub capability_presentation: Option, +} + +/// Admission obstruction for an optic invocation. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum OpticInvocationObstruction { + /// Echo did not issue or cannot resolve the artifact handle. + UnknownHandle, + /// The invocation operation id does not match the registered artifact. + OperationMismatch, + /// The invocation does not carry authority to use the registered artifact. + MissingCapability, + /// A placeholder presentation was supplied, but real grant validation does + /// not exist in this slice. + CapabilityValidationUnavailable, +} + +/// Admission outcome for a v0 optic invocation skeleton. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum OpticInvocationAdmissionOutcome { + /// Echo obstructed the invocation before runtime execution. + Obstructed(OpticInvocationObstruction), +} + /// Registration and lookup errors for Echo optic artifact handles. #[derive(Clone, Debug, Error, PartialEq, Eq)] pub enum OpticArtifactRegistrationError { @@ -187,6 +250,37 @@ impl OpticArtifactRegistry { .ok_or(OpticArtifactRegistrationError::UnknownHandle) } + /// Admits or obstructs an invocation against a registered optic artifact. + /// + /// This v0 skeleton intentionally has no success path. It proves that Echo + /// resolves handles internally and that a registered handle is not authority. + pub fn admit_optic_invocation( + &self, + invocation: &OpticInvocation, + ) -> OpticInvocationAdmissionOutcome { + let Ok(registered) = self.resolve_optic_artifact_handle(&invocation.artifact_handle) else { + return OpticInvocationAdmissionOutcome::Obstructed( + OpticInvocationObstruction::UnknownHandle, + ); + }; + + if invocation.operation_id != registered.operation_id { + return OpticInvocationAdmissionOutcome::Obstructed( + OpticInvocationObstruction::OperationMismatch, + ); + } + + if invocation.capability_presentation.is_none() { + return OpticInvocationAdmissionOutcome::Obstructed( + OpticInvocationObstruction::MissingCapability, + ); + } + + OpticInvocationAdmissionOutcome::Obstructed( + OpticInvocationObstruction::CapabilityValidationUnavailable, + ) + } + /// Returns the number of registered artifacts. #[must_use] pub fn len(&self) -> usize { diff --git a/crates/warp-core/tests/optic_invocation_admission_tests.rs b/crates/warp-core/tests/optic_invocation_admission_tests.rs new file mode 100644 index 00000000..6b47ffb4 --- /dev/null +++ b/crates/warp-core/tests/optic_invocation_admission_tests.rs @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: Apache-2.0 +// © James Ross Ω FLYING•ROBOTS +//! Regression tests for optic invocation admission obstruction. + +use warp_core::{ + OpticAdmissionRequirements, OpticApertureRequest, OpticArtifact, OpticArtifactHandle, + OpticArtifactOperation, OpticArtifactRegistry, OpticBasisRequest, OpticInvocation, + OpticInvocationAdmissionOutcome, OpticInvocationObstruction, OpticRegistrationDescriptor, +}; + +fn fixture_artifact() -> OpticArtifact { + OpticArtifact { + artifact_id: "optic-artifact:stack-witness-0001".to_owned(), + artifact_hash: "artifact-hash:stack-witness-0001".to_owned(), + schema_id: "schema:jedit-text-buffer-optic:v0".to_owned(), + requirements_digest: "requirements-digest:stack-witness-0001".to_owned(), + operation: OpticArtifactOperation { + operation_id: "operation:textWindow:v0".to_owned(), + }, + requirements: OpticAdmissionRequirements { + bytes: b"fixture admission requirements".to_vec(), + }, + } +} + +fn fixture_descriptor() -> OpticRegistrationDescriptor { + OpticRegistrationDescriptor { + artifact_id: "optic-artifact:stack-witness-0001".to_owned(), + artifact_hash: "artifact-hash:stack-witness-0001".to_owned(), + schema_id: "schema:jedit-text-buffer-optic:v0".to_owned(), + operation_id: "operation:textWindow:v0".to_owned(), + requirements_digest: "requirements-digest:stack-witness-0001".to_owned(), + } +} + +fn fixture_registry_and_handle() -> (OpticArtifactRegistry, OpticArtifactHandle) { + let mut registry = OpticArtifactRegistry::new(); + let handle = registry + .register_optic_artifact(fixture_artifact(), fixture_descriptor()) + .expect("fixture descriptor should register"); + (registry, handle) +} + +fn fixture_invocation(handle: OpticArtifactHandle) -> OpticInvocation { + OpticInvocation { + artifact_handle: handle, + operation_id: "operation:textWindow:v0".to_owned(), + canonical_variables_digest: b"vars-digest:textWindow".to_vec(), + basis_request: OpticBasisRequest { + bytes: b"basis-request:fixture".to_vec(), + }, + aperture_request: OpticApertureRequest { + bytes: b"aperture-request:fixture".to_vec(), + }, + capability_presentation: None, + } +} + +#[test] +fn optic_invocation_obstructs_unknown_handle() { + let registry = OpticArtifactRegistry::new(); + let invocation = fixture_invocation(OpticArtifactHandle { + kind: "optic-artifact-handle".to_owned(), + id: "unregistered-handle".to_owned(), + }); + + let outcome = registry.admit_optic_invocation(&invocation); + + assert_eq!( + outcome, + OpticInvocationAdmissionOutcome::Obstructed(OpticInvocationObstruction::UnknownHandle) + ); +} + +#[test] +fn optic_invocation_obstructs_operation_mismatch() { + let (registry, handle) = fixture_registry_and_handle(); + let mut invocation = fixture_invocation(handle); + invocation.operation_id = "operation:replaceRange:v0".to_owned(); + + let outcome = registry.admit_optic_invocation(&invocation); + + assert_eq!( + outcome, + OpticInvocationAdmissionOutcome::Obstructed(OpticInvocationObstruction::OperationMismatch) + ); +} + +#[test] +fn optic_invocation_obstructs_missing_capability_for_registered_handle() { + let (registry, handle) = fixture_registry_and_handle(); + let invocation = fixture_invocation(handle); + + let outcome = registry.admit_optic_invocation(&invocation); + + assert_eq!( + outcome, + OpticInvocationAdmissionOutcome::Obstructed(OpticInvocationObstruction::MissingCapability) + ); +} From a0f785830841c957d501ae4f872afb580d23143e Mon Sep 17 00:00:00 2001 From: James Ross Date: Tue, 12 May 2026 11:05:45 -0700 Subject: [PATCH 2/3] test(core): harden optic invocation obstruction --- CHANGELOG.md | 3 ++- crates/warp-core/src/optic_artifact.rs | 2 ++ .../tests/optic_invocation_admission_tests.rs | 23 +++++++++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4373993a..b9be8ad0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,8 @@ - `warp-core` now has an optic invocation admission skeleton that resolves registered artifact handles internally and obstructs unknown handles, operation mismatches, and registered-handle invocations without capability - presentation. + presentation. Admission outcomes are must-use, and placeholder capability + presentations still obstruct until real grant validation exists. - Echo-owned WASM package boundary tooling: `scripts/build-warp-wasm-package.sh` now builds `crates/warp-wasm/pkg` with the bundler target and the package export smoke test imports `crates/warp-wasm/pkg/rmg_wasm.js` to verify the diff --git a/crates/warp-core/src/optic_artifact.rs b/crates/warp-core/src/optic_artifact.rs index 6f97528d..9bdd10f3 100644 --- a/crates/warp-core/src/optic_artifact.rs +++ b/crates/warp-core/src/optic_artifact.rs @@ -160,6 +160,7 @@ pub enum OpticInvocationObstruction { } /// Admission outcome for a v0 optic invocation skeleton. +#[must_use = "optic invocation admission outcomes carry obstructions that must be handled"] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum OpticInvocationAdmissionOutcome { /// Echo obstructed the invocation before runtime execution. @@ -254,6 +255,7 @@ impl OpticArtifactRegistry { /// /// This v0 skeleton intentionally has no success path. It proves that Echo /// resolves handles internally and that a registered handle is not authority. + #[must_use = "optic invocation admission outcomes carry obstructions that must be handled"] pub fn admit_optic_invocation( &self, invocation: &OpticInvocation, diff --git a/crates/warp-core/tests/optic_invocation_admission_tests.rs b/crates/warp-core/tests/optic_invocation_admission_tests.rs index 6b47ffb4..204fa0d9 100644 --- a/crates/warp-core/tests/optic_invocation_admission_tests.rs +++ b/crates/warp-core/tests/optic_invocation_admission_tests.rs @@ -4,8 +4,9 @@ use warp_core::{ OpticAdmissionRequirements, OpticApertureRequest, OpticArtifact, OpticArtifactHandle, - OpticArtifactOperation, OpticArtifactRegistry, OpticBasisRequest, OpticInvocation, - OpticInvocationAdmissionOutcome, OpticInvocationObstruction, OpticRegistrationDescriptor, + OpticArtifactOperation, OpticArtifactRegistry, OpticBasisRequest, OpticCapabilityPresentation, + OpticInvocation, OpticInvocationAdmissionOutcome, OpticInvocationObstruction, + OpticRegistrationDescriptor, }; fn fixture_artifact() -> OpticArtifact { @@ -98,3 +99,21 @@ fn optic_invocation_obstructs_missing_capability_for_registered_handle() { OpticInvocationAdmissionOutcome::Obstructed(OpticInvocationObstruction::MissingCapability) ); } + +#[test] +fn optic_invocation_obstructs_placeholder_capability_presentation_until_grant_validation_exists() { + let (registry, handle) = fixture_registry_and_handle(); + let mut invocation = fixture_invocation(handle); + invocation.capability_presentation = Some(OpticCapabilityPresentation { + presentation_id: "presentation:placeholder".to_owned(), + }); + + let outcome = registry.admit_optic_invocation(&invocation); + + assert_eq!( + outcome, + OpticInvocationAdmissionOutcome::Obstructed( + OpticInvocationObstruction::CapabilityValidationUnavailable + ) + ); +} From a3f50c82fe3a4474629f4794590a153e416d3228 Mon Sep 17 00:00:00 2001 From: James Ross Date: Tue, 12 May 2026 12:30:46 -0700 Subject: [PATCH 3/3] test(core): satisfy optic admission review --- CHANGELOG.md | 4 +- crates/warp-core/src/optic_artifact.rs | 9 ++- .../tests/optic_artifact_registry_tests.rs | 77 ++++++++++++------- .../tests/optic_invocation_admission_tests.rs | 22 +++--- 4 files changed, 71 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9be8ad0..1deaa4b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,9 @@ registered artifact handles internally and obstructs unknown handles, operation mismatches, and registered-handle invocations without capability presentation. Admission outcomes are must-use, and placeholder capability - presentations still obstruct until real grant validation exists. + presentations still obstruct until real grant validation exists. The + registration and invocation regression fixtures avoid `expect(...)` so + all-target Clippy remains clean. - Echo-owned WASM package boundary tooling: `scripts/build-warp-wasm-package.sh` now builds `crates/warp-wasm/pkg` with the bundler target and the package export smoke test imports `crates/warp-wasm/pkg/rmg_wasm.js` to verify the diff --git a/crates/warp-core/src/optic_artifact.rs b/crates/warp-core/src/optic_artifact.rs index 9bdd10f3..add0a7a7 100644 --- a/crates/warp-core/src/optic_artifact.rs +++ b/crates/warp-core/src/optic_artifact.rs @@ -2,10 +2,11 @@ // © James Ross Ω FLYING•ROBOTS //! Echo-owned registry for Wesley-compiled optic artifacts. //! -//! This module intentionally stops at registration. It does not admit -//! invocations, validate capability grants, issue admission tickets, or execute -//! runtime work. The only authority proven here is that Echo accepted and -//! stored a specific Wesley artifact identity and its admission requirements. +//! This module owns optic artifact registration and the first admission-only +//! invocation gate. [`OpticArtifactRegistry::admit_optic_invocation`] resolves +//! handles internally, checks operation identity, and obstructs missing or +//! placeholder authority without validating grants, issuing admission tickets, +//! emitting law witnesses, or executing runtime work. use std::collections::BTreeMap; diff --git a/crates/warp-core/tests/optic_artifact_registry_tests.rs b/crates/warp-core/tests/optic_artifact_registry_tests.rs index 6eea72d7..27a8cb77 100644 --- a/crates/warp-core/tests/optic_artifact_registry_tests.rs +++ b/crates/warp-core/tests/optic_artifact_registry_tests.rs @@ -32,22 +32,32 @@ fn fixture_descriptor() -> OpticRegistrationDescriptor { } } +fn registration_err_or_panic( + result: Result, + context: &str, +) -> Result { + match result { + Ok(_) => Err(format!("{context}: expected registration error")), + Err(err) => Ok(err), + } +} + #[test] -fn optic_artifact_registry_registers_wesley_descriptor_and_resolves_handle() { +fn optic_artifact_registry_registers_wesley_descriptor_and_resolves_handle() -> Result<(), String> { let artifact = fixture_artifact(); let descriptor = fixture_descriptor(); let mut registry = OpticArtifactRegistry::new(); let handle = registry .register_optic_artifact(artifact.clone(), descriptor) - .expect("fixture descriptor should register"); + .map_err(|err| format!("fixture descriptor should register: {err:?}"))?; assert_eq!(handle.kind, "optic-artifact-handle"); assert!(!handle.id.is_empty()); let registered = registry .resolve_optic_artifact_handle(&handle) - .expect("fresh handle should resolve"); + .map_err(|err| format!("fresh handle should resolve: {err:?}"))?; assert_eq!(registered.artifact_id, artifact.artifact_id); assert_eq!(registered.artifact_hash, artifact.artifact_hash); @@ -55,104 +65,117 @@ fn optic_artifact_registry_registers_wesley_descriptor_and_resolves_handle() { assert_eq!(registered.operation_id, artifact.operation.operation_id); assert_eq!(registered.requirements_digest, artifact.requirements_digest); assert_eq!(registered.requirements, artifact.requirements); + Ok(()) } #[test] -fn optic_artifact_registry_rejects_tampered_artifact_hash() { +fn optic_artifact_registry_rejects_tampered_artifact_hash() -> Result<(), String> { let artifact = fixture_artifact(); let mut descriptor = fixture_descriptor(); descriptor.artifact_hash = "artifact-hash:tampered".to_owned(); let mut registry = OpticArtifactRegistry::new(); - let err = registry - .register_optic_artifact(artifact, descriptor) - .expect_err("tampered artifact hash should reject"); + let err = registration_err_or_panic( + registry.register_optic_artifact(artifact, descriptor), + "tampered artifact hash should reject", + )?; assert!(matches!( err, OpticArtifactRegistrationError::ArtifactHashMismatch )); + Ok(()) } #[test] -fn optic_artifact_registry_rejects_mismatched_artifact_id() { +fn optic_artifact_registry_rejects_mismatched_artifact_id() -> Result<(), String> { let artifact = fixture_artifact(); let mut descriptor = fixture_descriptor(); descriptor.artifact_id = "optic-artifact:other".to_owned(); let mut registry = OpticArtifactRegistry::new(); - let err = registry - .register_optic_artifact(artifact, descriptor) - .expect_err("mismatched artifact id should reject"); + let err = registration_err_or_panic( + registry.register_optic_artifact(artifact, descriptor), + "mismatched artifact id should reject", + )?; assert!(matches!( err, OpticArtifactRegistrationError::ArtifactIdMismatch )); + Ok(()) } #[test] -fn optic_artifact_registry_rejects_tampered_requirements_digest() { +fn optic_artifact_registry_rejects_tampered_requirements_digest() -> Result<(), String> { let artifact = fixture_artifact(); let mut descriptor = fixture_descriptor(); descriptor.requirements_digest = "requirements-digest:tampered".to_owned(); let mut registry = OpticArtifactRegistry::new(); - let err = registry - .register_optic_artifact(artifact, descriptor) - .expect_err("tampered requirements digest should reject"); + let err = registration_err_or_panic( + registry.register_optic_artifact(artifact, descriptor), + "tampered requirements digest should reject", + )?; assert!(matches!( err, OpticArtifactRegistrationError::RequirementsDigestMismatch )); + Ok(()) } #[test] -fn optic_artifact_registry_rejects_mismatched_operation_id() { +fn optic_artifact_registry_rejects_mismatched_operation_id() -> Result<(), String> { let artifact = fixture_artifact(); let mut descriptor = fixture_descriptor(); descriptor.operation_id = "operation:replaceRange:v0".to_owned(); let mut registry = OpticArtifactRegistry::new(); - let err = registry - .register_optic_artifact(artifact, descriptor) - .expect_err("mismatched operation id should reject"); + let err = registration_err_or_panic( + registry.register_optic_artifact(artifact, descriptor), + "mismatched operation id should reject", + )?; assert!(matches!( err, OpticArtifactRegistrationError::OperationIdMismatch )); + Ok(()) } #[test] -fn optic_artifact_registry_rejects_mismatched_schema_id() { +fn optic_artifact_registry_rejects_mismatched_schema_id() -> Result<(), String> { let artifact = fixture_artifact(); let mut descriptor = fixture_descriptor(); descriptor.schema_id = "schema:other:v0".to_owned(); let mut registry = OpticArtifactRegistry::new(); - let err = registry - .register_optic_artifact(artifact, descriptor) - .expect_err("mismatched schema id should reject"); + let err = registration_err_or_panic( + registry.register_optic_artifact(artifact, descriptor), + "mismatched schema id should reject", + )?; assert!(matches!( err, OpticArtifactRegistrationError::SchemaIdMismatch )); + Ok(()) } #[test] -fn optic_artifact_registry_rejects_unknown_handle_lookup() { +fn optic_artifact_registry_rejects_unknown_handle_lookup() -> Result<(), String> { let registry = OpticArtifactRegistry::new(); let handle = OpticArtifactHandle { kind: "optic-artifact-handle".to_owned(), id: "unregistered-handle".to_owned(), }; - let err = registry - .resolve_optic_artifact_handle(&handle) - .expect_err("unknown handle should reject"); + let err = registration_err_or_panic( + registry.resolve_optic_artifact_handle(&handle), + "unknown handle should reject", + )?; assert!(matches!(err, OpticArtifactRegistrationError::UnknownHandle)); + Ok(()) } diff --git a/crates/warp-core/tests/optic_invocation_admission_tests.rs b/crates/warp-core/tests/optic_invocation_admission_tests.rs index 204fa0d9..0c4423c6 100644 --- a/crates/warp-core/tests/optic_invocation_admission_tests.rs +++ b/crates/warp-core/tests/optic_invocation_admission_tests.rs @@ -34,12 +34,12 @@ fn fixture_descriptor() -> OpticRegistrationDescriptor { } } -fn fixture_registry_and_handle() -> (OpticArtifactRegistry, OpticArtifactHandle) { +fn fixture_registry_and_handle() -> Result<(OpticArtifactRegistry, OpticArtifactHandle), String> { let mut registry = OpticArtifactRegistry::new(); let handle = registry .register_optic_artifact(fixture_artifact(), fixture_descriptor()) - .expect("fixture descriptor should register"); - (registry, handle) + .map_err(|err| format!("fixture descriptor should register: {err:?}"))?; + Ok((registry, handle)) } fn fixture_invocation(handle: OpticArtifactHandle) -> OpticInvocation { @@ -74,8 +74,8 @@ fn optic_invocation_obstructs_unknown_handle() { } #[test] -fn optic_invocation_obstructs_operation_mismatch() { - let (registry, handle) = fixture_registry_and_handle(); +fn optic_invocation_obstructs_operation_mismatch() -> Result<(), String> { + let (registry, handle) = fixture_registry_and_handle()?; let mut invocation = fixture_invocation(handle); invocation.operation_id = "operation:replaceRange:v0".to_owned(); @@ -85,11 +85,12 @@ fn optic_invocation_obstructs_operation_mismatch() { outcome, OpticInvocationAdmissionOutcome::Obstructed(OpticInvocationObstruction::OperationMismatch) ); + Ok(()) } #[test] -fn optic_invocation_obstructs_missing_capability_for_registered_handle() { - let (registry, handle) = fixture_registry_and_handle(); +fn optic_invocation_obstructs_missing_capability_for_registered_handle() -> Result<(), String> { + let (registry, handle) = fixture_registry_and_handle()?; let invocation = fixture_invocation(handle); let outcome = registry.admit_optic_invocation(&invocation); @@ -98,11 +99,13 @@ fn optic_invocation_obstructs_missing_capability_for_registered_handle() { outcome, OpticInvocationAdmissionOutcome::Obstructed(OpticInvocationObstruction::MissingCapability) ); + Ok(()) } #[test] -fn optic_invocation_obstructs_placeholder_capability_presentation_until_grant_validation_exists() { - let (registry, handle) = fixture_registry_and_handle(); +fn optic_invocation_obstructs_placeholder_capability_presentation_until_grant_validation_exists( +) -> Result<(), String> { + let (registry, handle) = fixture_registry_and_handle()?; let mut invocation = fixture_invocation(handle); invocation.capability_presentation = Some(OpticCapabilityPresentation { presentation_id: "presentation:placeholder".to_owned(), @@ -116,4 +119,5 @@ fn optic_invocation_obstructs_placeholder_capability_presentation_until_grant_va OpticInvocationObstruction::CapabilityValidationUnavailable ) ); + Ok(()) }