From 8aa7d68000618687fd801f8593361a857b697e37 Mon Sep 17 00:00:00 2001 From: guangtao Date: Thu, 5 Nov 2026 21:26:50 +0800 Subject: [PATCH 001/105] Scope provider lifecycle invalidation to its original origin --- crates/ledger/src/lib.rs | 3 +- crates/ledger/src/persistence/authority.rs | 89 ++++++-- .../ledger/src/persistence/commit_observer.rs | 4 + crates/ledger/src/persistence/mod.rs | 2 +- crates/ledger/src/persistence/scope.rs | 67 ++++-- crates/ledger/src/provider.rs | 61 +++++- .../ledger/tests/unit/authority_footprint.rs | 21 ++ crates/ledger/tests/unit/provider.rs | 3 + .../ledger/tests/unit/provider_lifecycle.rs | 124 +++++++++++ crates/server/src/grpc_provider.rs | 5 + crates/server/tests/unit/provider_commit.rs | 82 ++++--- .../cedar/DomainMigrationComposition.lean | 26 +++ dev/proofs/cedar/lakefile.toml | 2 +- .../lean/ProviderLifecycleFootprint.lean | 99 +++++++++ .../quint/ProviderLifecycleFootprint.qnt | 71 +++++++ dev/sysml/ArchitectureViews.sysml | 1 + dev/sysml/WeaverExecution.sysml | 19 +- dev/sysml/runtime-trace.json | 3 +- .../10-routing-and-inference/10.00-index.org | 2 + .../10.08-send-window-promotion.org | 10 +- .../10.09-provider-delivery-join.d2 | 12 +- .../10.09-provider-delivery-join.svg | 4 +- .../10.11-lifecycle-footprints.org | 201 ++++++++++++++++++ go/dev/provider_backpressure_test.go | 7 +- go/dev/provider_delivery_bench_test.go | 35 ++- go/dev/provider_lifecycle_test.go | 157 ++++++++++++++ .../devrunner/benchmark_pipeline_test.go | 2 +- go/internal/devrunner/plan.go | 4 + 28 files changed, 1021 insertions(+), 95 deletions(-) create mode 100644 crates/ledger/tests/unit/authority_footprint.rs create mode 100644 crates/ledger/tests/unit/provider_lifecycle.rs create mode 100644 dev/proofs/lean/ProviderLifecycleFootprint.lean create mode 100644 dev/proofs/quint/ProviderLifecycleFootprint.qnt create mode 100644 docs/10-19-llm-gateway/10-routing-and-inference/10.11-lifecycle-footprints.org create mode 100644 go/dev/provider_lifecycle_test.go diff --git a/crates/ledger/src/lib.rs b/crates/ledger/src/lib.rs index 050bd5c9..10951e28 100644 --- a/crates/ledger/src/lib.rs +++ b/crates/ledger/src/lib.rs @@ -56,7 +56,8 @@ pub use provider::{ }; #[cfg(feature = "commit-observer")] pub use provider::{ - use_cached_release_programs, use_conservative_range_invalidation, use_separate_release_reads, + use_cached_release_programs, use_conservative_range_invalidation, + use_full_lifecycle_invalidation, use_separate_release_reads, }; mod store; mod stream_catalog; diff --git a/crates/ledger/src/persistence/authority.rs b/crates/ledger/src/persistence/authority.rs index e6f15ac5..da79d46c 100644 --- a/crates/ledger/src/persistence/authority.rs +++ b/crates/ledger/src/persistence/authority.rs @@ -22,18 +22,36 @@ pub(crate) struct Authority { #[derive(Default)] struct State { serial: u64, + whole: u64, global: u64, domains: [BTreeMap; 6], pending: BTreeMap, failed: bool, waiters: Vec, } +#[derive(Clone, Copy, PartialEq, Eq)] +enum Impact { + Full, + Origin, + Preserved, +} struct Mutation { scope: Scope, - invalidates: bool, + impact: Impact, external: BTreeMap, orphaned: bool, } +impl Mutation { + fn affects(&self, reader: &Scope) -> bool { + match (&self.scope, reader, self.impact) { + (_, _, Impact::Preserved) => false, + (Scope::Domains(writer), Scope::Domains(reader), Impact::Origin) => { + writer.key(0) == reader.key(0) + } + _ => self.scope.overlaps(reader), + } + } +} #[derive(Default)] pub(crate) struct Completion { qualification: Arc>, @@ -93,7 +111,11 @@ pub(super) struct Close<'a> { impl State { fn stamp(&self, scope: &Scope) -> Stamp { Stamp { - global: self.global, + global: if matches!(scope, Scope::All) { + self.whole + } else { + self.global + }, domains: match scope { Scope::All => None, Scope::Domains(keys) => Some(std::array::from_fn(|i| { @@ -105,7 +127,11 @@ impl State { }, } } - fn advance(&mut self, scope: &Scope) -> driver::Result<()> { + fn advance(&mut self, scope: &Scope, impact: Impact) -> driver::Result<()> { + self.whole = self + .whole + .checked_add(1) + .ok_or_else(|| error("whole-view revision exhausted"))?; match scope { Scope::All => { self.global = self @@ -114,7 +140,7 @@ impl State { .ok_or_else(|| error("authority revision exhausted"))? } Scope::Domains(keys) => { - for i in 0..6 { + for i in 0..if impact == Impact::Origin { 1 } else { 6 } { if let Some(key) = keys.key(i) { let value = self.domains[i].entry(key.to_owned()).or_default(); *value = value @@ -127,25 +153,40 @@ impl State { Ok(()) } fn closed(&self, scope: &Scope) -> bool { - self.failed - || self - .pending - .values() - .any(|entry| entry.invalidates && entry.scope.overlaps(scope)) + self.failed || self.pending.values().any(|entry| entry.affects(scope)) } } impl Authority { pub(super) fn close(&self, scope: Scope) -> driver::Result> { - self.close_kind(scope, true) + self.close_kind(scope, Impact::Full) } pub(super) fn close_progress( &self, scope: Scope, proof: &crate::provider::RangeProgress, ) -> driver::Result> { - self.close_kind(scope, proof.invalidates()) + self.close_kind( + scope, + if proof.invalidates() { + Impact::Full + } else { + Impact::Preserved + }, + ) } - fn close_kind(&self, scope: Scope, invalidates: bool) -> driver::Result> { + pub(super) fn close_lifecycle( + &self, + scope: Scope, + proof: &crate::provider::OriginLifecycle, + ) -> driver::Result> { + let impact = if proof.origin_only() && matches!(scope, Scope::Domains(_)) { + Impact::Origin + } else { + Impact::Full + }; + self.close_kind(scope, impact) + } + fn close_kind(&self, scope: Scope, impact: Impact) -> driver::Result> { let mut state = self.state.lock().map_err(error)?; if state.failed { return Err(error("authority sealed until owner recovery")); @@ -159,7 +200,7 @@ impl Authority { id, Mutation { scope: scope.clone(), - invalidates, + impact, external: BTreeMap::new(), orphaned: false, }, @@ -291,6 +332,17 @@ impl Close<'_> { if self.receipt.is_some() { return Err(error("one delivery receipt per scope")); } + if self + .authority + .state + .lock() + .map_err(error)? + .pending + .get(&self.id) + .is_some_and(|entry| entry.impact == Impact::Origin) + { + return Err(error("origin lifecycle cannot issue a delivery receipt")); + } let receipt = Arc::new(Completion::default()); self.receipt = Some(receipt.clone()); Ok(receipt) @@ -301,7 +353,7 @@ impl Close<'_> { .pending .get_mut(&self.id) .ok_or_else(|| error("authority cut absent"))?; - if !mutation.invalidates { + if mutation.impact != Impact::Full { return Err(error("range progress cannot reconcile external authority")); } mutation.external.insert(path.to_owned(), reconciled); @@ -321,7 +373,10 @@ impl Close<'_> { if !known { state.failed = true; } - if modified && mutation.invalidates && state.advance(&self.scope).is_err() { + if modified + && mutation.impact != Impact::Preserved + && state.advance(&self.scope, mutation.impact).is_err() + { state.failed = true; } if committed && mutation.external.values().all(|complete| *complete) { @@ -382,3 +437,7 @@ impl Drop for Close<'_> { } } } + +#[cfg(test)] +#[path = "../../tests/unit/authority_footprint.rs"] +mod footprint_tests; diff --git a/crates/ledger/src/persistence/commit_observer.rs b/crates/ledger/src/persistence/commit_observer.rs index 655a75d2..8b506d7d 100644 --- a/crates/ledger/src/persistence/commit_observer.rs +++ b/crates/ledger/src/persistence/commit_observer.rs @@ -13,6 +13,10 @@ pub enum Cut { AfterRangePrepareCommit, BeforeDeliveryCommit, AfterDeliveryCommit, + BeforeAdmissionCommit, + AfterAdmissionCommit, + BeforeLifecycleCommit, + AfterLifecycleCommit, BeforeSnapshotPublication, AfterSnapshotPublication, } diff --git a/crates/ledger/src/persistence/mod.rs b/crates/ledger/src/persistence/mod.rs index 286286f4..ff5e3386 100644 --- a/crates/ledger/src/persistence/mod.rs +++ b/crates/ledger/src/persistence/mod.rs @@ -32,6 +32,6 @@ pub use scope::ProviderScopePhase; #[cfg(not(feature = "commit-observer"))] pub(crate) use scope::ProviderScopePhase; pub use scope::{WriteScope, begin}; -pub(crate) use scope::{begin_family, begin_provider_progress, begin_provider_use}; +pub(crate) use scope::{begin_family, begin_provider_lifecycle, begin_provider_progress}; pub use session::{LedgerCustody, Session}; pub use timing::{Timing, TransactionTimings}; diff --git a/crates/ledger/src/persistence/scope.rs b/crates/ledger/src/persistence/scope.rs index 0598f384..b9f7bceb 100644 --- a/crates/ledger/src/persistence/scope.rs +++ b/crates/ledger/src/persistence/scope.rs @@ -21,6 +21,11 @@ pub enum ProviderScopePhase { RevalidateDelivery, } +enum Change<'a> { + Semantic, + Progress(&'a crate::provider::RangeProgress), + Lifecycle(&'a crate::provider::OriginLifecycle), +} /// Exclusive native transaction; final guarded callbacks keep this scope alive. pub struct WriteScope<'a> { connection: &'a driver::Connection, @@ -53,22 +58,42 @@ pub struct WriteScope<'a> { } /// Acquire an immediate write transaction with exclusive Rust session custody. pub fn begin(session: &mut Session) -> driver::Result> { - start(session, None, None, ProviderScopePhase::Other, None) + start( + session, + None, + None, + ProviderScopePhase::Other, + Change::Semantic, + ) } /// Parallel MVCC admission or final use for one original claim/budget/history family. /// Global mutations use `begin`, excluding every live family scope through commit. pub fn begin_family<'a>(session: &'a mut Session, family: &str) -> driver::Result> { - start(session, Some(family), None, ProviderScopePhase::Other, None) + start( + session, + Some(family), + None, + ProviderScopePhase::Other, + Change::Semantic, + ) } -/// The caller must rejoin the live stamp in this scope before any effect. -pub(crate) fn begin_provider_use<'a>( +/// Read custody remains the complete domain set. Only the sealed provider +/// lifecycle write set may invalidate its origin lane alone in MVCC. +pub(crate) fn begin_provider_lifecycle<'a>( session: &'a mut Session, family: &str, - expected: &weaver_contracts::DomainStamp, + expected: Option<&weaver_contracts::DomainStamp>, phase: ProviderScopePhase, + proof: &crate::provider::OriginLifecycle, ) -> driver::Result> { - let expected = (!crate::task_origins::locked_original_evidence()).then_some(expected); - start(session, Some(family), expected, phase, None) + let expected = expected.filter(|_| !crate::task_origins::locked_original_evidence()); + start( + session, + Some(family), + expected, + phase, + Change::Lifecycle(proof), + ) } /// The sealed token is constructed only in provider's exact progress paths. @@ -80,7 +105,13 @@ pub(crate) fn begin_provider_progress<'a>( progress: &crate::provider::RangeProgress, ) -> driver::Result> { let expected = (!crate::task_origins::locked_original_evidence()).then_some(expected); - start(session, Some(family), expected, phase, Some(progress)) + start( + session, + Some(family), + expected, + phase, + Change::Progress(progress), + ) } fn start<'a>( @@ -88,7 +119,7 @@ fn start<'a>( family: Option<&str>, expected: Option<&weaver_contracts::DomainStamp>, phase: ProviderScopePhase, - progress: Option<&crate::provider::RangeProgress>, + change: Change<'_>, ) -> driver::Result> { session.require_quiescent()?; let concurrent = session.owner.journal == super::Journal::Mvcc; @@ -112,12 +143,16 @@ fn start<'a>( super::scheduler::Scope::Domains(keys.clone()) }); // Close before waiting for either the scheduler or native writer. - let authority = match progress { - Some(progress) => session + let authority = match change { + Change::Progress(progress) => session .owner .authority .close_progress(close_scope, progress)?, - None => session.owner.authority.close(close_scope)?, + Change::Lifecycle(proof) => session + .owner + .authority + .close_lifecycle(close_scope, proof)?, + Change::Semantic => session.owner.authority.close(close_scope)?, }; let mut owner_entered = None; let mut domains_entered = None; @@ -225,6 +260,12 @@ impl WriteScope<'_> { ) { self.authority.replace_receipt(receipt); } + pub(crate) fn commit_provider_admission(self) -> driver::Result<()> { + self.commit_observed::<5>() + } + pub(crate) fn commit_lifecycle(self) -> driver::Result<()> { + self.commit_observed::<4>() + } pub(crate) fn commit_delivery_refresh(self) -> driver::Result<()> { self.commit_observed::<3>() } @@ -259,6 +300,8 @@ impl WriteScope<'_> { let (before, after) = match PHASE { 1 => (Cut::BeforeRangePrepareCommit, Cut::AfterRangePrepareCommit), 2 => (Cut::BeforeDeliveryCommit, Cut::AfterDeliveryCommit), + 5 => (Cut::BeforeAdmissionCommit, Cut::AfterAdmissionCommit), + 4 => (Cut::BeforeLifecycleCommit, Cut::AfterLifecycleCommit), 3 => ( Cut::BeforeSnapshotPublication, Cut::AfterSnapshotPublication, diff --git a/crates/ledger/src/provider.rs b/crates/ledger/src/provider.rs index 9b656fac..0b7033ea 100644 --- a/crates/ledger/src/provider.rs +++ b/crates/ledger/src/provider.rs @@ -22,6 +22,32 @@ use weaver_contracts::{ pub(crate) struct RangeProgress { _sealed: (), } +/// Sealed write-set obligation: only run state/target, dispatch marker or raw +/// terminal usage changes; no reservation, history, quota or publication write. +pub(crate) struct OriginLifecycle { + _sealed: (), +} +#[cfg(feature = "commit-observer")] +thread_local! { + static FULL_LIFECYCLE_INVALIDATION: std::cell::Cell = const { std::cell::Cell::new(false) }; +} +#[cfg(feature = "commit-observer")] +/// Safe same-image test control: retain broad lifecycle invalidation. +pub fn use_full_lifecycle_invalidation(full: bool) { + FULL_LIFECYCLE_INVALIDATION.set(full); +} +impl OriginLifecycle { + pub(crate) fn origin_only(&self) -> bool { + #[cfg(feature = "commit-observer")] + { + !FULL_LIFECYCLE_INVALIDATION.get() + } + #[cfg(not(feature = "commit-observer"))] + { + true + } + } +} #[cfg(feature = "commit-observer")] thread_local! { static CONSERVATIVE_RANGE_INVALIDATION: std::cell::Cell = const { std::cell::Cell::new(false) }; @@ -161,7 +187,7 @@ impl Ledger { &publication?, original.as_ref(), )?; - tx.commit().map_err(db)?; + tx.commit_provider_admission().map_err(db)?; self.provider_receipt(&plan.family, &plan.node)? .ok_or(Error::Conflict("provider receipt missing")) } @@ -191,7 +217,14 @@ impl Ledger { #[cfg(feature = "commit-observer")] warm_release_programs(&self.connection); self.connection.prepare_provider_domain(); - let tx = crate::persistence::begin_family(&mut self.connection, family).map_err(db)?; + let tx = crate::persistence::begin_provider_lifecycle( + &mut self.connection, + family, + None, + ProviderScopePhase::Other, + &OriginLifecycle { _sealed: () }, + ) + .map_err(db)?; let oauth_expires = tx.check_provider_oauth(prepared.as_ref())?; let (plan, selected, digest) = authorize_provider_consumption( &tx, @@ -202,7 +235,7 @@ impl Ledger { original.as_ref(), )?; mark_provider_consumed(&tx, family, node, &selected.route.target)?; - tx.commit().map_err(db)?; + tx.commit_lifecycle().map_err(db)?; Ok(ProviderDispatch { plan, route: selected.route, @@ -228,7 +261,7 @@ impl Ledger { self.check_provider_session(permit)?; burn_dispatch(&mut self.connection, permit)?; let (mut tx, domains) = - begin_provider_effect(&mut self.connection, permit, ProviderScopePhase::Other)?; + begin_lifecycle_effect(&mut self.connection, permit, ProviderScopePhase::Other)?; guard_live(&tx, permit, &domains, "invokeProvider", 0, "protobuf")?; let result = tx.request_effect(send)?; record_dispatch_callback(&tx, permit)?; @@ -282,7 +315,7 @@ impl Ledger { ) -> Result<()> { self.check_provider_session(permit)?; let (tx, domains) = - begin_provider_effect(&mut self.connection, permit, ProviderScopePhase::Other)?; + begin_lifecycle_effect(&mut self.connection, permit, ProviderScopePhase::Other)?; let progress = release_progress(&tx, permit)?; guard_live(&tx, permit, &domains, "emitProvider", 0, format)?; if progress.pending { @@ -306,7 +339,7 @@ impl Ledger { ) .map_err(db)?; } - tx.commit().map_err(db)?; + tx.commit_lifecycle().map_err(db)?; Ok(()) } pub fn provider_receipt(&self, family: &str, node: &str) -> Result> { @@ -324,7 +357,7 @@ fn burn_dispatch( session: &mut crate::persistence::Session, permit: &ProviderDispatch, ) -> Result<()> { - let (tx, domains) = begin_provider_effect(session, permit, ProviderScopePhase::Other)?; + let (tx, domains) = begin_lifecycle_effect(session, permit, ProviderScopePhase::Other)?; guard_live(&tx, permit, &domains, "invokeProvider", 0, "protobuf")?; // Persist a separate affine dispatch burn: borrowing a handle cannot repeat this callback. let burn = crate::persistence::exec( @@ -336,7 +369,7 @@ fn burn_dispatch( if burn != 1 { return Err(Error::Conflict("provider dispatch already burned")); } - tx.commit().map_err(db)?; + tx.commit_lifecycle().map_err(db)?; Ok(()) } fn record_dispatch_callback(tx: &WriteScope<'_>, permit: &ProviderDispatch) -> Result<()> { @@ -460,13 +493,19 @@ fn mark_provider_consumed( Ok(()) } -pub(super) fn begin_provider_effect<'a>( +fn begin_lifecycle_effect<'a>( session: &'a mut crate::persistence::Session, p: &ProviderDispatch, phase: ProviderScopePhase, ) -> Result<(WriteScope<'a>, DomainView)> { - let tx = crate::persistence::begin_provider_use(session, &p.plan.family, &p.domains, phase) - .map_err(db)?; + let tx = crate::persistence::begin_provider_lifecycle( + session, + &p.plan.family, + Some(&p.domains), + phase, + &OriginLifecycle { _sealed: () }, + ) + .map_err(db)?; require_provider_effect(tx, p) } diff --git a/crates/ledger/tests/unit/authority_footprint.rs b/crates/ledger/tests/unit/authority_footprint.rs new file mode 100644 index 00000000..f56ad2cf --- /dev/null +++ b/crates/ledger/tests/unit/authority_footprint.rs @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +use super::{Impact, State}; +use crate::persistence::scheduler::Scope; +use proptest::{prop_assert_eq, prop_assert_ne, proptest}; + +proptest! { + #[test] + fn local_commit_retires_whole_and_own_but_preserves_peer(origin in 0u64..128, shared in 0u64..128) { + let own=Scope::Domains([format!("origin-{origin}"),format!("budget-{shared}"),format!("history-{shared}")].into()); + let peer=Scope::Domains([format!("origin-{}",origin+1),format!("budget-{shared}"),format!("history-{shared}")].into()); + let mut state=State::default(); + let whole_before=state.stamp(&Scope::All);let own_before=state.stamp(&own);let peer_before=state.stamp(&peer); + state.advance(&own,Impact::Origin).expect("local commit"); + prop_assert_ne!(state.stamp(&Scope::All),whole_before); + prop_assert_ne!(state.stamp(&own),own_before); + prop_assert_eq!(state.stamp(&peer),peer_before); + } +} diff --git a/crates/ledger/tests/unit/provider.rs b/crates/ledger/tests/unit/provider.rs index 37cc950a..c6509a49 100644 --- a/crates/ledger/tests/unit/provider.rs +++ b/crates/ledger/tests/unit/provider.rs @@ -885,3 +885,6 @@ mod delivery; #[path = "provider_snapshot.rs"] mod snapshot_delivery; + +#[path = "provider_lifecycle.rs"] +mod lifecycle; diff --git a/crates/ledger/tests/unit/provider_lifecycle.rs b/crates/ledger/tests/unit/provider_lifecycle.rs new file mode 100644 index 00000000..79366d86 --- /dev/null +++ b/crates/ledger/tests/unit/provider_lifecycle.rs @@ -0,0 +1,124 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +use super::fixture_nodes; +use proptest::{prop_assert, prop_assert_eq, proptest, test_runner::Config}; +use std::{ + collections::BTreeSet, + sync::{Arc, Mutex}, + task::{Context, Poll, Waker}, + time::{Duration, Instant}, +}; +use weaver_contracts::{DomainBinding, Task}; +use weaver_ledger::{ + DeliveryCursor, DeliveryFrame, + persistence::{ + self, Journal, Session, + commit_observer::{Cut, Decision, Observer}, + }, +}; + +struct Probe { + cursor: Mutex, + frames: [DeliveryFrame; 3], + seen: Mutex<[Option; 3]>, +} +impl Probe { + fn during_request(&self) { + let mut seen = self.seen.lock().expect("request observation"); + let at = if seen[0] == Some(true) && seen[1] == Some(true) { + 2 + } else { + 0 + }; + let cx = Context::from_waker(Waker::noop()); + seen[2] = Some(matches!( + self.cursor + .lock() + .expect("cursor") + .poll(&self.frames[at], &cx, &mut Some(())), + Poll::Ready(Ok(())) + )); + } +} +impl Observer for Probe { + fn observe(&self, cut: Cut) -> Decision { + let at = match cut { + Cut::BeforeLifecycleCommit | Cut::BeforeAdmissionCommit => 0, + Cut::AfterLifecycleCommit | Cut::AfterAdmissionCommit => 1, + _ => return Decision::Continue, + }; + let mut seen = self.seen.lock().expect("observations"); + if seen[at].is_none() { + let cx = Context::from_waker(Waker::noop()); + // If the earlier frame was fenced, preserve its cursor for the + // after-commit check instead of advancing to an unoffered interval. + let frame = if at == 1 && seen[0] == Some(true) { + 1 + } else { + 0 + }; + seen[at] = Some(matches!( + self.cursor + .lock() + .expect("cursor") + .poll(&self.frames[frame], &cx, &mut Some(())), + Poll::Ready(Ok(())) + )); + } + Decision::Continue + } +} + +proptest! { + #![proptest_config(Config::with_cases(32))] + #[test] + fn peer_lifecycle_preserves_complete_view_but_shared_admission_does_not( + phase in 0u8..4, same_origin in proptest::bool::ANY, + mvcc in proptest::bool::ANY, conservative in proptest::bool::ANY, + ) { + let directory=tempfile::tempdir().expect("store");let path=directory.path().join("local.db"); + let storage=Session::open_with_journal(&path,if mvcc {Journal::Mvcc}else{Journal::Wal}).expect("journal"); + let (mut ledger,mut plan)=fixture_nodes(&path,&["infer","second"]); + let policy=super::POLICY.replace("context.family == \"f\"", "[\"f\",\"peer\"].contains(context.family)").replace("context.node == \"infer\"", "[\"infer\",\"second\"].contains(context.node)"); + ledger.publish_typed(Some(0),&policy,super::SCHEMA,2).expect("explicit peer Policy"); + plan.revision=1;plan.fence=2; + let mut peer=plan.clone(); + + if same_origin {peer.node="second".into();} else { + peer.family="peer".into(); + let record:String=persistence::one(&storage,"SELECT record FROM tasks WHERE family='f'",(),|r|r.get(0)).expect("original task"); + let mut task:Task=serde_json::from_str(&record).expect("typed task");task.family=peer.family.clone(); + task.stream_contracts.insert(peer.node.clone(),peer.digest().expect("bound peer")); + ledger.register_task_domains(&task,&DomainBinding{origin:"peer-origin".into(),budget:"f".into(),history:"f".into(),budget_limit:8},None).expect("shared original domains"); + } + ledger.enqueue_provider(&plan).expect("original hold");if phase!=3 {ledger.enqueue_provider(&peer).expect("peer hold");} + let eligible=BTreeSet::from(["primary".into()]); + let own=ledger.consume_provider("f","infer",&eligible).expect("own consume"); + ledger.dispatch_provider(&own,||Ok(())).expect("own dispatch"); + let peer_permit=if phase>0 && phase<3 {Some(ledger.consume_provider(&peer.family,&peer.node,&eligible).expect("peer consume"))} else {None}; + if phase==2 { ledger.dispatch_provider(peer_permit.as_ref().expect("permit"),||Ok(())).expect("peer dispatch"); } + let releases=ledger.prepare_provider_releases(&own,&[("first",1),("second",1),("third",1)],"protobuf").expect("manifest"); + let mut staged=None; + let (_,tail)=ledger.release_provider_group_for_delivery(&own,releases,"protobuf",|_,d|{staged=Some(d.split());Ok(())}).expect("snapshot"); + let (first,frame0)=staged.expect("first");let mut tail=tail.into_iter();let(second,frame1)=tail.next().expect("second").split();let(third,frame2)=tail.next().expect("third").split(); + first.acknowledge(Instant::now()+Duration::from_secs(1)).expect("first ack"); + second.acknowledge(Instant::now()+Duration::from_secs(1)).expect("second ack");third.acknowledge(Instant::now()+Duration::from_secs(1)).expect("third ack"); + let probe=Arc::new(Probe{cursor:Mutex::new(DeliveryCursor::new(&plan).expect("cursor")),frames:[frame0,frame1,frame2],seen:Mutex::new([None,None,None])}); + ledger.observe_provider_commit(probe.clone()); + weaver_ledger::use_full_lifecycle_invalidation(conservative); + match phase { + 0 => {ledger.consume_provider(&peer.family,&peer.node,&eligible).expect("observed consumption");} + 1 => {ledger.dispatch_provider(peer_permit.as_ref().expect("permit"),||{probe.during_request();Ok(())}).expect("observed dispatch");} + 2 => {ledger.complete_provider_with_usage(peer_permit.as_ref().expect("permit"),"protobuf",Some([1,1,0,0])).expect("observed terminal");} + _ => {ledger.enqueue_provider(&peer).expect("observed shared admission");} + } + weaver_ledger::use_full_lifecycle_invalidation(false); + let accepted=phase!=3 && mvcc && !same_origin && !conservative; + prop_assert_eq!(*probe.seen.lock().expect("checked actual native cuts"),[Some(accepted),Some(accepted),if phase==1 {Some(accepted)}else{None}]); + let current=ledger.execution_domains("f").expect("current view");prop_assert_eq!((current.held,current.history_count),(8,2)); + prop_assert_eq!(ledger.provider_receipt("f","infer").expect("receipt").expect("original").held,if same_origin {8}else{4}); + prop_assert!(ledger.consume_provider("f","infer",&eligible).is_err(),"original claim reopened"); + } +} diff --git a/crates/server/src/grpc_provider.rs b/crates/server/src/grpc_provider.rs index 4e332f94..58524c22 100644 --- a/crates/server/src/grpc_provider.rs +++ b/crates/server/src/grpc_provider.rs @@ -92,6 +92,10 @@ impl Gateway { std::env::var("WEAVER_TEST_SEPARATE_RELEASE_READS").as_deref() == Ok("1"), ); #[cfg(test)] + weaver_ledger::use_full_lifecycle_invalidation( + std::env::var_os("WEAVER_TEST_FULL_LIFECYCLE_INVALIDATION").is_some(), + ); + #[cfg(test)] weaver_ledger::use_conservative_range_invalidation( std::env::var_os("WEAVER_TEST_CONSERVATIVE_RANGE_INVALIDATION").is_some(), ); @@ -134,6 +138,7 @@ impl Gateway { weaver_ledger::use_fresh_provider_domain_plan(false); weaver_ledger::use_separate_release_reads(false); weaver_ledger::use_cached_release_programs(false); + weaver_ledger::use_full_lifecycle_invalidation(false); weaver_ledger::use_conservative_range_invalidation(false); } #[cfg(test)] diff --git a/crates/server/tests/unit/provider_commit.rs b/crates/server/tests/unit/provider_commit.rs index 742bd641..6daf6d6b 100644 --- a/crates/server/tests/unit/provider_commit.rs +++ b/crates/server/tests/unit/provider_commit.rs @@ -44,10 +44,17 @@ impl Observer for CommitObserver { if cut != self.selected { return Decision::Continue; } - if matches!(cut, Cut::BeforeDeliveryCommit | Cut::AfterDeliveryCommit) - && self - .delivery_used - .swap(true, std::sync::atomic::Ordering::SeqCst) + if matches!( + cut, + Cut::BeforeDeliveryCommit + | Cut::AfterDeliveryCommit + | Cut::BeforeLifecycleCommit + | Cut::AfterLifecycleCommit + | Cut::BeforeAdmissionCommit + | Cut::AfterAdmissionCommit + ) && self + .delivery_used + .swap(true, std::sync::atomic::Ordering::SeqCst) { return Decision::Continue; } @@ -73,6 +80,8 @@ impl Observer for CommitObserver { let marker = match cut { Cut::BeforeRangePrepareCommit | Cut::AfterRangePrepareCommit => durable_range_marker(), Cut::BeforeDeliveryCommit | Cut::AfterDeliveryCommit => durable_delivery_marker(), + Cut::BeforeLifecycleCommit | Cut::AfterLifecycleCommit => lifecycle_marker(), + Cut::BeforeAdmissionCommit | Cut::AfterAdmissionCommit => admission_marker(), _ => durable_marker(), }; socket @@ -90,6 +99,36 @@ impl Observer for CommitObserver { } } } +fn admission_marker() -> i64 { + run_marker("SELECT COUNT(*) FROM provider_runs") +} +fn lifecycle_marker() -> i64 { + run_marker("SELECT COUNT(*) FROM provider_runs WHERE state!='queued'") +} +fn run_marker(query: &str) -> i64 { + let path = std::env::var("WEAVER_DB").expect("database"); + if !std::path::Path::new(&path).exists() { + return 0; + } + let journal = if std::env::var("WEAVER_STORAGE_JOURNAL").as_deref() == Ok("mvcc") { + persistence::Journal::Mvcc + } else { + persistence::Journal::Wal + }; + let session = persistence::Session::open_with_journal(path, journal) + .expect("independent lifecycle reader"); + let table: bool = persistence::one( + &session, + "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE name='provider_runs')", + (), + |r| r.get(0), + ) + .expect("schema read"); + if !table { + return 0; + } + persistence::one(&session, query, (), |r| r.get(0)).expect("committed native state") +} fn durable_range_marker() -> i64 { if durable_marker() == 0 { return 0; @@ -150,34 +189,7 @@ fn durable_delivery_marker() -> i64 { .expect("durable released ranges") } fn durable_marker() -> i64 { - let path = std::env::var("WEAVER_DB").expect("fixture database"); - if !std::path::Path::new(&path).exists() { - return 0; - } - let journal = if std::env::var("WEAVER_STORAGE_JOURNAL").as_deref() == Ok("mvcc") { - persistence::Journal::Mvcc - } else { - persistence::Journal::Wal - }; - let session = - persistence::Session::open_with_journal(path, journal).expect("independent native reader"); - let table: bool = persistence::one( - &session, - "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE name='provider_runs')", - (), - |r| r.get(0), - ) - .expect("schema read"); - if !table { - return 0; - } - persistence::one( - &session, - "SELECT COALESCE(MAX(dispatched),0) FROM provider_runs", - (), - |r| r.get(0), - ) - .expect("persisted dispatch marker") + run_marker("SELECT COALESCE(MAX(dispatched),0) FROM provider_runs") } pub(crate) fn mutation_started(operation: &str, phase: &str) { if operation == "racing-a" @@ -207,6 +219,10 @@ fn serve_observed_gateway() { Ok("after") => Cut::AfterCommit, Ok("prepare-before") => Cut::BeforeRangePrepareCommit, Ok("prepare-after") => Cut::AfterRangePrepareCommit, + Ok("lifecycle-before") => Cut::BeforeLifecycleCommit, + Ok("lifecycle-after") => Cut::AfterLifecycleCommit, + Ok("admission-before") => Cut::BeforeAdmissionCommit, + Ok("admission-after") => Cut::AfterAdmissionCommit, Ok("delivery-before") => Cut::BeforeDeliveryCommit, Ok("delivery-after") => Cut::AfterDeliveryCommit, _ => panic!("explicit commit cut required"), @@ -222,6 +238,8 @@ fn serve_observed_gateway() { durable_range_marker(), Cut::BeforeDeliveryCommit | Cut::AfterDeliveryCommit => durable_delivery_marker(), + Cut::BeforeLifecycleCommit | Cut::AfterLifecycleCommit => lifecycle_marker(), + Cut::BeforeAdmissionCommit | Cut::AfterAdmissionCommit => admission_marker(), _ => durable_marker(), } ) diff --git a/dev/proofs/cedar/DomainMigrationComposition.lean b/dev/proofs/cedar/DomainMigrationComposition.lean index 068bdb75..a46335b7 100644 --- a/dev/proofs/cedar/DomainMigrationComposition.lean +++ b/dev/proofs/cedar/DomainMigrationComposition.lean @@ -2,6 +2,7 @@ -- -- SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 +import ProviderLifecycleFootprint import ProviderSnapshotPublication import ProviderSemanticProgress import CedarPooSpec.Gateway.ZeroTrust @@ -111,6 +112,31 @@ theorem published_snapshot_preserves_spec_final_use #print axioms published_snapshot_preserves_spec_final_use +/-- Preserve the observer's cached predicate, then bind it to the CURRENT SPEC + actual state. Other origins may change the whole world; global invariants + come from the current reachable run, never equality with an old world. -/ +theorem peer_lifecycle_preserves_spec_final_use [DecidableEq Family] + (use : Gateway.ZeroTrust.FinalUse proposal) + (events : GatewayHeadCAS.Run c owner GatewayHeadCAS.initial use.actual) + (store : Weaver.ProviderLifecycleFootprint.Store Family) + (writer observer : Family) (next : Weaver.ProviderLifecycleFootprint.Local) + (distinct : observer ≠ writer) + (observe : GatewayHeadCAS.State → Weaver.ProviderLifecycleFootprint.View Family) + (current : observe use.actual = Weaver.ProviderLifecycleFootprint.view + (Weaver.ProviderLifecycleFootprint.transition store writer next) observer) + (allow : Weaver.ProviderLifecycleFootprint.View Family → Prop) + (qualified : allow (Weaver.ProviderLifecycleFootprint.view store observer)) : + allow (observe use.actual) ∧ + (Gateway.ZeroTrust.specialize proposal (reachableDomain c)).required effect use.actual ∧ + (∀ account, booked c use.actual.base account ≤ c.capacity account) ∧ + (∀ key, (use.actual.base.messages key).claims ≤ 1 ∧ + (use.actual.base.messages key).sends ≤ 1) ∧ original.Refines prepared.profile := by + refine ⟨?_, gateway_final_use_preserves_domain_contract use events⟩ + rw [current, Weaver.ProviderLifecycleFootprint.different_origin_preserves_complete_view store writer observer next distinct] + exact qualified + +#print axioms peer_lifecycle_preserves_spec_final_use + theorem head_cas_preserves_original_obligations (step : GatewayHeadCAS.Step c owner before after) (claimed : (before.base.messages key).claimed = true) diff --git a/dev/proofs/cedar/lakefile.toml b/dev/proofs/cedar/lakefile.toml index b152bf58..626c9796 100644 --- a/dev/proofs/cedar/lakefile.toml +++ b/dev/proofs/cedar/lakefile.toml @@ -46,7 +46,7 @@ roots = ["AnchorBrokerCommit","AnchorReconfiguration","AnchoredRecoveryAndEgress [[lean_lib]] name = "ExecutionResearch" srcDir = "../lean" -roots = ["BrokerConsumptionQueue","CommittedSemanticProfile","DeviceIsolationRecovery","DynamicImageCustody","DynamicImportBoundary","DynamicLoaderPublication","DynamicPairedEvidence","FencedIntentContinuation","FloorIntentDecision","GambitLocatorClosure","GatewayHeadCAS","GerbilExitQualification","KeyBoundaryQueue","LlmAccountCommit","LlmAdmissionFloor","LlmAppendHandoff","LlmAttemptLedger","LlmAuthoritativeScope","LlmBeneficiaryRegistration","LlmBootstrapInvitation","LlmCallerCustody","LlmCanonicalRegistry","LlmCheckpointTruncation","LlmCustodyPublication","LlmEnrollmentCredential","LlmExecutionReconciliation","LlmExecutorOffer","LlmIncarnationIssuance","LlmJoinEnqueue","LlmManifestSwitch","LlmMultiKeyRegistry","LlmPolicyContinuation","LlmPolicyPublication","LlmRecoveryCAS","LlmRegistryPublication","LlmResultProjection","LlmRouting","LlmSemanticContract","LlmSourceCustody","LlmSourceJoin","LlmSubjectAuthority","LlmWalActivation","LogicalRangeRecovery","ProtectedSignerRelease","ProviderEgressWindow","ProviderSemanticProgress","ProviderSnapshotPublication","RoutineRoutingConfig","RuntimeAdmission","SemanticGatewaySlice","SharedDomains","StreamingExecution"] +roots = ["BrokerConsumptionQueue","CommittedSemanticProfile","DeviceIsolationRecovery","DynamicImageCustody","DynamicImportBoundary","DynamicLoaderPublication","DynamicPairedEvidence","FencedIntentContinuation","FloorIntentDecision","GambitLocatorClosure","GatewayHeadCAS","GerbilExitQualification","KeyBoundaryQueue","LlmAccountCommit","LlmAdmissionFloor","LlmAppendHandoff","LlmAttemptLedger","LlmAuthoritativeScope","LlmBeneficiaryRegistration","LlmBootstrapInvitation","LlmCallerCustody","LlmCanonicalRegistry","LlmCheckpointTruncation","LlmCustodyPublication","LlmEnrollmentCredential","LlmExecutionReconciliation","LlmExecutorOffer","LlmIncarnationIssuance","LlmJoinEnqueue","LlmManifestSwitch","LlmMultiKeyRegistry","LlmPolicyContinuation","LlmPolicyPublication","LlmRecoveryCAS","LlmRegistryPublication","LlmResultProjection","LlmRouting","LlmSemanticContract","LlmSourceCustody","LlmSourceJoin","LlmSubjectAuthority","LlmWalActivation","LogicalRangeRecovery","ProtectedSignerRelease","ProviderEgressWindow","ProviderSemanticProgress","ProviderSnapshotPublication","ProviderLifecycleFootprint","RoutineRoutingConfig","RuntimeAdmission","SemanticGatewaySlice","SharedDomains","StreamingExecution"] [[lean_lib]] name = "DomainMigrationComposition" diff --git a/dev/proofs/lean/ProviderLifecycleFootprint.lean b/dev/proofs/lean/ProviderLifecycleFootprint.lean new file mode 100644 index 00000000..44af1aba --- /dev/null +++ b/dev/proofs/lean/ProviderLifecycleFootprint.lean @@ -0,0 +1,99 @@ +-- SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +-- +-- SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +import Std + +namespace Weaver.ProviderLifecycleFootprint + +/-- The concrete host must retain every shared dependency, including the exact + cross-family reservation projection. This is not a monotone-Policy model. -/ +structure Shared where + policy : Nat + oauth : Nat + held : Nat + history : Nat + quota : Nat + roots : Nat + deriving DecidableEq + +structure Local where + target : Nat + state : Nat + dispatched : Nat + usage : Nat + deriving DecidableEq + +structure Store (Family : Type) where + shared : Shared + retained : Family → Nat + localState : Family → Local + originalHold : Family → Nat + +structure View (Family : Type) where + shared : Shared + retained : Family → Nat + own : Local + originalHold : Family → Nat + +def view (s : Store Family) (observer : Family) : View Family := + ⟨s.shared, s.retained, s.localState observer, s.originalHold⟩ + +def transition [DecidableEq Family] (s : Store Family) (writer : Family) (next : Local) : Store Family := + {s with localState := fun f => if f = writer then next else s.localState f} + +theorem different_origin_preserves_complete_view [DecidableEq Family] + (s : Store Family) (writer observer : Family) (next : Local) (distinct : observer ≠ writer) : + view (transition s writer next) observer = view s observer := by + simp [view, transition, distinct] + +theorem arbitrary_cedar_predicate_preserved [DecidableEq Family] + (s : Store Family) (writer observer : Family) (next : Local) (distinct : observer ≠ writer) + (allow : View Family → Prop) : + allow (view (transition s writer next) observer) ↔ allow (view s observer) := by + rw [different_origin_preserves_complete_view s writer observer next distinct] + +theorem local_transition_keeps_every_original_hold [DecidableEq Family] + (s : Store Family) (writer observer : Family) (next : Local) : + (transition s writer next).originalHold observer = s.originalHold observer := rfl + +/-- Scope equality remains required for final use. This lemma only justifies + the write footprint; native read/scheduling custody remains the full set. -/ +structure Cut (Family : Type) where + whole : Nat + shared : Nat + origins : Family → Nat + +def advanceOrigin [DecidableEq Family] (c : Cut Family) (writer : Family) : Cut Family := + {c with whole := c.whole + 1, origins := fun f => if f = writer then c.origins f + 1 else c.origins f} + +def stamp (c : Cut Family) (observer : Family) : Nat × Nat := (c.shared, c.origins observer) + +theorem origin_commit_keeps_peer_stamp [DecidableEq Family] + (c : Cut Family) (writer observer : Family) (distinct : observer ≠ writer) : + stamp (advanceOrigin c writer) observer = stamp c observer := by + simp [stamp, advanceOrigin, distinct] + +theorem origin_commit_retires_own_stamp [DecidableEq Family] (c : Cut Family) (writer : Family) : + stamp (advanceOrigin c writer) writer ≠ stamp c writer := by + simp [stamp, advanceOrigin] + +/-- A whole-store observer includes every origin's local state. Its aggregate + revision is separate from the shared revision used by domain readers. -/ +theorem origin_commit_retires_whole_reader [DecidableEq Family] (c : Cut Family) (writer : Family) : + (advanceOrigin c writer).whole ≠ c.whole := by simp [advanceOrigin] + +/-- A new reservation changes a shared coordinate; origin-only publication + cannot preserve arbitrary Cedar predicates on that view. -/ +theorem shared_admission_requires_shared_invalidation (s : Store Family) (observer : Family) : + (view {s with shared := {s.shared with held := s.shared.held + 1}} observer).shared.held ≠ + (view s observer).shared.held := by simp [view] + +#print axioms different_origin_preserves_complete_view +#print axioms arbitrary_cedar_predicate_preserved +#print axioms local_transition_keeps_every_original_hold +#print axioms origin_commit_keeps_peer_stamp +#print axioms origin_commit_retires_whole_reader +#print axioms origin_commit_retires_own_stamp +#print axioms shared_admission_requires_shared_invalidation +end Weaver.ProviderLifecycleFootprint diff --git a/dev/proofs/quint/ProviderLifecycleFootprint.qnt b/dev/proofs/quint/ProviderLifecycleFootprint.qnt new file mode 100644 index 00000000..7deb4120 --- /dev/null +++ b/dev/proofs/quint/ProviderLifecycleFootprint.qnt @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +module ProviderLifecycleFootprint { + pure val families=Set(0,1,2) + type State={whole:int,cut:int,actual:int,origin:int->int,local:int->int, + certCut:int->int,certView:int->int,certOrigin:int->int,certLocal:int->int, + pending:Set[int],used:Set[int],writer:int->int,shared:int->bool, + owner:int,certOwner:int->int,held:int,failed:bool,allowed:bool, + offers:int->int,bad:bool,calls:int} + var s:State + action init=s'={whole:0,cut:0,actual:0,origin:families.mapBy(_=>0),local:families.mapBy(_=>0), + certCut:families.mapBy(_=>0),certView:families.mapBy(_=>0), + certOrigin:families.mapBy(_=>0),certLocal:families.mapBy(_=>0), + pending:Set(),used:Set(),writer:Set(0,1,2,3,4,5).mapBy(_=>0), + shared:Set(0,1,2,3,4,5).mapBy(_=>false),owner:1, + certOwner:families.mapBy(_=>1),held:12,failed:false,allowed:true, + offers:families.mapBy(_=>0),bad:false,calls:3} + def closed(f:int):bool=s.pending.exists(id=>s.shared.get(id) or s.writer.get(id)==f) + action begin(id:int,f:int,broad:bool):bool=all {not(s.used.contains(id)),not(s.failed), + s'={...s,pending:s.pending.union(Set(id)),used:s.used.union(Set(id)), + writer:s.writer.set(id,f),shared:s.shared.set(id,broad)}} + action commitLocal(id:int):bool=all {s.pending.contains(id),not(s.shared.get(id)), + val f=s.writer.get(id) + s'={...s,whole:s.whole+1,pending:s.pending.exclude(Set(id)),origin:s.origin.set(f,s.origin.get(f)+1), + local:s.local.set(f,s.local.get(f)+1)}} + action commitAdmission(id:int):bool=all {s.pending.contains(id),s.shared.get(id), + s'={...s,whole:s.whole+1,pending:s.pending.exclude(Set(id)),cut:s.cut+1,actual:s.actual+1,held:s.held+4}} + action rollback(id:int):bool=all {s.pending.contains(id),s'={...s,pending:s.pending.exclude(Set(id))}} + action unknown(id:int):bool=all {s.pending.contains(id),s'={...s,failed:true}} + action revoke=s'={...s,whole:s.whole+1,cut:s.cut+1,actual:s.actual+1,allowed:false} + action migrate=s'={...s,whole:s.whole+1,cut:s.cut+1,actual:s.actual+1} + action restart=s'={...s,owner:s.owner+1,failed:false,pending:Set()} + action qualify(f:int):bool=all {not(closed(f)),not(s.failed),s.allowed,s.local.get(f)==0, + s.certOwner.get(f)==s.owner, + s'={...s,certCut:s.certCut.set(f,s.cut),certView:s.certView.set(f,s.actual), + certOrigin:s.certOrigin.set(f,s.origin.get(f)),certLocal:s.certLocal.set(f,s.local.get(f))}} + action offer(f:int):bool=all {not(closed(f)),not(s.failed),s.allowed, + s.certOwner.get(f)==s.owner,s.certCut.get(f)==s.cut,s.certOrigin.get(f)==s.origin.get(f), + s.offers.get(f)==0, + s'={...s,offers:s.offers.set(f,1),bad:s.bad or s.certView.get(f)!=s.actual or s.certLocal.get(f)!=s.local.get(f)}} + // Unsafe mutants change an actual dependency without its corresponding cut. + action unsafeAdmissionAsLocal(id:int):bool=all {s.pending.contains(id), + s'={...s,pending:s.pending.exclude(Set(id)),actual:s.actual+1,held:s.held+4}} + action unsafeTerminalWithoutOwnCut(f:int):bool=s'={...s,local:s.local.set(f,s.local.get(f)+1)} + action wholeOffer=all {s.whole==0,s.pending.size()==0,not(s.failed),s.owner==1,s'=s} + action step={nondet f=families.oneOf() + nondet id=Set(0,1,2,3,4,5).oneOf() + nondet broad=Set(true,false).oneOf() + any {begin(id,f,broad),commitLocal(id),commitAdmission(id),rollback(id),unknown(id), + revoke,migrate,restart,qualify(f),offer(f)}} + val safe=not(s.bad) and s.held>=12 and s.calls==3 and families.forall(f=>s.offers.get(f)<=1) + run peerFrameCrossesPendingLocalTest=init.then(begin(0,0,false)).then(offer(1)).expect(safe) + run peerFrameCrossesCommittedLocalTest=init.then(begin(0,0,false)).then(commitLocal(0)).then(offer(1)).expect(safe) + run ownPendingLocalBlocksTest=init.then(begin(0,0,false)).then(offer(0).fail()) + run ownCommittedLocalBlocksTest=init.then(begin(0,0,false)).then(commitLocal(0)).then(offer(0).fail()) + run sharedAdmissionClosesPeersTest=init.then(begin(0,0,true)).then(offer(1).fail()) + run sharedAdmissionRequiresRefreshTest=init.then(begin(0,0,true)).then(commitAdmission(0)).then(offer(1).fail()) + run newViewResumesPeerTest=init.then(begin(0,0,true)).then(commitAdmission(0)).then(qualify(1)).then(offer(1)).expect(safe) + run localRollbackPreservesOwnTest=init.then(begin(0,0,false)).then(rollback(0)).then(offer(0)).expect(safe) + run localUnknownSealsPeersTest=init.then(begin(0,0,false)).then(unknown(0)).then(offer(1).fail()) + run restartCannotAdoptOldPeerTest=init.then(begin(0,0,false)).then(unknown(0)).then(restart).then(offer(1).fail()) + run migrationRetiresPeerTest=init.then(migrate).then(offer(1).fail()) + run revocationRetiresPeerTest=init.then(revoke).then(offer(1).fail()) + run twoLocalWritersRetainThirdTest=init.then(begin(0,0,false)).then(begin(1,1,false)).then(commitLocal(1)).then(offer(2)).expect(safe and closed(0)) + run localCommitRetiresWholeReaderTest=init.then(begin(0,0,false)).then(commitLocal(0)).then(wholeOffer.fail()) + run localPendingBlocksWholeReaderTest=init.then(begin(0,0,false)).then(wholeOffer.fail()) + run unsafeNarrowAdmissionCounterexampleTest=init.then(begin(0,0,false)).then(unsafeAdmissionAsLocal(0)).then(offer(1)).expect(not(safe)) + run unsafeSkipOwnTerminalCounterexampleTest=init.then(unsafeTerminalWithoutOwnCut(0)).then(offer(0)).expect(not(safe)) +} diff --git a/dev/sysml/ArchitectureViews.sysml b/dev/sysml/ArchitectureViews.sysml index cd10d4c7..eb4111fa 100644 --- a/dev/sysml/ArchitectureViews.sysml +++ b/dev/sysml/ArchitectureViews.sysml @@ -257,6 +257,7 @@ package WeaverViews { requirement delivery : WeaverExecution::ProviderDeliveryJoin; requirement semanticProgress : WeaverExecution::ProviderSemanticProgress; requirement publicationContract : WeaverExecution::ProviderSnapshotPublication; + requirement lifecycleFootprint : WeaverExecution::ProviderLifecycleFootprint; expose WeaverExecution::providerDeliveryJoin::changes; expose WeaverExecution::providerDeliveryJoin::validated; expose WeaverExecution::providerDeliveryJoin::publication; diff --git a/dev/sysml/WeaverExecution.sysml b/dev/sysml/WeaverExecution.sysml index 727f6bc9..08e12edb 100644 --- a/dev/sysml/WeaverExecution.sysml +++ b/dev/sysml/WeaverExecution.sysml @@ -302,6 +302,23 @@ package WeaverExecution { reopen only on the exact fenced image and outcome. */ } + requirement def ProviderLifecycleFootprint { + doc /* Read custody and invalidation are different footprints. Admission + appends original claims and changes held/history/quota projections, + so it still closes all sharing origins. Settlement, migration, + Policy, OAuth/witness and unclassified writes remain broad. */ + doc /* Exact consumed state/target, dispatch markers and terminal state + or usage observations change only the original origin's live view. + Cross-origin exposure reads digest/reserved/plan ceiling, original + claims and holds, never a peer's run state, target or raw usage. + Close and advance that origin lane only, retaining the full native + read/scheduler set. Same-origin frames still retire. Unknown outcomes + seal the whole owner; no lifecycle transition releases unknown hold. + Whole-store readers use a separate aggregate revision advanced by + every semantic commit; domain readers retain shared plus origin + revisions. WAL retains its conservative global profile. */ + } + requirement def ProviderSnapshotPublication { doc /* Existing ready ranges form a bounded immutable manifest. A native transaction rechecks Cedar for every actual row, original claim, @@ -435,7 +452,7 @@ package WeaverExecution { } part def EgressMutationBarrier { attribute displayName : String = "Rust / close"; - attribute responsibility : String = "Policy + OAuth + domains\nKeep every pending ID"; + attribute responsibility : String = "Run edits / origin cut\nShared edits / shared cut"; attribute glyph : String = "policy"; attribute visualRole : String = "governance"; port closed : EgressWindowPort; diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index c1665719..52853457 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -1,4 +1,5 @@ -[ +[ {"id":"ProviderLifecycleFootprint","witnesses":[{"file":"crates/ledger/src/provider.rs","pattern":"struct OriginLifecycle"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"enum Impact"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_lifecycle"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_provider_lifecycle"},{"file":"crates/ledger/tests/unit/provider_lifecycle.rs","pattern":"fn peer_lifecycle_preserves_complete_view_but_shared_admission_does_not"},{"file":"go/dev/provider_lifecycle_test.go","pattern":"func TestProviderLifecycleCommitRecovery"},{"file":"crates/ledger/tests/unit/authority_footprint.rs","pattern":"fn local_commit_retires_whole_and_own_but_preserves_peer"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem origin_commit_retires_whole_reader","declaration":"Weaver.ProviderLifecycleFootprint.origin_commit_retires_whole_reader"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem arbitrary_cedar_predicate_preserved","declaration":"Weaver.ProviderLifecycleFootprint.arbitrary_cedar_predicate_preserved"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem shared_admission_requires_shared_invalidation","declaration":"Weaver.ProviderLifecycleFootprint.shared_admission_requires_shared_invalidation"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem peer_lifecycle_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.peer_lifecycle_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderLifecycleFootprint.qnt","pattern":"run unsafeNarrowAdmissionCounterexampleTest"}]}, + {"id":"ProviderSnapshotPublication","witnesses":[{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn release_provider_group_for_delivery"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"struct Snapshot"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn share_qualification"},{"file":"crates/ledger/src/provider.rs","pattern":"fn begin_snapshot_validation"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn take_refresh"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem pending_close_defers_renewal","declaration":"Weaver.ProviderSnapshotPublication.pending_close_defers_renewal"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn a_request_arriving_during_qualification_cannot_trigger_a_second_native_read"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn one_snapshot_requalification_covers_every_exact_frame"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn post_staging_native_failure_cannot_publish_a_partial_snapshot"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn queue_snapshot"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func awaitDeliveryCuts"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem final_use_joins_snapshot","declaration":"Weaver.ProviderSnapshotPublication.final_use_joins_snapshot"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem published_snapshot_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.published_snapshot_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSnapshotPublication.qnt","pattern":"run ungatedArcLoadIsCounterexampleTest"}]}, {"id":"ProviderSemanticProgress","witnesses":[{"file":"crates/ledger/src/provider.rs","pattern":"struct RangeProgress"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_progress"},{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn stage_group"},{"file":"crates/ledger/tests/unit/provider_delivery.rs","pattern":"fn exact_range_progress_preserves_queued_authorization"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderSemanticProgressProperty"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_released_binding","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_released_binding"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_image","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_image"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem range_progress_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.range_progress_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSemanticProgress.qnt","pattern":"run hiddenSemanticEditIsCounterexampleTest"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"}]}, {"id":"ProviderDeliveryJoin","witnesses":[{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn bounded_trace_retains_every_requalification"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeTraceChunksPreserveAllRecords"},{"file":"crates/ledger/tests/unit/persistence_owner.rs","pattern":"fn descriptor_copy_is_not_a_retained_execution_owner"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem retained_role_blocks_custody_retirement","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.retained_role_blocks_custody_retirement"},{"file":"dev/proofs/quint/ProviderDeliveryPipeline.qnt","pattern":"run threeInertFramesNeedNoStopAndWaitTest"},{"file":"crates/server/src/grpc_delivery_producer.rs","pattern":"fn reserve_guarded"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"pub fn poll"},{"file":"crates/server/src/grpc_delivery.rs","pattern":"impl Stream for ResponseStream"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryCommitAndReceiverRecovery"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryReceiverProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem orphaned_witness_cannot_activate","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.orphaned_witness_cannot_activate"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem acknowledged_delivery_preserves_same_actual_view","declaration":"Weaver.DomainMigrationComposition.acknowledged_delivery_preserves_same_actual_view"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run committedWithoutAcknowledgmentCannotAcceptTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run rollbackCannotEraseIndependentWitnessTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run oldOwnerCannotRequalifyAfterRestartTest"}]}, diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.00-index.org b/docs/10-19-llm-gateway/10-routing-and-inference/10.00-index.org index 7b7269ed..24c1c8fd 100644 --- a/docs/10-19-llm-gateway/10-routing-and-inference/10.00-index.org +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.00-index.org @@ -65,3 +65,5 @@ No Gateway runtime or dependency pin is changed. [[file:10.09-provider-delivery-join.svg]] - [[file:10.10-snapshot-publication.org][Published range snapshots and the final delivery boundary]] + +- [[file:10.11-lifecycle-footprints.org][Lifecycle write footprints and shared admission]] diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.08-send-window-promotion.org b/docs/10-19-llm-gateway/10-routing-and-inference/10.08-send-window-promotion.org index d76fc5f0..681f4030 100644 --- a/docs/10-19-llm-gateway/10-routing-and-inference/10.08-send-window-promotion.org +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.08-send-window-promotion.org @@ -39,7 +39,7 @@ socket revocation. Bytes already accepted by Tonic cannot be recalled. * Complete writer mediation =Global= means =persistence::begin=; =family= means =begin_family= or -=begin_provider_use=. Both construct the same mandatory =WriteScope= close +=begin_provider_lifecycle=. They construct the same mandatory =WriteScope= close protocol. The production persistence module is private. External embedding holds the opaque =LedgerCustody= instead of a raw =Session=. Fault injection and storage-corruption APIs require the test-host =commit-observer= feature; @@ -59,11 +59,11 @@ its dev-only activation does not qualify arbitrary raw SQL for production. | | Domain roots, epochs, shared membership and migration | =register_family_alias=; =migrate_execution_domains=; =domains::{binding,migration}= | Global; root identity and held/history reconciliation occur inside the transaction. | Global migration closes all old/new lanes and advances the global revision; old domain permits fail full requalification. | | -| Claim admission, nonce consumption, request dispatch and retained exposure | =enqueue=, =consume=, =dispatch=; =enqueue_provider=, =consume_provider=, =dispatch_provider= and =burn_dispatch=; =execution_exposure::retain= | Family; one canonical claim plus original reservation manifest; dispatch burn precedes actual request. | Admission, burn and exposure updates close the family conflict roots before scheduler acquisition; no recovery path creates another call. | +| Claim admission, nonce consumption, request dispatch and retained exposure | =enqueue=, =consume=, =dispatch=; =enqueue_provider=, =consume_provider=, =dispatch_provider= and =burn_dispatch=; =execution_exposure::retain= | Family; one canonical claim plus original reservation manifest; dispatch burn precedes actual request. | Admission and exposure updates close the full conflict roots; sealed provider lifecycle writes close their own origin in MVCC while retaining full read/scheduler custody; no recovery path creates another call. | | | Shared budget and three-dimensional quota | =domains::evidence::{charge,history}= and =provider_quota::{reserve,release}=, invoked by the preceding admission and settlement owners | Family; atomic held updates and exact reservation rows share the deciding transaction. | Use distinct origin, budget, history, API-key, user and tenant namespaces. Shared quota identities serialize even for disjoint execution roots. | | -| History, stream cursor, range and terminal state | Generic =register_stream=, =enqueue_message=, =claim_stream=, =connect_stream=, =resume_message=, =consume_range=, =write_range=; provider grouped preparation, =release_provider= and =complete_provider_with_usage= | Global stream registration/custody; family range/terminal scopes; durable releases are the current profile. | Generic streams and provider terminal updates remain semantic. The two certified provider progress paths retain the same outcome owner while preserving the semantic cut. A receiver certificate never substitutes for durable consumption. | +| History, stream cursor, range and terminal state | Generic =register_stream=, =enqueue_message=, =claim_stream=, =connect_stream=, =resume_message=, =consume_range=, =write_range=; provider grouped preparation, =release_provider= and =complete_provider_with_usage= | Global stream registration/custody; family range/terminal scopes; durable releases are the current profile. | Generic streams remain broadly semantic; provider terminal updates are origin-semantic in MVCC, with no budget release. The two certified provider progress paths retain the same outcome owner while preserving the semantic cut. A receiver certificate never substitutes for durable consumption. | | | Catalog, purchase rates, historical user formula and metering identity | =publish_provider_catalog=, =install_metering=, =rotate_meter_credential=; =metering::bind= | Global publication/configuration; family quote binding. | Global configuration/publication invalidates every receiver certificate. Immutable metering identity projects only after acknowledged commit. | | @@ -467,3 +467,7 @@ per known native group commit, with independent acknowledgments and the same final owner gate. Read-only renewal also shares that qualification. See [[file:10.10-snapshot-publication.org][the source-led design, models and separate paired acceptance]] for the new comparison; the earlier numbers are not results for this implementation. + +The next [[file:10.11-lifecycle-footprints.org][lifecycle footprint design]] narrows only audited provider run changes +to their original origin. It retains broad shared admission/settlement and all +native read locks; the historical measurements above remain unchanged. diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2 b/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2 index 6a213c98..56458453 100644 --- a/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2 +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2 @@ -73,8 +73,9 @@ vars: { d2-config: { data: { figure: |json "model9": "dev/sysml/ExecutionReaderViews.sysml", "proof0": "dev/proofs/cedar/DomainMigrationComposition.lean", "proof1": "dev/proofs/lean/ProviderEgressWindow.lean", - "proof2": "dev/proofs/lean/ProviderSemanticProgress.lean", - "proof3": "dev/proofs/lean/ProviderSnapshotPublication.lean", + "proof2": "dev/proofs/lean/ProviderLifecycleFootprint.lean", + "proof3": "dev/proofs/lean/ProviderSemanticProgress.lean", + "proof4": "dev/proofs/lean/ProviderSnapshotPublication.lean", "sdkCapture": "dev/sysml/captures/WeaverViews-providerDeliveryJoin.json" }, "copy": {}, @@ -106,7 +107,8 @@ vars: { d2-config: { data: { figure: |json "proof0", "proof1", "proof2", - "proof3" + "proof3", + "proof4" ], "evidenceRefs": [] }, @@ -205,10 +207,10 @@ vars: { d2-config: { data: { figure: |json "modelSource": { "ref": "sdkCapture", "view": "WeaverViews::providerDeliveryJoin", - "modelHash": "0552676290a45913aa8d582f27f7a5d97b1650520252987d5fb202cafe8a7423", + "modelHash": "3c45556818345c7270d26e7d40d6ad5d25bd2b585713bf03143e9a14a5387ed2", "portProjection": "owner", "labels": { - "n0": "Rust / close\nPolicy + OAuth + domains\nKeep every pending ID", + "n0": "Rust / close\nRun edits / origin cut\nShared edits / shared cut", "n1": "Rust / qualify group\nPending clear; each row\nCedar + claim + domains", "n2": "Turso / commit group\nBurn the bounded group\nPublish one qualified cut", "n3": "Rust / prepare frame\nExact bytes and next span\nReserve transport credit", diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.svg b/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.svg index e07b480e..eedb39bb 100644 --- a/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.svg +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.svg @@ -37,12 +37,12 @@ SPDX-FileComment: Weaver-authored diagram; embedded third-party fonts and marks .scene-title{font-size:26px}.scene-detail{font-size:26px}.scene-group-title{font-size:26px} @font-face{font-family:"Kalam";font-style:normal;font-weight:400;src:url(data:font/woff2;base64,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) format('woff2')} -@font-face{font-family:"Kalam";font-style:normal;font-weight:700;src:url(data:font/woff2;base64,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) format('woff2')}{"renderer":{"package":"@deterministic-engineering/render","version":"1.0.0","icons":{"agent":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","agent-request":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","authentication":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","authorization":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","bounded-write":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","budget":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","budget-ledger":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","capture":"a647d42aa11f4e5e85d0bbf66f483f57f3c4ba3a9536362ed0eaaaae10a89cee","catalog":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","claim":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","decision":"3535642a5b613372c3fd374151ec90aafa19b64b2d33d10b19162cad07a35c7a","document":"0bf9674a401262da8a646305cab00006954721c07765b9962e0dee1c31d560f7","evidence":"0a91b169aaa644829a054cbb94194efffaf4298f2b6f8fa8c6ec2b7b413a1766","go":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","history":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","kubernetes":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","ledger":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","library":"df474fa36a74016b79236fff58a980a8c18c682d1866211776e349a0eb4b2979","message":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","model":"0cfd1f9ed3873f556ace725a7b6a251ebe75d7d976567699276f34df36b2443b","model-catalog":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","model-provider":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","obligation":"e76f4d34a7190400446c89e4e7d187762b885808a64a00c99455599d902570c5","pending":"cca7589bc3b1dcdebacb867c6836c6fc166257f05823555a268354ff9bfac00c","permission-check":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","policy":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","provider":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","publication":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","question":"dbf231e1568dc37189d5674d73c4bfc58a17eb8ada579b3f03bf2813d33c56f4","recovery":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","reference":"3814c570f79ab294252c36530de464c9364814b797afb862d9c62e728a8660fc","route-choice":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","routine":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","routing":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","rust":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","selection":"82b4ab6faf195fea0a891c35268e61c186e93e7c6a9d7967a4f6a73dbf25ae7f","stream":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","task-contract":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","telemetry":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","unknown":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","unknown-hold":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","writer":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e"}},"design":{"audience":"Gateway developers and security reviewers","medium":"GitHub at 830 CSS pixels","message":"One native outcome qualifies the group.\nRevocation closes delivery; unknown retains the hold.","questionRefs":["q1"],"requiredSubjects":["n0","n1","n2","n3","n4","n5"],"requiredRelations":[],"focalSubjects":["n4"]},"evidence":[],"layout":"model-view","presentation":{"objectRows":[["n0","n1","n2"],["n3","n4","n5"]],"notation":"objects","options":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL"},"icons":{"n0":"policy","n1":"authorization","n2":"ledger","n3":"stream","n4":"writer","n5":"stream"},"roles":{"n0":"governance","n1":"governance","n2":"ledger","n3":"semantic","n4":"execution","n5":"execution"},"edgeLabels":true,"graph":{"id":"declared-reading-order","children":[{"id":"n0","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n1","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n2","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n3","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n4","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n5","layoutOptions":{"elk.partitioning.partition":"1"}}],"layoutOptions":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.partitioning.activate":"true"}},"textColumns":22},"drawing":{"mode":"sketch","options":{"seed":29,"roughness":1.3,"strokeWidth":1.2,"fillStyle":"hachure","hachureGap":9,"fillWeight":0.6}},"fonts":[{"family":"Kalam","weight":400,"source":"@fontsource/kalam/files/kalam-latin-400-normal.woff2"},{"family":"Kalam","weight":700,"source":"@fontsource/kalam/files/kalam-latin-700-normal.woff2"}],"palette":{"background":"#F6FAF9","surface":"#FFFFFF","ink":"#163C43","muted":"#496A70","border":"#C9DDDA","accent":"#087E82","secondary":"#946044","tint":"#E1F1EC","secondaryTint":"#F4EADA","onAccent":"#FFFFFF","supported":"#237653","pending":"#986320","conflict":"#A13E54"},"inputSHA256":"296fa7e8d2e70f48f2d12d9b7eee93747345c43ac344a05d5bac31926247518c","model":{"subjects":[{"id":"n0","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::changes","label":"Rust / close\nPolicy + OAuth + domains\nKeep every pending ID"},{"id":"n1","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::validated","label":"Rust / qualify group\nPending clear; each row\nCedar + claim + domains"},{"id":"n2","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::publication","label":"Turso / commit group\nBurn the bounded group\nPublish one qualified cut"},{"id":"n3","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::staged","label":"Rust / prepare frame\nExact bytes and next span\nReserve transport credit"},{"id":"n4","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::receiver","label":"Rust / consume once\nLive cut + owner + expiry\nOne-use frame cursor"},{"id":"n5","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::tonic","label":"Tonic / accept once\nOne current Rust owner\nObserve delivery later"}],"relations":[{"id":"edge:0","src":"n0","dst":"n1","label":"closeBeforeWrite","kind":"connection","fromPort":"n0.0","toPort":"n1.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:1","src":"n2","dst":"n4","label":"exactRevision","kind":"connection","fromPort":"n2.1","toPort":"n4.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:2","src":"n3","dst":"n4","label":"inertOnly","kind":"connection","fromPort":"n3.0","toPort":"n4.1","srcArrow":"none","dstArrow":"none"},{"id":"edge:3","src":"n1","dst":"n2","label":"qualifiedManifest","kind":"connection","fromPort":"n1.1","toPort":"n2.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:4","src":"n4","dst":"n5","label":"oneOffer","kind":"connection","fromPort":"n4.2","toPort":"n5.0","srcArrow":"none","dstArrow":"none"}]},"modelSource":{"ref":"sdkCapture","modelHash":"0552676290a45913aa8d582f27f7a5d97b1650520252987d5fb202cafe8a7423","view":"WeaverViews::providerDeliveryJoin","portProjection":"owner","labels":{"n0":"Rust / close\nPolicy + OAuth + domains\nKeep every pending ID","n1":"Rust / qualify group\nPending clear; each row\nCedar + claim + domains","n2":"Turso / commit group\nBurn the bounded group\nPublish one qualified cut","n3":"Rust / prepare frame\nExact bytes and next span\nReserve transport credit","n4":"Rust / consume once\nLive cut + owner + expiry\nOne-use frame cursor","n5":"Tonic / accept once\nOne current Rust owner\nObserve delivery later"}},"modelTrace":{"modelHash":"0552676290a45913aa8d582f27f7a5d97b1650520252987d5fb202cafe8a7423","requestedView":"WeaverViews::providerDeliveryJoin","resolvedView":"WeaverViews::providerDeliveryJoin","renderingSHA256":"7ccb18149fc7b8d421ef3b4233b562beeb3b8b7042ba4fb05db0667a25252507","capturedRenderingJSON":"{\"modelHash\":\"0552676290a45913aa8d582f27f7a5d97b1650520252987d5fb202cafe8a7423\",\"requestedView\":\"WeaverViews::providerDeliveryJoin\",\"rendering\":{\"view\":\"WeaverViews::providerDeliveryJoin\",\"kind\":\"interconnection\",\"stated\":\"render asInterconnectionDiagram\",\"nodes\":[{\"id\":\"n0\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::changes\",\"nameSynthesized\":false,\"type\":\"EgressMutationBarrier\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n0.0\",\"name\":\"closed\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":502,\"startCol\":9,\"endLine\":502,\"endCol\":46}},{\"id\":\"n1\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::validated\",\"nameSynthesized\":false,\"type\":\"DeliveryValidation\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n1.0\",\"name\":\"closed\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n1.1\",\"name\":\"validated\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":503,\"startCol\":9,\"endLine\":503,\"endCol\":45}},{\"id\":\"n2\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::publication\",\"nameSynthesized\":false,\"type\":\"PublishedRangeSnapshot\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n2.0\",\"name\":\"qualified\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n2.1\",\"name\":\"preserved\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":504,\"startCol\":9,\"endLine\":504,\"endCol\":51}},{\"id\":\"n3\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::staged\",\"nameSynthesized\":false,\"type\":\"InertProviderFrame\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n3.0\",\"name\":\"stagedBytes\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":505,\"startCol\":9,\"endLine\":505,\"endCol\":42}},{\"id\":\"n4\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::receiver\",\"nameSynthesized\":false,\"type\":\"DeliveryReceiver\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n4.0\",\"name\":\"validated\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n4.1\",\"name\":\"staged\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n4.2\",\"name\":\"offer\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":506,\"startCol\":9,\"endLine\":506,\"endCol\":42}},{\"id\":\"n5\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::tonic\",\"nameSynthesized\":false,\"type\":\"ProviderEgressTransport\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n5.0\",\"name\":\"acceptedBytes\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":507,\"startCol\":9,\"endLine\":507,\"endCol\":46}}],\"edges\":[{\"from\":\"n0\",\"to\":\"n1\",\"fromPort\":\"n0.0\",\"toPort\":\"n1.0\",\"label\":\"closeBeforeWrite\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":508,\"startCol\":9,\"endLine\":508,\"endCol\":80}},{\"from\":\"n2\",\"to\":\"n4\",\"fromPort\":\"n2.1\",\"toPort\":\"n4.0\",\"label\":\"exactRevision\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":509,\"startCol\":9,\"endLine\":509,\"endCol\":86}},{\"from\":\"n3\",\"to\":\"n4\",\"fromPort\":\"n3.0\",\"toPort\":\"n4.1\",\"label\":\"inertOnly\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":510,\"startCol\":9,\"endLine\":510,\"endCol\":76}},{\"from\":\"n1\",\"to\":\"n2\",\"fromPort\":\"n1.1\",\"toPort\":\"n2.0\",\"label\":\"qualifiedManifest\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":511,\"startCol\":9,\"endLine\":511,\"endCol\":91}},{\"from\":\"n4\",\"to\":\"n5\",\"fromPort\":\"n4.2\",\"toPort\":\"n5.0\",\"label\":\"oneOffer\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":512,\"startCol\":9,\"endLine\":512,\"endCol\":75}}],\"columns\":[],\"rows\":[],\"notes\":[],\"notices\":[],\"shown\":[]}}","portProjection":"owner","nodes":[{"id":"n0","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":502,"startCol":9,"endLine":502,"endCol":46}},{"id":"n1","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":503,"startCol":9,"endLine":503,"endCol":45}},{"id":"n2","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":504,"startCol":9,"endLine":504,"endCol":51}},{"id":"n3","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":505,"startCol":9,"endLine":505,"endCol":42}},{"id":"n4","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":506,"startCol":9,"endLine":506,"endCol":42}},{"id":"n5","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":507,"startCol":9,"endLine":507,"endCol":46}}],"edges":[{"id":"edge:0","index":0,"from":"n0","to":"n1","fromPort":"n0.0","toPort":"n1.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":508,"startCol":9,"endLine":508,"endCol":80}},{"id":"edge:1","index":1,"from":"n2","to":"n4","fromPort":"n2.1","toPort":"n4.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":509,"startCol":9,"endLine":509,"endCol":86}},{"id":"edge:2","index":2,"from":"n3","to":"n4","fromPort":"n3.0","toPort":"n4.1","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":510,"startCol":9,"endLine":510,"endCol":76}},{"id":"edge:3","index":3,"from":"n1","to":"n2","fromPort":"n1.1","toPort":"n2.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":511,"startCol":9,"endLine":511,"endCol":91}},{"id":"edge:4","index":4,"from":"n4","to":"n5","fromPort":"n4.2","toPort":"n5.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":512,"startCol":9,"endLine":512,"endCol":75}}]},"view":{"source":"docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2","title":"Commit a group. Gate every frame.","purpose":"workflow","kind":"routing","question":{"subjectRefs":["n4"],"ref":"q1","text":"How can a shared snapshot stay safe during revocation?","focusRefs":["model"]},"basis":{"captureRef":"docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2#design-view","modelRefs":["Project.sysml","dev/sysml/AdmissionReaderViews.sysml","dev/sysml/ArchitectureReaderViews.sysml","dev/sysml/ArchitectureViews.sysml","dev/sysml/AssuranceReaderViews.sysml","dev/sysml/AttemptReaderViews.sysml","dev/sysml/AuthorityReaderViews.sysml","dev/sysml/ControlActivation.sysml","dev/sysml/CorrespondenceReaderView.sysml","dev/sysml/ExecutionReaderViews.sysml","dev/sysml/FloorReaderViews.sysml","dev/sysml/GatewayArchitecture.sysml","dev/sysml/PolicyEvidenceDesign.sysml","dev/sysml/ProviderRpc.sysml","dev/sysml/ReaderDesigns.sysml","dev/sysml/ResearchReaderViews.sysml","dev/sysml/StoragePersistence.sysml","dev/sysml/StreamingExecution.sysml","dev/sysml/WeaverExecution.sysml","dev/sysml/ZeroTrustRefinement.sysml"],"obligationRefs":["proof0","proof1","proof2","proof3"],"evidenceRefs":[]}},"questions":[{"subjectRefs":["n4"],"ref":"q1","text":"How can a shared snapshot stay safe during revocation?","focusRefs":["model"]}],"references":{"model":"dev/sysml/WeaverExecution.sysml","model0":"Project.sysml","model1":"dev/sysml/AdmissionReaderViews.sysml","model10":"dev/sysml/FloorReaderViews.sysml","model11":"dev/sysml/GatewayArchitecture.sysml","model12":"dev/sysml/PolicyEvidenceDesign.sysml","model13":"dev/sysml/ProviderRpc.sysml","model14":"dev/sysml/ReaderDesigns.sysml","model15":"dev/sysml/ResearchReaderViews.sysml","model16":"dev/sysml/StoragePersistence.sysml","model17":"dev/sysml/StreamingExecution.sysml","model18":"dev/sysml/WeaverExecution.sysml","model19":"dev/sysml/ZeroTrustRefinement.sysml","model2":"dev/sysml/ArchitectureReaderViews.sysml","model3":"dev/sysml/ArchitectureViews.sysml","model4":"dev/sysml/AssuranceReaderViews.sysml","model5":"dev/sysml/AttemptReaderViews.sysml","model6":"dev/sysml/AuthorityReaderViews.sysml","model7":"dev/sysml/ControlActivation.sysml","model8":"dev/sysml/CorrespondenceReaderView.sysml","model9":"dev/sysml/ExecutionReaderViews.sysml","proof0":"dev/proofs/cedar/DomainMigrationComposition.lean","proof1":"dev/proofs/lean/ProviderEgressWindow.lean","proof2":"dev/proofs/lean/ProviderSemanticProgress.lean","proof3":"dev/proofs/lean/ProviderSnapshotPublication.lean","sdkCapture":"dev/sysml/captures/WeaverViews-providerDeliveryJoin.json"},"sourceSHA256":{"dev/d2/themes/assurance.d2":"f7723f53e005a68c803a38ce5c04cd733f46f4a2688fa4b17c66f9d5b308fe24","dev/d2/themes/data.d2":"19fceb46186892da02b763217963cc3ca2a35021219c0d353fdeec84604ddaee","dev/d2/themes/flow.d2":"1f13588619d0c8087c08d8afd023c4c0efe12726711c311e623eea3872726c1f","dev/d2/themes/routing.d2":"f185df198e7435d12b17b7b57b62dfc5795597d95eb926159ee13b448727bcce","dev/d2/themes/sequence.d2":"6e39472720dccc717f984c95b79570494b6ce3828b86227629841649e6c956e6","dev/d2/themes/state.d2":"f1a35cbca0f9cbb055ea9f793ba3dfb86e5fee4e462038ef3e72b94baa61d781","dev/d2/themes/system.d2":"b2a32ec6959ca5df9103c16454c4e34b758e061f850f7de6b619bcbc5fcf17a6","dev/d2/themes/vocabulary.d2":"add21e9b87eab485e5daabf6316fea44eb56b1007b70123f24b0e32e3357f744","dev/proofs/cedar/DomainMigrationComposition.lean":"43597bf8b1bd946981098605e14ed089d949d40b09492478ecba2b0c6e7e2ff6","dev/proofs/cedar/QualifiedReview.lean":"1ae16e06ad03a2906fa8c21dbeea1e3eb7700aa1e9359e64848dec65ccfd079f","dev/proofs/cedar/WeaverPolicyBridge.lean":"a9628a8123d504a34f64bf986feb4471325aa2b0ddc603d76b62632481eab67b","dev/proofs/cedar/ZeroTrustEnrichment.lean":"0c4b138843cc176c27d42d4a31177a3c12486b2d8ff124a6453e3d0922170884","dev/proofs/lean/ProviderEgressWindow.lean":"c4a15b4ccd3a6474290b71374499087dba7dac7a1fda53f3a870100ec2e768a9","dev/proofs/lean/ProviderRpc.lean":"e79d7639ac11220585e59e85dc5bec12b6717f7b51fb28fdcd62dc96d8fae38e","dev/proofs/lean/ProviderSemanticProgress.lean":"d32e010145a7dfcd646daeeeb4b08c0e852b9006bca404681af7e7fe10d0eaa0","dev/proofs/lean/ProviderSnapshotPublication.lean":"312c0380e334fbc5380815d882c6b5b0007747100f818becbee9c6784eeb5716","dev/proofs/lean/RuntimeAdmission.lean":"6111d4b9e93ebaa9f7cc44a55ed504c88c20c8d9de81e947a2e13b3f4a13b13c","dev/proofs/lean/SharedDomains.lean":"10eef67918986264689b09f0a6c0d53b314d7bf43b42f4b9652b403570beb58d","dev/proofs/lean/StreamingExecution.lean":"3fba798a7887a0b2ae29a7e3f0aaa3d7e2fb191e5f1f28109a4a73d28e27b776","dev/sysml/AdmissionReaderViews.sysml":"27ebc6c98ec3a1f7f9081e77a130953c3b646a1fdf6f1d6fc1fa6ed6376e9623","dev/sysml/ArchitectureReaderViews.sysml":"52ffbccbb17bd257e8ad9f4aa9f727c8ce0c00149e7d6738b82042ba06fdd0e3","dev/sysml/ArchitectureViews.sysml":"902a70ba53ad01d8a1abfcdcc86d7ba5d8778cfe332228656c4a8019dd613f55","dev/sysml/AssuranceReaderViews.sysml":"cd99fb7e9b23e08beac265bc832a8debee0dc1e1d318b0f64d5263519270e390","dev/sysml/AttemptReaderViews.sysml":"0d87cf71e15c26566422a6ddb5945fdb8add8af0484d9d024c32b97597675e21","dev/sysml/AuthorityReaderViews.sysml":"6fa25bd3a64e7f89987caec8e4773928be2cbea0a3c943299e536ca81978316d","dev/sysml/captures/WeaverAdmissionReaderViews-beneficiaryRegistration.json":"d87efd08c93734f2b18c0dcfba2ba77c9078f0e3c34563e6860f234719e082ab","dev/sysml/captures/WeaverAdmissionReaderViews-bootstrapInvitation.json":"9b047f56f6bfbcbe02e27a1537bef6dd5b1650c2d3664a1149112aa2b032a55c","dev/sysml/captures/WeaverAdmissionReaderViews-callerCustody.json":"d984f0608eaf254b81a856505528b967fe4884f8b84b6180faf33f2663f923f9","dev/sysml/captures/WeaverAdmissionReaderViews-custodyPublication.json":"9f689e10f5b6d44575a36b8bb7663a1fceea8f3aa81dcd69b80fb3198a5579b7","dev/sysml/captures/WeaverAdmissionReaderViews-enrollmentCredential.json":"f80dd14ea5ad3597ad1e8139470cca62c63fde909a6ecd2a29f219d2dc3abbba","dev/sysml/captures/WeaverAdmissionReaderViews-incarnationIssuance.json":"10cd21afb335cc35cda5ce6225f6a721a6b373d9f7ee1aa35c3bf099bb3a267b","dev/sysml/captures/WeaverAdmissionReaderViews-routineRouting.json":"f69a4c2a94f9b2c86237b7d9d5ec58199c8ca710ab9f020e559f96a74affe050","dev/sysml/captures/WeaverAdmissionReaderViews-sourceCustody.json":"1be9072350fcbaedeef0100741b4e8e938ff469e8814ab844fab1299fd400ae6","dev/sysml/captures/WeaverAdmissionReaderViews-sourceJoin.json":"e77d48d3f9ed61a719df3f2ce862a9ae4a9f91f8febe1147565275067e9b2cb4","dev/sysml/captures/WeaverAdmissionReaderViews-subjectAuthority.json":"afb444c245d22dd4a139cce78b48bfa03ad63314b648c0bdff4f0a764f4eb45d","dev/sysml/captures/WeaverArchitectureReaderViews-adapterBroker.json":"b85845695802284d76e4788cf6907e139ba06925a04377bf3ae542ceaae77e50","dev/sysml/captures/WeaverArchitectureReaderViews-anchorBroker.json":"5e776c0c44263f39f49cb2e5f393342a8c1a94f7cfe9b9b100246e0619def1e2","dev/sysml/captures/WeaverArchitectureReaderViews-anchorEgress.json":"349359d471fb5b959ba0e40e4cf5a2c9310f4818d15bc6e326c43080d477fa24","dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json":"45c89724ce08970f568143eef94bf6f3b05e7ecabbecc31178c1ea952f134012","dev/sysml/captures/WeaverArchitectureReaderViews-codePolicy.json":"d8ac1cfdf27c41b21c77c67e0e72099bc0e0bab6e7fc606b4407997adcaa3c53","dev/sysml/captures/WeaverArchitectureReaderViews-configPrefix.json":"5fedc70b9c6599341b9419cea0e20c16549b728bf1cacdc7c34a594b7c654f9e","dev/sysml/captures/WeaverArchitectureReaderViews-driverCompletion.json":"7cafd41a51b8339885b81626fa21a784627eaf07c96d6697cae359171d75af87","dev/sysml/captures/WeaverArchitectureReaderViews-fencing.json":"56996abfe53dfc9e99acadadb1b48f7534804ba4ff47e51f3855b35283e06c92","dev/sysml/captures/WeaverArchitectureReaderViews-gatePersistence.json":"d4773e04604faf9c04f50d6de93b22c995a5d62fd911dfe6036012770e6a9d6e","dev/sysml/captures/WeaverArchitectureReaderViews-journalLifecycle.json":"55ff661d0283be5ac5d378ee324b65cb6e8a3c3310ac77e5722a9cf9a21311ca","dev/sysml/captures/WeaverArchitectureReaderViews-logicalObservation.json":"a04ad8d61fabdb327a5377ff675ba384b0f80870cee02b03249bd8b09e53cdfc","dev/sysml/captures/WeaverArchitectureReaderViews-manifest.json":"3f1fdb05f6a647c364912ced6d232fea7fd483e962ca7d34da9c13e21516917e","dev/sysml/captures/WeaverArchitectureReaderViews-migration.json":"0cb0c9aedd08ef758ed649892cc1966ed45d2a6ce1b5fd2d4bce8d7030cb5432","dev/sysml/captures/WeaverArchitectureReaderViews-policyExecution.json":"3316106c937d56a0167810d2aa39ce6c57ae62033d1ec06dff2dfad947ce8fd0","dev/sysml/captures/WeaverArchitectureReaderViews-quorumPromises.json":"5c4adc99dd0d4a83baab649bbcdc4f3ea9a763ef3acb6e3548b16eaac3d023e0","dev/sysml/captures/WeaverArchitectureReaderViews-relationships.json":"2666a2c572ea908525221f5a2b3862f95d648847a879c509a1b8913f7707ca1c","dev/sysml/captures/WeaverArchitectureReaderViews-settlementAnchor.json":"fab168f8e7936791b8ad205e430de176f938084b3b14cbce6932e8c9ff4331b6","dev/sysml/captures/WeaverArchitectureReaderViews-sharedBudget.json":"d6bf6f951e30a94dd6006e95e6566cf176ad2919781b2bf42153bacf04d91365","dev/sysml/captures/WeaverArchitectureReaderViews-sharedExposure.json":"2b87c2d368a1236aecb98a70749819e942d43f9f778f5bd551b3f1f7af4f130c","dev/sysml/captures/WeaverArchitectureReaderViews-spentState.json":"0b691f59c5300da121388069da393ceb43a7f2196a26a6801db29dc8565690a3","dev/sysml/captures/WeaverArchitectureReaderViews-writerSettlement.json":"bc74aacce9e218a29751bb0bbd3380770a0199199e9ee6ca848cb2ce49b94a87","dev/sysml/captures/WeaverArchitectureReaderViews-zeroAssurance.json":"8dd5dce180a53aa4ee73612f419e67ff300eff118b5950f6a8cc8ad043929206","dev/sysml/captures/WeaverAssuranceReaderViews-brokerQueue.json":"313778381bbbce8a186284b5146889aaae2a536c80b6b68f18edeb1d0312403d","dev/sysml/captures/WeaverAssuranceReaderViews-continuation.json":"5828925f1c87076b94a871b130bd0d0c66dcf18d0a76191db030807a908afdcd","dev/sysml/captures/WeaverAssuranceReaderViews-deviceEvidence.json":"680daedc47fc34e34d0173e9027be5cbd9b5bae675b9d68d4f7042e86538c327","dev/sysml/captures/WeaverAssuranceReaderViews-gatewayHead.json":"e2c7c6314dac94ff8d3f9748671e3a51e4c056d786268240f1e087cd1c483e85","dev/sysml/captures/WeaverAssuranceReaderViews-keySession.json":"a26f71774b65516d69fef0bff7ff8558100aa4710e3bfa4424d1f0abd9fbd25b","dev/sysml/captures/WeaverAssuranceReaderViews-rangeRecovery.json":"11055eab811a587eae3d6ac89efb2f031af9691a8b962f7e37e0cc3524172869","dev/sysml/captures/WeaverAssuranceReaderViews-signer.json":"84f5178f51834209d9550a331561e9e9c8478c4fd6fe3e2d55bbb9681eafa398","dev/sysml/captures/WeaverAttemptReaderViews-admission.json":"32b0fb972e2ea136b1c397825d33a88457ddca5f88c9e458893ac38bf9ca4972","dev/sysml/captures/WeaverAttemptReaderViews-outcome.json":"34052a87cc97391fd11cf7508dd6ed218aa800b27a6f6a893e402688ffa6eb6b","dev/sysml/captures/WeaverAuthorityReaderViews-attemptLedger.json":"44a9f547ef835880499ad8582cb33be462a3e71d2afb6e6273de13f0c1d92312","dev/sysml/captures/WeaverAuthorityReaderViews-canonical.json":"0dab7845a03948b33b2f8f4b41b5f349673a8a9b88dbc0b889548e000bf34b74","dev/sysml/captures/WeaverAuthorityReaderViews-multiKey.json":"33315aac2bbee80ec1430a3c981c86042bfd8774653a7d34f2ea43842e47ba29","dev/sysml/captures/WeaverAuthorityReaderViews-publication.json":"0816d964877aa2eab2407998470e09e5c65e6711dde78bfb53522da9ab5575e0","dev/sysml/captures/WeaverAuthorityReaderViews-recoveryCAS.json":"b1b769ae1d827d4efb803902252182f95c4b4500f4e68a9cacbcfca1c8334231","dev/sysml/captures/WeaverAuthorityReaderViews-scope.json":"87df09bd01e20690a50a82b14ed12a59144cffe3d164b45bb3dee427c1c3ad4d","dev/sysml/captures/WeaverCorrespondenceReaderView-correspondence.json":"3e9fe135611387aaf24f3685d55841485ac4cfae23262c72b926a2e63cbc7f2c","dev/sysml/captures/WeaverExecutionReaderViews-accountCommit.json":"6ca09eaff7009e236c443712eacdc092dc5ef83761cabfc72a28799426ff4185","dev/sysml/captures/WeaverExecutionReaderViews-admissionFloor.json":"179f2d7b5441947c45e13ce7032c4da6722680ec29e6de5cdee680b6dfd41ff6","dev/sysml/captures/WeaverExecutionReaderViews-appendHandoff.json":"05ed86cf69dfdfd2e4089bd5266fe9c38a5938880e5627a1175dcd4e4bdfb6bc","dev/sysml/captures/WeaverExecutionReaderViews-checkpoint.json":"da2f772d0ce2c336b0f41518889f66a6d4e046ab93ba9504744747b469ba9aaa","dev/sysml/captures/WeaverExecutionReaderViews-executionEvidence.json":"ded466601b2e30067cdbd565f46c95fa76534ad72c0ce42817bc9d1b4661b6fd","dev/sysml/captures/WeaverExecutionReaderViews-executorOffer.json":"3554b39e08c0c4c25017b88289726fda644359b916a709a88a23beaf5e0b0659","dev/sysml/captures/WeaverExecutionReaderViews-joinEnqueue.json":"135496a89d2265214e93a9feaf8102cded686dca2bec439223ed4f22feb478fa","dev/sysml/captures/WeaverExecutionReaderViews-manifestSwitch.json":"69e9ba6dfb46697d850f8f6e022ede33916888610438deb3e729303596f1fd9c","dev/sysml/captures/WeaverExecutionReaderViews-resultProjection.json":"a9315278f0ce22f27a578bae0f189b96569162a5a16cce1e0fca3e47ca9eac13","dev/sysml/captures/WeaverExecutionReaderViews-walActivation.json":"ea6fa1f4d6d495dd31e9854cb532d3a6355889a0a9402e9815d04ee3e5932f5f","dev/sysml/captures/WeaverFloorReaderViews-floorOrdering.json":"c71adc113df321f1c5ad07c865101a891ace07fc95f52634a91e8d90da71bede","dev/sysml/captures/WeaverFloorReaderViews-floorRecovery.json":"b24f19e4286832219e90a35b4199e4a34b594cf6dd7033e4ed76b1aa7b13b66e","dev/sysml/captures/WeaverResearchReaderViews-embeddedTooling.json":"bcdf6ab96cc6c30c8ed12fa0643e8ab9720c370e65497048174f72faa74edb14","dev/sysml/captures/WeaverResearchReaderViews-floorTransport.json":"2d0d25f00bd9642d2e4600a467ac6f5bf9c7ba7ac07b9e15b03b35582fb3a906","dev/sysml/captures/WeaverResearchReaderViews-gerbilLifecycle.json":"9c8aab334fa495b40ad114b2a86d8f87385e3a2c8d4e32f17f435e07dc0ade9a","dev/sysml/captures/WeaverResearchReaderViews-gxiLifecycle.json":"dab4ed7df91fbf70fa3f33519c18027a8fece0920e5acf7047435e3d252b8e86","dev/sysml/captures/WeaverResearchReaderViews-parentReplay.json":"36d4db898165c527159ec9098b3fcb0a6bc0187f717a67d8f1652c080d1bf55f","dev/sysml/captures/WeaverResearchReaderViews-profileBinding.json":"934eb50a770d3276c74dd88e50c3e0c6be5bbaee6bb36448eaec756733e6b363","dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json":"c2a8a69ab92caf2f57836ca82d1b0a1a086dbb72e5ba0ef6e9b281d8cf34016e","dev/sysml/captures/WeaverResearchReaderViews-runtimeAssets.json":"cb7986f5ce5327c166f8718caf602bb8209e8f2473b2fba1deb97b9f78765e34","dev/sysml/captures/WeaverResearchReaderViews-semanticSlice.json":"e8614c7c8264d0ba61b2b576c8aeb844b14fcb0df4360dc87314e3b56080f586","dev/sysml/captures/WeaverViews-architecture.json":"9cc7ce9f26ea2a60f1062326b07b56c894985345a3bf579cabfdab3b4674d194","dev/sysml/captures/WeaverViews-assurance.json":"d4c06e6e373cde42a3b1d5dff7a05379f21c5fad918e23151cfade91940a6bee","dev/sysml/captures/WeaverViews-contractRefinement.json":"ae1605a065537e6057d4502e8016fa356393197ad9c68de2cb1c6e89b3327434","dev/sysml/captures/WeaverViews-execution.json":"f72884d7065d7363193edcf4c945eb16454520c8d04d3bac773a847b4e6754b2","dev/sysml/captures/WeaverViews-gateway.json":"6a757256dbed8898daef5a1bee65a75158eb5e9db8b8ea9fe7f37400e5781a02","dev/sysml/captures/WeaverViews-providerDeliveryJoin.json":"7ccb18149fc7b8d421ef3b4233b562beeb3b8b7042ba4fb05db0667a25252507","dev/sysml/captures/WeaverViews-providerEgressWindow.json":"91b66f3ef7341689f6494e52fbcf603029626d9862ba1b8ce6a8fd2561a3c09c","dev/sysml/captures/WeaverViews-rangeRecovery.json":"964279992fdff2c88c2042c5607931c05297455d7e8b00f7868fd5d6a0a251aa","dev/sysml/captures/WeaverViews-routeExecution.json":"bc24258d138678678584b0a2398ac049773527f764388a2b2cd80547aad313b6","dev/sysml/captures/WeaverViews-routeSelection.json":"920f7a9ee393e5b77997fc337b1c9c87b9e86443ca74e2f2b443204f8d2ef25d","dev/sysml/captures/WeaverViews-storage.json":"fcf62f4bb231a33951032497a40ecb4eed511cfbd11e13979fe20f49b69868c6","dev/sysml/captures/WeaverViews-streamAdmission.json":"f13bd03b95aa6e817ec9ad7359269cfa451955558fc2a4bb9d4eac384aab629b","dev/sysml/captures/WeaverViews-zeroTrust.json":"5990ad3170ad7db45d405e65fbb9898c1a9af3b4f473f03a2eff531ec6bf89db","dev/sysml/ControlActivation.sysml":"78bc6792c3a64ee54210720d3d88c1984b5c876d3a0647b6829bf904a811014f","dev/sysml/CorrespondenceReaderView.sysml":"24b811c00528feaab3547d5db3b7fada290ff89478ac2be0a1d252d8ea1e5828","dev/sysml/ExecutionReaderViews.sysml":"88f690ed1fed91f63f7571d14bf5d7c1c8d14ee3b8d1d17ae333dfd7a6176df3","dev/sysml/FloorReaderViews.sysml":"93401ba5b2009dd54614f7e5aff81d91a20085efbb77b3a143726ffdea16592c","dev/sysml/GatewayArchitecture.sysml":"dbec3964b7873ed0633964b05d1ba1ee828050aed35a3066858d0c38893f2642","dev/sysml/PolicyEvidenceDesign.sysml":"6a7d738b004be62e7412ea68080944f8cb6fb3aea785258efaefc2efc1c4e0e6","dev/sysml/ProviderRpc.sysml":"60a7ae2140742902a487dd29565d543591a1d080eeef37745241e142df101cc0","dev/sysml/ReaderDesigns.sysml":"4df8352980f9727b85a26533dc5ebfd67730540359d553a17d562574f3ea2529","dev/sysml/ResearchReaderViews.sysml":"cb10ed4ab79e911197834a8102e8a84986c567a358098e36d234d15b9c5acaec","dev/sysml/StoragePersistence.sysml":"b6b58b8802a557a7f3af787c2e7875be64865169ca3fd7e9973b13f6c3dc792d","dev/sysml/StreamingExecution.sysml":"d0d4d92300fba2b908ace30d9065cb2bac1d86f3b7c98219c1853a30f3110e85","dev/sysml/WeaverExecution.sysml":"7eaafa80c814f9a900693f05725a5b6eac0231e91c13d5df57f4733a9d1faff3","dev/sysml/ZeroTrustRefinement.sysml":"7cbec57110f03ed68469a1f49cb2046769516b09a6eb1b9433d866161bba6a82","docs/10-19-llm-gateway/10-routing-and-inference/10.02-llm-routing.d2":"513cad143cde846a9393bb5020dc4843caa1bb844204d3d0c13d1b5ada5efc70","docs/10-19-llm-gateway/10-routing-and-inference/10.05-route-execution.d2":"7c3ff8609c24983d0b27511756d8c5c04d0dc2cf5c973fc7012eaa0acda421e2","docs/10-19-llm-gateway/10-routing-and-inference/10.07-provider-egress-window.d2":"3c9c7c67296700d3b08cea62dddd5bdd011e7bafd61c2b4ecf1e38c32a94d6e7","docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2":"2d0002f71610b4c827df31c51ce9de1fdbeff9c454d868eace56d89bf29cff8c","docs/10-19-llm-gateway/11-attempts-and-failover/11.02-attempt-ledger.d2":"5438329d7af60e9596b5fe4519b04a27a7c36ce1d1dc1aa5442db6df7167cd8e","docs/10-19-llm-gateway/12-semantic-contracts/12.02-semantic-contract.d2":"8560ac03652d2dfb8aeb7797c0e3b61031e49f9a3276d3207c8758a32037c530","docs/10-19-llm-gateway/13-authoritative-scope/13.02-authoritative-scope.d2":"e5950b420b85e30891bdb2264c7fad7ccd9ec9934b6175906d592d683b3a844c","docs/10-19-llm-gateway/14-registry-publication/14.02-registry-publication.d2":"9153743fc734fb044f94a4d22175fbe963f0f15f02598143dfbd7a06cd880177","docs/10-19-llm-gateway/15-recovery-cas/15.02-recovery-cas.d2":"c5de2f6cb52b0450361b2ed0523f647bdcad1fc43d410231f91ae86aee450859","docs/10-19-llm-gateway/16-policy-publication/16.02-policy-publication.d2":"4be00575666b7ada7185a30e553b42b9c36fe9109ce89df3d0dbb4b30ac10cab","docs/10-19-llm-gateway/17-policy-continuation/17.02-policy-continuation.d2":"4108a821aba5a2de1ffebc59b9e0d9180130bb3f598ac2130d59a83e8eca571f","docs/10-19-llm-gateway/18-canonical-registry/18.02-canonical-registry.d2":"f3b44cf54b006df34b528075bbc54742963a53e2afd4cbee435f81095b59b800","docs/10-19-llm-gateway/19-multi-key-registry/19.02-multi-key-registry.d2":"c44a2569dec8ae1fab46acb1ddd58f8b468e7ea7b11136c120a6bf2b042cf8b7","docs/20-29-execution-authority/20-result-projection/20.02-result-projection.d2":"696df32a9d705c6915bcc43a33616126cdce61ce5af0ae198c0dca5bc898d645","docs/20-29-execution-authority/21-join-enqueue/21.02-join-enqueue.d2":"430f46389111827b9f0ad5c9c3193366729fffe917ef18a5bfa0ec8238f6ab02","docs/20-29-execution-authority/22-executor-offer/22.02-executor-offer.d2":"0d93c13abcc1bd79afb32e6ae8a965cc5ec3b0c30fc1958f2f212e12b5e4b65a","docs/20-29-execution-authority/23-execution-reconciliation/23.02-execution-reconciliation.d2":"14c698ad47a243d46d788ab3494b1ad22ae7f14a163140eb6b4f5e8e071c6269","docs/20-29-execution-authority/24-account-commit/24.02-account-commit.d2":"10d6a5116d2c8be77ce7f27312d9d49ad832645c6748bb7bd68bb6942055990e","docs/20-29-execution-authority/25-wal-activation/25.02-wal-activation.d2":"9ebcd14701116e583157282a1678a6f1e0fe70e1ee4b9b7e038b520d4392ce05","docs/20-29-execution-authority/26-checkpoint-truncation/26.02-checkpoint-truncation.d2":"c5c1a35a16fe9b33029169b16d4c0af113f49e665eed0074ce524fc7a15bdb77","docs/20-29-execution-authority/27-manifest-switch/27.02-manifest-switch.d2":"c4de2ef519af25b2c41194df561860ad0236b0309b3178b388204c29cebf9f41","docs/20-29-execution-authority/28-append-handoff/28.02-append-handoff.d2":"f7646793e8540ec5f1e587d5e13deaf16d166180f80107ac8f9c904ea5c9372c","docs/20-29-execution-authority/29-admission-floor/29.02-admission-floor.d2":"0b9794f3d5fdfc7dcdbb519426eecf7e6ec6cb707de5017387c9aa47208ea385","docs/30-39-assurance/31-protected-signer/31.02-protected-signer.d2":"bc787086ae26a1a6cd56e51a2b4182c86e476f13e28ed1f5d80363b1d827e013","docs/30-39-assurance/32-key-boundary/32.02-key-boundary.d2":"1b616363aa68166988cc1d09404d637da406f048b9647676ec5f42d15f1762ca","docs/30-39-assurance/33-device-isolation/33.02-device-isolation.d2":"f4b086efce29484b70d4d4b2c04dad3887976d69187c25234e734e90260a6c7c","docs/30-39-assurance/34-floor-decision/34.02-floor-decision.d2":"78e2de9f044edb41944a56c1c8c8251a9cacd3470cf73c16b87f5ba100139a04","docs/30-39-assurance/34-floor-decision/34.04-floor-recovery.d2":"296d821eae11d4b77a552ae21d91eadcddcf032a15989dd35490128397044203","docs/30-39-assurance/35-intent-continuation/35.02-intent-continuation.d2":"08475ba17d7c98911a7db912041b669d049c75315c861322f72a5b50a471df55","docs/30-39-assurance/36-gateway-head-cas/36.02-gateway-head-cas.d2":"51669df10ec208197e690f656b962b259959af5f225243b62e5ff6bbea5637a5","docs/30-39-assurance/37-broker-consumption-queue/37.02-broker-consumption-queue.d2":"1ad636df3ba980d5f25b1a330c00c8b21f152958fe7c86617736e1b1f85a1ed8","docs/30-39-assurance/38-logical-range-recovery/38.02-logical-range-recovery.d2":"8ed5e1adc741da6852d027828993a83816cadb0c7bc1732bfaf121b2a64878d3","docs/40-49-admission-coordination/40-source-join/40.02-source-join.d2":"b8815cf59a1be49a4657b6ec3857d39e6d7d39ab4bb3ed44521c71ffe0ec5cee","docs/40-49-admission-coordination/41-source-custody/41.02-source-custody.d2":"feef18f62d537d4eb0659c0f1d719218df1a3eda506c9468b59423b151550bd7","docs/40-49-admission-coordination/42-custody-publication/42.02-custody-publication.d2":"24f019e8633cc816f7488e3f65384d2dea96ac8a3685714665a47bc6144b1e5c","docs/40-49-admission-coordination/43-caller-custody/43.02-caller-custody.d2":"6352167e4d3427fd9a66befb74fb3eebf91a127c5e82ecff8312b24178d5117f","docs/40-49-admission-coordination/44-incarnation-issuance/44.02-incarnation-issuance.d2":"215f52c84c9f41c36352f8b6da8b4670f1b375672cfc9efdf6a8bd1df95c946e","docs/40-49-admission-coordination/45-bootstrap-invitation/45.02-bootstrap-invitation.d2":"9e019de8289428a97580fe66ccefc6b9d0a43c1bac07433d2f29596f4d407401","docs/40-49-admission-coordination/46-beneficiary-registration/46.02-beneficiary-registration.d2":"322b848fdd67ea88c99b509cb5d913d7a5023e327edea51f16f44816356d81ce","docs/40-49-admission-coordination/47-enrollment-credential/47.02-enrollment-credential.d2":"ea0aa0bed915bea42d3d65c8f6572f799eb63d0aee1018b75803e61ef034d303","docs/40-49-admission-coordination/48-subject-authority/48.02-subject-authority.d2":"9f707fbc6e5ba8933a0e4d9d057f013c5764afc503f819288f628d3f9709f88d","docs/40-49-admission-coordination/49-routine-routing-config/49.02-routine-routing-config.d2":"7fa18b652ba97e8fe66f402a9a85d65740db9d3ffadff7890db7d72826c498b6","docs/50-59-research-program/51-qualified-semantic-slice/51.06-semantic-gateway-slice.d2":"d63df655a635fccac3c92eded92c039a3f079c24fa2b7a2fd0dc1f3fabd3c0f5","docs/50-59-research-program/52-committed-profile-binding/52.04-committed-profile.d2":"3ea30976830c607bf8cec62cbabc4291c384bd5f368049a45777f6f981d87d6e","docs/50-59-research-program/53-gerbil-exit/53.04-gerbil-lifecycle.d2":"b7b623664edc6e86efe62eeee7f5977dc207f0cb12e40cb6f0e77e38160695de","docs/50-59-research-program/54-dynamic-gxi-exit/54.04-dynamic-lifecycle.d2":"d4d410dd8cb10de6d3526b54ac7f96731d2f2a94dd9763aad96a0926608e251c","docs/50-59-research-program/55-dynamic-gxi-paired/55.04-runtime-boundary.d2":"573b248a6b7ce2d7eee1e70a469c54e4f195c4894ec7b0f61c8406fae843eccc","docs/50-59-research-program/56-gambit-image-closure/56.04-locator-boundary.d2":"0c45ee11d269b0cab8998c7fc3432ec851b9390b7530486225134b261d8d7de8","docs/50-59-research-program/57-runtime-implementation/57.03-runtime-boundary.d2":"193d22a5bd9e4b23260334d085df8aa5ec19c349f13cd9f56eaa26fe54f7e3ac","docs/50-59-research-program/58-streaming-execution/58.03-streaming-runtime.d2":"76ea49c83b4b36af1e775f80475d40747640b80a330434bf86635e255e84ef14","docs/50-59-research-program/58-streaming-execution/58.05-range-progress-recovery.d2":"aef20c8ad7d7420a65422add6d9fb635bdbe32e42e49427d3179bf20499ae4cd","docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2":"6f4e8218ea262e35efaebaf8cc2f96345b2ef1e7e9c1a6b12b68290dd99c683d","docs/50-59-research-program/59-provider-rpc/59.21-verification-ownership.d2":"e035ae7e56ee5e6498f131ed62f4792547c1e716aa5ed29865b333f54665e8f1","docs/50-59-research-program/59-provider-rpc/59.26-semantic-execution-ecosystem.d2":"50c091b094125693e2debe73599a63405849f1f55ab3658030674692c9334e14","docs/50-59-research-program/59-provider-rpc/59.30-governance-adapter-acceptance.d2":"88cbbd45e63358bb45a58fb27f85e275b9cc9fb3d3aee6af19eabed0912545d2","docs/50-59-research-program/59-provider-rpc/59.43-floor-transport-owner.d2":"36c4d6b561332ab30deb464a92bb4c2f02ceed5c8a1ca66617f72b6086b2c555","docs/50-59-research-program/59-provider-rpc/59.44-cloud-rpc-arrow-boundaries.d2":"fe0ac2220e04f6ccea851247ecf8ae1cab4ec8c8ba8744010c478992c233ebed","docs/50-59-research-program/59-provider-rpc/59.45-slow-consumer-zero-trust.d2":"e36cf58a239a2d9f0c99789bb7484de4e26180a8f941970540f72b530a79d813","docs/50-59-research-program/59-provider-rpc/59.46-functional-security-frameworks.d2":"e541b969352e8149e71e5b539988f9955b525e5e5ba3e7e7270bd4a98fbe19f5","docs/50-59-research-program/59-provider-rpc/59.47-property-testing-framework.d2":"f66ed065dcf955a233968ca295517c642be30dad9b24e23a781fe34e4bed45d9","docs/50-59-research-program/59-provider-rpc/59.49-policy-proposal-barrier.d2":"3a8559bb22f812075d9d7de4a397978995d06c32ed22e9415f990413551aebb6","docs/50-59-research-program/59-provider-rpc/59.50-parent-contract-and-replay.d2":"2db3983f56e938c927b68077551573c8e86362da892f47890459ab7b3f929c64","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-architecture.d2":"10e92e79b69f4b0813551dd2ddadc5ad225b7b0fa8374ed7015b7f2fe66bb6e1","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-contract-refinement.d2":"204c9e20d9027b7a38bf2a964da9a7cadb92744561fa9f1eb3fa29d00f4fa386","docs/50-59-research-program/59-provider-rpc/59.52-reviewed-publication-cas.d2":"4e0998e61717d5441e242cde0dfc52198312b67b63f0ce8b0425a423d1b88a24","docs/50-59-research-program/59-provider-rpc/59.53-artifact-registry-recovery.d2":"f7083a48413d41ad99e7191281bd6e74a92b33c7cc1f4f2f9ae322bb1405088a","docs/50-59-research-program/59-provider-rpc/59.54-source-incarnation-authority.d2":"1e55c0487f01d70462e8df6b46eff9e799b0dc592c0e780c759fa602e3d84444","docs/50-59-research-program/59-provider-rpc/59.55-evidence-reviewed-publication.d2":"c66435372642f7a93ca7fc6f78c2abcbc364a4dde447d10dcc4b2b21ccc06456","docs/50-59-research-program/59-provider-rpc/59.56-runtime-assets-and-authority-floor.d2":"c675469701bb6994fed1976d1e90d01dc1cc4e416a6788f865494fa3243d32c1","docs/50-59-research-program/59-provider-rpc/59.57-schema-bound-candidate-replay.d2":"5ca15af556e0a4ba5bdf1742cf81182ad72e7f51b2eb63352b839e068a7ad7d2","docs/50-59-research-program/59-provider-rpc/59.58-independent-source-recovery.d2":"4b21999b3554be15374448f36ffbccf517b32784a65cadde0f4c1eb8308da377","docs/50-59-research-program/59-provider-rpc/59.59-retained-root-and-recovery-coverage.d2":"37fdf1d3dd01f087434a6108b43a5657d7aecf79a2b9e60638d70eb0b1a4984b","docs/50-59-research-program/59-provider-rpc/59.60-persistent-source-key-custody.d2":"d27df3a14df5d57ad725c1455c82a4ab5bad45b78acea8cd1a76e59958b710eb","docs/50-59-research-program/59-provider-rpc/59.61-authority-bound-replay-pair.d2":"bd4962775564848a90ec49439301cf0cdfbaa4018956344e809f5b318bea6ccd","docs/50-59-research-program/59-provider-rpc/59.62-burn-exposure-recovery.d2":"fab4ea6d0981d75dd4c704f302268f3c5af0898e299e8e0fb38b34d07200b22c","docs/50-59-research-program/59-provider-rpc/59.63-mrr-admission-contract.d2":"ed3c604e0d350049f00528c7117675a7db751b3d6683719b03be116bcf49d5c5","docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.d2":"7164874fdbeec99f2185e1091f759466a68a3b7d9b239db6a503f16383fce50e","docs/50-59-research-program/59-provider-rpc/59.65-turso-concurrent-admission.d2":"0ade3ea326e2066ce908129e383b7e0f371a429710ed0a0bad30ddcfd61f034e","docs/50-59-research-program/59-provider-rpc/59.66-bounded-writer-reuse.d2":"9390a3c12f06c2f33e3df99088dc39de92d3bccc971ddf5a632910515a67623e","docs/50-59-research-program/59-provider-rpc/59.67-writer-owner-lifecycle.d2":"c28559ccf38b2f3320d84bbc0ffc6133e2708081e95bff39d5ed75d064287bde","docs/50-59-research-program/59-provider-rpc/59.69-hot-path-cost-boundaries.d2":"e5789625590fab63bc3635627b7e20ac41f64b8f40cbeee84d51a85f27ab31f1","docs/50-59-research-program/59-provider-rpc/59.75-complete-entry-and-output-contract.d2":"d667501bc15d6c31d986994f641d8d38f63c1d910784e6852e596c24c4e4c7c7","docs/50-59-research-program/59-provider-rpc/59.75-package-linkage.d2":"bc655ae71cc46e0d5b7f42637b78530f262c3142394485e2a9ba31f6516a0a10","docs/50-59-research-program/59-provider-rpc/59.76-embedded-tooling-and-darwin-io.d2":"87655d7c6d81c1ab203f886930f1630003e006c0edb71f90ac3ca23a0cb91845","docs/50-59-research-program/59-provider-rpc/59.77-mrr-turso-storage.d2":"72a4dceeb20cca337276f64537d47dbbd2ac0ce359a7a63997090e6476a40c96","docs/50-59-research-program/59-provider-rpc/59.84-quint-preparation-and-completion.d2":"17f485d7c541506c42003ebba887705ea61972f00c9498aa3c0d153a33b02922","docs/architecture/08-diagram-catalog.org":"353a4296584381207513468ef291e7e1aefdcd6f9f2b854c92be90aab47577ea","docs/architecture/diagrams/00a-readme-overview.d2":"1e6119c9d5b2d8a40d3bec0c8add35e8c078dd739e46fcf45c589b8125c7c46f","docs/architecture/diagrams/00c-gateway-runtime.d2":"c1d93cc1f635803872e3349c89b5127145bdcdd2b85e9a48f83d63f0bda439da","docs/architecture/diagrams/00d-zero-trust-overview.d2":"0d3d1a5de0967db2331b9be81468cee1b7cb1d1d98966c5e541e4fc24023f2e6","docs/architecture/diagrams/01-system-boundaries.d2":"69b4622c26b18a8518d46f79db8ce281c756a16f7f1a46977272086bf4dc38e0","docs/architecture/diagrams/01-system-relationships.d2":"dde40fac8667b79a070fda14ebd892f1f1e7c1217726595179b541c855f80c2c","docs/architecture/diagrams/02-admission-sequence.d2":"97077cb16cd4457fe14092caeb4bc8cf2912d434763a08fcf350cd6a4c2b2c74","docs/architecture/diagrams/03-attempt-state.d2":"e696fc0f1d63f58100405852e88e8a7dfb1a625e43be398f3bb54bbc1d90e13a","docs/architecture/diagrams/03a-attempt-observation.d2":"6b387ec7fbcff7d5e3e129bad7ea9590afe0324800a5a13bf7a89377ad86c387","docs/architecture/diagrams/04-consume-timeout.d2":"2ccfe8d033069e0d891531f3b5afef4febf21b2722209a612454d14321cac940","docs/architecture/diagrams/05-fencing-boundaries.d2":"1103ed75ac615b1a2f8239c0321d046a5a87acfa235d5042d8a529e23acd7483","docs/architecture/diagrams/06-source-admission.d2":"4d20817291c5de93b7f97366e6cb1b4af954f22de1ebcb3012c139a4b9dbd82c","docs/architecture/diagrams/07-post-claim-outcomes.d2":"63258620c15c2f52963dcdba33b4ac82cd12aadd1c2de005cd029655493493c1","docs/architecture/diagrams/08-code-as-policy.d2":"fc2263ff1ae000055e6054b89beee60f53b9621707510354c34ef45057889676","docs/architecture/diagrams/09-claim-wins-race.d2":"9eff775ddac29c47acd2c0b69fb1ff98ba9a20943da970c2804e270979555c41","docs/architecture/diagrams/10-commit-dispatch-sequence.d2":"fa5d56c49bc3f590c88cf7c3b63e180afd2d2a39fca878d1515917077ff1687a","docs/architecture/diagrams/11-zero-trust-assurance.d2":"ea93840da2ff4bdac59349f5ad7a56cee5506600283d0c364c53275dde0b5b48","docs/architecture/diagrams/12-execution-correspondence.d2":"1dd66ee8c517fd9c6f2f4b1700aeec3e620d699fbe9eeee20df8e05a7f1decb0","docs/architecture/diagrams/13-policy-to-execution.d2":"4bb05b74c3bc0ca997c5e5035ddc949fa374db3ff49bf2104a6c9753e12be3ef","docs/architecture/diagrams/14-adapter-broker-boundary.d2":"b855fa0482a5524226354b26bc8d7ecef0daf2ab1cab54c1783eba0ff29fab01","docs/architecture/diagrams/15-stream-message-authorization.d2":"cedf1c545a853ec2a9ae51bea928b04376d192f1a4c2af117fa54f475ad541e0","docs/architecture/diagrams/16-authoritative-spent-state.d2":"201bd9fe5eb6101543d939e3d83aca646e2b07c13ff1e3c56779571a0cd1172e","docs/architecture/diagrams/17-logical-message-observation.d2":"2333ad147295ead60ed6a92dc824cf6f5769f3828eff1e0cdf58e50aace7b1e1","docs/architecture/diagrams/18-shared-identity-budget.d2":"5ab4992fd8b6a6abf518fb0bbc8c2c8ad8b920d0be74a6e734d846319252ffa7","docs/architecture/diagrams/19-finite-domains-and-migration.d2":"b72b451d0bb97de46831e4b266d8fdd22d59e7d54db99446d53549f081a008e2","docs/architecture/diagrams/20-anchor-recovery-and-egress.d2":"9479271410f1bb57f92106a1d91ec73c73872568d9fcda55cac5aa64b89e5c9f","docs/architecture/diagrams/21-composed-journal-transport-lifecycle.d2":"0fffe555ee4c2c1222c97eebd24ca9b0df91a4d3ec118300ae3b88240004c3c8","docs/architecture/diagrams/22-finite-stream-manifest.d2":"60b33eb6d06aeaa1027546a1fc9d6c07069c3cd3c7d23df8ff8d63a341afe2ea","docs/architecture/diagrams/23-driver-completion-recovery.d2":"271963db2cd881bb82e164bb1544c7bcf311e1781f20170d858ccb65a596d8f5","docs/architecture/diagrams/24-writer-settlement-closure.d2":"ea1930326b0073e7fabd8b64ef3ffea781f1aef60db0d942f9ab14f1150296e9","docs/architecture/diagrams/25-settlement-anchor-recovery.d2":"8904bfcda525de21b48ea8f2db8d12aaa27e85818ccde43fb545851dc522ba3b","docs/architecture/diagrams/26-gate-consumption-persistence.d2":"42e676634ecb40cfb2dee06db1f5497d0e58c05f30097618c3852eb946992f0d","docs/architecture/diagrams/27-anchor-commit-broker-fencing.d2":"5c2ae36987b00655bbcdba36352e03b61765739ad2f3fc80a561ff0d325a9461","docs/architecture/diagrams/28-anchor-configuration-prefix.d2":"1ac0eeb3c76f5ae0ce3565d4469e50210786c3bc53c703a1a61d519dfa075512","docs/architecture/diagrams/29-quorum-durable-promises.d2":"2e4a24c3fae49e710d5afc31d4681a9efc8c2e8af3fa58a0957ede05fe7c0255","docs/architecture/diagrams/39-shared-execution-exposure.d2":"2c08f5b3d4531a7be2aadec8f1ff9d4476495418e94e84c1ff643583ac991ce4","docs/architecture/diagrams/assets/agent-request.svg":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","docs/architecture/diagrams/assets/bounded-write.svg":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","docs/architecture/diagrams/assets/budget-ledger.svg":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","docs/architecture/diagrams/assets/components/activity.svg":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","docs/architecture/diagrams/assets/components/book-open.svg":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","docs/architecture/diagrams/assets/components/bot.svg":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","docs/architecture/diagrams/assets/components/brain.svg":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","docs/architecture/diagrams/assets/components/circle-question-mark.svg":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","docs/architecture/diagrams/assets/components/clipboard-check.svg":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","docs/architecture/diagrams/assets/components/coins.svg":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","docs/architecture/diagrams/assets/components/database.svg":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","docs/architecture/diagrams/assets/components/file-check.svg":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","docs/architecture/diagrams/assets/components/fingerprint-pattern.svg":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","docs/architecture/diagrams/assets/components/message-square.svg":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","docs/architecture/diagrams/assets/components/rotate-ccw-clock.svg":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","docs/architecture/diagrams/assets/components/rotate-ccw.svg":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","docs/architecture/diagrams/assets/components/route.svg":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","docs/architecture/diagrams/assets/components/send.svg":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e","docs/architecture/diagrams/assets/components/shield-check.svg":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","docs/architecture/diagrams/assets/components/ticket-check.svg":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","docs/architecture/diagrams/assets/components/waves-horizontal.svg":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","docs/architecture/diagrams/assets/components/workflow.svg":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","docs/architecture/diagrams/assets/go.svg":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","docs/architecture/diagrams/assets/kubernetes.svg":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","docs/architecture/diagrams/assets/model-catalog.svg":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","docs/architecture/diagrams/assets/model-provider.svg":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","docs/architecture/diagrams/assets/permission-check.svg":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","docs/architecture/diagrams/assets/route-choice.svg":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","docs/architecture/diagrams/assets/rust.svg":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","docs/architecture/diagrams/assets/task-contract.svg":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","docs/architecture/diagrams/assets/unknown-hold.svg":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","Project.sysml":"c0c96eba7c5dbce2fde3c5c0f13353acfb1291eee59bcb8eb2ee1860f527aba4"},"rendered":{"observation":{"canvas":{"x":0,"y":0,"width":980,"height":686.21875},"subjects":[{"id":"n0","role":"default","x":40,"y":311,"width":278.65625,"height":122.59375},{"id":"n1","role":"default","x":350.65625,"y":311,"width":278.671875,"height":122.609375},{"id":"n2","role":"default","x":661.328125,"y":311,"width":278.65625,"height":122.59375},{"id":"n3","role":"default","x":40,"y":511.609375,"width":278.65625,"height":122.59375},{"id":"n4","role":"default","x":350.65625,"y":511.609375,"width":278.671875,"height":122.609375},{"id":"n5","role":"default","x":661.328125,"y":511.609375,"width":278.65625,"height":122.59375}],"relations":["edge:0","edge:1","edge:2","edge:3","edge:4"],"headings":[{"role":"title","x":32,"y":32,"width":916,"height":63},{"role":"question","x":32,"y":95,"width":916,"height":56},{"role":"note","x":32,"y":167,"width":916,"height":48},{"role":"note","x":32,"y":215,"width":916,"height":48}]},"readability":{"minimumTextSize":24.14725378787879,"samples":23},"bounds":{"objects":{"x":32,"y":291,"width":916,"height":363.21875}}}}Commit a group. Gate every frame.?How can a shared snapshot stay safe during revocation?One native outcome qualifies the group.Revocation closes delivery; unknown retains the hold. +@font-face{font-family:"Kalam";font-style:normal;font-weight:700;src:url(data:font/woff2;base64,d09GMgABAAAAAFaAABEAAAAAzyQAAFYgAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhwbHhxkBmAAhAgIdAmXFhEICoLsXILFNwuDQAABNgIkA4Z8BCAFhBwHIAyBGRuZuBXjmIXbQYJA9XI8G2F3bKuWzgzkdohQxX4f8P8JCTLkMHlc2qIYK0DBG+pjP3o/bYx+elObdo1mu0V3Ux706zGe6J034rAvZXMcB3uIDWWNo/ysFdiFo/eLT6UaulanZjlbev8FG6Fi4Sxv/Mek7ixraCbFKYLFUPBFYOMyRrJy8vrPs7k/94ETMYoZK9/MbUbkx1/VzZUu3T2dHimsKL6X8iPtExsUn4FAsjlsrFOGqzppU7nu4r//TatzLr4qQyZxABvYdqUHgC1L6VlyS+VFZ4BKFef7ewdgbab0RSbHRZJXwRV3xwVwZAnSLRjkFGW6sBp1YdRS537vrPVP58LN9bu1Q27pw5vAieEniD4WcTJ32MakLURw1GZmz/7+F7z4AANMOMAssQD4eJ68vf0bWJ3PKPLAJNIoa/f9JzfrQxyIMMigCR7327fm7aVoulPyfzW1uq/dMzcpkjkEDjsZAnuIS10ee97Kg9r3tDxEVdeqzU1kS4m8iSyrRSYU2A6QjL/7K6PJOos+LN7I9qh7BZ6TogqnvgLZBQq4JFMR9Iryp7ljhlnbdHLCU8sbPAUC/pc5+39dEkKsRFD0ql5v61/2Wz9EiFvtRCsUlwoFcufvnjc3REWephtUVEdFg7NyrfGzn8dkDDhgjWB4lf/PdFX6qxsjdnjz4OyuZ72NgWHWhOdMdtlml0lV1Sp1dasldYsxEsMOrWUMGgNqYEGMQaqWVkiCZ2bWMXvGekaMeU+shbUuPRteZIyJLrrLkovju/CCILksOPh/uJ967v095RkNMOot2po2bfSJ5uG02fIKYZEI49q7pN/kOhar+TWA32GHKV8icXLP//9+pROUJIMjFDpAIzYb3j7H1+p4xft9//0Td7exgpIaZDlLFyhtj2fbAnglLqA0yeqQXDeA9jZSSNQftvzmz55Zo0CA9OlX3dgj/ZhvjcxEkP7ON5m9hRz7S50Jiy1k1SdxJmPp7LTd92iCgoDJ5fRcIABuCCqzhQTcRbjnPla/XoZpTqeia24NJIiklqZxUIrTHaQhJJXvZve1FHiMWuKQtve5BxJfnCCOzQRJM6TPzeAGHe5p5Vt/4JUgEMogMkf2UgE2OhFAGZyD6kuwaDpDcG1npJT6mlgErsUizvc7QIyI7yJMMTXVnJ8ALjsKIY5QXgvSCnIUJs90UqhQw1+6whd0j5GIOOqPnNBCpEHTRor34GgDVYYqHhxrZHs9ONHIjntwspHd9uBUI7vrwelGvvTgTAM/UU/H6Cy6RNfoPLpF9+gSekbP6Cp6R+/oGvpAn+g62qM9uqn/w4NbjdZnD243Bh97cKcx+OxcuMsTFGS9iU46Y+CI8PDK89UfjYZRJXvzRm7n7tL5GThBO4iCLDgED3ytVRGLjPcR5mnmLGxd+fQjsAKv7f5/bFT78bOPPqWtB/0//95/7x8efLjr5Imjh54feHRz2o37J0AIAh30uPFA/XO2InSuZbote7j07vJlWu0KY+jSUHylN9wFW7y4aajLWvb9C7VxUycJBMK6rxV4zejya/pWf3g2nrGwHSaI61tkRncYgADHQxkYawnbBClVD4gMLiMSdXeSkRFG4MMHcvNHX8CQrIf1p5/eijVxS+fSkrd0tg3YyW3rbCsSYU83YiGtlHgxUoVXqOGhHyaI370hhNSQ5Xo9D+WkFrS+B4KqGqKtKoQlP1bNqBBqkBvdCFTlB09VOPqEM9Yq0c3ISaxYjJJ65HBRBXDqWaLi1kMqlgV9ElH//gftVFENcvOjDx9M90m9KGK9s+o7N4bR1n2yq0r0yxs9MPeAL+BfNgoIbUtHdjRR9XhLo2pl9BMUHRiWwwMORzDfFXNchRWq8WgB6v1hkLW7bh0OwcwO0EOS1qMttcORGwF1FB5G3jLhmUd3Un9Gx0eDqBjSVc2UExYRYZ6JQDhBBBs1fx8OKePeGrF63cqIKCXGxnmC7MkYoy0MqClfifAN+oRTRkvQCoo6M8YJTLhlBA44HEfhcVtkQHQDMRDIfAl6/cUnflLpRVrTqWwNTtLrj/7154qIsZucPmeKEsRfvgbiURrRc4zbalQfM1yKHCg6gpgTUDFOnhzoJDdc/K43vd6yQvXndUMDzPdKrv7KiGwZnX2VLDLockPioglgRSqiJAz3iPjteyBNUwn29sUzLhxqhoVjSFBxHQLR200kpiHGqIvu35TP5p1tLmjGDCVI38iYpQT5/DuI9AWl9A1O+gEv/UIl/UEtRRAkBY0E/RepBCEn7qtswZVsw/XntUZTXNt1opdIQzrS0CukoQGkIYE0lEcaMpCGTKSh10hDBaQBQQEuFAcGJlyUktJKSgJ4cdLciBKxaLNoWUuZgNYFG7Z0a2Jl7qPWGatHqELRwphj2UoqZmt/W0Fq1e64C0nUCA9qVuvYfTh+UJxoFyBcsyG3A7/95lRPZC3VMHs9Y4NQoK15HUE2b/8aNSk/UWRshYeJVR9lZJsSg9wl5BYjCHVveRm/Twrf18EPjDXeH+H6FmJ29XrGDhFy5MZBwuZnUN4Yx5IAitiBtOpGkeexyYWLjIHuzFd1lv0202d1s83M2afqfDAZkIhiR1iafVYux4kHL6KGPw+TYSRUZDdqvkSkM8KDD2Xdd786AchNabo1IwzIhswIyUn7DHjRxfEC/Mb9//Cq0VHNHCM3UWlGIR4jUKcbd15Ab+h5IOfVTtXswzop1kpy/xIMCAegwQdixvjgGgGhdPVosOZzFGIN2cLtQLXtEZ+RmfDyBqZkCVWssMOFlINDVRiSHh6u6Kww/XT2DZMg79y8zSePQvNUwsyNUv1Imw9FnB3iuI/8htixE6ePErt21PVCMPuKnacB5DJnCR6SKgOTyXCooEAuayk3jlEKHFPt5Pgv0SoQQ8Ae88GFrBnLefO11TpjvCHdHnhibeW1g6UHW5Oj7IAuepjF/kqtbFj1TJ2nKQEm5mzKcYbYDpn9B7lakKOJwuvVYo4kOedsBcOLeeoBKtOCkcUagpaMsUyn2itNsFpD0Jox1qHn3miCzRqCtoyxDZXeaYLdGoL2jLEPNT5ogsMaglxjeJDzURMc1xB0YjydEnuujrOCOYd7cq4RLhaQgxwup30O3qZ93qX94ftBDh+mgw8f00E+pYN8Tge5Koa4Toe4SYe4TYee7mg7yNkvUH13PgdOqeQ/bP1ceZOVBIE0DTsIqgfmtH9jZGn93URvgFcTqPj3J+iQnY0LECGARIuxvM6QedcIIlAKtrijK0ZyMweXIbMgQ59aVsbzsAxKiUOSpgBnymFDJl2xqZ04MkCsxAXaiPlOFmIRrLQVQW/8u+0fZGP+3e7vj/RCL5Ri5w/DlNEazgbrSZdhs9AhBky01eRw+KIumhC2ud6sFsd8MvennrjQHnHG4zq02/l43qbjMnY1ex1CXMKsM1OIPa6S21pph+tm2I/9sjuNrtmhQp5GD9jCXesDApB2VosIa6rJIA0xtHbRY5koKotBlYaQDsIEh13kush2ke8i6SKALlLqoQ4bt7EbvwFwuc19DpA3mfSO2BJ7YiEGIF63iC7Y4ANAsONS72p2tmZfs9QMNYNSNWsY7UtwtoQSfAlylbn/Sq/FKe0DVk0vmWcPAMHUUTR2djz2YwB7KukEkJ8Y1NB4pYRjY1LjmpMEH6OU6WtlTXo4vG1+/8f8eNRxSVqKaU3YXn5C1bFeH0L8ugTgQ2ZVjsaU6r+mo8r10sqNujSDCjJMdDmRUQE3ZLQ5RKHtDLT0sYlRlVPcA2I21SjzqM5rOtIEidWeDdvm2DCEFPWJncw9YDFNJIUDiOWxgIAWSkcbYA9Ml0eDM3o380QpvM0N2IlfS0uvS9gcCdPlxkHSmgCvtPrLrex7gB3JYhyxHel1ONtL/YPocsA5sG8CX8Jf8SXer8gJIm4Qjlb5WysYdtk2YbQnpyC5o3N07EOFuy7aYd1Zz0anpH3HIMUcZcH+eet2ga2C8zCrr6LQhHm+WfWjsEuwC55duoTcLs7meUmXltfgcob1OwY3pMlI8MaMIiFuHo6BSPN43JWKU1Q+d8s1efbdUJh+1zcxcs1n3CFXXVdfqC4Wk/QAUtbU0o6gymdn+Ya0fOz5cWgDsahyi0xhV8QU87kttRq6wl7TzRjVCqTq55roYxW6RLwDYqEkdOSNjXoLTTWVOyhKxT2XAVWRbs1nSzRk2tqtclf4LbgqF1cRaV7hhEDxB9Y0ud8+HPK/97AhvfE4NnCE5Vp6oCKoS3Rhq/ilYu80XB4HVqgckoOvrVF5aE1eMSO9rG94y+qK5qasNGW2dlKk2s+Cwk+YbF06TQHrs1BevHhYVCnK+pypRg0KF5crW8d0aRZ8ouLcQHOCgGX8ci+d/HE4GGCmLtHHWpnVp8GT11HuibqgQfmFHlDAg+VK5kiyllXfGqv6j0KFLEJLkC6mWSzrlwtsr5ACDyW8N87d59r4k092DlNp/sk4SSf/wb2aiHkKCkOqQPPXcvY8m7TfFzrb+u8pST0IrcOOiBZnbhxR/q4ixRwJsa5+LuKJXf0HnHTzoMn6mcyUlpKS0LUvx4B3ykSK70ikYRfYAphviGJibeti1NagLTBJ5gMtOoano1irQQaf67Prhz9OxCh82JIHkusqr9H0qMrl9jxxXrG6BCkwEsbBA3P87cvUxGFwI/qlQcjJQ0nhIUU521w0nheBpgCvkPbaWZt/yG0DSGDYsS53S5QDRCS+RqfwOOhBSOWuKMJjHeMdQBjZbJxIOG9cZ8aJwkjwLSwzud3WKv3u/mPEHq7Ygjv/vzCsipZhiWEpF+tIqz0hllkWFBk+4p91gvSfdOWrirljye3H6rDHe9Hmm3viOknTbnAHNMqXdGENfbsFGxIW4SM1M41AgATegiguNzlMgyOtJ5nHtCVbNg2ASMApR8BrxSNQBGUavrnkVZZnaAwl/DaI9UcckeI+TEH24LwmjvXZ9QD9jcPb6PMhdnSqeMGwjUgV+oQ/AMMdlYU7HqQY/xPKaV0xYj7hjfkCQX+uIC3qYBOG/byolIMh/+Ydj/Za5+vOs4gmjHEtgebREgqPTJeICkrrgG3/0nuVEYt1lOWWSYHhI1RwW26tYDrNLq6J54/QwytzR0rvM+/wdGtZErlz5wc2qimm4cHktvO9QyfvX9hOCfvZ4A/K4pReFcRshC2wZSqHxb0o5n5dZDH4zWgFTSzX2z8EGUd7LctTQwrG5curKth08TtLNy5wd4zmsm4brfC5MM1pB5CcZbHU1KI5DVxhF9JrUlodydBHqlzYq0hk1aT0qGvWPmWr3haPWA6a6pr9hWHgjk2XWxw/N3i0PV6eidHaEm2wFwQDe2zBC6SgW3d00+6y7Wb/mnJafgWqPXH3Y7D+WLpWELrSiCDBrAv6mSaMVSIpf1m+068Ez1vWL9keXm7yt16Y+Jov6fJQsLCWYymRnE0nQ94Wc0fIN8AgFgk8xo4AYa7ZtDLW40cLF0HVgZ8GMkQ6RycC7wQRQipSoLtxWMWsxMyUcG4U6GtOMneVCN9FJxLUQIP/VA0a4kVNrDYeN9gCcTZiSJgAw50jfhHzVmtQl+rf8iLbOExQzkgbL1GtAWlCFI2UVXEsK/K+XtY6fKege58zczNyqQVb7mGtUjei6OGsdVrlO1CEXrFRYyb3YoUrSxFY3duubS5JseS2Z7K82CKLOWMi6xlmzqfOY4Wqg8eCzty2xLFxOGcX9LkeXRrylVLGtRPuhKJQUBg9fxi2LbCzqm0KPq9I8jcdIBtxDL9pViCwWhZa9cZpSds3EKDDY3IXSJyKeJueuyH33nj8UrQBo/tg2nYengbmtPELxIX+y+yyViW+aMJqwv88moITJ96dkyZLAUyLRU5vF8JEECxrZ6BPIY1mTbqNd1AzdXPMNiKBhMPLaQqVGOXVcumMFJWK5R+H9t2QfN1eV7W6BTAsDEDaMq5u7rIifs525h9FfFHpgmKqab4nc6Hv0gnvhGtZFaqGjtLoLQ9VPOetpiHE/7AJp6p5FYYEaggIl1CbzupKuAffVxODinQkUKy6wq/3yDVFanqenLS4kRCrrEZmEdOFii4z0bgfNoy1zIOvYU5g7KWUpkRXnQGHeTXpmYi0w26p8npcI3eNTev7TCBVNmajQ2GtekPOEHHQMo0I0ocGoCltLwd5ujNGqj4qFQ/Ok37mIEwDC/7xJKDxWTHtyC4QbAHDdWp2XxfsueMMj5UClnkqkY2lNLFVpuLNadV6hwn87rW6IICPaeJFIFNaK8jwsEqCq6iVnEYwfWKth3mQ6pGPW7gmymSg8FgJibQWJG7IQvnA5KC9Em3QxGwYozP6wBFvfCCPpzWhyPlyitdNaGAkxFngf/eRPG/vW8zrx6gLms5Bua+Ugd+5DausIDfUC4vdfdROCamnRNmqpGTAH7KAm8sBiYEjwoRqgY50vZNHVRD2loilnqXmfjzU/WJVsWal1qhQG91gms6CnOPF5fWUoN+tHKCerB+tbnADFI8FD4WV0D6gj6mwKdkHEjPCrrr3C3tpPvecDBofpS0wP3MHTWAsivWrmiOCbgTc0yd4N+XH61P3DsOeAaPL2ja0gvfwFEnIlmKzx1y+Hu/bdL98ZiAGvpvTqPK6h+A5yqbm4ZBcq9LaUppjS6hP5bdEeP8eDShMp6kQy/WAXDiCzB12u7j87Dq0XZ5EJ7GtJdUEvGhTN55SSEf93K30ncpQ6jKSSfFnAjvfl2daFrlXZKHofZILDJ7HhENzYUCtR9RoZIrbY1JQFlj5wdhC/6s4ObmZ5kMrpcGMKyzGwZFU4vr03pTraidCu6ZGEe1wROjmLVgFUYe1fPMaUGnj+6Rlnajmgi01er0jmJGIj1dIC8RRs3wKD4Qmk1eLKyrZkwklsEk20R9zx7DnUdS/ATs0iHw/FXKSo4/PfXYPO26vYETafjF5L8RXSlRRenJL2B/LtcrPznM6bgt45cQKUqfmXHGVd0VDXi7WqpfLbsjOpxwpUeS1raXwnw8Se1DlCaE3ArFfihObvqOEXKQioiVxIfCTT8IDzWyZljdi2wFqNPqYzNdsuf3Vfxbko5qwPTzaggc/FVGYV68iExqG9LsuYR/B42NJ1Sex1YOrFWNPhrsG6XmrqMrpAkx5o3OAWkIYWd5+rB9SRdBC4cyga1CaOXPNDA+33rEEISmbhrKy4Aw3jAXkvP7oXaVvN0vpB/mTRAzEuvZGg0ixXpnhX29ca2yRpE3qwTkd4x01JKnYiN9z9L1lnLPOWB8gBUeW4C8ZkIDbf0KaW3k5+s38Iipo81eoulJ+/giJP/P44+ozf5SKd2vPVSFQ4n+VccntCFnqv2OzMBm6zb1wfPZcJ7p4lraDRROhZ9NzU89hA8KKkWwdS7RBH6L41wb+sWezIv1uAe1KJOXdLazFkinvxynuBORymos1ueRKIFeX4xf2sdfnSTDXa/Y6exUgq00/mjP4BN36PVUaOrKhb7SpNPTNsujj7Yt0VE8xzVQ8enDEyPewxu6MInr4DiDu5kqi5ZJyXvztepK7b9cTBXLKL1+T6+wBbPArg70Wa7yNnEbbuo/Hw2fF3gi4Bw/g+2fkIxm+uH9Z5SsbfF0gBW2xpKc5fvDB2wpzZgTGcJ7eyjhRoU/srM7L8Qq/4OsljAtKU0Iol/iPnGlAyg8V43MjzsxD+SFh/E1h+ZnFgp72t1ZbTKxj2nn79IkUFcsnejI72uOnL/6h4xD8d09EOwR8M9sTtEzR3i8/Z4s4ElNAVZgVdUVyanFMWZdOS/yZM2KAIAnNnC5Ylp1ucppc3MgwHfGOa5b05Pkl9AdouOR9uuQt1xONLQujgHB8dufX/OCFFVixhy4eg9WVb10Lh12hHWlNjGsC59qPoQw2pnxZHEzz1kopbaMuV/IpcbfxIurFlNz6Kxpb3t82cWaZgjsMZBdkyFfZ6J1HXuE+XEJvm8X/JH1b5PH5x2rP38exHisljz5HroeG3O1z6ZFIgQRbNvnzh8l1kszxou58Isfpgm8XnOa5OxTcUoi2vxVXU0sw0ilv+X08BRyExp6TmGehy5XxMerEdX1IAxgz3shgzwIDg2xHeuljHjWC98yr9FYoZW7Z6dku1D9LfJmX9E2r1jaDe5z1QonhvVxY+ZiPpeJ5IOPmaf0Jb09q5+4NOYDAps0L3Q9lFTavXbno+7d9J/xteHm/nTvh3BPFfnlLsmTPLUriSdLPydGq7itda9WU0d0Y6L+94EkgZaENiXBUx2ots1hvfKgmRjUBj8KVmBZwr8fsGdFvo+y1jMCe/h9pshhEYpGsiWW/8XTg4GpsHgvctoY86R6OUFh1YezpSOIXzGPciEAmnIYfx4XZ8Rxztl8AsQCCqniC5rSGRD9fGjfwERjOdNUvdjd9lUbrYURaE8OsEVVu1+RqOLKQI0zg5QVgB/xjMwfFKW8+f+p8Uu3gLXFmPQkCg1Mdjqp3KdqqMNoYXWGSNBAiqg73aTlmtBzG0EuBmZxHFLAHFoN47z0fjJ60y2J/QwVrb3/sg9ZfiDCfnEIl+QwcxESCrSwNyBtGQdhDAvFHDdDkfWhSubiCgCxbuw4VciZ14PPoOWjsD6CUXD0AsGYPibeEJjefLIBSd5OEx9HwIjU51WfgIKPehyJCFSx7JBuwf/S/g9SB3W5FOOhFWi+9v6XYhORWU9disKEtNJcWk/iB8b+UWlzkSPuaBsUzVF6XhHWgLmWvzTKCfcWtJOo3F3cR4d0QvTAfFc7nroZITgXavdoA3CEdXuZnWvBuWqB3wS8zrhvt2rf2i2wCFCJkQuJQEneqHSMOXO6dWz/vbTj9o8M7nJvQKsuJjuZuOKewprcTrAxobt/PB83ufU7CrvEoOtLLdc25CZYsAhQqZJHjkBLPa49W/nX2oRgGdmZxaWh3mV9SWs1l7KPlWiflyeUxO3sbinyM7AROyc6F2Gvh2YrxQrhMTeprv+lA0xGLalThu/c3RnRn39/aIq8I8jQXECiHMZxSIIY4lzKJA2thsZRbVEZ515IomJNWVJBTpVreqqjMzsgWp6FxjPDu4rpj18xXquc619em496o7nd927J3eKheh+PjKQWBkM/fX6/Ys4nmfvuznzP38nLGjiK+PM2KEMRjqF9EwOteZ4j18gNgdnwSCbsiNWAcaBOsZW8c3MrCGJMSvrj1UgdXFhGEbwYn3ojGZ9AptAJ/Ctx9n9NO0f1iEJN78HYE7lVyDHqdLVZOu6ah2aNJUkBow8dIb/duGRUDdGvDYoyOz95g1rrxP5YnXvqnF789jOafIZC/5k27EFvi6B53Gl6ha6LATES7F6uxpLZIdm0meTFe6Vgi2llMpwrrE2x72QXLbfjOpGISQmPV1PG26EvoJPdY+qsIZ3vDVN3mfWkX8jY356m8BU01NvEJGn9Sx1qhdePXw627MVYi7qA0+ZAIu5WSURVAnVo8SX+Fz80MB1nleSzcYI2ztiS70selXJvWET2pmLSuqkOlNb7GVz8SbiuLA+/7j1NjlKpMdDCA0a1nOqwIcqGyiyw2lhTXRZoNohlqSdbGtjdNeQ0S4qrSiGw2sFBtI86k0j+czxsJuQ58+qaX2aiv+St7sbZKG37G5dSLy852LilKk18F4IHtUOagSg+2GqnqqfsvRaEeG2pwj1OZDmFj70vG1IyCk88c7opmoD7CM/ZF65xcplF0sp5rKik+6IWc7jw+GV5fMfhcaCkcHY++2X24uz/zRwUsM9b2f1Um0JXnSgim5AOWWm0y1128E0LQB3Hcu13/VvD9LLTQ2yPK9ug6+K5cgT3lTV3oebln+iYJuJSTW7h3zuvzWl5tLkxuDkgjO4YfuP7ViOEgH05Z4l/J/dlo1jBTGjI4KrR8ylnvKXDcv4yXFdoJ07DReE6eIv3n99RRih1jkl1glSNTWlyEhudYkvpmkd291FnSoyvMYJq3DigPxMeakO8lBZRvkcEOcOnnnz0t/jFnSOLq0DHNCG76QnLD3BNpMhbEJz4hmJWDSxsR06wCwUJac8ec7XqGGUESe3Fh2Rz3ZCFhhrfiZX86E+7R/d3fk1VwzLu4no9GmF75A36A/nlqfdak4mtKBXIQA68QxBytrIaTxPfRO6Cu7EgKUofMRFz+f3scjmUS1+14f7yZJMAiVOW+/2IjDGxHKSxk8ODxa6gOhyq4vvIbr66LzkQDDpEs9Hc00HR+y99odjGbZVFu+ygZ3sJ/S/plL24jcnnp34Urp6ZnG2dKorUagQPlK4qmC8uLot7ljUPW5NoCNR7aKXwQ5zwfYuDs3Iqm2pePhXs2ZB84ESg9fkCQiCNyCs39HMX4jbPDDq/b2X30uKmU3WqnbGmEmOKC92HBwYimlPPw71G+GE0KkdY6ZzBm6XPwpqSCSuwN910ixqyhIrgR4BSKUUZpjTGf1W6qU1BZ6svARbfh749HgWfEiUplrHaq84o1wq2MUhEP0GY6K2YDAgc0QNcWwy+BTWGGceN+h08RrLUkz1/M0R5X0VowGhXc+pcvxUMl2hIi6BYyFzMgenk4gNjnOHDmEdlQpockVEPl44NFJwz0TKJlk6BACHnDi1kf3Wbom1oyF3f/fOlEcuMjz8u6ndV1c87UU3sfd7sQ2RGMoKEDbNFIjJLFGnp7jZsZn+35fyYwrZT+n5Xg3zaquoEUCFC0R1EYy+2iIxAtXZTpBBSJXWvaxXOLHebCqvaYohgAVHOoHDpyT0pzar4sATrRZlzkzMr1WsTd9Uw6rCHh9a7lJ28FcsBr2dTtlyxNQNZ6EOmPP2+cfS1l4K3aKyC9rRDHLzvETYLwK9A1xYTm9Lx1UTATSofYeePfrnO0D1ZmNQwmXN1Vg6ov5CEhMTiCaWYq/GaEyJRMBUw5Ok7aPBjjLFJQhjrZ6F9ynpoZFLyrWEhibQtCc2Mkbxm/BojhPkMi0RwI1gZM5HDufiDe6ORiBYdbkJ9RO1BR7UTaDjb5uWUJRDhF531HQqofIaMQu5I0+HMogQC+YdxD+e0EFZcyqHirFOYp2dMHFy4j2dvStmEpqWyY7aP1qi+IRkGNAf6Ll21oStoBjsEacrLaHur5FLypKJlIqPM1bJlXRRmVxUsLW9wR9948KROpmN3Txi8hOEBGS6YuFRUJffAbwWZglZShGCXceJm1B+1CJRLouguuAVmOPbLwPxtDdvJr1LocNCtlF0V/c/Pe0kapSg3LRdqZ/Ug7yn/0yvbau/lcT3Jd5tF4Xe6XtRt5yshu9nwvuCp53/uncuBIbZG67aGeUQd6bLZmoHTp6gISB/bj32JVviCua8Q2foqKPNjwEYrW2VUtv3k5aIStpjKNYuK20r8B1+3i9XwXXJllufVVLf5XgsltSCG/K7t11h61XKrZ2J+vKu3d/W71zTMzuA0InM4lxWU7HsatRWEYK+m2rummcNO91aV08f7rGRz6PY+ZLSdryPV5rKYK88NHz658u/iW29JBsNzp/Fjykz7T89Yxh2f/opn8vxMANBJLge1NOeppqrab/SeXwdkD7bzsVNEmShF3VaeWCtI8B59nhZ9uwjmutj6E+utdUqze9AZgifg2krrdcH2ygTvNWONJN0oS8X/OfObAjQNjvhf6ecFxejrMsu/lJNOE8eePgs93vzdQtY6G1+kl/mqTuLm+uUWHdUByD7oMXJmeBb1UFXG8kkMEW7R+s6WG+Wvt+ngg/k8uo8xvyEiG3Inpjodn0LGFgr2y70QAjNYl9UVJBx4RXDaLjdZ4QGawZjbzVybBviQakV5Rv6S4FD40sX7T+oXtvGu8582Gpy/DFPcx3UzXq2p4PmkTzYpgmhgw5zjZVfxVBYlpS9O1QofQF0CmCkTbD6xtYHS2luYQVO4REtkVXj7UkBpXJCkZGRZSk8ZkOD+Gl7k373IdzUtI0WSvU/+QVTRTZDjT1mnsgb/7beMLesxnKL2VANJxLnQ/k+HpCS9x7Lzv0Kqhu4bS0rasj9Ag8yeqYGnNUmqj40IQKYwycfassbLl0tLilAVk/qHCgzjmjWRq9cFdfwnD13cY+Xquc/p09nGbW59cVZq5T4iNItbTQ9KclH+XKwpt9vLqgiq/PQsEg8mO4ZNNLNqGrJNMqyy72t81tKWxqxQq7hUeBJA0DiLx8BNZQxO/++9fG7UREDgmpe3IfWIHRmJamsxpB2gJwiEYgJC5L9SYY3REqIXWOBfnQGGLJFVjwRKW29gFkRtPiGatsxiN9ODsiJ9OgalSHoPvELwif93In5o0C6k8vBuQDo3FheljcAfvTAVyfZyDzlunfD4A24TJ3cvFEUTt71g4of3R78VKGDd7obSLLIRP3KLkZc0S3GTSBOYyUCgDUlGdZCHtldK69DUvEiincMhgJ+vsKnuaUHDs+MCbwq1vV7PDiMs8GhHn63NQLSJ9RBkmT24tLNYnlxcVB48tLjmEjaU+/U3+WAPMD/qJD+eXVWvbyUnm8ApU7K+MCnotrbXeVrtaA8HoLCJ6d1njbioF5w5x8+Rn13cVbNa0HAokGEGavlFJ2awVv98a3re508Jy5LOJePCSKCdbW5NZmmeH0aFkvGg53y3raxgim/h4d4iLsmAavBEORoaPjyn3hXOiLnQ0uTo1Pyc9Wc/Xq75bW44KWCF0BMmGRLUORm36ixGVJpmb77HG3Bvfnk7Bsp11pBgBiTdkOVBZO5f77GDdYH2ftpWwxFlcHkJskDZu7cAQRl+WIHOdse4QnNbEqIXJ3uPV4FFieiU1BMu5K/mQxt5CIF+sPlwmcRfoBDuF46kvav4nlc9wTrDrhE6HTGqqDeuQlGMVxeKCebzPbxIEvdGAqM/a15Cn4SgvWMxA7HEIiDJcG0AZzoeA0ta3u5b+ETJIljw9oZVYrDo+rx+d3SOjeRvCtD3eZSFDwkS5yC3ypPSmSxyDRKx3COBe5kLOmKdn75cpWfWyP7wpTie0jKX2clDmR4yaMxzsGpX8JnERa+bmL9Kt97w55GgKhJruTkaOXycVN0WylZVBBg7PxE8jb6FWW8WZ9XT4n15Up1OZ1g7CmR3YBOPnxqxOGhnvCXE1Hhk3fOmt1SHH8VPX2iGEDCMBmGvLDVv4+p9GwDyVrrq2M284G/TA5gzn4N55x1/LwOqtuBjVdbV+nkLTvALjKapD9P3WFQEjX3FdD8SkFeQsZ7zd/6v5IDaOPlvIA4CfGvq7AptFWL2DJ1oE7wMWIrlWLTFDOG/Z+6dIQnQVB6BUd/9oaAqm9ERVQfXL+nKThE1vwOd5gJANv3i+rrr3Yt0jKozOjgCR7W/MVE6mJA1fTwq3aIlaWqt+fd2s/6MNFeaGcPtzd3VfnLuw/bNtLeq22nYMV2VrvKVW6SiUkztq5Jsaq0omTFlgbTwRI7aIye3BwpNUCt6hms71WnqmN9VQhD+wUtyx0MKo7qHsCPlPVWTXHGLUyjyvV+RGK/zK3kBXe7g2XCggE0E1MFFjna2LBAiAS8ZakH6pwKemsYqsR0e8VfHNqSx04y5KDpvmYCEvVYPl65au6zwwC7FF3qz7VsWthbpIYSjXkcfGY8A3Y/NpRGDwN5U10BV4sdXhoUMI5CX+kFGwkaK+OrAJ1U8tEc0BGL0iEME8XuSghy1saualF1vzzxDo2zHIqJlKJeZos974ieBkYkPUPERd55MuqdZHBRXA8J4PGOjD2perFrLoeX5eSYNASrlKA084d5sT4mH+oqrjtg4YMQ7N7oiv2EWGTbZ2m1Jzycz08wkuVmxNZb/llLyStRFm5AhNP81eYkE7X7a/KZxp3M2ETbYGeZJUAZnrLSDOxQT79Kd5tVhRMFeEBvfrlWukg/tJm3gLUg5DHR5dP8ojxaHjTX6PxiJ0Z2yixYlgwigdy6IYM4Mum+xtHAiVvja6/oqhNX3Tk4g61ZRMYNU/JnmwRm7TU0tepHRzUzYXN0n5noqCJL5wfMcnhvhXgBZ5RihSL161zJBoFTJpvWwwJSEeEiipOdl8ePqDRP3PvpIT8jFpMKipDHRZK/XYBhNIqDKjyRXkPjs8KTOAE4ai1VkheXzs8o4DwmT0DV7B/uaKPG1hQSJKakLCWQwOXxFpggm7sckZVi6IK5tVM0lRk8YsS/a1N89pn5UknNhCBbQjt533vLoHY3XSAVcrqalUfCDMQULMm1AFG7jXQ+fwPdP6WDqcu+9HwFI6qtnkGAwa+WQMkp1MBdeBDuwyMUyMtKDZnOZN9Wqyj37IoaGYvc4Nkw1FWYXesiAXJnXbIJrKFk1azKcbTj65czWVLKyNtnoC9rdrf7/9HS7DUXmr8fPA5n8zZ8RDM7FOyXOxRhiUlFZnNMO0qwwl7bRjoFZkKtm72GkEjHA8BKYY6XnR8KPAEEuf5qx/lDd5lPhLNp+GoRCizdoyZtwthVDeYF102aTDyWSabHdRVsDrMKS7GeXNGQKbuxHjbwQqrqg9UMEbvKX6LQWK7IYsskGHQ45XIi+uICg0EPPp+E+TcmFwKjkHzWHwTbntVneoMAONjne7QqzGod8fPe8TJ4KlhHF319apuZu2FGeR8K/x4n+mdOS+4qtnsYa7stqIc8CGWyUktj1Nyyvi2vI9M9IIlKzGisZemx0DY3J/QEGdvrjkZjr/38jpBBc5FYTxaEkJadVQKUqgR5O/wIIE8Q1gFt/YgzhiddIlf6dQKfjcsMuOXwo8pwtcbja8ZPg0Q05B/OA06tY15eWbMVltdVVl9saIjmGGQ/lCi9jukRQ1lHLMBflVRm5iSvb+SYPck6MV7RTcrMSVPOgNGvU16lSe4pPR/LO/zQlUpazvYEad/oT4+DMQbtfC4s2rO7oPzzROfXxnqtvM7Pq+obnZUbevdKjPEJna7Q18oV5lFjWIUAiJTpK4koRv1fmsJqp5/DkLQsqYPmOFnuMBgF6Km7FmeTqD4TJpCEFx1G0KBv0LBxXOvTvIDNMGCngbTiL5EBmFY+6fU1IIXubHSJiQZdzboAC/0johP57Sb5OXwjBvuXD5Chi2SFYohNLEWWerxfDSrf7nexKSWBleFc5RmP86z+myzdd28skEwMnclQwQt9nz97OGt+e5CzX1uU3PzrdHSmv8Z0ZKGuvL0rMcEvdod0n6+axqKDHMaf8i3kWFz1czbv4ZB+n4cEyCCpseYbNzXoCyToXw0rJr+4pY/nWTqM/70ZizOZko0gbIRi8C/Nlag4pJOqIQwrbhfWMzwTSLVeMbn85NN1vCoT7Id66msANJHHHGAspZqhtk4UUqdhGfhCh8ICTLTEQsSdsYl2j7+tnB6GZdEXYX9zXqk/jBH9vRj9a6XpIsDwtfK6vrjzfA6/GYXUIRSosE5Tny8ygo7UB8PLzej4xFnUaoAOgCjuWx+JvEYnTBRkcvBhBh5PHg0NdvMugbGnhtSXqqL/AVKKBDVDZcX7cW+L5/zpMaqcFHAayx3qaUv82SpLNeKXtGTxXRfN6dKLyU8HPBfOZx9X/YVfwXoVTLT1kJschoU8XxSPzCVwajnZXfeCZIrKH3c3hqkTNT/AW1pJCK+j0o/ZA7BblNyo1l8V7HhYsKaejfQt5Kfcm85XGv7bpNy7lOWSb+XRV6fuLAN0neiobUcp80/aqBgwUOW7i179EvAoXUwc/Gq5whPoXCudNMpZZmltvNd83RiCsuLMkIC/JathVwMp2y0pZF3o7XYQdQjJPdLKT/0bXh+AgRVi2skeNAAiMv52Uo90NyvqRWkKfLaMqZVgqRXgiqUdooQSDKyPrdWsQDhCTMZSBGebTWs1VGhd8y4i9jb6f2H4YnBcgrt+ZrpKCtH2P/NaHTXlZYr7mrP/70QarzKrH7bBWJzTkaS1m4MDL1ZqIhzD3N3HEeLXRmQTT0yTDCf/RpJd0WRvRRydfU6XhDOgHdmv+CLaDkXvsrDrIM4nlMXWmm3oFt8FU0mE5TOf6/53Fplq/t8ddbjwhrD1XhTZLTMf9EVZHZveOX8GauMpfe7pGqWKtDjiLEER4dIefTWnnJjEqfZcS3AmOfcaOS5eOLOJ8N7b7jf4wnOlV6MSE2DuMXwy7LhjZZ5CwHm2bbHMHo0leL840UcDO/WY5BdB58WsYLNKFcwSiz5CvNtH+1hyDdW0sI4YykK0iD84jekYs/G0O+6H12L0ZqF+z5JWNPL1b1jpLhJdFBpJzUk+d7ON7AyW6Jv8alhEpDmDWLY6dvc/hRT5nFnLYZv5N2KiqCpNNLMkCeFw+FyyGc/IVsqyUyU/SPrVUMwybSH2CS6NPpJ5cJO4jtcmeiBRP8KWUgBb5Fk7jn9Z/ig7x+CgLR0knZ3kibkQJaWwsKU/bUgvmahKz45avA51mBCTxgGJiXjfoOaqxLynYmfvIpa94PzRLfkF8bqQuM/hVG8ngjTEqMsDCa2ynv9jHV6goKltbWg+B/sVDB7lFW3N7wkXs/Is3Uh5vT9Zo9FVFXNjTaUWV+SLiyTD60NQtb+ooVcGEm7PKrRrwK+AKYV68IrngQ772sPNgV0xLLr82uRBnilwlYiLZmITAzDG/bT43jJXPorbI4DokmrES+wmyH5fSQ+xHgIvwzJLYBsucuxkztJVeYBQlku3QLP3ZL/LXa3IYkDaEXZK5edrRBGV5OiRW/+nY+CWo65RdNqHd9Q4jWjXggGx8++2QoI7RVvaqXtXxNnvKH+6CbK1Rrz53/D16tPw3i0jU1vUVlESAJjUn8voIDKbOa+thRsKiSgWW78+6f9aaganmNd4oJdFGW0XyS8sQwuUNNepcVNBq7CXAjjHw0/MMhe47aajBVyKey7mfYp48GNdCE0YW5E/FIYWtVcKUN+ECPKIjjDdMKw6gAFveh7HJQoRahTdpEmf2WFmUZG6sNFEQbnfB5mBcNE8013GxdXDp2XcwcyDAwpvBO9dcTan/GNxBsEoVLjqvKTt3D0BY4Sh5Bvyu3hin19cjxfpYrfmAuXWvQGqOLDNjHT7VzOo4FbMy7aMHcT2ZPKa+Ai7l3T1fumtFRvoRDYAlvm9/lW3uaQsqj5pYcWPMy763upht2tXzxeGMTUi5Wfalu5ihQjTFWaWBf/+NKoQZlLUqNhiumehz2kUWqpZ86vfjcT9PjFOwr/yUa8NXqYkvBLiunIrqwPw/5T6gX4Uh8Du2tpm9iE61zlA/lXNVs+sI1CURcp4s58r6PTjEI35gaiNogQ0aqigsjx59ZshOsvBWbeaq+Tysbc296u0/ZC14XzlFZdW21/imfO0jG84cC9qTr4yBLqyX5CMNvWHNY7WqU5nfbzJAPA0bleZRYnqiuIFO47CJJV1I2SIH0+dnGhsyGr80sPergh0BKefAGxKDcSXt5F1XualOvGR72PeE5fOU+qHex4U/BLtjZQh0xky16CtD0ZYRkm58JKJ6Ph7H+u/yrMVamwHNZvzrempeaX2Hq3vRCgEFkg7wEPR6Fh8KlcFbnNCEhIwmbYZRaAvJkIw7/jwNBK5iNK0Ig6AX1RnLiU9tk4xo0bKwwQNeelzQwjdPrZnY0whXR7QJnLj8NyDL+klY7CjEDsOIcWeYd1wTovtfWoNRvPUN3u9MACl0zBaYYnKV53KkEub452RTx0cdSyoFnUM/8r0hnzNgp3F39oxJn3s6Fumzu56s2FHj9h2JX5MWZhr7LpVw4hJy3Ju702t3vPoRZw1Ftu7Avs3sZ5RiaiAQnitva5rb9eshLFA35i8gBT3ciXkUyIy/AWz034qqTJYZrAY63O8SUo1tdPvxO8y+L0tiCbNRfiC+lPI0MDnS1dMwa1JRpBxOF0VqSc63BHf1UCt4dclG3SuS0Qp7bxsHvUNjIJcSmg+obBMqFC8tluxtF5Il1pVr62rke+qm/I/ZSWNuVowRZDmy5J6UV8Eq2wAWSGwY7qw9UNf8sJf/mv5HCCuASd3F5CLlheL93fNo5ulTPTmeF19/StTct1VmjMjqMAXf5+9i//TNPvtrVD2G1GB0DzctFfKSjylLA30qk7X/iufHCgcZ8nKA/4NpSNP7H/pUA3Pkfnxc55WSQhny4N1ihehIQ96ayTYf3fMxWXWHPJfwBUvAYrTAP8FdUE6gAsIrGbYIxVIrKY2koyBQsOqNeTP5SQphcMd686SJQ8owx5i2J7r8cZeUHbkmxJdOq9UwzUddpD1mJXNvjQBJqKsxYdmelVw4j5CZ+FRWtocOrrfP+E9C/jOeiyJ+pL2bm7b41P/Zli59kFB3/6993WsldSIc6ddwoEsm2Eaj9wNSGU9M1zAyfEL0PGjeLSC5Lv9g7i6KTP+UEYhWA7E0bYPe5oirV7Yi2J/eTvoCai+2bFBmvE45cosHZNjz06Qt9h/GVhP1Y6865QKWTbUdLEBl/r4xgU9q2F71IjoIBr/llXCdCwYDhJDjO8OixzXMWdBL4wE3ZbHXT0RByZI2KVE5qTAJJ0OyJpNxW+oAoCtiLaOV6vpf3UDEJE8b8H6mucgXPacSUFsSHnRo8yZ95AO+vLkq5nZH6uWauDCa/x28iIDJZFZQgssqScpGMMpM8IPq50uUS9VhehmBWeOrXa1Z7OfU0TlAVB4qu3eR2NZ9lozJoX4A8+X7BEUqZAt+L444EaDdlv5Y6x8aXaC0XUXUGeQUAvdn4Dh/9Pg3AHEV3LG1n9BE8o/+PEfJa+FugwsXPL/XiPwxSlRbKLBLAlmHD0gAdQDR1w7gkXfLpyIBNHocl5CchuEj0ESsPKYTt4NW2uT1D6stGTFxWduj8YFvo4udX8v8nBpRQpPYNDbwc11H726arkM+iCGBtwmxqlsYAzXMqNL69cZ4WeW50csqL8OeX+/8TrGUR7z4Onu3G93HThVW0J7rug6dkdJr3GdfV0SG9wVTOJPslGIZEMaH12MW8G+tlhQj25JOGXAkNAZ7LZSsgrfd5EhbpTIkGFOmtiiMqgSjooXZiT0897h+66Zidc1RSGfLHh6Z5bOabogt8i1n4/uP+drsee/bFvwhyRiUw4GCQ+2FRp5b5249JtIFVJNSccwdkDrdKcW2RPosVJ96z9syEnGjl6VSQzKuDr44CuY4NAb3Jg+xFadTS0OdQFd459c2lKVgimg/3w/P4nFa1MuCQp2FxZRJN1njFcV62zKl2HiKO0UXYRvCr9T+So5t1HpTWNOTFOk1jBw4mOb3CGWMWERG2aWCeEEnRAsz08oBjQeEuT8PfHFEueviLOQQKVskIoULdqDhgKFTp4Sdh7bQ+OoJJW4ugiwMHj8Re9C68OC+VdEFtUM7ZJHf4jzWI4KsXaJPE1VKEaBzEFdumxsPSPEAjS3eQXbFSTWpGOF4d+6uTYY199t96PQI4jNPQ3ZxTtdzRU2lWVota5ASmspzrnrNLl1QgCqwRdqw+a7ElwWK6h5mo0GCbJ+GvQ2m4uvXJXTu1B6pJ49+bqV7aMjQO5YsGlLU8tmWdYlwkoKawnhHeYghNNggekF46uVgR7IzT8YAHLvfD6c02CUgiAqTP5hbiIDZnOWVZDXabgIq9MjhdMArB6hGPLCt2bAFbo6T7gwqIoOXgcNMM+sgneJOH8OKsqM5Ewgl7FJdgVW7Ko30dyX44WAQVxS8R1W8UQZoiwLmcb0gPHN1p26F3EXN9/wVNjNIjcVHvhbImDspxkICqzFQ+atjntumA1LQFBmGk1i8Joum+mSExmbhwA+hUJpXQ/u2TSMdwDqpcipKbyZk8qyOCAJvCtQ1tVEQ35pORzvndcZGphY8TL+HfSOd6Odmi2PWAJ9T2baIPGzj7ZifDgb8aa++LRh48UY7Iy5DLHBCvLUZMBufDzqEz1KzD/7MGzoaFUBHleVNyU/NjacpOG8Yh8UTO1LRyn4CmeSCMU+mhNAFPj0pyehkELCnHyh/mxVLVJApAcokFVVq0Kk+xdIb3A0XIKNwQpOe/saHtfrZmrpNVaD/bx+LFLFEplTBEOij7he18PBTHoqIbQmQ2Xtxj7JzeLHz5dHw6PS3nbV2VRiNwHVSJD/igs9Ax84EFfTq5wFN1ETiUCvbhWMnLezl5sAdOVeJDleaTUxqjrds7hQgFhHDxrExTV/OecXFKYpbXQYohVI+Tpxn0M/fB9LNKs66mQXemawDWe6O3F2RUf3fvUToRbRVviU/t0snxDALU5DDFBReqT3Zc6ih8plMUOTjrgj32dFAHWeC63PhrBBd2hKjLUOyITJJpT++8NLB3vaZxbSVfQ78lEIQya78KuxMZBWObQgU/bDAWxUMyBDw8MAKc0aCkChqahPMBedoVQo4EqUvBLhR5JwDGoUa9Zu0Kxk9xSUDEDcGIyoJS7gOfYATBFu08hY3MSC5YBDJ6AIL/Tphl+JWNJ7OZKJRSDQ55HpbxMAAbg3ARILUbj1YMYREnTxtOEbwO8DqvBxQwQzBSJ8Ce7DZ4yxorkAkHKUsFISD1owswwvy2g5QpGMghSb0OJlcF9UmONNlQYjUUR56CoRZpsPwz7sRiQlPhYu06VeKpeuolwycVUrgQnxGtidgunyKFI00Gt2Fd4Zhj+9Jy7Vc7xayQI40bUtzM36lQ6Z2V92iRBLEWHnDhGnP7LrEvLqgCLoNKGD1VeIM3pBdPwqsZkCWM9/NDXKwoPgQe8xgDZENlCt0Ko52D0eWkOGlQvkj8D/OdyKgVWSplASK1IDs0sSR6ZRP4qVgHR9NLjQkT87LAaWCitenYJPX6JHab2a3EtsYGZaov2itMT0IJtTqWo7Lep6w9arcBbg0K8wrUpG0IjGR7Hpo0XZcnr5AbzGB3iJrFivYBKHHAFEyehpUPDWJGe3el+9MKCppLNNFycTsBDQFbCxxO3FsGzjj7Ew9cK+DM0PKwD0a3YVSSzDnPQ3RTFYZ7sVwKkrOszL767CTjwGMEusfEJZcJjT1qzRocjRBTkYb+Kc7IPIMaC0wm04t8ULi46/0dRu4NTzH4loFuCQgkuAkhfQDYEdu6jDNyxX3u03SxgRcZtqhSZkqLeNT2DJiOfmgh7bsgIVOqxaX3SHT8xRXM+ZpDbmSRGikkXiFnKWaJIeEPdwMwk+XURK/zqJxZsReDtE5t9wKlyfwGTSR+ongS6zsUmBG2RlxIqdTgyp4qCK50zZ8DzcPOtsUsEgHClC1B+9cdU3JAk2OhOt10PALGApob/Jlw7/9JCXlvAnH68Nf5aKx83NtqO8QDKYMjIHseSxSbzEPEZ81GWjaXWK+09IugMIPdtZZ0zwXHg7VtXkjTBdIZnqb51Z7HCtap2FbVJdvCva3QnkbgXGUEvLpkFrTzM4dEljQ5GRyJmmlIGj2gXAGwYCg2h/NVJQZa92vOcX3Ga/HRQKgIifvLICsisS/bR9k2BpqlCNwPLDwqgyqsGHHGVbq5lIA0LFyJ0MfyQnIL8+gpwMA1trmfrdE2hBi9cUoiIePrRKedBpbFpGqMkTRgn2dhWZs1b4QwkfPZgl2OiAMYbnDmoo6ZjOYGCMYjXdTgG84oDFpCw9Vv31aDABGvNo0+4TUGl5OxCa0bzPN5j21KECo2/wVK/Aabs4w5Tw8wiyzduToPjVPXvDGF9K9g3KFQMmFwHrLTerrXPx5lR1UiHDo3pAS1dUQdmRI1yvEILrH9pnkCI2eU/oJ87/9FT3MeKAIIpFn9vLidgIYEzoM8bTx+Kpgxm/DSV4JxRXEepcKeUuY7JQF2MIY4n+T/+Yqs2T+mxbmdbarVG0VzFZ2DhsDD6q/fFpmMfXGp0/EO7yQMTVtAN2QCF9PKZ21BeJJ+glrxccXpbZiBOXOkEf8X6U7J6rJPUlrsGUKg6990EWtbphjuS4ZY48VQd7AyXYuqwaCUOCAZMktipwxVPl9ieKmrxBFHboknEyX+YHMyT7fs2fCMDggF7F2bwVRMnF9ynad5tc0hBHnUSE0whbiWVU6T4AxU910riQr8SBmdtjYrVvBY5RJrprpwcj8UNbMh7XsfCMonLXsveTwjCLiHDPsud720Tk5Qj2Q0tlwTreQDIA7pGtGAf5u8DeaNflJrjy1VEoWcm/wLhRhsWWm4xPrAVisKztHNcXW1yYDPTwsMBFU/x1Ud9ltkkkuSeqeHnYyqayrJj/OvlGmbZWaH8z6ZVM6vlbmH376uOaPAnqO+6cglKLmZvfc1gbtYiPTOETCEDaWpifa22mDrlXJtXG4Ht25wHHDMak9hP8rT6xzrFii6lTnISLxlPcGyaZg8nVRBaQ1C1sLoeEVFR9URuLTTiwE1Sfx95CnWATVUMlyKBroChYCpv2+9VLvbCpuvifkLJ28+FJlW9y8+/SrxNm8n/eLzlcAuu9ab6U8+ug1zVMJ4j3WQXd5JFXzoBpG66nU+MOWVl2etVnGEgHsb1HhNvQZHILPzPBWq3A6UygtlzTLkW9X3/mrQYFZYGTRJ1FdxKO+HhTKEaKrXnp6Bk9ggERZAeqly5c/E5hQbWK0TkwqdOAily9Cah4GlxATxaBdCCHvUtpS17RbsmqAIVwmcXCPyX1AI+wEcEhvzyrBAXP4NJRUmCdLsIE+LiK+If+sO+58+LUuSUke4qi5AajxC48OeyPAMWN3HwhaB+zf+Enf0gah/eZwxDB32/CWG0lWIDOYGoGp5FSigBBTHxHouIraeYZiKrN+ndhuyn1CC3qAQLA2yaCYb4eRqKLc6XhKkNqn/TSMwikHsb4F1ePl8f/k+3O42Y681VgayUd3yIixmwuy0t4jcL2ozxi6gLZylu7TCDMsNBRHcGPHIm1MZ1JLdSehKtr/iSmhNXOBR0xiiHYT50ZS8C0Oi4FhBQ16/2CbzGlsAtimCgES+wUksacHwnxxAKGKTOdLFCWVnsW7Ct/POm/wR5yZlGRGMzTy5gao+T0zbZFpWvxpyYHCQHwzdVY36sQN9xvw4zOpk4mYvCAhQkuGg8t+ZCfvI1S6vikxwDJ0RXuM1f+/WCwxZdc9YAubD/g5xY/R3eVIRS1f7hYT4T1QypFNDOX9DAMF/2Jz7OYqJSk+a9/rep0c3jRRczq7DoxtfvamyNAoEh+ByWBzW6mwfjR5xW0xrQlMg1KQfXQEQj22M4WomJZrFvE4mEglDNEHe8d+MBEBDQknKKiIwLTISe/UwT2rOnBEOOMCD3lkgtxFAMzCFveDCaa1JHRhRKPAF/t6te3/jyQVQbJHpFqdtWc9tc+Li24qQsqoELpYifDHPL4O3HtnAhq5VCXRDCXPV4BRtlAzqlhuuTeaIUIVB/gZZU/c8u0SSUHlZszgjCf+n7w9vQ1QoD6FMFnZF2RyDInE2PICP2hQ8wl+GR/JYU48XhlkElhz1bpl2atWFVpTkaVKqcprNrA7H0q3HOk2FrRsM7Pa2GxTATEwVnOwPnXFVTDxOyV2yXSS4i0ApMktwxIrP6wwwkHX8jCPVJ+zL/nlvueqKYw96gSHHkfxQUW+jfeZOwGyw9s43m2mTg7OquQ126gQUEU/JKDh4gkXQbFO+brPoVaFXAWWfGVqOx+puPSLJ8+2Mccjhvl0lfr9ioRVM3BZBBOwyLdkZlUk6oTmZqAmyhsW89ShkLey2Le+2TBmMV5lgWVPMMSB1OLC3CyRMrhvIeSU2va2ZuM8ma+pwkXxpyc3U0nquXkauQxOzI+/j7iwtV+5rMVcyK05aTsq6Z2Y8PfhBbOGLp+NhHOLn5Jkz4F4G6bjDnXwvGbE91Jchb1JHqhVM0axpDgydXeh3JZJNgJJpoaRZllLD2xJlj5WKtg1XiqhgoQhxfaJjgreCYiq6HLaWGeS7XScpp6XofvCNw76/B0/hE1ZMg1PnUkWD4P3qRtQ8wFATay11Senq2eEcW7lWwx68QrdbavtsNa+SeVZndfNmWvM14vYDG01WC8Up6LZceafu/VB///X2+viwXMSvyesDdQYvR1I6bR1ElIGIvSK28ocPbHIVcp54E439ScBuW6K+zXHZd3rved/FZoWpNMX81bLaG3v/edfuVO8F4ylRzphEJEEzM62qEBeDrhPiPVMNUQpD3fHzh93aWYTyw4FhI26Dbgvahi6VWFjmerWyaR2o0EfhFSPsD9Ay6vYB/xSfvH17mcYHSmcun6XLkvihCl5HpaZum88/wPm6bSx88PLh4/Fj6Ju5ndOU8jZ1djD4gcLT4hfWPH/azNmDdcQMI4WER/bTfls30dxd7/dfPMzjkH44WsSnra2xkezGTjTaaPRaCutz6EJmVDsrvLkPbBX2SIqJWyMyDdrdN4GAYGW1PJs0VaplEgWV3Z5LEP1oI8qSWy7KNpy+OmnBUi9rYL2DrWD2KQixd6BxuzhnHe5hdshyzFtTyfLa2kiml7+BfeZvePM+eHHvBkH54nzJIAidRXMpCdAKjGc2po5mSGrnqHo7vKiUUdXOLnshdbAXWX+KSmqV3afgHuiLx/1jknklKJisIFlG1VBBglvi8qwa67wJUyhzyKdzS5HMgGalFCchrg9/iun2sWstfPjq8fPpcxzah+4hy6jbucRgEggJsFtFEOtdFyxe8TIOGalM60uujUw1pQVmjRUOWpIFniOCdqQqWf+Nra5aDOKvXwb3XAgIxzUlxlLxKdreXrZIKLdwfeGctahakgOs10zE7hKDmWiTeBbL5Dww5WwDdQ4BEAb4iH0gbMWYQUODsWBhfElICLvID/pBHpbAqQvOObdNpkLfieDdynZ7wrMalf46EXJAxk9qsi2JbNKchghzFAguSdA4nYamigL6xt4IzOAxm4VTjK+TEh0nMWs9l0zlnaStzZAOaczUftS2WvvKTDUlthmuCAbOTnVJJPhOW41DXSiH/3Cyw+ZtyWhhuvtcylYVWlnaNemYjalPcuAoU0pTZ+LQ25WJQ1IfLZSyxZYtm8TPG6OtmJKzYlDILhUOLaixqkt11/eUFDWc6vPaJKVYdcRaO0+jOq47rlpk2JYkHnUjDVbAoTcDk+xu3B/oFilG1Xwt3TJ5tLbdBlsTXMnseqVDqArw4+TIVoy/aW6LICLFGLGvfp7ruSqhpoZIgdeqt0UnIv1K7dqtiNnYkqpo864tsjjik5iqV/Awadm3MlP73q0Mff9tMk2ywvyS6sAnPe2rIFJ1PuiG5KUk1sbak5gECaJmBsI6Kn5bVBcwR9y7Mk9iMXvzm3FUouP6Gz233gBJINdjN6ferQg03vnQmgaLXCWCwxa1tQiOh5/6lgkX36DpBVFTsb5v9dPzcKEd5Y07ozxOHunj0wf9baEx4ocDRtiGUcDo2OLFSsA9WUwhXdDGkyeABVx4cwmANKYc6MUi0OA4H9I7KDfLcNH2qSKaSzw3xRnjuXp+P9qiHPcbVZtAbkswMvIlJAxtQaO8Byjjb7gXZMDVrrbnW3j7SVvzXsZSDNzVKafpyj/566di7fGMI3FDXGGDIDFgrcYIzRqxVuVoODmTpCyOZfrznhIL7z3rP4aPusxScqf38zkSKKMVtlqrQsinL8N1ZINFn+BLt6XSAHjWp2xTgfYN397UNsd45SyuweIsOWvIDQopI6JAbBIOvdXoOtFtQQAKBYukWSxkmevZE++v8/f6djquSjF5kyD61KaQVFXZToiPnnnrLFM8iwHPbyvK+4aeSEDW6kQtHVfQhpTnZspgO2sztmh+dFAzDQteLH6PdY2BqdLKnvmBK3VfuBgYdb2XO3yOn02VZ7RnvTOuK1MccNCpa82352vrczuVU1BNqDpItNa61aN6CaY0IzkraE3VhCr+IKEWN5IY96iyHFNzqt59Nr5Or01lN8wTh544PsweVmCGwyMpz+7wOstDPDeaj+2lOPWXMf4TKCjnhivWtvtEaQ/Mhql95VqLHhKWbY9q4E5D/dw8Z0YmbgUqhBA4Hz4R3w/mWbAdKh4R+gYVrWVdAKlUFzMho32YxrXP5ZzF2DxWi3Ns1Y5kUlXTFDLMXV5ukOvAtIARNx6mSkCq1BKMwv673VIWjVxV7LHq2ML+EzwN96Yqc62i0OPQvQ7dULMecZjO40d7pSPkATgEDo6hKwou4gpAGYG65nec22CKPvcYvEPXmn9omBtNi6/92PPMyPg2xKu86tlvwaHXDZYrD65goZEnRtwGZVY/mo558UWkR7JcoFW0sNYr3+1JSsm+k1BLvWZCbjeLFlux1ErHIsAP1a3zII1m47p1DANRAMgui1Rz5aOMPpPnHY3nZCmiWu2Z1ph97rT+8R6uPIvFRDvxwo2quKhYEpnlpXTq4RO9AVRQhZ8NbkXr0pmBrT8Nlo+9RT63N54+CrTH4CSqNEWnhWGPpANFvGfplEr9WhLxzUUSOo00R0VXyj4w0eMW0M+anbr1g4AzKGXSteVQDalJClnkrOmaZ0bGOlZ4iWuAnbjboiVjXonKXf4FBiQq24RCtxFaU79pzcKk9XYUHPNUFHCK/Xv8EJUThpgg6naKZItTn5ul5t/vRoAImEh2FZ0F1+scRxzJkMAm2pcQ8KiKAoK3Che/ZZV6ETOSbNtyzC5xlfpqCT39ldxoJ2I+PHRb/lRljwqP3q0YpwNbRXdY+LzCT1/YojpjvXr6lsLVQ/vS0PzEOJN+fLmrY7Jk30gw0fm6vUOsGZh0rflPQm5QqDmT8K3sbydxS6gTK5MVVImcg1BbKqs+UyVt6sGwUT3c64fmAUHlYZOd8mzPXEr+cC56TIkubI6c/lLbO63SA+Go/WbBGZ9ZTKmgNMVcFVCDW3BLlvQy7JAF3Tt182fb1KJYJAPiM5ilUnbWYGWrTDAAKMb2LWXL6LGhr3Y6KhmJLXZIUdXMhifHQqqseCFvvmLKaNQiNzdGbLn7XG6NJG3fLxnPqTE2FLEb5kQayyQhuUGhZKfhMlH81p5DBRhd71TbYiMyYarrXixWXiwkFS9QgP2m3uHvNJnp7FaKMvQZcXsLjWKzgpz5RdnNrFfQCuyy7R+DdyiCYispIqw0VCNPe5yCzTJ6MsDpI42NqHomNTGVviBywxg6uxMbYuYrfvhdu10NGXF3JZgzrvfyvbCdVPZWmWXyeM3XmIziXLM3zCvPeBYuZmdc9KtKVehiiXGoccgsPNmCjhvrhjHrXkpvqKRaQ5/Fw85/h9KOBjUxcFWdohLap1fmzboXo19HMgS89ViXqY5De0dKkvJLPHI0zoFmnYiyuZw3ts2saeQqzhoJCfhhmrZ3OXYR6VZpPzGVV3CBTC3SxSbkdoELca5Dnu8iI06jt/tKcUBRpiYp4oyAq0j6EOT73SF8s1XLgDWqterv9dRMeaYqXW2hdr6ECXw6Rd4iisxtWQgIh8PDvA1o8yC7Ec+w5Zf7PXe9Ng3pxMNfv6r99NhUtFt/ZZAyz9IkJOEfiHKbMVCM1ycSqciv2y4XeBQyxVWmjLsnWbe7ymLZCSnXdA/kS79tMxsWqsw2RBB/kI+7PL/P0zdOD+eH3XZ6m9+43HS4AxdJXKeWj6wRDWg0VPlazXGCqy5cUPrRtrQXy3XpRH5V4p9ZS64fCneIxePq85RXZVs5fG+WUHXlledSEy1ctES1JCOKV28XovFdIn11GlOfrPmaFFR90htihSo4dysOJLUFd3QJvHOl6r9zSygoYtQPLODj148PZW5U4EXrjn+DNzoPQ59dBOIkjlE+6dtB/wnGJEl2kve0iiMcKhETJkndX6IhOxs6C9MCSl1qabDQ0A2PeyLJeeD9l4/5GgAMMZjoMJKpqCU7bwGe2dcFDH/r5M3SGWhg9V+Cv+ry37bgFJtBECp+oYEaP42MW4x7XJdM0Whi6s+qBSg7/tjhAKlNgpYuQ1H0LJJmyC3d0gJuEa2VmxebpXIDiFAEufGmISPksgPNI46y8jZPGGP8ZlH30lcZhZtD2bu8ps/ELsMR73L8ucBoAYxOiuOBm4rktL4A/ib/MOqlUD7uFHifFri/z4uJUBzPrnFJkc2kSQk3mcxZ3TIbcDLHIQnbSyb5pHR1uZGGY1W07Jj5SHgmnjffFuWmFMm2784PRUDcEuOBnsh3/CuyczzsX3+wqxw67yiCszQMNXTZClKRHVtp0tSOHWg1+GS/ooPScQ2csVfqNV/dZBt8c6cmTxG1egHHwN/nN9TRZdK8xpnlNnty0cw0lQx01zxqtn2YhqY2CGCocKYueRH+Pu/kRV4LP9oYNSgsstz7zDZyQUGwBZsobOgLiZjrs0slyEE52SAtjji9jUIfUuKRxjv0MaAxY3vEkqYHG/9lDzbPYoU4pWs5+rZ3TGo0Zf89F7ZREwtsnvlZxh4Hzni010w3xVD6hHqbiAAw5P/MkNognvVJrsJLAC49rDh9EDFkj/33zqV4RuCRhIMuAj4qcViahvD8SvNZljH5IF8tJI+WwxYcFP838r7WPtVt3JBTRUHzQJXxIeCuHt5XKp/eroe61ZSqDkq+EnjHqqF/EKzGiKmYxEL6jFWsv/uFhTvdVK3yVH8r4LtYE+i9Q2YLDddSvRratFCLrTteR06slZBmaxQhMAt71egbo2ayBJ9zZ7WZC2bvK2s98NrghfFrCr1aQrJhjEutiqwUyeMto1Kdg9INV/WC/Grqkgv8XC7O2giQQab/lFL5+EpgRoovBbpFiB71lUTeitAr/v95x6AMwyTyZA5enqRk6HPOMNmawStc6QhPek6m5bSOs3kbmKR97CHQeUZPalBnaqWVdBCgVXayCuwuHasprBY86YQGefd3FcjsqIwCdHO1OH2UVU0JLXBpLzIts11NFa2grFHsypBpR4uqqEof/TOMJmMRYx41bAzqTqqiqa30HFbXsTjrIQhpM8RA3YT1RQYwMtDbKElkR8JNUvk7FIgB6Y8fpz9bNZjSwQzPsLfqO4rHeb6iiKiBR0nMxjMuqqCnmnznD5HpAWfg/rB5aM8GLGfAbKfPaN6lS1BtTMZbdf6yFQDriLn0SVE2VMaGo2tTq69MVealpLPxjt8YWWukT3WN9nFavTmzWxw6kLLtOu074YNUe5fEfCIQf2ikoNIDELnOEIyW0BwBJLqMXzpc6ZkEmcLPZJDIcqYAB1/PFKHw8EwnzGRK1dVqk1SPcyvQkq7+1I5kEDuwC03oTKuc2nXcHEMXtW2sdqioLTCjK6BSljI0mkc3oh3RFNDhcjalOs3ozDOwA+3hJDDVOG/Hk8k7MM6JL12fSUtUvCtNaEPd67bGkEo6wtmORrShGZ3avJJsSysaS1STl/UpxDctUZbGtVebc5q70VVteaL2Wzk2umNRTKFd3zqeqd/AUlRFpcJIZBm7xtWrhRbvSC9PbWhByzbjTbDbjeWuT4I3tT0TWhF/qFU5AzvSDI76Dlq3+nhnenFjvdXmFZ6XY3zBrsvE5osW4zlHO+wICN6iNkSNx1iGkLUVnxB/6z/ACgGO/yXwPe9A/fwsWNld97toLqWWlcB+vh7cXngxf9Dg81Hsy/LD3ENSUNUI03T+j/MrMJby+PXjFp2vWyucSGa/o8CXKYzp2PGaJ+P6r8z70YOrS7lFJWId4P9x8l+J8WPqSQUAAA==) format('woff2')}{"renderer":{"package":"@deterministic-engineering/render","version":"1.0.0","icons":{"agent":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","agent-request":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","authentication":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","authorization":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","bounded-write":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","budget":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","budget-ledger":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","capture":"a647d42aa11f4e5e85d0bbf66f483f57f3c4ba3a9536362ed0eaaaae10a89cee","catalog":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","claim":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","decision":"3535642a5b613372c3fd374151ec90aafa19b64b2d33d10b19162cad07a35c7a","document":"0bf9674a401262da8a646305cab00006954721c07765b9962e0dee1c31d560f7","evidence":"0a91b169aaa644829a054cbb94194efffaf4298f2b6f8fa8c6ec2b7b413a1766","go":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","history":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","kubernetes":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","ledger":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","library":"df474fa36a74016b79236fff58a980a8c18c682d1866211776e349a0eb4b2979","message":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","model":"0cfd1f9ed3873f556ace725a7b6a251ebe75d7d976567699276f34df36b2443b","model-catalog":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","model-provider":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","obligation":"e76f4d34a7190400446c89e4e7d187762b885808a64a00c99455599d902570c5","pending":"cca7589bc3b1dcdebacb867c6836c6fc166257f05823555a268354ff9bfac00c","permission-check":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","policy":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","provider":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","publication":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","question":"dbf231e1568dc37189d5674d73c4bfc58a17eb8ada579b3f03bf2813d33c56f4","recovery":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","reference":"3814c570f79ab294252c36530de464c9364814b797afb862d9c62e728a8660fc","route-choice":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","routine":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","routing":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","rust":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","selection":"82b4ab6faf195fea0a891c35268e61c186e93e7c6a9d7967a4f6a73dbf25ae7f","stream":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","task-contract":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","telemetry":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","unknown":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","unknown-hold":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","writer":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e"}},"design":{"audience":"Gateway developers and security reviewers","medium":"GitHub at 830 CSS pixels","message":"One native outcome qualifies the group.\nRevocation closes delivery; unknown retains the hold.","questionRefs":["q1"],"requiredSubjects":["n0","n1","n2","n3","n4","n5"],"requiredRelations":[],"focalSubjects":["n4"]},"evidence":[],"layout":"model-view","presentation":{"objectRows":[["n0","n1","n2"],["n3","n4","n5"]],"notation":"objects","options":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL"},"icons":{"n0":"policy","n1":"authorization","n2":"ledger","n3":"stream","n4":"writer","n5":"stream"},"roles":{"n0":"governance","n1":"governance","n2":"ledger","n3":"semantic","n4":"execution","n5":"execution"},"edgeLabels":true,"graph":{"id":"declared-reading-order","children":[{"id":"n0","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n1","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n2","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n3","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n4","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n5","layoutOptions":{"elk.partitioning.partition":"1"}}],"layoutOptions":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.partitioning.activate":"true"}},"textColumns":22},"drawing":{"mode":"sketch","options":{"seed":29,"roughness":1.3,"strokeWidth":1.2,"fillStyle":"hachure","hachureGap":9,"fillWeight":0.6}},"fonts":[{"family":"Kalam","weight":400,"source":"@fontsource/kalam/files/kalam-latin-400-normal.woff2"},{"family":"Kalam","weight":700,"source":"@fontsource/kalam/files/kalam-latin-700-normal.woff2"}],"palette":{"background":"#F6FAF9","surface":"#FFFFFF","ink":"#163C43","muted":"#496A70","border":"#C9DDDA","accent":"#087E82","secondary":"#946044","tint":"#E1F1EC","secondaryTint":"#F4EADA","onAccent":"#FFFFFF","supported":"#237653","pending":"#986320","conflict":"#A13E54"},"inputSHA256":"7fa2e85429b63d40aeaac63eee5fa8551dcff25ff1048095d1c1d39d3e9bcf1f","model":{"subjects":[{"id":"n0","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::changes","label":"Rust / close\nRun edits / origin cut\nShared edits / shared cut"},{"id":"n1","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::validated","label":"Rust / qualify group\nPending clear; each row\nCedar + claim + domains"},{"id":"n2","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::publication","label":"Turso / commit group\nBurn the bounded group\nPublish one qualified cut"},{"id":"n3","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::staged","label":"Rust / prepare frame\nExact bytes and next span\nReserve transport credit"},{"id":"n4","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::receiver","label":"Rust / consume once\nLive cut + owner + expiry\nOne-use frame cursor"},{"id":"n5","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::tonic","label":"Tonic / accept once\nOne current Rust owner\nObserve delivery later"}],"relations":[{"id":"edge:0","src":"n0","dst":"n1","label":"closeBeforeWrite","kind":"connection","fromPort":"n0.0","toPort":"n1.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:1","src":"n2","dst":"n4","label":"exactRevision","kind":"connection","fromPort":"n2.1","toPort":"n4.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:2","src":"n3","dst":"n4","label":"inertOnly","kind":"connection","fromPort":"n3.0","toPort":"n4.1","srcArrow":"none","dstArrow":"none"},{"id":"edge:3","src":"n1","dst":"n2","label":"qualifiedManifest","kind":"connection","fromPort":"n1.1","toPort":"n2.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:4","src":"n4","dst":"n5","label":"oneOffer","kind":"connection","fromPort":"n4.2","toPort":"n5.0","srcArrow":"none","dstArrow":"none"}]},"modelSource":{"ref":"sdkCapture","modelHash":"3c45556818345c7270d26e7d40d6ad5d25bd2b585713bf03143e9a14a5387ed2","view":"WeaverViews::providerDeliveryJoin","portProjection":"owner","labels":{"n0":"Rust / close\nRun edits / origin cut\nShared edits / shared cut","n1":"Rust / qualify group\nPending clear; each row\nCedar + claim + domains","n2":"Turso / commit group\nBurn the bounded group\nPublish one qualified cut","n3":"Rust / prepare frame\nExact bytes and next span\nReserve transport credit","n4":"Rust / consume once\nLive cut + owner + expiry\nOne-use frame cursor","n5":"Tonic / accept once\nOne current Rust owner\nObserve delivery later"}},"modelTrace":{"modelHash":"3c45556818345c7270d26e7d40d6ad5d25bd2b585713bf03143e9a14a5387ed2","requestedView":"WeaverViews::providerDeliveryJoin","resolvedView":"WeaverViews::providerDeliveryJoin","renderingSHA256":"1e069227046954ec329a5a30eace9332a6c1288613939e11d45a79a65ae247c9","capturedRenderingJSON":"{\"modelHash\":\"3c45556818345c7270d26e7d40d6ad5d25bd2b585713bf03143e9a14a5387ed2\",\"requestedView\":\"WeaverViews::providerDeliveryJoin\",\"rendering\":{\"view\":\"WeaverViews::providerDeliveryJoin\",\"kind\":\"interconnection\",\"stated\":\"render asInterconnectionDiagram\",\"nodes\":[{\"id\":\"n0\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::changes\",\"nameSynthesized\":false,\"type\":\"EgressMutationBarrier\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n0.0\",\"name\":\"closed\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":519,\"startCol\":9,\"endLine\":519,\"endCol\":46}},{\"id\":\"n1\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::validated\",\"nameSynthesized\":false,\"type\":\"DeliveryValidation\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n1.0\",\"name\":\"closed\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n1.1\",\"name\":\"validated\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":520,\"startCol\":9,\"endLine\":520,\"endCol\":45}},{\"id\":\"n2\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::publication\",\"nameSynthesized\":false,\"type\":\"PublishedRangeSnapshot\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n2.0\",\"name\":\"qualified\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n2.1\",\"name\":\"preserved\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":521,\"startCol\":9,\"endLine\":521,\"endCol\":51}},{\"id\":\"n3\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::staged\",\"nameSynthesized\":false,\"type\":\"InertProviderFrame\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n3.0\",\"name\":\"stagedBytes\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":522,\"startCol\":9,\"endLine\":522,\"endCol\":42}},{\"id\":\"n4\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::receiver\",\"nameSynthesized\":false,\"type\":\"DeliveryReceiver\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n4.0\",\"name\":\"validated\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n4.1\",\"name\":\"staged\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n4.2\",\"name\":\"offer\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":523,\"startCol\":9,\"endLine\":523,\"endCol\":42}},{\"id\":\"n5\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::tonic\",\"nameSynthesized\":false,\"type\":\"ProviderEgressTransport\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n5.0\",\"name\":\"acceptedBytes\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":524,\"startCol\":9,\"endLine\":524,\"endCol\":46}}],\"edges\":[{\"from\":\"n0\",\"to\":\"n1\",\"fromPort\":\"n0.0\",\"toPort\":\"n1.0\",\"label\":\"closeBeforeWrite\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":525,\"startCol\":9,\"endLine\":525,\"endCol\":80}},{\"from\":\"n2\",\"to\":\"n4\",\"fromPort\":\"n2.1\",\"toPort\":\"n4.0\",\"label\":\"exactRevision\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":526,\"startCol\":9,\"endLine\":526,\"endCol\":86}},{\"from\":\"n3\",\"to\":\"n4\",\"fromPort\":\"n3.0\",\"toPort\":\"n4.1\",\"label\":\"inertOnly\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":527,\"startCol\":9,\"endLine\":527,\"endCol\":76}},{\"from\":\"n1\",\"to\":\"n2\",\"fromPort\":\"n1.1\",\"toPort\":\"n2.0\",\"label\":\"qualifiedManifest\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":528,\"startCol\":9,\"endLine\":528,\"endCol\":91}},{\"from\":\"n4\",\"to\":\"n5\",\"fromPort\":\"n4.2\",\"toPort\":\"n5.0\",\"label\":\"oneOffer\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":529,\"startCol\":9,\"endLine\":529,\"endCol\":75}}],\"columns\":[],\"rows\":[],\"notes\":[],\"notices\":[],\"shown\":[]}}","portProjection":"owner","nodes":[{"id":"n0","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":519,"startCol":9,"endLine":519,"endCol":46}},{"id":"n1","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":520,"startCol":9,"endLine":520,"endCol":45}},{"id":"n2","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":521,"startCol":9,"endLine":521,"endCol":51}},{"id":"n3","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":522,"startCol":9,"endLine":522,"endCol":42}},{"id":"n4","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":523,"startCol":9,"endLine":523,"endCol":42}},{"id":"n5","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":524,"startCol":9,"endLine":524,"endCol":46}}],"edges":[{"id":"edge:0","index":0,"from":"n0","to":"n1","fromPort":"n0.0","toPort":"n1.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":525,"startCol":9,"endLine":525,"endCol":80}},{"id":"edge:1","index":1,"from":"n2","to":"n4","fromPort":"n2.1","toPort":"n4.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":526,"startCol":9,"endLine":526,"endCol":86}},{"id":"edge:2","index":2,"from":"n3","to":"n4","fromPort":"n3.0","toPort":"n4.1","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":527,"startCol":9,"endLine":527,"endCol":76}},{"id":"edge:3","index":3,"from":"n1","to":"n2","fromPort":"n1.1","toPort":"n2.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":528,"startCol":9,"endLine":528,"endCol":91}},{"id":"edge:4","index":4,"from":"n4","to":"n5","fromPort":"n4.2","toPort":"n5.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":529,"startCol":9,"endLine":529,"endCol":75}}]},"view":{"source":"docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2","title":"Commit a group. Gate every frame.","purpose":"workflow","kind":"routing","question":{"subjectRefs":["n4"],"ref":"q1","text":"How can a shared snapshot stay safe during revocation?","focusRefs":["model"]},"basis":{"captureRef":"docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2#design-view","modelRefs":["Project.sysml","dev/sysml/AdmissionReaderViews.sysml","dev/sysml/ArchitectureReaderViews.sysml","dev/sysml/ArchitectureViews.sysml","dev/sysml/AssuranceReaderViews.sysml","dev/sysml/AttemptReaderViews.sysml","dev/sysml/AuthorityReaderViews.sysml","dev/sysml/ControlActivation.sysml","dev/sysml/CorrespondenceReaderView.sysml","dev/sysml/ExecutionReaderViews.sysml","dev/sysml/FloorReaderViews.sysml","dev/sysml/GatewayArchitecture.sysml","dev/sysml/PolicyEvidenceDesign.sysml","dev/sysml/ProviderRpc.sysml","dev/sysml/ReaderDesigns.sysml","dev/sysml/ResearchReaderViews.sysml","dev/sysml/StoragePersistence.sysml","dev/sysml/StreamingExecution.sysml","dev/sysml/WeaverExecution.sysml","dev/sysml/ZeroTrustRefinement.sysml"],"obligationRefs":["proof0","proof1","proof2","proof3","proof4"],"evidenceRefs":[]}},"questions":[{"subjectRefs":["n4"],"ref":"q1","text":"How can a shared snapshot stay safe during revocation?","focusRefs":["model"]}],"references":{"model":"dev/sysml/WeaverExecution.sysml","model0":"Project.sysml","model1":"dev/sysml/AdmissionReaderViews.sysml","model10":"dev/sysml/FloorReaderViews.sysml","model11":"dev/sysml/GatewayArchitecture.sysml","model12":"dev/sysml/PolicyEvidenceDesign.sysml","model13":"dev/sysml/ProviderRpc.sysml","model14":"dev/sysml/ReaderDesigns.sysml","model15":"dev/sysml/ResearchReaderViews.sysml","model16":"dev/sysml/StoragePersistence.sysml","model17":"dev/sysml/StreamingExecution.sysml","model18":"dev/sysml/WeaverExecution.sysml","model19":"dev/sysml/ZeroTrustRefinement.sysml","model2":"dev/sysml/ArchitectureReaderViews.sysml","model3":"dev/sysml/ArchitectureViews.sysml","model4":"dev/sysml/AssuranceReaderViews.sysml","model5":"dev/sysml/AttemptReaderViews.sysml","model6":"dev/sysml/AuthorityReaderViews.sysml","model7":"dev/sysml/ControlActivation.sysml","model8":"dev/sysml/CorrespondenceReaderView.sysml","model9":"dev/sysml/ExecutionReaderViews.sysml","proof0":"dev/proofs/cedar/DomainMigrationComposition.lean","proof1":"dev/proofs/lean/ProviderEgressWindow.lean","proof2":"dev/proofs/lean/ProviderLifecycleFootprint.lean","proof3":"dev/proofs/lean/ProviderSemanticProgress.lean","proof4":"dev/proofs/lean/ProviderSnapshotPublication.lean","sdkCapture":"dev/sysml/captures/WeaverViews-providerDeliveryJoin.json"},"sourceSHA256":{"dev/d2/themes/assurance.d2":"f7723f53e005a68c803a38ce5c04cd733f46f4a2688fa4b17c66f9d5b308fe24","dev/d2/themes/data.d2":"19fceb46186892da02b763217963cc3ca2a35021219c0d353fdeec84604ddaee","dev/d2/themes/flow.d2":"1f13588619d0c8087c08d8afd023c4c0efe12726711c311e623eea3872726c1f","dev/d2/themes/routing.d2":"f185df198e7435d12b17b7b57b62dfc5795597d95eb926159ee13b448727bcce","dev/d2/themes/sequence.d2":"6e39472720dccc717f984c95b79570494b6ce3828b86227629841649e6c956e6","dev/d2/themes/state.d2":"f1a35cbca0f9cbb055ea9f793ba3dfb86e5fee4e462038ef3e72b94baa61d781","dev/d2/themes/system.d2":"b2a32ec6959ca5df9103c16454c4e34b758e061f850f7de6b619bcbc5fcf17a6","dev/d2/themes/vocabulary.d2":"add21e9b87eab485e5daabf6316fea44eb56b1007b70123f24b0e32e3357f744","dev/proofs/cedar/DomainMigrationComposition.lean":"c1eea3510b34077fc22ea7e5f596c0b0cbbf0119ae56f984b1ad5ddc5fe65a64","dev/proofs/cedar/QualifiedReview.lean":"1ae16e06ad03a2906fa8c21dbeea1e3eb7700aa1e9359e64848dec65ccfd079f","dev/proofs/cedar/WeaverPolicyBridge.lean":"a9628a8123d504a34f64bf986feb4471325aa2b0ddc603d76b62632481eab67b","dev/proofs/cedar/ZeroTrustEnrichment.lean":"0c4b138843cc176c27d42d4a31177a3c12486b2d8ff124a6453e3d0922170884","dev/proofs/lean/ProviderEgressWindow.lean":"c4a15b4ccd3a6474290b71374499087dba7dac7a1fda53f3a870100ec2e768a9","dev/proofs/lean/ProviderLifecycleFootprint.lean":"4786544c8a8193c5221bda2f7cd5cf20531bd1856d88b10ae29b280f223e307c","dev/proofs/lean/ProviderRpc.lean":"e79d7639ac11220585e59e85dc5bec12b6717f7b51fb28fdcd62dc96d8fae38e","dev/proofs/lean/ProviderSemanticProgress.lean":"d32e010145a7dfcd646daeeeb4b08c0e852b9006bca404681af7e7fe10d0eaa0","dev/proofs/lean/ProviderSnapshotPublication.lean":"312c0380e334fbc5380815d882c6b5b0007747100f818becbee9c6784eeb5716","dev/proofs/lean/RuntimeAdmission.lean":"6111d4b9e93ebaa9f7cc44a55ed504c88c20c8d9de81e947a2e13b3f4a13b13c","dev/proofs/lean/SharedDomains.lean":"10eef67918986264689b09f0a6c0d53b314d7bf43b42f4b9652b403570beb58d","dev/proofs/lean/StreamingExecution.lean":"3fba798a7887a0b2ae29a7e3f0aaa3d7e2fb191e5f1f28109a4a73d28e27b776","dev/sysml/AdmissionReaderViews.sysml":"27ebc6c98ec3a1f7f9081e77a130953c3b646a1fdf6f1d6fc1fa6ed6376e9623","dev/sysml/ArchitectureReaderViews.sysml":"52ffbccbb17bd257e8ad9f4aa9f727c8ce0c00149e7d6738b82042ba06fdd0e3","dev/sysml/ArchitectureViews.sysml":"45d14e970e29ef204e500de8de94ab3a18319f2bf7e537d69ebe6138f713a14e","dev/sysml/AssuranceReaderViews.sysml":"cd99fb7e9b23e08beac265bc832a8debee0dc1e1d318b0f64d5263519270e390","dev/sysml/AttemptReaderViews.sysml":"0d87cf71e15c26566422a6ddb5945fdb8add8af0484d9d024c32b97597675e21","dev/sysml/AuthorityReaderViews.sysml":"6fa25bd3a64e7f89987caec8e4773928be2cbea0a3c943299e536ca81978316d","dev/sysml/captures/WeaverAdmissionReaderViews-beneficiaryRegistration.json":"04499e24efe1ec856cc2ef487dd18d018f0ecc85671462e4624ae785d6e1ce4b","dev/sysml/captures/WeaverAdmissionReaderViews-bootstrapInvitation.json":"bd052f79d004aa66c6b6b057e51c485b70419e041994a3ef0f9df7a56cd94e21","dev/sysml/captures/WeaverAdmissionReaderViews-callerCustody.json":"49dcf1fbb83e65666d09cdf8f9c389cb5e79a4466de5c6b1a6b062f83c25e9eb","dev/sysml/captures/WeaverAdmissionReaderViews-custodyPublication.json":"4dea2586eb9fbc092d6ec0efbf4333e476a667c308515a5831289d48f1e5343d","dev/sysml/captures/WeaverAdmissionReaderViews-enrollmentCredential.json":"99e37452ee8cb2ecf45e2e7c0c4d56f9625a34f7f6a346b0f893ee2673028542","dev/sysml/captures/WeaverAdmissionReaderViews-incarnationIssuance.json":"3bd35be32d187ef9fb4a1b7c2981bcdab75d276eb5a7ecb848330f1f419d4a71","dev/sysml/captures/WeaverAdmissionReaderViews-routineRouting.json":"9320eec5667b9ab60fc4b56bf7a8077cca4f699591df43ae8a6c4bf7a79f27ff","dev/sysml/captures/WeaverAdmissionReaderViews-sourceCustody.json":"4d6d6b376d8b061b12c3a334c6c3caedd00707959239cae49e9a18508fb8be8b","dev/sysml/captures/WeaverAdmissionReaderViews-sourceJoin.json":"2454cbfa94032bbf056eaa0dee3bbeb8bc6864a635471d013651d11988f2f98f","dev/sysml/captures/WeaverAdmissionReaderViews-subjectAuthority.json":"d97bb7e9ab14531f07b30adcf42625a3602324ceef3d93d1b5345e2b398e8263","dev/sysml/captures/WeaverArchitectureReaderViews-adapterBroker.json":"a876e33e57bbd52c0ecd63b0efe89f8303f376aa3f74ddcb38781dff18469b51","dev/sysml/captures/WeaverArchitectureReaderViews-anchorBroker.json":"9f456ed9accdddd94b311765d8e9b8da7771bb4dd25a3b4d47dc8ee55f52c733","dev/sysml/captures/WeaverArchitectureReaderViews-anchorEgress.json":"dc9fe4cc8613327473a26f03d5dfe82fa0fecb9c0506b32fea8bd9029c5aaa34","dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json":"d5ea66646d34b275e00647fc169a23b1bd700ab155a0546216bd5397871fab03","dev/sysml/captures/WeaverArchitectureReaderViews-codePolicy.json":"911b72414b876d03ffd4537853b11ff1da5a28f521f3c72da5c0cc7331e95676","dev/sysml/captures/WeaverArchitectureReaderViews-configPrefix.json":"8eb8cf6f9cbf65bb002f8ffa3497e8b43d01497740fea56b0b1d01f98f60f86a","dev/sysml/captures/WeaverArchitectureReaderViews-driverCompletion.json":"5184bbcad85bc10b924750fb0a999964a8a68878ae5a11a2a7b4b5b364d16b41","dev/sysml/captures/WeaverArchitectureReaderViews-fencing.json":"3770227e6015c758ae90797cd21187fff7d5e3ddfeff62f6e47071db943b637f","dev/sysml/captures/WeaverArchitectureReaderViews-gatePersistence.json":"96429db758d36f7038e077eebe027bb4bfb0be70c754102107d99d420db3de99","dev/sysml/captures/WeaverArchitectureReaderViews-journalLifecycle.json":"e3670e3891ec00f9291280b7791105c82330c185cf0da95fa0c95b625e4305a9","dev/sysml/captures/WeaverArchitectureReaderViews-logicalObservation.json":"ccbb19106752ff90e26727b700f52113a14adfadac99a1c9fd7ab25cd5c2c158","dev/sysml/captures/WeaverArchitectureReaderViews-manifest.json":"459cdecf7befda6d6ca94b8256a6e85af0562a4ee542420d001681acd21418d9","dev/sysml/captures/WeaverArchitectureReaderViews-migration.json":"19a8802c591a066e2d750f22849de9118fed7b23067d3460edb0d5b104138be9","dev/sysml/captures/WeaverArchitectureReaderViews-policyExecution.json":"c94dd51b1fdb94aca8fb4c8fd3b75bf6700aa555e904d676c0461fdfa9d575a6","dev/sysml/captures/WeaverArchitectureReaderViews-quorumPromises.json":"1dafc3bcbe572e0ad57397bc1c58a3a22c5f43f4c2e7bffa39120831591d10f2","dev/sysml/captures/WeaverArchitectureReaderViews-relationships.json":"49f3a30a2eb3c79b7ea90c651f2eded9aa3595b083d43e3f01df3e4fee4916ce","dev/sysml/captures/WeaverArchitectureReaderViews-settlementAnchor.json":"aac54f6f428f23545a673162c0cdc25afea928e14e24b85c851e728efafac285","dev/sysml/captures/WeaverArchitectureReaderViews-sharedBudget.json":"5593a5a6e9868d4a46297ec4772f20d96700a08cc99c19e0f1ac5f91773bf7f9","dev/sysml/captures/WeaverArchitectureReaderViews-sharedExposure.json":"02e557c5edfa0b58497f5e15354da2b0e7a76572ac1e0ceefd6e2dfae651a914","dev/sysml/captures/WeaverArchitectureReaderViews-spentState.json":"8769248ffd03df9ad5b3003ae83ff71e2a8039eb0e7bff242324152d9964ce7b","dev/sysml/captures/WeaverArchitectureReaderViews-writerSettlement.json":"33e10db472521769ac4ff201b3e721fa6fc8b19368fb57877f16f23e5b6c8c45","dev/sysml/captures/WeaverArchitectureReaderViews-zeroAssurance.json":"ea0bc966793ad36678fc690dc0d9b7e45bef6c0d3d57806494869429dd862849","dev/sysml/captures/WeaverAssuranceReaderViews-brokerQueue.json":"d1f8518678c9c8c36e3bcebb63ceb558b43786410f8411029a621bb346c8fd8e","dev/sysml/captures/WeaverAssuranceReaderViews-continuation.json":"3c1ef926be8eb3fbcb5b7a4f36b8d66d8fcf7c5504c2c54e4a4f90de72dec0e9","dev/sysml/captures/WeaverAssuranceReaderViews-deviceEvidence.json":"ad4df25c08bfc83d494b72ca7ec1cfeda7e3f57c4bfcda972e8f7cd3f2ee6a6f","dev/sysml/captures/WeaverAssuranceReaderViews-gatewayHead.json":"3d758f63c9d4dc90535298aa80d6fca3dfe198f6a9c51f35e23c1874cf7c58c5","dev/sysml/captures/WeaverAssuranceReaderViews-keySession.json":"e85e734aca17c200b6be205fca56930d50b3852c8d9a4e32dc180d2978bc7a8b","dev/sysml/captures/WeaverAssuranceReaderViews-rangeRecovery.json":"8e2d4bfbc6fd3388057d187f6d3abe7f99c8c80ad3ca26e1c3c4130cc9b8d389","dev/sysml/captures/WeaverAssuranceReaderViews-signer.json":"1d04fd69e45695c0010c23e2ed9da37bf4198335cb63755bdb587065f5bc10f5","dev/sysml/captures/WeaverAttemptReaderViews-admission.json":"288bb3aaed51572cb6b4a2e2131e1b34b45a341082bb3f854ba022d4a5096fda","dev/sysml/captures/WeaverAttemptReaderViews-outcome.json":"ba21d6881b4092b19b2a660f0f32b07598464234ec077ce8d40f292b246070f4","dev/sysml/captures/WeaverAuthorityReaderViews-attemptLedger.json":"6beb328a34e7f3b55bbb7919c3eb08cec666dc6be2ad86207d90dc717b749625","dev/sysml/captures/WeaverAuthorityReaderViews-canonical.json":"7397b46316bda6455956948bd00f8893f46a72f0f2c1854cadf641ce42c2e318","dev/sysml/captures/WeaverAuthorityReaderViews-multiKey.json":"6e7cef11b6c2df934538ba4e65bb515c2d127bf857788325394293efc9b7fb2b","dev/sysml/captures/WeaverAuthorityReaderViews-publication.json":"d98be08fa846fc8114cc4af1d47557a03e52d0c15da44877fe6e5b0278dfae86","dev/sysml/captures/WeaverAuthorityReaderViews-recoveryCAS.json":"f8a68b4c84f5776db7568fd280fd1c38077720515eb6f0ff13124e190b2bf75b","dev/sysml/captures/WeaverAuthorityReaderViews-scope.json":"92b125a292f593db4c04b60125a387a039fc337ac3a4f5cacbaaa57ee8ddf196","dev/sysml/captures/WeaverCorrespondenceReaderView-correspondence.json":"562f7f9983c4f56bfab54f51462e2253bed98aaf7bd6fbddab36ca7396c08cf1","dev/sysml/captures/WeaverExecutionReaderViews-accountCommit.json":"a00590aff4a21272cf4dd278c83e1c71a4c76c938ef4a4a87248862999b70417","dev/sysml/captures/WeaverExecutionReaderViews-admissionFloor.json":"0a47fe13c770b7881608c7e700d2caa860dcb4eecd21271378132d6c7722ef47","dev/sysml/captures/WeaverExecutionReaderViews-appendHandoff.json":"0d84875d7d5a235a25c5c5bac12a44ece098cd7dd98d89a36ba94b9fa42e0e84","dev/sysml/captures/WeaverExecutionReaderViews-checkpoint.json":"a67c2efe1400a76464e423d2ac1f64aeea052ee5e15bbc2ea9a33a55256a964a","dev/sysml/captures/WeaverExecutionReaderViews-executionEvidence.json":"f472326e0d72a3f6ec5e429e31b3efe0cca25b3ca3f2378a85150524dedfec1c","dev/sysml/captures/WeaverExecutionReaderViews-executorOffer.json":"5a567b79aeca9603c5bf4b0b3e12cedc08b3e2d0d30865be6e4ee96fc246b7a7","dev/sysml/captures/WeaverExecutionReaderViews-joinEnqueue.json":"6c52bec12f30f905cb05d5c0cf318a339ee2a1460d9174c7dd18420137cd47e6","dev/sysml/captures/WeaverExecutionReaderViews-manifestSwitch.json":"09004c8c5d2220b6f07c7093bbbca6bb26dd5cf109c1e246cda0a049bf79a060","dev/sysml/captures/WeaverExecutionReaderViews-resultProjection.json":"b3a297a46c0cea352a1764966a8617fe0a694ab0a25c711437b8c16bfab4fdb2","dev/sysml/captures/WeaverExecutionReaderViews-walActivation.json":"696165c219207691ac3e0240f8f7ba0083761089c6d49670655364b85cd4175f","dev/sysml/captures/WeaverFloorReaderViews-floorOrdering.json":"58c3404d7c1e84c17c0a41050e5588ebd6119d0bde797d75c36b6009a429404f","dev/sysml/captures/WeaverFloorReaderViews-floorRecovery.json":"bed1c9ca5d75dd698a6e8df308bd224018786a773e8efe3ab072fa791244da4c","dev/sysml/captures/WeaverResearchReaderViews-embeddedTooling.json":"45dd0569338be5e2f736797115d29c569017f8fba24f886b38be9cda0e5278b4","dev/sysml/captures/WeaverResearchReaderViews-floorTransport.json":"fbdb56bef60900927007fa5c6520d344e99848d682cc7690c7a0cdcb9937f4a0","dev/sysml/captures/WeaverResearchReaderViews-gerbilLifecycle.json":"1741aac62e80cf945309de63d5dde0054b11f8c3302bda8f04aebce25c455145","dev/sysml/captures/WeaverResearchReaderViews-gxiLifecycle.json":"09aed11e7515ece76965e2aadf577ba1a41190b583cb7c603461704f86a83f19","dev/sysml/captures/WeaverResearchReaderViews-parentReplay.json":"b00f83a1cb339bd01829b621c95c3e491e4ed8f9e13f362979ef48ec0d504c53","dev/sysml/captures/WeaverResearchReaderViews-profileBinding.json":"b5e4f9787698f14f5b1db4f866d375f8a0d2c12870178558decdd26615e7e2f7","dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json":"068636681000f55369db15c557dffe55236f228fca2662ed489a4daf24a72c3f","dev/sysml/captures/WeaverResearchReaderViews-runtimeAssets.json":"39e79818a0a1008768fa34e3bd24142374d29fd9de48c83c8759c3cb916d59d2","dev/sysml/captures/WeaverResearchReaderViews-semanticSlice.json":"218063c3c0773ca8712926545243c2d44e0306d13636915132348fb6eee10d37","dev/sysml/captures/WeaverViews-architecture.json":"cb1d25c840996da4d0c1d3b927e9fb9a636e7b4be6d330e5fc6193bb70e5b79b","dev/sysml/captures/WeaverViews-assurance.json":"6c9cb909df1134aa3baea1d129ed4f269740186d78c130513e16e36fc63aa1c6","dev/sysml/captures/WeaverViews-contractRefinement.json":"99a584b7a7ac202c054837e547d802fe402147ee3667fcc5fb74b69841ba2967","dev/sysml/captures/WeaverViews-execution.json":"8914ec28010e6869c849d32b69b756c80f5f4192d4186965c348178ac9016989","dev/sysml/captures/WeaverViews-gateway.json":"abcc5c0dd2b8ae483be7994d42fe87872eea6bae38a4447619936bc491067a02","dev/sysml/captures/WeaverViews-providerDeliveryJoin.json":"1e069227046954ec329a5a30eace9332a6c1288613939e11d45a79a65ae247c9","dev/sysml/captures/WeaverViews-providerEgressWindow.json":"c11b316d78990b8d02ffc09759c7b3c2d4333a243b6667cf82bb005cbb87d47b","dev/sysml/captures/WeaverViews-rangeRecovery.json":"5835d25e0c6c34f24dd54d11b92f85498025b33cf2191744847adb97348c11c6","dev/sysml/captures/WeaverViews-routeExecution.json":"881e66b2795823ba04fdde6cb0848851352ceb076fd0e839e4c8eee667ba0fc3","dev/sysml/captures/WeaverViews-routeSelection.json":"b35aa6bb1e46bbe66c30edfc928f49af0ba3d81d1f90e9ebbfd9a30560aa107d","dev/sysml/captures/WeaverViews-storage.json":"e737d85441f9167d86a15384009e71a2bc190913298c67219b1d45b3857a1e51","dev/sysml/captures/WeaverViews-streamAdmission.json":"48f7b17066ac2d1c5cfbc0fc9f2557301cc4b1dd1c91cec5ca38d5dfa02dd840","dev/sysml/captures/WeaverViews-zeroTrust.json":"366c70992a29e424dbe37c462d3e7f5481cc78a240f96ec1d459a4107fa28edd","dev/sysml/ControlActivation.sysml":"78bc6792c3a64ee54210720d3d88c1984b5c876d3a0647b6829bf904a811014f","dev/sysml/CorrespondenceReaderView.sysml":"24b811c00528feaab3547d5db3b7fada290ff89478ac2be0a1d252d8ea1e5828","dev/sysml/ExecutionReaderViews.sysml":"88f690ed1fed91f63f7571d14bf5d7c1c8d14ee3b8d1d17ae333dfd7a6176df3","dev/sysml/FloorReaderViews.sysml":"93401ba5b2009dd54614f7e5aff81d91a20085efbb77b3a143726ffdea16592c","dev/sysml/GatewayArchitecture.sysml":"dbec3964b7873ed0633964b05d1ba1ee828050aed35a3066858d0c38893f2642","dev/sysml/PolicyEvidenceDesign.sysml":"6a7d738b004be62e7412ea68080944f8cb6fb3aea785258efaefc2efc1c4e0e6","dev/sysml/ProviderRpc.sysml":"60a7ae2140742902a487dd29565d543591a1d080eeef37745241e142df101cc0","dev/sysml/ReaderDesigns.sysml":"4df8352980f9727b85a26533dc5ebfd67730540359d553a17d562574f3ea2529","dev/sysml/ResearchReaderViews.sysml":"cb10ed4ab79e911197834a8102e8a84986c567a358098e36d234d15b9c5acaec","dev/sysml/StoragePersistence.sysml":"b6b58b8802a557a7f3af787c2e7875be64865169ca3fd7e9973b13f6c3dc792d","dev/sysml/StreamingExecution.sysml":"d0d4d92300fba2b908ace30d9065cb2bac1d86f3b7c98219c1853a30f3110e85","dev/sysml/WeaverExecution.sysml":"9bb74725a7ede555fa9168ba1de95cc0b9e780f4769ebcdcbc5e7b659b8c6f9a","dev/sysml/ZeroTrustRefinement.sysml":"7cbec57110f03ed68469a1f49cb2046769516b09a6eb1b9433d866161bba6a82","docs/10-19-llm-gateway/10-routing-and-inference/10.02-llm-routing.d2":"513cad143cde846a9393bb5020dc4843caa1bb844204d3d0c13d1b5ada5efc70","docs/10-19-llm-gateway/10-routing-and-inference/10.05-route-execution.d2":"7c3ff8609c24983d0b27511756d8c5c04d0dc2cf5c973fc7012eaa0acda421e2","docs/10-19-llm-gateway/10-routing-and-inference/10.07-provider-egress-window.d2":"3c9c7c67296700d3b08cea62dddd5bdd011e7bafd61c2b4ecf1e38c32a94d6e7","docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2":"ae2cb959a5c54c205f8483d7d8dbf5da42fe89b64aff557789b6e9d682bcfdd2","docs/10-19-llm-gateway/11-attempts-and-failover/11.02-attempt-ledger.d2":"5438329d7af60e9596b5fe4519b04a27a7c36ce1d1dc1aa5442db6df7167cd8e","docs/10-19-llm-gateway/12-semantic-contracts/12.02-semantic-contract.d2":"8560ac03652d2dfb8aeb7797c0e3b61031e49f9a3276d3207c8758a32037c530","docs/10-19-llm-gateway/13-authoritative-scope/13.02-authoritative-scope.d2":"e5950b420b85e30891bdb2264c7fad7ccd9ec9934b6175906d592d683b3a844c","docs/10-19-llm-gateway/14-registry-publication/14.02-registry-publication.d2":"9153743fc734fb044f94a4d22175fbe963f0f15f02598143dfbd7a06cd880177","docs/10-19-llm-gateway/15-recovery-cas/15.02-recovery-cas.d2":"c5de2f6cb52b0450361b2ed0523f647bdcad1fc43d410231f91ae86aee450859","docs/10-19-llm-gateway/16-policy-publication/16.02-policy-publication.d2":"4be00575666b7ada7185a30e553b42b9c36fe9109ce89df3d0dbb4b30ac10cab","docs/10-19-llm-gateway/17-policy-continuation/17.02-policy-continuation.d2":"4108a821aba5a2de1ffebc59b9e0d9180130bb3f598ac2130d59a83e8eca571f","docs/10-19-llm-gateway/18-canonical-registry/18.02-canonical-registry.d2":"f3b44cf54b006df34b528075bbc54742963a53e2afd4cbee435f81095b59b800","docs/10-19-llm-gateway/19-multi-key-registry/19.02-multi-key-registry.d2":"c44a2569dec8ae1fab46acb1ddd58f8b468e7ea7b11136c120a6bf2b042cf8b7","docs/20-29-execution-authority/20-result-projection/20.02-result-projection.d2":"696df32a9d705c6915bcc43a33616126cdce61ce5af0ae198c0dca5bc898d645","docs/20-29-execution-authority/21-join-enqueue/21.02-join-enqueue.d2":"430f46389111827b9f0ad5c9c3193366729fffe917ef18a5bfa0ec8238f6ab02","docs/20-29-execution-authority/22-executor-offer/22.02-executor-offer.d2":"0d93c13abcc1bd79afb32e6ae8a965cc5ec3b0c30fc1958f2f212e12b5e4b65a","docs/20-29-execution-authority/23-execution-reconciliation/23.02-execution-reconciliation.d2":"14c698ad47a243d46d788ab3494b1ad22ae7f14a163140eb6b4f5e8e071c6269","docs/20-29-execution-authority/24-account-commit/24.02-account-commit.d2":"10d6a5116d2c8be77ce7f27312d9d49ad832645c6748bb7bd68bb6942055990e","docs/20-29-execution-authority/25-wal-activation/25.02-wal-activation.d2":"9ebcd14701116e583157282a1678a6f1e0fe70e1ee4b9b7e038b520d4392ce05","docs/20-29-execution-authority/26-checkpoint-truncation/26.02-checkpoint-truncation.d2":"c5c1a35a16fe9b33029169b16d4c0af113f49e665eed0074ce524fc7a15bdb77","docs/20-29-execution-authority/27-manifest-switch/27.02-manifest-switch.d2":"c4de2ef519af25b2c41194df561860ad0236b0309b3178b388204c29cebf9f41","docs/20-29-execution-authority/28-append-handoff/28.02-append-handoff.d2":"f7646793e8540ec5f1e587d5e13deaf16d166180f80107ac8f9c904ea5c9372c","docs/20-29-execution-authority/29-admission-floor/29.02-admission-floor.d2":"0b9794f3d5fdfc7dcdbb519426eecf7e6ec6cb707de5017387c9aa47208ea385","docs/30-39-assurance/31-protected-signer/31.02-protected-signer.d2":"bc787086ae26a1a6cd56e51a2b4182c86e476f13e28ed1f5d80363b1d827e013","docs/30-39-assurance/32-key-boundary/32.02-key-boundary.d2":"1b616363aa68166988cc1d09404d637da406f048b9647676ec5f42d15f1762ca","docs/30-39-assurance/33-device-isolation/33.02-device-isolation.d2":"f4b086efce29484b70d4d4b2c04dad3887976d69187c25234e734e90260a6c7c","docs/30-39-assurance/34-floor-decision/34.02-floor-decision.d2":"78e2de9f044edb41944a56c1c8c8251a9cacd3470cf73c16b87f5ba100139a04","docs/30-39-assurance/34-floor-decision/34.04-floor-recovery.d2":"296d821eae11d4b77a552ae21d91eadcddcf032a15989dd35490128397044203","docs/30-39-assurance/35-intent-continuation/35.02-intent-continuation.d2":"08475ba17d7c98911a7db912041b669d049c75315c861322f72a5b50a471df55","docs/30-39-assurance/36-gateway-head-cas/36.02-gateway-head-cas.d2":"51669df10ec208197e690f656b962b259959af5f225243b62e5ff6bbea5637a5","docs/30-39-assurance/37-broker-consumption-queue/37.02-broker-consumption-queue.d2":"1ad636df3ba980d5f25b1a330c00c8b21f152958fe7c86617736e1b1f85a1ed8","docs/30-39-assurance/38-logical-range-recovery/38.02-logical-range-recovery.d2":"8ed5e1adc741da6852d027828993a83816cadb0c7bc1732bfaf121b2a64878d3","docs/40-49-admission-coordination/40-source-join/40.02-source-join.d2":"b8815cf59a1be49a4657b6ec3857d39e6d7d39ab4bb3ed44521c71ffe0ec5cee","docs/40-49-admission-coordination/41-source-custody/41.02-source-custody.d2":"feef18f62d537d4eb0659c0f1d719218df1a3eda506c9468b59423b151550bd7","docs/40-49-admission-coordination/42-custody-publication/42.02-custody-publication.d2":"24f019e8633cc816f7488e3f65384d2dea96ac8a3685714665a47bc6144b1e5c","docs/40-49-admission-coordination/43-caller-custody/43.02-caller-custody.d2":"6352167e4d3427fd9a66befb74fb3eebf91a127c5e82ecff8312b24178d5117f","docs/40-49-admission-coordination/44-incarnation-issuance/44.02-incarnation-issuance.d2":"215f52c84c9f41c36352f8b6da8b4670f1b375672cfc9efdf6a8bd1df95c946e","docs/40-49-admission-coordination/45-bootstrap-invitation/45.02-bootstrap-invitation.d2":"9e019de8289428a97580fe66ccefc6b9d0a43c1bac07433d2f29596f4d407401","docs/40-49-admission-coordination/46-beneficiary-registration/46.02-beneficiary-registration.d2":"322b848fdd67ea88c99b509cb5d913d7a5023e327edea51f16f44816356d81ce","docs/40-49-admission-coordination/47-enrollment-credential/47.02-enrollment-credential.d2":"ea0aa0bed915bea42d3d65c8f6572f799eb63d0aee1018b75803e61ef034d303","docs/40-49-admission-coordination/48-subject-authority/48.02-subject-authority.d2":"9f707fbc6e5ba8933a0e4d9d057f013c5764afc503f819288f628d3f9709f88d","docs/40-49-admission-coordination/49-routine-routing-config/49.02-routine-routing-config.d2":"7fa18b652ba97e8fe66f402a9a85d65740db9d3ffadff7890db7d72826c498b6","docs/50-59-research-program/51-qualified-semantic-slice/51.06-semantic-gateway-slice.d2":"d63df655a635fccac3c92eded92c039a3f079c24fa2b7a2fd0dc1f3fabd3c0f5","docs/50-59-research-program/52-committed-profile-binding/52.04-committed-profile.d2":"3ea30976830c607bf8cec62cbabc4291c384bd5f368049a45777f6f981d87d6e","docs/50-59-research-program/53-gerbil-exit/53.04-gerbil-lifecycle.d2":"b7b623664edc6e86efe62eeee7f5977dc207f0cb12e40cb6f0e77e38160695de","docs/50-59-research-program/54-dynamic-gxi-exit/54.04-dynamic-lifecycle.d2":"d4d410dd8cb10de6d3526b54ac7f96731d2f2a94dd9763aad96a0926608e251c","docs/50-59-research-program/55-dynamic-gxi-paired/55.04-runtime-boundary.d2":"573b248a6b7ce2d7eee1e70a469c54e4f195c4894ec7b0f61c8406fae843eccc","docs/50-59-research-program/56-gambit-image-closure/56.04-locator-boundary.d2":"0c45ee11d269b0cab8998c7fc3432ec851b9390b7530486225134b261d8d7de8","docs/50-59-research-program/57-runtime-implementation/57.03-runtime-boundary.d2":"193d22a5bd9e4b23260334d085df8aa5ec19c349f13cd9f56eaa26fe54f7e3ac","docs/50-59-research-program/58-streaming-execution/58.03-streaming-runtime.d2":"76ea49c83b4b36af1e775f80475d40747640b80a330434bf86635e255e84ef14","docs/50-59-research-program/58-streaming-execution/58.05-range-progress-recovery.d2":"aef20c8ad7d7420a65422add6d9fb635bdbe32e42e49427d3179bf20499ae4cd","docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2":"6f4e8218ea262e35efaebaf8cc2f96345b2ef1e7e9c1a6b12b68290dd99c683d","docs/50-59-research-program/59-provider-rpc/59.21-verification-ownership.d2":"e035ae7e56ee5e6498f131ed62f4792547c1e716aa5ed29865b333f54665e8f1","docs/50-59-research-program/59-provider-rpc/59.26-semantic-execution-ecosystem.d2":"50c091b094125693e2debe73599a63405849f1f55ab3658030674692c9334e14","docs/50-59-research-program/59-provider-rpc/59.30-governance-adapter-acceptance.d2":"88cbbd45e63358bb45a58fb27f85e275b9cc9fb3d3aee6af19eabed0912545d2","docs/50-59-research-program/59-provider-rpc/59.43-floor-transport-owner.d2":"36c4d6b561332ab30deb464a92bb4c2f02ceed5c8a1ca66617f72b6086b2c555","docs/50-59-research-program/59-provider-rpc/59.44-cloud-rpc-arrow-boundaries.d2":"fe0ac2220e04f6ccea851247ecf8ae1cab4ec8c8ba8744010c478992c233ebed","docs/50-59-research-program/59-provider-rpc/59.45-slow-consumer-zero-trust.d2":"e36cf58a239a2d9f0c99789bb7484de4e26180a8f941970540f72b530a79d813","docs/50-59-research-program/59-provider-rpc/59.46-functional-security-frameworks.d2":"e541b969352e8149e71e5b539988f9955b525e5e5ba3e7e7270bd4a98fbe19f5","docs/50-59-research-program/59-provider-rpc/59.47-property-testing-framework.d2":"f66ed065dcf955a233968ca295517c642be30dad9b24e23a781fe34e4bed45d9","docs/50-59-research-program/59-provider-rpc/59.49-policy-proposal-barrier.d2":"3a8559bb22f812075d9d7de4a397978995d06c32ed22e9415f990413551aebb6","docs/50-59-research-program/59-provider-rpc/59.50-parent-contract-and-replay.d2":"2db3983f56e938c927b68077551573c8e86362da892f47890459ab7b3f929c64","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-architecture.d2":"10e92e79b69f4b0813551dd2ddadc5ad225b7b0fa8374ed7015b7f2fe66bb6e1","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-contract-refinement.d2":"204c9e20d9027b7a38bf2a964da9a7cadb92744561fa9f1eb3fa29d00f4fa386","docs/50-59-research-program/59-provider-rpc/59.52-reviewed-publication-cas.d2":"4e0998e61717d5441e242cde0dfc52198312b67b63f0ce8b0425a423d1b88a24","docs/50-59-research-program/59-provider-rpc/59.53-artifact-registry-recovery.d2":"f7083a48413d41ad99e7191281bd6e74a92b33c7cc1f4f2f9ae322bb1405088a","docs/50-59-research-program/59-provider-rpc/59.54-source-incarnation-authority.d2":"1e55c0487f01d70462e8df6b46eff9e799b0dc592c0e780c759fa602e3d84444","docs/50-59-research-program/59-provider-rpc/59.55-evidence-reviewed-publication.d2":"c66435372642f7a93ca7fc6f78c2abcbc364a4dde447d10dcc4b2b21ccc06456","docs/50-59-research-program/59-provider-rpc/59.56-runtime-assets-and-authority-floor.d2":"c675469701bb6994fed1976d1e90d01dc1cc4e416a6788f865494fa3243d32c1","docs/50-59-research-program/59-provider-rpc/59.57-schema-bound-candidate-replay.d2":"5ca15af556e0a4ba5bdf1742cf81182ad72e7f51b2eb63352b839e068a7ad7d2","docs/50-59-research-program/59-provider-rpc/59.58-independent-source-recovery.d2":"4b21999b3554be15374448f36ffbccf517b32784a65cadde0f4c1eb8308da377","docs/50-59-research-program/59-provider-rpc/59.59-retained-root-and-recovery-coverage.d2":"37fdf1d3dd01f087434a6108b43a5657d7aecf79a2b9e60638d70eb0b1a4984b","docs/50-59-research-program/59-provider-rpc/59.60-persistent-source-key-custody.d2":"d27df3a14df5d57ad725c1455c82a4ab5bad45b78acea8cd1a76e59958b710eb","docs/50-59-research-program/59-provider-rpc/59.61-authority-bound-replay-pair.d2":"bd4962775564848a90ec49439301cf0cdfbaa4018956344e809f5b318bea6ccd","docs/50-59-research-program/59-provider-rpc/59.62-burn-exposure-recovery.d2":"fab4ea6d0981d75dd4c704f302268f3c5af0898e299e8e0fb38b34d07200b22c","docs/50-59-research-program/59-provider-rpc/59.63-mrr-admission-contract.d2":"ed3c604e0d350049f00528c7117675a7db751b3d6683719b03be116bcf49d5c5","docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.d2":"7164874fdbeec99f2185e1091f759466a68a3b7d9b239db6a503f16383fce50e","docs/50-59-research-program/59-provider-rpc/59.65-turso-concurrent-admission.d2":"0ade3ea326e2066ce908129e383b7e0f371a429710ed0a0bad30ddcfd61f034e","docs/50-59-research-program/59-provider-rpc/59.66-bounded-writer-reuse.d2":"9390a3c12f06c2f33e3df99088dc39de92d3bccc971ddf5a632910515a67623e","docs/50-59-research-program/59-provider-rpc/59.67-writer-owner-lifecycle.d2":"c28559ccf38b2f3320d84bbc0ffc6133e2708081e95bff39d5ed75d064287bde","docs/50-59-research-program/59-provider-rpc/59.69-hot-path-cost-boundaries.d2":"e5789625590fab63bc3635627b7e20ac41f64b8f40cbeee84d51a85f27ab31f1","docs/50-59-research-program/59-provider-rpc/59.75-complete-entry-and-output-contract.d2":"d667501bc15d6c31d986994f641d8d38f63c1d910784e6852e596c24c4e4c7c7","docs/50-59-research-program/59-provider-rpc/59.75-package-linkage.d2":"bc655ae71cc46e0d5b7f42637b78530f262c3142394485e2a9ba31f6516a0a10","docs/50-59-research-program/59-provider-rpc/59.76-embedded-tooling-and-darwin-io.d2":"87655d7c6d81c1ab203f886930f1630003e006c0edb71f90ac3ca23a0cb91845","docs/50-59-research-program/59-provider-rpc/59.77-mrr-turso-storage.d2":"72a4dceeb20cca337276f64537d47dbbd2ac0ce359a7a63997090e6476a40c96","docs/50-59-research-program/59-provider-rpc/59.84-quint-preparation-and-completion.d2":"17f485d7c541506c42003ebba887705ea61972f00c9498aa3c0d153a33b02922","docs/architecture/08-diagram-catalog.org":"353a4296584381207513468ef291e7e1aefdcd6f9f2b854c92be90aab47577ea","docs/architecture/diagrams/00a-readme-overview.d2":"1e6119c9d5b2d8a40d3bec0c8add35e8c078dd739e46fcf45c589b8125c7c46f","docs/architecture/diagrams/00c-gateway-runtime.d2":"c1d93cc1f635803872e3349c89b5127145bdcdd2b85e9a48f83d63f0bda439da","docs/architecture/diagrams/00d-zero-trust-overview.d2":"0d3d1a5de0967db2331b9be81468cee1b7cb1d1d98966c5e541e4fc24023f2e6","docs/architecture/diagrams/01-system-boundaries.d2":"69b4622c26b18a8518d46f79db8ce281c756a16f7f1a46977272086bf4dc38e0","docs/architecture/diagrams/01-system-relationships.d2":"dde40fac8667b79a070fda14ebd892f1f1e7c1217726595179b541c855f80c2c","docs/architecture/diagrams/02-admission-sequence.d2":"97077cb16cd4457fe14092caeb4bc8cf2912d434763a08fcf350cd6a4c2b2c74","docs/architecture/diagrams/03-attempt-state.d2":"e696fc0f1d63f58100405852e88e8a7dfb1a625e43be398f3bb54bbc1d90e13a","docs/architecture/diagrams/03a-attempt-observation.d2":"6b387ec7fbcff7d5e3e129bad7ea9590afe0324800a5a13bf7a89377ad86c387","docs/architecture/diagrams/04-consume-timeout.d2":"2ccfe8d033069e0d891531f3b5afef4febf21b2722209a612454d14321cac940","docs/architecture/diagrams/05-fencing-boundaries.d2":"1103ed75ac615b1a2f8239c0321d046a5a87acfa235d5042d8a529e23acd7483","docs/architecture/diagrams/06-source-admission.d2":"4d20817291c5de93b7f97366e6cb1b4af954f22de1ebcb3012c139a4b9dbd82c","docs/architecture/diagrams/07-post-claim-outcomes.d2":"63258620c15c2f52963dcdba33b4ac82cd12aadd1c2de005cd029655493493c1","docs/architecture/diagrams/08-code-as-policy.d2":"fc2263ff1ae000055e6054b89beee60f53b9621707510354c34ef45057889676","docs/architecture/diagrams/09-claim-wins-race.d2":"9eff775ddac29c47acd2c0b69fb1ff98ba9a20943da970c2804e270979555c41","docs/architecture/diagrams/10-commit-dispatch-sequence.d2":"fa5d56c49bc3f590c88cf7c3b63e180afd2d2a39fca878d1515917077ff1687a","docs/architecture/diagrams/11-zero-trust-assurance.d2":"ea93840da2ff4bdac59349f5ad7a56cee5506600283d0c364c53275dde0b5b48","docs/architecture/diagrams/12-execution-correspondence.d2":"1dd66ee8c517fd9c6f2f4b1700aeec3e620d699fbe9eeee20df8e05a7f1decb0","docs/architecture/diagrams/13-policy-to-execution.d2":"4bb05b74c3bc0ca997c5e5035ddc949fa374db3ff49bf2104a6c9753e12be3ef","docs/architecture/diagrams/14-adapter-broker-boundary.d2":"b855fa0482a5524226354b26bc8d7ecef0daf2ab1cab54c1783eba0ff29fab01","docs/architecture/diagrams/15-stream-message-authorization.d2":"cedf1c545a853ec2a9ae51bea928b04376d192f1a4c2af117fa54f475ad541e0","docs/architecture/diagrams/16-authoritative-spent-state.d2":"201bd9fe5eb6101543d939e3d83aca646e2b07c13ff1e3c56779571a0cd1172e","docs/architecture/diagrams/17-logical-message-observation.d2":"2333ad147295ead60ed6a92dc824cf6f5769f3828eff1e0cdf58e50aace7b1e1","docs/architecture/diagrams/18-shared-identity-budget.d2":"5ab4992fd8b6a6abf518fb0bbc8c2c8ad8b920d0be74a6e734d846319252ffa7","docs/architecture/diagrams/19-finite-domains-and-migration.d2":"b72b451d0bb97de46831e4b266d8fdd22d59e7d54db99446d53549f081a008e2","docs/architecture/diagrams/20-anchor-recovery-and-egress.d2":"9479271410f1bb57f92106a1d91ec73c73872568d9fcda55cac5aa64b89e5c9f","docs/architecture/diagrams/21-composed-journal-transport-lifecycle.d2":"0fffe555ee4c2c1222c97eebd24ca9b0df91a4d3ec118300ae3b88240004c3c8","docs/architecture/diagrams/22-finite-stream-manifest.d2":"60b33eb6d06aeaa1027546a1fc9d6c07069c3cd3c7d23df8ff8d63a341afe2ea","docs/architecture/diagrams/23-driver-completion-recovery.d2":"271963db2cd881bb82e164bb1544c7bcf311e1781f20170d858ccb65a596d8f5","docs/architecture/diagrams/24-writer-settlement-closure.d2":"ea1930326b0073e7fabd8b64ef3ffea781f1aef60db0d942f9ab14f1150296e9","docs/architecture/diagrams/25-settlement-anchor-recovery.d2":"8904bfcda525de21b48ea8f2db8d12aaa27e85818ccde43fb545851dc522ba3b","docs/architecture/diagrams/26-gate-consumption-persistence.d2":"42e676634ecb40cfb2dee06db1f5497d0e58c05f30097618c3852eb946992f0d","docs/architecture/diagrams/27-anchor-commit-broker-fencing.d2":"5c2ae36987b00655bbcdba36352e03b61765739ad2f3fc80a561ff0d325a9461","docs/architecture/diagrams/28-anchor-configuration-prefix.d2":"1ac0eeb3c76f5ae0ce3565d4469e50210786c3bc53c703a1a61d519dfa075512","docs/architecture/diagrams/29-quorum-durable-promises.d2":"2e4a24c3fae49e710d5afc31d4681a9efc8c2e8af3fa58a0957ede05fe7c0255","docs/architecture/diagrams/39-shared-execution-exposure.d2":"2c08f5b3d4531a7be2aadec8f1ff9d4476495418e94e84c1ff643583ac991ce4","docs/architecture/diagrams/assets/agent-request.svg":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","docs/architecture/diagrams/assets/bounded-write.svg":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","docs/architecture/diagrams/assets/budget-ledger.svg":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","docs/architecture/diagrams/assets/components/activity.svg":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","docs/architecture/diagrams/assets/components/book-open.svg":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","docs/architecture/diagrams/assets/components/bot.svg":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","docs/architecture/diagrams/assets/components/brain.svg":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","docs/architecture/diagrams/assets/components/circle-question-mark.svg":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","docs/architecture/diagrams/assets/components/clipboard-check.svg":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","docs/architecture/diagrams/assets/components/coins.svg":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","docs/architecture/diagrams/assets/components/database.svg":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","docs/architecture/diagrams/assets/components/file-check.svg":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","docs/architecture/diagrams/assets/components/fingerprint-pattern.svg":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","docs/architecture/diagrams/assets/components/message-square.svg":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","docs/architecture/diagrams/assets/components/rotate-ccw-clock.svg":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","docs/architecture/diagrams/assets/components/rotate-ccw.svg":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","docs/architecture/diagrams/assets/components/route.svg":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","docs/architecture/diagrams/assets/components/send.svg":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e","docs/architecture/diagrams/assets/components/shield-check.svg":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","docs/architecture/diagrams/assets/components/ticket-check.svg":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","docs/architecture/diagrams/assets/components/waves-horizontal.svg":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","docs/architecture/diagrams/assets/components/workflow.svg":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","docs/architecture/diagrams/assets/go.svg":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","docs/architecture/diagrams/assets/kubernetes.svg":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","docs/architecture/diagrams/assets/model-catalog.svg":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","docs/architecture/diagrams/assets/model-provider.svg":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","docs/architecture/diagrams/assets/permission-check.svg":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","docs/architecture/diagrams/assets/route-choice.svg":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","docs/architecture/diagrams/assets/rust.svg":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","docs/architecture/diagrams/assets/task-contract.svg":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","docs/architecture/diagrams/assets/unknown-hold.svg":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","Project.sysml":"c0c96eba7c5dbce2fde3c5c0f13353acfb1291eee59bcb8eb2ee1860f527aba4"},"rendered":{"observation":{"canvas":{"x":0,"y":0,"width":980,"height":686.21875},"subjects":[{"id":"n0","role":"default","x":40,"y":311,"width":278.65625,"height":122.59375},{"id":"n1","role":"default","x":350.65625,"y":311,"width":278.671875,"height":122.609375},{"id":"n2","role":"default","x":661.328125,"y":311,"width":278.65625,"height":122.59375},{"id":"n3","role":"default","x":40,"y":511.609375,"width":278.65625,"height":122.59375},{"id":"n4","role":"default","x":350.65625,"y":511.609375,"width":278.671875,"height":122.609375},{"id":"n5","role":"default","x":661.328125,"y":511.609375,"width":278.65625,"height":122.59375}],"relations":["edge:0","edge:1","edge:2","edge:3","edge:4"],"headings":[{"role":"title","x":32,"y":32,"width":916,"height":63},{"role":"question","x":32,"y":95,"width":916,"height":56},{"role":"note","x":32,"y":167,"width":916,"height":48},{"role":"note","x":32,"y":215,"width":916,"height":48}]},"readability":{"minimumTextSize":24.14725378787879,"samples":23},"bounds":{"objects":{"x":32,"y":291,"width":916,"height":363.21875}}}}Commit a group. Gate every frame.?How can a shared snapshot stay safe during revocation?One native outcome qualifies the group.Revocation closes delivery; unknown retains the hold. -Rust / closePolicy + OAuth + domainsKeep every pending ID +Rust / closeRun edits / origin cutShared edits / shared cut diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.11-lifecycle-footprints.org b/docs/10-19-llm-gateway/10-routing-and-inference/10.11-lifecycle-footprints.org new file mode 100644 index 00000000..4da37961 --- /dev/null +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.11-lifecycle-footprints.org @@ -0,0 +1,201 @@ +# SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +# +# SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +#+title: Lifecycle write footprints and shared admission +#+language: en +#+options: toc:2 + +[[file:10.00-index.org][Routing and inference index]] +[[file:10.10-snapshot-publication.org][Published snapshot design and previous evidence]] +[[file:10.09-provider-delivery-join.svg]] + +* Complete deciding view and concrete dependency audit + +A transaction's read/scheduling footprint is not its invalidation footprint. +The existing scheduler still covers original origin, shared budget/history and +API-key/user/tenant identities. This design narrows only the exact lifecycle +write's authority closure and revision publication in MVCC. Native transaction +isolation, shared read guards and Cedar evaluation remain unchanged. + +| Path | Actual writes | Observation by another canonical origin | Required invalidation | +|------+---------------+-----------------------------------------+-----------------------| +| New provider admission | Original claim/reservation, task held, budget held, domain history, quote and three quota reservations/totals | =domains::evidence= reconciles every original member; =exposure_manifest::projected= reads provider digest/reserved/plan ceiling; quota checks sum reserved minus signed releases. These change. | Keep the complete shared scope, including its pending barrier. | +| Repeated admission | The existing logical digest is checked and plan data may update | Do not assume a no-op or infer dynamic SQL effects. | Keep the existing conservative complete scope. | +| Queued-to-consumed transition | Only =provider_runs.state= and =target= for one family/node | The cross-origin retained-member projection excludes state and target; neither held, original manifest, history nor quota sum changes. | Close and advance this original origin; keep full transaction read/scheduler custody. | +| Affine dispatch burn and guarded write acknowledgment | Only =provider_runs.dispatched= for one family/node | The cross-origin reservation projection and quota reconciliation do not read this field. | Same original-origin closure. Ambiguous native outcome still seals the whole owner. | +| Terminal observation | Only =provider_runs.state= and optional =provider_terminal_usage= tokens | Another origin's claim/exposure checks read retained members and its own live run, not a peer's terminal state or raw usage. Raw tokens are not signed settlement. | Same original-origin closure. No refund, claim reset or reservation mutation. | +| Independent metering application and settlement | Application ID, account/hold/balance and quota deltas | Shared retained exposure and quota sums change. | Full existing shared scope and atomic application. | +| Policy/review/pending, OAuth/witness, migration, profile and unclassified SQL | Existing semantic inputs or unknown write set | May change the complete actual view. | Existing broad/global closure and currentness rules. | + +The hold books maximum original exposure at admission. Starting that reserved +run does not add the exposure again; raw completion does not return it. A new +allocation or independently signed settlement changes that shared exposure. +This is the architectural reason peer progress can preserve a qualification. + +The closed concrete read set includes schema/entities/context, actual target, +profile and original task/claim, cross-origin digest/reserved/ceiling bijection, +shared held/history and three quota projections, quote/formula, OAuth validity +and witness, source pending and fencing. It excludes only the peer lifecycle +fields listed above. No monotonicity of an arbitrary Cedar Policy is assumed. Distinctness means +different authority-bound original origin IDs, not different caller labels or +aliases; same-origin work always remains in the same invalidation lane. +Adding another cross-origin dependency on peer run state or raw usage requires +retiring this classification before exposing that input to Policy. + +* Authority protocol and recovery + +A sealed =OriginLifecycle= token can be constructed only in the provider owner. +The audited consume, burn, guarded acknowledgment and terminal paths use it. +Admission does not. =Impact::Origin= closes only matching origin readers and +advances that origin revision at known commit; snapshots still compare all six +namespace revisions and the global revision at the final one-use owner turn. +A peer can therefore keep its exact qualification during a local transaction. +Same-origin frames are closed while it is pending and retired after commit. +Whole-store readers use an independent aggregate semantic revision: every +semantic commit, including origin-only changes, retires that whole-store stamp. +Using only the global publication revision for a whole-store reader would miss +a committed local update. Domain readers instead retain global plus six +namespace revisions, avoiding accidental invalidation by that aggregate. +An origin-only transaction cannot issue a delivery receipt or reconcile external +witness IO. Generic scoped writes remain fully invalidating by default. + +Read custody is still the complete conflict set. Root discovery, native +transaction, claim/held/history reconciliation and scheduler fairness are not +relaxed. A migration or source cut racing discovery retains the existing fenced +rejoin and global barrier. This separates unnecessary delivery invalidation +from necessary serialization of shared native reads. + +WAL currently issues global authority scopes and retains broad invalidation. +Its immediate native writer and snapshots remain one conservative profile; +origin-only publication is not mixed with a snapshot that lacks domain stamps. + +A known native commit with a lost RPC acknowledgment remains the original +consumed claim. Restart cannot call a provider again or infer zero exposure +from zero observed upstream calls. A known absent consume, in contrast, leaves +the queued original and its retained reservation: it may resume the same claim +under current authorization after restart. Neither case refunds the hold. +Actual native commit ambiguity seals the owner independently of write footprint. +Old workers, owner replacement and global revocation remain final-use barriers. + +* Models and executable acceptance + +=ProviderLifecycleFootprint.lean= proves complete-view equality for every other +origin over arbitrary family types, preservation of arbitrary predicates on that +view, and preservation of every original hold. Origin-only commit preserves +peer stamps and changes its own. A shared-admission lemma demonstrates why held +changes cannot use that exemption. The actual imported SPEC final-use and finite +shared-domain contract are reused through =DomainMigrationComposition=; Host +SQL/read-set, identity, native durability and transport mediation stay explicit. +A peer's dispatch may change the global execution ledger. Composition binds the +preserved observer projection to the CURRENT SPEC actual state, while the +current reachable execution chain proves global budget and unique-use bounds. +It never identifies the changed whole world with an old cached world, nor +derives every Host premise from projection equality alone. + +=ProviderLifecycleFootprint.qnt= explores concurrent local/shared tickets, +rollback, unknown native results, revocation, migration and old-owner recovery. +Its unsafe local-admission and missing-own-terminal-cut variants are executable +counterexamples. It models cuts independently from native read scheduling. + +Rust proptest exercises same/different origins, WAL/MVCC, a safe broad-cut +control, consume/dispatch/terminal and real shared admission. An observer polls +actual acknowledged frames before and after real native commits. Cross-origin +MVCC local writes preserve both exact transfers; own-origin or shared writes +block them. Held/history and consumed original claims are inspected afterward. +The property also polls a third exact frame from inside the live request-effect +callback while full native read custody is held. Go drives real mTLS/gRPC crash/ack-loss tests and positive known-absence recovery, +using testing/quick rather than a script or a replacement in-memory engine. + +The paired benchmark reuses the existing immutable-image driver. Both arms +prepare and publish identical four-range manifests, thirteen frames and four +native final-queue groups. Only broad lifecycle closure versus origin-local +closure differs. Each shared/disjoint and injected/no-injection arm retains +128 completed streams at concurrency four, all frame observations, all original +holds and the original deadlines. Preparation, native commit sums, renewal, +final owner, Tonic delivery and Go receive are reported separately. Neither +independent percentile addition nor an unchanged-view subset proves a complete +path below one millisecond. Low-background qualification requires actual host +evidence; interference is retained rather than relabeled as idle. + +* Local validation evidence + +| Gate | Checked outcome | Boundary | +|------+-----------------+----------| +| Lean / SPEC | Complete current Lake project builds; the declaration closure contains 3,935 declarations. Peer-view and whole-reader lemmas compose with the imported final-use/domain contract. | SQL/read-set adequacy, canonical origin identity, native durability and transport mediation remain Host premises. | +| Quint | Seventeen named schedules and 2,000 seeded runs of 80 transitions pass. Counterexamples reject narrowing shared admission and skipping the same-origin terminal cut. | Bounded exploration complements the arbitrary-origin Lean proofs. | +| Rust | 54 ledger library tests, 128 real-Turso integration/PBT tests, 29 broker and 28 server library tests pass. The request-scope property additionally passes after extending it to three exact frames. | Three server fixture entrypoints are intentionally started by Go rather than ordinary Rust test selection. | +| Go | Complete uncached race suite and 21 real TLS/gRPC fault/property groups pass. The added group covers both journals, known absence, commit loss, crashes and old-worker restart. | Calls are counted at the actual provider; zero calls are not refund evidence. | +| Static gates | Workspace/all-target/all-feature Clippy and ASP deny checks pass. | No warning suppression or dependency change. | +| Views | The exact selected SysML/Design view passes upstream Library capture, Chromium at 830 px and the unchanged five-second, thirty-second and eighteen-pixel gates. | Selected-view evidence is not an all-diagram claim. | + +The first lifecycle property failed because the existing fixture explicitly +allowed only family f. The new test now publishes a separate explicit peer +Policy before either claim; the production Policy and old negative controls +remain unchanged. A second initial failure queried a nonexistent table before +fresh-store initialization. The independent observer now checks file/schema +existence without creating the database or modifying it. + +The older spent-claim assertion required exactly one provider call. Consumption +ack loss happens before any provider invocation, so the new assertion explicitly +requires zero while preserving digest, state, target, reservation, held amount +and the rejection of reconnect. All old users retain their one-call expectation. +The Go pipeline inventory rejected the newly registered benchmark until its +exact responsibility was added to the required set. ASP/Clippy found missing +public documentation and an unnecessary return; both were fixed at source. +All initial logs and the failing property seed remain in ignored local cache. +No failure was converted into a passing workload by changing a timeout or limit. + +* First same-image MVCC comparison + +All four complete cohorts pass frame/call/scope/hold accounting. Each arm has +128 completed streams at concurrency four, thirteen one-row Protobuf frames, +four native preparations and four final-queue transactions. All 13,312 frames +are accounted for. Control and candidate use the same immutable Release image; +only the test host's broad lifecycle-cut control differs. The production path +uses the sealed origin classification, not a configurable safety bypass. + +Every cell is full-domain control / origin-cut candidate. Scope waiting is per +scope, frame timing per frame, and commit cost is the per-stream native sum +before its P99 is selected. Independent percentiles are not added. + +| Shared roots | Injected pressure | Streams/s | Renewals/frame | Ack-to-Tonic P99 us | Tonic-to-Go P99 us | Rust-queue-to-Go P99 ms | +|--------------+-------------------+-----------+----------------+--------------------+-------------------+-------------------------| +| yes | none | 33.44 / 36.92 | 0.09615 / 0 | 13406 / 479 | 1509 / 1013 | 13.76 / 1.855 | +| yes | six workers requested | 24.61 / 27.38 | 0.09856 / 0 | 21660 / 2376 | 4077 / 3560 | 22.27 / 5.209 | +| no | none | 153.3 / 152.6 | 0 / 0 | 45 / 60 | 153 / 271 | 0.509 / 0.604 | +| no | six workers requested | 70.41 / 66.30 | 0 / 0 | 2222 / 1687 | 2880 / 2410 | 4.491 / 4.503 | + +| Shared roots | Injected pressure | Prepare wait P99 ms/scope | All-ticket wait P99 ms/scope | Commit sum P99 ms/stream | Stream P99 ms | +|--------------+-------------------+---------------------------+-----------------------------+-------------------------+---------------| +| yes | none | 15.64 / 11.05 | 15.64 / 12.77 | 5.741 / 4.416 | 198.0 / 186.0 | +| yes | six requested | 23.51 / 17.05 | 22.50 / 18.65 | 9.372 / 4.325 | 287.7 / 225.9 | +| no | none | 0.001875 / 0.001833 | 0.001417 / 0.001625 | 1.436 / 1.433 | 29.49 / 28.96 | +| no | six requested | 0.008834 / 0.002417 | 0.003167 / 0.002209 | 25.44 / 17.36 | 117.0 / 176.4 | + +The candidate has zero renewed frames in every cohort. The shared control has +65 and 76 renewed frames of 1,664 respectively. Candidate final owner-turn P99 +is 14.17--17.83 microseconds. The six-worker helper achieves 5.318 shared and +2.597 disjoint CPU equivalents; it is not a fixed six-core saturation bound. + +Ten low-frequency process snapshots plus before/after snapshots accompany this +run. Scheme/GSI/GXI and compiler or Node work appears in the surrounding host +window. Initial samples may include image preparation, which precedes timed +cohorts. This is shared-host evidence, not isolated low-background acceptance. +No foreign task was stopped, no sample discarded, and no limit changed. + +The structural prediction is accepted: irrelevant cross-origin lifecycle changes +no longer cause renewal, while native tests still block real shared admission, +same-origin changes and revocation. Shared confirmation-to-Tonic reaches the +local submillisecond target in the no-injection cohort. The COMPLETE path does +not: 1.855 ms Rust-queue-to-Go and 11.05 ms preparation waiting remain above the +requested target. A zero-renewal subset cannot erase those costs. Native read +custody still serializes shared transactions, and transport/host scheduling is +still measured rather than assumed free. + +The disjoint cohorts are a negative control for the dependency classification: +they already have no peer invalidation. Their no-injection throughput is +approximately unchanged; injected throughput and stream P99 regress in this +run. The design does not claim universal latency or throughput improvement. +The remaining low-background acceptance is kept open until a qualifying host +window exists; a model pass is not a performance pass. diff --git a/go/dev/provider_backpressure_test.go b/go/dev/provider_backpressure_test.go index 857ce42d..79571549 100644 --- a/go/dev/provider_backpressure_test.go +++ b/go/dev/provider_backpressure_test.go @@ -208,12 +208,17 @@ func drainStream(stream grpc.ServerStreamingClient[pb.ProviderFrame], encoding p } } func originalStillSpent(t *testing.T, f *fixture, before *pb.ProviderReceipt) { + t.Helper() + originalStillSpentWithCalls(t, f, before, 1) +} + +func originalStillSpentWithCalls(t *testing.T, f *fixture, before *pb.ProviderReceipt, calls int64) { t.Helper() if _, _, err := execute(t, f, pb.Encoding_ARROW_IPC, 2); err == nil { t.Fatal("reconnected RPC reopened original claim") } after := inspect(t, f) - if after.Digest != before.Digest || after.Events != before.Events || after.Held != 4 || f.primary.Load() != 1 || f.backup.Load() != 0 { + if after.Digest != before.Digest || after.Events != before.Events || after.Held != 4 || after.State != before.State || after.Reserved != before.Reserved || after.Target != before.Target || f.primary.Load() != calls || f.backup.Load() != 0 { t.Fatalf("original outcome changed: before=%v after=%v calls=%d", before, after, f.primary.Load()) } } diff --git a/go/dev/provider_delivery_bench_test.go b/go/dev/provider_delivery_bench_test.go index 210f9f00..bfd3af1a 100644 --- a/go/dev/provider_delivery_bench_test.go +++ b/go/dev/provider_delivery_bench_test.go @@ -32,15 +32,37 @@ func BenchmarkProviderDeliveryJoin(b *testing.B) { } func benchmarkProviderDeliveryJoin(b *testing.B, image string, shared, loaded bool) { + benchmarkProviderDeliveryComparison(b, image, shared, loaded, deliveryComparison{ + labels: [2]string{"single-range", "published-snapshot"}, + controls: [2][]string{{"WEAVER_TEST_SINGLE_RANGE_COMMIT=1"}, nil}, queues: [2]int{13, 4}, + }) +} + +type deliveryComparison struct { + labels [2]string + controls [2][]string + queues [2]int +} + +func BenchmarkProviderLifecycleFootprint(b *testing.B) { + image := wifImage(b, true) + comparison := deliveryComparison{labels: [2]string{"full-domain", "origin-cut"}, + controls: [2][]string{{"WEAVER_TEST_FULL_LIFECYCLE_INVALIDATION=1"}, nil}, queues: [2]int{4, 4}} + for _, shared := range []bool{true, false} { + for _, loaded := range []bool{false, true} { + b.Run(fmt.Sprintf("shared=%t/pressure=%t", shared, loaded), func(b *testing.B) { benchmarkProviderDeliveryComparison(b, image, shared, loaded, comparison) }) + } + } +} + +func benchmarkProviderDeliveryComparison(b *testing.B, image string, shared, loaded bool, comparison deliveryComparison) { b.Helper() b.StopTimer() const ranges, parallel, samples = 13, 4, 128 var arms [2]providerTailArm for i := range arms { env := []string{"WEAVER_STORAGE_JOURNAL=mvcc", "WEAVER_TEST_PROVIDER_TAIL=1", "WEAVER_TEST_PROVIDER_SCOPE_TRACE=1"} - if i == 0 { - env = append(env, "WEAVER_TEST_SINGLE_RANGE_COMMIT=1") - } + env = append(env, comparison.controls[i]...) arms[i].fixture = domainBenchmarkFixture(b, image, env, burstProviderSSE(ranges)) } var stopPressure func() (time.Duration, time.Duration) @@ -63,13 +85,10 @@ func benchmarkProviderDeliveryJoin(b *testing.B, image string, shared, loaded bo b.ReportMetric(cpu.Seconds()/wall.Seconds(), "pressure-cpu-equivalents") } b.ReportMetric(0, "ns/op") - for i, label := range []string{"single-range", "published-snapshot"} { + for i, label := range comparison.labels { arm := &arms[i] reportProviderTailArm(b, arm, label) - queues := ranges - if i == 1 { - queues = (ranges + 3) / 4 - } + queues := comparison.queues[i] reportScheduledEncoding(b, arm, label, ranges, (ranges+3)/4, queues, shared) reportDeliveryJoin(b, arm, label) arm.fixture.stop(b) diff --git a/go/dev/provider_lifecycle_test.go b/go/dev/provider_lifecycle_test.go new file mode 100644 index 00000000..55c8ea11 --- /dev/null +++ b/go/dev/provider_lifecycle_test.go @@ -0,0 +1,157 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build integration && !windows + +package dev + +import ( + "context" + pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" + "math/rand" + "strings" + "testing" + "testing/quick" + "time" +) + +func TestProviderLifecycleCommitRecovery(t *testing.T) { + for _, journal := range []string{"wal", "mvcc"} { + for _, mode := range []string{"control", "rollback-before", "crash-before", "lost-after", "crash-after"} { + t.Run(journal+"/"+mode, func(t *testing.T) { checkLifecycleRecovery(t, journal, mode) }) + } + } +} +func TestProviderLifecycleRecoveryProperty(t *testing.T) { + property := func(mvcc, before, crash bool) bool { + journal := "wal" + if mvcc { + journal = "mvcc" + } + mode := "lost-after" + if before { + mode = "rollback-before" + } + if crash { + mode = "crash-after" + if before { + mode = "crash-before" + } + } + checkLifecycleRecovery(t, journal, mode) + return true + } + if err := quick.Check(property, &quick.Config{MaxCount: 4, Rand: rand.New(rand.NewSource(293))}); err != nil { + t.Fatal(err) + } +} +func checkLifecycleRecovery(t *testing.T, journal, mode string) { + t.Helper() + controller := observeCommit(t) + before := strings.HasSuffix(mode, "before") + cut, phase, marker := "lifecycle-after", "AfterLifecycleCommit", 1 + if before { + cut, phase, marker = "lifecycle-before", "BeforeLifecycleCommit", 0 + } + f := fixtureWithInvocation(t, completeSSE, false, observedServer(t), []string{"--exact", "provider_commit_tests::serve_observed_gateway", "--ignored", "--nocapture"}, []string{"WEAVER_STORAGE_JOURNAL=" + journal, "WEAVER_TEST_COMMIT_SOCKET=" + controller.path, "WEAVER_TEST_COMMIT_CUT=" + cut}) + ctx, cancel := context.WithTimeout(t.Context(), 12*time.Second) + defer cancel() + controller.await(t, ctx, "Boot", 0) + type result struct { + frames int + err error + } + done := make(chan result, 1) + go func() { + count := 0 + _, err := f.client.Execute(ctx, f.plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { count++; return nil }) + done <- result{count, err} + }() + event := controller.await(t, ctx, phase, marker) + if mode == "control" { + resumeCommit(t, event, 'c') + } else if mode == "rollback-before" { + resumeCommit(t, event, 'r') + } else if mode == "lost-after" { + resumeCommit(t, event, 'l') + } else { + if err := f.child.Process.Kill(); err != nil { + t.Fatal(err) + } + select { + case <-f.exited: + case <-ctx.Done(): + t.Fatal("fault did not terminate original owner") + } + f.child = nil + f.client.Connection.Close() + f.admin.Connection.Close() + event.socket.Close() + } + select { + case r := <-done: + if mode == "control" { + if r.err != nil || r.frames != 5 { + t.Fatal("positive lifecycle control", r) + } + } else if r.err == nil || r.frames != 0 { + t.Fatal("unconfirmed consumption emitted frames", r) + } + case <-ctx.Done(): + t.Fatal("old worker did not end") + } + expected := "unknown" + if before { + expected = "queued" + } + if mode == "control" { + expected = "complete" + } + if f.child != nil { + assertNoFaultWorkerUnwind(t, f) + f.stop(t) + } + f.start(t) + controller.await(t, ctx, "Boot", marker) + receipt := inspect(t, f) + if receipt.State != expected || receipt.Held != 4 { + t.Fatal("restart changed original claim/hold", receipt) + } + if before { + // The known-absent consume may proceed using the retained original hold. + // The test observer is armed again after restart; resume its exact old cut. + retry := make(chan error, 1) + go func() { + _, err := f.client.Execute(ctx, f.plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }) + retry <- err + }() + resumed := controller.await(t, ctx, phase, 0) + resumeCommit(t, resumed, 'c') + select { + case err := <-retry: + if err != nil { + t.Fatal("known-absent original did not resume", err) + } + case <-ctx.Done(): + t.Fatal("resume stalled") + } + } else { + calls := int64(0) + if mode == "control" { + calls = 1 + } + originalStillSpentWithCalls(t, f, receipt, calls) + } + want := int64(0) + if before || mode == "control" { + want = 1 + } + if f.primary.Load() != want || f.backup.Load() != 0 { + t.Fatal("lifecycle recovery duplicated/substituted provider", f.primary.Load(), f.backup.Load(), want) + } + if inspect(t, f).Held != 4 { + t.Fatal("observation released unknown budget") + } + f.stop(t) +} diff --git a/go/internal/devrunner/benchmark_pipeline_test.go b/go/internal/devrunner/benchmark_pipeline_test.go index e15896b1..fa696e50 100644 --- a/go/internal/devrunner/benchmark_pipeline_test.go +++ b/go/internal/devrunner/benchmark_pipeline_test.go @@ -98,7 +98,7 @@ func TestPublishedPipelineKeepsSchemeOutsideExecutionQualification(t *testing.T) "execution-benchmark-target": true, "execution-policy-tests": true, "execution-backend-tests": true, "execution-policy-benchmark": true, "execution-ledger-benchmark": true, "execution-provider-benchmark": true, - "execution-delivery-join-pair": true, "execution-encoding-benchmark": true, "execution-range-prepare-pair": true, + "execution-lifecycle-footprint-pair": true, "execution-delivery-join-pair": true, "execution-encoding-benchmark": true, "execution-range-prepare-pair": true, "execution-scheduled-encoding-pair": true, "execution-contention-pair": true, "execution-provider-integration": true, "published-pipeline-benchmark": true, "execution-header-seal-pair": true, "execution-header-wait-pair": true, diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index 301d5c2f..77383597 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -65,6 +65,9 @@ func Plan(goBinary string) []Stage { {"provider-egress-window-lean", "elan", []string{"run", proofToolchain, "lean", "--json", "dev/proofs/lean/ProviderEgressWindow.lean"}}, {"provider-egress-promotion-quint-tests", "quint", []string{"test", "dev/proofs/quint/ProviderEgressPromotion.qnt", "--main", "ProviderEgressPromotion", "--seed", "293"}}, {"provider-egress-promotion-quint-safety", "quint", []string{"run", "dev/proofs/quint/ProviderEgressPromotion.qnt", "--main", "ProviderEgressPromotion", "--invariant", "safe", "--max-samples", "2000", "--max-steps", "80", "--seed", "293"}}, + {"provider-lifecycle-footprint-tests", "quint", []string{"test", "dev/proofs/quint/ProviderLifecycleFootprint.qnt", "--main", "ProviderLifecycleFootprint", "--seed", "293"}}, + {"provider-lifecycle-footprint-safety", "quint", []string{"run", "dev/proofs/quint/ProviderLifecycleFootprint.qnt", "--main", "ProviderLifecycleFootprint", "--invariant", "safe", "--max-samples", "2000", "--max-steps", "80", "--seed", "293"}}, + {"provider-lifecycle-footprint-lean", "elan", []string{"run", proofToolchain, "lean", "--json", "dev/proofs/lean/ProviderLifecycleFootprint.lean"}}, {"provider-snapshot-publication-tests", "quint", []string{"test", "dev/proofs/quint/ProviderSnapshotPublication.qnt", "--main", "ProviderSnapshotPublication", "--seed", "293"}}, {"provider-snapshot-publication-safety", "quint", []string{"run", "dev/proofs/quint/ProviderSnapshotPublication.qnt", "--main", "ProviderSnapshotPublication", "--invariant", "safe", "--max-samples", "2000", "--max-steps", "80", "--seed", "293"}}, {"provider-snapshot-publication-lean", "elan", []string{"run", proofToolchain, "lean", "--json", "dev/proofs/lean/ProviderSnapshotPublication.lean"}}, @@ -223,6 +226,7 @@ func Stages(mode, goBinary string) ([]Stage, error) { {"execution-provider-benchmark", "cargo", []string{"bench", "-p", "weaver-broker", "--bench", "gateway", "--locked", "--offline", "--", "broker/https_guarded_sse_three_events", "--noplot"}}, {"execution-encoding-benchmark", "cargo", []string{"bench", "-p", "weaver-server", "--features", "arrow", "--bench", "gateway", "--locked", "--offline", "--", "server/encoding_guard_hold", "--noplot"}}, {"execution-delivery-join-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderDeliveryJoin$", "-benchtime=1x", "-count=1", "-v"}}, + {"execution-lifecycle-footprint-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderLifecycleFootprint$", "-benchtime=1x", "-count=1", "-v"}}, {"execution-range-prepare-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderRangePreparationGroup$", "-benchtime=1x", "-count=1", "-v"}}, {"execution-scheduled-encoding-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderScheduledEncoding$", "-benchtime=1x", "-count=1", "-v"}}, {"execution-contention-pair", goBinary, []string{"-C", "go", "test", "-count=1", "-tags=integration", "./dev", "-run", "^TestContentionPairs$", "-v"}}, From de76c7222a385d8eb2d93e605acd554f1af98f97 Mon Sep 17 00:00:00 2001 From: guangtao Date: Thu, 5 Nov 2026 23:11:56 +0800 Subject: [PATCH 002/105] Share provider read custody while preserving current-cut delivery --- crates/ledger/src/lib.rs | 2 +- crates/ledger/src/persistence/scheduler.rs | 53 +++- crates/ledger/src/persistence/scope.rs | 19 +- crates/ledger/src/persistence/scope_trace.rs | 27 +- crates/ledger/src/provider.rs | 19 ++ .../tests/unit/persistence_scheduler.rs | 83 +++++- crates/ledger/tests/unit/provider.rs | 3 + .../tests/unit/provider_read_custody.rs | 150 ++++++++++ crates/ledger/tests/unit/scope_trace.rs | 2 +- crates/server/src/grpc_provider.rs | 6 + .../cedar/DomainMigrationComposition.lean | 26 ++ dev/proofs/cedar/lakefile.toml | 2 +- dev/proofs/lean/ProviderReadCustody.lean | 123 +++++++++ dev/proofs/quint/ProviderReadCustody.qnt | 64 +++++ dev/sysml/ArchitectureViews.sysml | 1 + dev/sysml/WeaverExecution.sysml | 49 +++- dev/sysml/runtime-trace.json | 3 +- .../10-routing-and-inference/10.00-index.org | 2 + .../10.09-provider-delivery-join.d2 | 12 +- .../10.09-provider-delivery-join.svg | 6 +- .../10.11-lifecycle-footprints.org | 7 + .../10.12-read-custody.org | 256 ++++++++++++++++++ go/dev/provider_delivery_bench_test.go | 13 +- go/dev/provider_domain_program_test.go | 2 +- go/dev/provider_range_scopes_test.go | 42 ++- go/dev/provider_read_custody_test.go | 85 ++++++ go/dev/provider_scheduler_bench_test.go | 24 ++ .../devrunner/benchmark_pipeline_test.go | 2 +- go/internal/devrunner/plan.go | 4 + 29 files changed, 1039 insertions(+), 48 deletions(-) create mode 100644 crates/ledger/tests/unit/provider_read_custody.rs create mode 100644 dev/proofs/lean/ProviderReadCustody.lean create mode 100644 dev/proofs/quint/ProviderReadCustody.qnt create mode 100644 docs/10-19-llm-gateway/10-routing-and-inference/10.12-read-custody.org create mode 100644 go/dev/provider_read_custody_test.go diff --git a/crates/ledger/src/lib.rs b/crates/ledger/src/lib.rs index 10951e28..cee0173c 100644 --- a/crates/ledger/src/lib.rs +++ b/crates/ledger/src/lib.rs @@ -56,7 +56,7 @@ pub use provider::{ }; #[cfg(feature = "commit-observer")] pub use provider::{ - use_cached_release_programs, use_conservative_range_invalidation, + use_cached_release_programs, use_conservative_range_invalidation, use_exclusive_provider_reads, use_full_lifecycle_invalidation, use_separate_release_reads, }; mod store; diff --git a/crates/ledger/src/persistence/scheduler.rs b/crates/ledger/src/persistence/scheduler.rs index dbdfd856..ea510192 100644 --- a/crates/ledger/src/persistence/scheduler.rs +++ b/crates/ledger/src/persistence/scheduler.rs @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 -//! Process-local custody for overlapping MVCC write scopes. +//! FIFO read-set custody with exclusive original-origin provider writes. use super::{driver, owner::error}; use std::{ collections::VecDeque, @@ -26,11 +26,29 @@ impl Scope { } } +#[derive(Clone, Copy, PartialEq, Eq)] +enum Access { + Exclusive, + OriginWrite, +} + struct Ticket { + access: Access, id: u64, scope: Scope, } +impl Ticket { + fn conflicts(&self, other: &Self) -> bool { + match (&self.scope, &other.scope, self.access, other.access) { + (Scope::Domains(a), Scope::Domains(b), Access::OriginWrite, Access::OriginWrite) => { + a.key(0) == b.key(0) + } + _ => self.scope.overlaps(&other.scope), + } + } +} + #[derive(Default)] pub(super) struct Scheduler { state: Mutex, @@ -52,12 +70,12 @@ impl State { } fn eligible(&self, at: usize) -> bool { - let candidate = &self.waiting[at].scope; + let candidate = &self.waiting[at]; self.waiting .iter() .take(at) .chain(&self.active) - .all(|older| !older.scope.overlaps(candidate)) + .all(|older| !older.conflicts(candidate)) } } @@ -69,6 +87,8 @@ pub(super) struct Grant<'a> { #[cfg(feature = "commit-observer")] pub arrival: u64, #[cfg(feature = "commit-observer")] + pub origin_write: bool, + #[cfg(feature = "commit-observer")] pub granted: u64, } @@ -81,11 +101,34 @@ impl Scheduler { &self, scope: Scope, cancelled: Option<&(dyn Fn() -> bool + Send + Sync)>, + ) -> driver::Result> { + self.acquire_access(scope, Access::Exclusive, cancelled) + } + + /// Only sealed provider progress/lifecycle callers can select this lease. + /// It still reads all six namespaces; only its origin is writable. + pub fn acquire_origin( + &self, + scope: Scope, + cancelled: Option<&(dyn Fn() -> bool + Send + Sync)>, + ) -> driver::Result> { + self.acquire_access(scope, Access::OriginWrite, cancelled) + } + + fn acquire_access( + &self, + scope: Scope, + access: Access, + cancelled: Option<&(dyn Fn() -> bool + Send + Sync)>, ) -> driver::Result> { let mut state = self.state.lock().map_err(error)?; let ticket = state.event(); let global = matches!(scope, Scope::All); - state.waiting.push_back(Ticket { id: ticket, scope }); + state.waiting.push_back(Ticket { + id: ticket, + scope, + access, + }); loop { let position = state .waiting @@ -111,6 +154,8 @@ impl Scheduler { #[cfg(feature = "commit-observer")] arrival: ticket, #[cfg(feature = "commit-observer")] + origin_write: access == Access::OriginWrite && !global, + #[cfg(feature = "commit-observer")] granted: state.event(), }); } diff --git a/crates/ledger/src/persistence/scope.rs b/crates/ledger/src/persistence/scope.rs index b9f7bceb..1204cff5 100644 --- a/crates/ledger/src/persistence/scope.rs +++ b/crates/ledger/src/persistence/scope.rs @@ -26,7 +26,7 @@ enum Change<'a> { Progress(&'a crate::provider::RangeProgress), Lifecycle(&'a crate::provider::OriginLifecycle), } -/// Exclusive native transaction; final guarded callbacks keep this scope alive. +/// Session-owned native transaction; compatible original origins may coexist. pub struct WriteScope<'a> { connection: &'a driver::Connection, authority: super::authority::Close<'a>, @@ -142,6 +142,8 @@ fn start<'a>( let close_scope = keys.as_ref().map_or(super::scheduler::Scope::All, |keys| { super::scheduler::Scope::Domains(keys.clone()) }); + let shared_reads = + !matches!(&change, Change::Semantic) && crate::provider::shared_provider_reads(); // Close before waiting for either the scheduler or native writer. let authority = match change { Change::Progress(progress) => session @@ -170,14 +172,23 @@ fn start<'a>( #[cfg(feature = "commit-observer")] let arrived = Instant::now(); let grant = super::timing::measure(&mut session.timings.domain_wait, || { - scheduler.acquire(super::scheduler::Scope::Domains(keys), cancelled) + if shared_reads { + scheduler.acquire_origin(super::scheduler::Scope::Domains(keys), cancelled) + } else { + scheduler.acquire(super::scheduler::Scope::Domains(keys), cancelled) + } })?; domains_entered = Some(Instant::now()); #[cfg(feature = "commit-observer")] if let Some(trace) = session.scope_trace.as_mut() { scope_trace = Some( - super::scope_trace::Arrival::capture(phase, grant.arrival, arrived) - .granted(trace, grant.granted), + super::scope_trace::Arrival::capture( + phase, + grant.arrival, + arrived, + grant.origin_write, + ) + .granted(trace, grant.granted), ); } // Key discovery is a hint. An intervening global scope may have migrated roots. diff --git a/crates/ledger/src/persistence/scope_trace.rs b/crates/ledger/src/persistence/scope_trace.rs index 17c0a863..8169d2fa 100644 --- a/crates/ledger/src/persistence/scope_trace.rs +++ b/crates/ledger/src/persistence/scope_trace.rs @@ -10,6 +10,7 @@ pub(super) const CAPACITY: usize = 64; pub(super) struct Arrival { phase: ProviderScopePhase, order: u64, + origin_write: bool, at: Instant, } @@ -23,6 +24,8 @@ pub(super) struct Granted<'a> { /// Process-local observations of atomic domain admission. pub struct ProviderScopeSample { pub phase: ProviderScopePhase, + /// Actual granted lease mode, not inferred from the phase name. + pub origin_write: bool, pub arrival: u64, pub grant: u64, pub wait: Duration, @@ -30,8 +33,18 @@ pub struct ProviderScopeSample { } impl Arrival { - pub(super) fn capture(phase: ProviderScopePhase, order: u64, at: Instant) -> Self { - Self { phase, order, at } + pub(super) fn capture( + phase: ProviderScopePhase, + order: u64, + at: Instant, + origin_write: bool, + ) -> Self { + Self { + phase, + order, + at, + origin_write, + } } pub(super) fn granted(self, trace: &mut Trace, order: u64) -> Granted<'_> { Granted { @@ -73,11 +86,16 @@ impl Trace { }; let _ = write!( line, - " {phase}:{}:{}:{}:{}", + " {phase}:{}:{}:{}:{}:{}", sample.arrival, sample.grant, sample.wait.as_nanos(), - sample.hold.as_nanos() + sample.hold.as_nanos(), + if sample.origin_write { + "origin" + } else { + "exclusive" + } ); } eprintln!("{line}"); @@ -98,6 +116,7 @@ impl Granted<'_> { pub(super) fn record(self) { self.trace.record(ProviderScopeSample { phase: self.arrival.phase, + origin_write: self.arrival.origin_write, arrival: self.arrival.order, grant: self.order, wait: self.at.duration_since(self.arrival.at), diff --git a/crates/ledger/src/provider.rs b/crates/ledger/src/provider.rs index 0b7033ea..1df641b9 100644 --- a/crates/ledger/src/provider.rs +++ b/crates/ledger/src/provider.rs @@ -36,6 +36,25 @@ thread_local! { pub fn use_full_lifecycle_invalidation(full: bool) { FULL_LIFECYCLE_INVALIDATION.set(full); } +#[cfg(feature = "commit-observer")] +thread_local! { + static EXCLUSIVE_PROVIDER_READS: std::cell::Cell = const { std::cell::Cell::new(false) }; +} +/// Safe same-image control retaining full-domain exclusive read custody. +#[cfg(feature = "commit-observer")] +pub fn use_exclusive_provider_reads(exclusive: bool) { + EXCLUSIVE_PROVIDER_READS.set(exclusive); +} +pub(crate) fn shared_provider_reads() -> bool { + #[cfg(feature = "commit-observer")] + { + !EXCLUSIVE_PROVIDER_READS.get() + } + #[cfg(not(feature = "commit-observer"))] + { + true + } +} impl OriginLifecycle { pub(crate) fn origin_only(&self) -> bool { #[cfg(feature = "commit-observer")] diff --git a/crates/ledger/tests/unit/persistence_scheduler.rs b/crates/ledger/tests/unit/persistence_scheduler.rs index f15b8b22..fec9d761 100644 --- a/crates/ledger/tests/unit/persistence_scheduler.rs +++ b/crates/ledger/tests/unit/persistence_scheduler.rs @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 -use super::{Scheduler, Scope, State, Ticket}; +use super::{Access, Scheduler, Scope, State, Ticket}; use proptest::{prop_assert_eq, proptest}; use std::{ sync::{ @@ -26,13 +26,13 @@ proptest! { ) { let split = split.min(roots.len()); let mut state = State { - waiting: roots.iter().enumerate().map(|(id, roots)| Ticket { + waiting: roots.iter().enumerate().map(|(id, roots)| Ticket { access: Access::Exclusive, id: id as u64, scope: scope(*roots), }).collect(), - active: vec![Ticket {id: 32, scope: scope(active)}], + active: vec![Ticket { access: Access::Exclusive,id: 32, scope: scope(active)}], ..State::default() }; - state.waiting.insert(split, Ticket {id: 33, scope: scope(candidate)}); + state.waiting.insert(split, Ticket { access: Access::Exclusive,id: 33, scope: scope(candidate)}); let conflict = (0..3).any(|i| { active[i] == candidate[i] || roots.iter().take(split).any(|root| root[i] == candidate[i]) }); @@ -103,3 +103,78 @@ fn waiting_multi_root_range_precedes_younger_conflicts() { drop(disjoint); }); } + +proptest! { + #[test] + fn read_custody_conflicts_with_every_overlapping_writer( + a in proptest::array::uniform3(0u8..8), b in proptest::array::uniform3(0u8..8), + read_a in proptest::bool::ANY, read_b in proptest::bool::ANY, + ) { + let left = Ticket { id: 0, scope: scope(a), access: if read_a { Access::OriginWrite } else { Access::Exclusive } }; + let right = Ticket { id: 1, scope: scope(b), access: if read_b { Access::OriginWrite } else { Access::Exclusive } }; + let conflict = if read_a && read_b { a[0] == b[0] } else { (0..3).any(|i| a[i] == b[i]) }; + prop_assert_eq!(left.conflicts(&right), conflict); + prop_assert_eq!(right.conflicts(&left), conflict); + let global = Ticket { id: 2, scope: Scope::All, access: Access::OriginWrite }; + prop_assert_eq!(left.conflicts(&global), true); + } +} + +#[test] +fn compatible_origins_share_reads_but_an_older_writer_blocks_younger_readers() { + let scheduler = Scheduler::default(); + let first = scheduler + .acquire_origin(scope([1, 2, 3]), None) + .expect("first reader"); + let peer = scheduler + .acquire_origin(scope([4, 2, 3]), None) + .expect("peer shares budget/history"); + assert!( + scheduler + .acquire_origin(scope([1, 5, 6]), Some(&|| true)) + .is_err() + ); + drop(peer); + let (announced, queue) = mpsc::channel(); + let (ordered, result) = mpsc::channel(); + let deadline = Instant::now() + Duration::from_secs(2); + thread::scope(|threads| { + for (writer, roots) in [(true, [7, 2, 8]), (false, [9, 2, 3])] { + let announced = announced.clone(); + let ordered = ordered.clone(); + let owner = &scheduler; + threads.spawn(move || { + let once = AtomicBool::new(false); + let signal = || { + if !once.swap(true, Ordering::Relaxed) { + let _ = announced.send(()); + } + Instant::now() >= deadline + }; + let granted = if writer { + owner.acquire(scope(roots), Some(&signal)) + } else { + owner.acquire_origin(scope(roots), Some(&signal)) + }; + if let Ok(_grant) = granted { + ordered.send(writer).expect("order"); + } + }); + queue + .recv_timeout(Duration::from_secs(1)) + .expect("registered"); + } + assert!(result.try_recv().is_err()); + drop(first); + assert!( + result + .recv_timeout(Duration::from_secs(1)) + .expect("writer first") + ); + assert!( + !result + .recv_timeout(Duration::from_secs(1)) + .expect("reader after writer") + ); + }); +} diff --git a/crates/ledger/tests/unit/provider.rs b/crates/ledger/tests/unit/provider.rs index c6509a49..c845a14c 100644 --- a/crates/ledger/tests/unit/provider.rs +++ b/crates/ledger/tests/unit/provider.rs @@ -888,3 +888,6 @@ mod snapshot_delivery; #[path = "provider_lifecycle.rs"] mod lifecycle; + +#[path = "provider_read_custody.rs"] +mod read_custody; diff --git a/crates/ledger/tests/unit/provider_read_custody.rs b/crates/ledger/tests/unit/provider_read_custody.rs new file mode 100644 index 00000000..fc830032 --- /dev/null +++ b/crates/ledger/tests/unit/provider_read_custody.rs @@ -0,0 +1,150 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Positive native concurrency, not a scheduler-only or mocked SQL acceptance. +use super::fixture_nodes; +use std::{ + collections::BTreeSet, + sync::{Arc, Mutex, mpsc}, + thread, + time::Duration, +}; +use weaver_contracts::{DomainBinding, Task}; +use weaver_ledger::{ + Ledger, + persistence::{ + self, Journal, Session, + commit_observer::{Cut, Decision, Observer}, + }, +}; + +struct Pause { + arrived: mpsc::Sender<()>, + resume: Mutex>, +} +impl Observer for Pause { + fn observe(&self, cut: Cut) -> Decision { + if cut == Cut::BeforeRangePrepareCommit { + self.arrived + .send(()) + .expect("native prepare reached commit"); + self.resume + .lock() + .expect("resume") + .recv() + .expect("release native commit"); + } + Decision::Continue + } +} + +#[test] +fn shared_reads_keep_distinct_origin_native_writes_concurrent() { + let directory = tempfile::tempdir().expect("store"); + let path = directory.path().join("shared-read.db"); + let storage = Session::open_with_journal(&path, Journal::Mvcc).expect("MVCC"); + let (mut ledger, mut plan) = fixture_nodes(&path, &["infer"]); + let policy = super::POLICY.replace( + "context.family == \"f\"", + "[\"f\",\"peer\"].contains(context.family)", + ); + ledger + .publish_typed(Some(0), &policy, super::SCHEMA, 2) + .expect("peer Policy"); + plan.revision = 1; + plan.fence = 2; + let mut peer = plan.clone(); + peer.family = "peer".into(); + let record: String = persistence::one( + &storage, + "SELECT record FROM tasks WHERE family='f'", + (), + |r| r.get(0), + ) + .expect("original"); + let mut task: Task = serde_json::from_str(&record).expect("typed"); + task.family = peer.family.clone(); + task.stream_contracts + .insert(peer.node.clone(), peer.digest().expect("peer contract")); + ledger + .register_task_domains( + &task, + &DomainBinding { + origin: "peer-origin".into(), + budget: "f".into(), + history: "f".into(), + budget_limit: 8, + }, + None, + ) + .expect("shared constraints"); + for plan in [&plan, &peer] { + ledger.enqueue_provider(plan).expect("reserve"); + } + let targets = BTreeSet::from(["primary".into()]); + let mut workers = Vec::new(); + for family in ["f", "peer"] { + let mut worker = Ledger::open(&path).expect("independent session"); + let permit = worker + .consume_provider(family, "infer", &targets) + .expect("consume on deciding session"); + worker + .dispatch_provider(&permit, || Ok(())) + .expect("one request per origin"); + workers.push((worker, permit)); + } + let (arrived, observed) = mpsc::channel(); + thread::scope(|threads| { + let mut releases = Vec::new(); + let mut jobs = Vec::new(); + for (mut worker, permit) in workers { + let (resume, receiver) = mpsc::channel(); + releases.push(resume); + let observer = Arc::new(Pause { + arrived: arrived.clone(), + resume: Mutex::new(receiver), + }); + jobs.push(threads.spawn(move || { + worker.observe_provider_commit(observer); + worker.prepare_provider_releases(&permit, &[("one", 1), ("two", 1)], "protobuf") + })); + } + let first = observed.recv_timeout(Duration::from_secs(3)); + let second = observed.recv_timeout(Duration::from_secs(3)); + for release in releases { + let _ = release.send(()); + } + let outcomes: Vec<_> = jobs + .into_iter() + .map(|job| job.join().expect("worker")) + .collect(); + let errors: Vec<_> = outcomes.iter().map(|o| o.as_ref().err()).collect(); + assert!( + first.is_ok() && second.is_ok(), + "both native writers must coexist before commit: {first:?}, {second:?}; {errors:?}" + ); + for outcome in outcomes { + assert_eq!(outcome.expect("independent native commit").len(), 2); + } + }); + assert_eq!( + ledger.execution_domains("f").expect("actual budget").held, + 8 + ); + assert_eq!( + ledger + .execution_domains("f") + .expect("actual history") + .history_count, + 2 + ); + let rows: i64 = persistence::one( + &storage, + "SELECT COUNT(*) FROM provider_releases", + (), + |r| r.get(0), + ) + .expect("all committed"); + assert_eq!(rows, 4); +} diff --git a/crates/ledger/tests/unit/scope_trace.rs b/crates/ledger/tests/unit/scope_trace.rs index 2aff1cc1..4da47519 100644 --- a/crates/ledger/tests/unit/scope_trace.rs +++ b/crates/ledger/tests/unit/scope_trace.rs @@ -11,7 +11,7 @@ proptest! { fn bounded_trace_retains_every_requalification(count in 1usize..256) { let mut trace = Trace::new("trace-test"); for ordinal in 0..count { - trace.record(ProviderScopeSample {phase: ProviderScopePhase::RevalidateDelivery, + trace.record(ProviderScopeSample {origin_write: ordinal % 2 == 0, phase: ProviderScopePhase::RevalidateDelivery, arrival: ordinal as u64*2+1, grant: ordinal as u64*2+2, wait: Duration::ZERO, hold: Duration::ZERO}); prop_assert!(trace.samples.len() <= CAPACITY); diff --git a/crates/server/src/grpc_provider.rs b/crates/server/src/grpc_provider.rs index 58524c22..aa35e8e9 100644 --- a/crates/server/src/grpc_provider.rs +++ b/crates/server/src/grpc_provider.rs @@ -92,7 +92,12 @@ impl Gateway { std::env::var("WEAVER_TEST_SEPARATE_RELEASE_READS").as_deref() == Ok("1"), ); #[cfg(test)] + weaver_ledger::use_exclusive_provider_reads( + std::env::var_os("WEAVER_TEST_EXCLUSIVE_PROVIDER_READS").is_some(), + ); + #[cfg(test)] weaver_ledger::use_full_lifecycle_invalidation( + std::env::var_os("WEAVER_TEST_FULL_LIFECYCLE_INVALIDATION").is_some(), ); #[cfg(test)] @@ -138,6 +143,7 @@ impl Gateway { weaver_ledger::use_fresh_provider_domain_plan(false); weaver_ledger::use_separate_release_reads(false); weaver_ledger::use_cached_release_programs(false); + weaver_ledger::use_exclusive_provider_reads(false); weaver_ledger::use_full_lifecycle_invalidation(false); weaver_ledger::use_conservative_range_invalidation(false); } diff --git a/dev/proofs/cedar/DomainMigrationComposition.lean b/dev/proofs/cedar/DomainMigrationComposition.lean index a46335b7..6e155cc6 100644 --- a/dev/proofs/cedar/DomainMigrationComposition.lean +++ b/dev/proofs/cedar/DomainMigrationComposition.lean @@ -2,6 +2,7 @@ -- -- SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 +import ProviderReadCustody import ProviderLifecycleFootprint import ProviderSnapshotPublication import ProviderSemanticProgress @@ -137,6 +138,31 @@ theorem peer_lifecycle_preserves_spec_final_use [DecidableEq Family] #print axioms peer_lifecycle_preserves_spec_final_use +/-- Scheduler compatibility preserves only the declared observer read projection. + The current SPEC FinalUse and reachable run remain separate host obligations, + including currentness, owner fencing and the original shared exposure. -/ +theorem read_custody_preserves_spec_final_use + (use : Gateway.ZeroTrust.FinalUse proposal) + (events : GatewayHeadCAS.Run c owner GatewayHeadCAS.initial use.actual) + (reader : Weaver.ProviderReadCustody.Access) + (before after : Nat → Nat) + (steps : Weaver.ProviderReadCustody.Steps reader before after) + (observe : GatewayHeadCAS.State → Nat → Nat) + (current : observe use.actual = after) + (allow : (Nat → Nat) → Prop) + (depends : Weaver.ProviderReadCustody.ReadsOnly allow reader.reads) + (qualified : allow before) : + allow (observe use.actual) ∧ + (Gateway.ZeroTrust.specialize proposal (reachableDomain c)).required effect use.actual ∧ + (∀ account, booked c use.actual.base account ≤ c.capacity account) ∧ + (∀ key, (use.actual.base.messages key).claims ≤ 1 ∧ + (use.actual.base.messages key).sends ≤ 1) ∧ original.Refines prepared.profile := by + refine ⟨?_, gateway_final_use_preserves_domain_contract use events⟩ + rw [current] + exact Weaver.ProviderReadCustody.finite_interleaving_preserves_policy steps depends qualified + +#print axioms read_custody_preserves_spec_final_use + theorem head_cas_preserves_original_obligations (step : GatewayHeadCAS.Step c owner before after) (claimed : (before.base.messages key).claimed = true) diff --git a/dev/proofs/cedar/lakefile.toml b/dev/proofs/cedar/lakefile.toml index 626c9796..15b3e376 100644 --- a/dev/proofs/cedar/lakefile.toml +++ b/dev/proofs/cedar/lakefile.toml @@ -46,7 +46,7 @@ roots = ["AnchorBrokerCommit","AnchorReconfiguration","AnchoredRecoveryAndEgress [[lean_lib]] name = "ExecutionResearch" srcDir = "../lean" -roots = ["BrokerConsumptionQueue","CommittedSemanticProfile","DeviceIsolationRecovery","DynamicImageCustody","DynamicImportBoundary","DynamicLoaderPublication","DynamicPairedEvidence","FencedIntentContinuation","FloorIntentDecision","GambitLocatorClosure","GatewayHeadCAS","GerbilExitQualification","KeyBoundaryQueue","LlmAccountCommit","LlmAdmissionFloor","LlmAppendHandoff","LlmAttemptLedger","LlmAuthoritativeScope","LlmBeneficiaryRegistration","LlmBootstrapInvitation","LlmCallerCustody","LlmCanonicalRegistry","LlmCheckpointTruncation","LlmCustodyPublication","LlmEnrollmentCredential","LlmExecutionReconciliation","LlmExecutorOffer","LlmIncarnationIssuance","LlmJoinEnqueue","LlmManifestSwitch","LlmMultiKeyRegistry","LlmPolicyContinuation","LlmPolicyPublication","LlmRecoveryCAS","LlmRegistryPublication","LlmResultProjection","LlmRouting","LlmSemanticContract","LlmSourceCustody","LlmSourceJoin","LlmSubjectAuthority","LlmWalActivation","LogicalRangeRecovery","ProtectedSignerRelease","ProviderEgressWindow","ProviderSemanticProgress","ProviderSnapshotPublication","ProviderLifecycleFootprint","RoutineRoutingConfig","RuntimeAdmission","SemanticGatewaySlice","SharedDomains","StreamingExecution"] +roots = ["BrokerConsumptionQueue","CommittedSemanticProfile","DeviceIsolationRecovery","DynamicImageCustody","DynamicImportBoundary","DynamicLoaderPublication","DynamicPairedEvidence","FencedIntentContinuation","FloorIntentDecision","GambitLocatorClosure","GatewayHeadCAS","GerbilExitQualification","KeyBoundaryQueue","LlmAccountCommit","LlmAdmissionFloor","LlmAppendHandoff","LlmAttemptLedger","LlmAuthoritativeScope","LlmBeneficiaryRegistration","LlmBootstrapInvitation","LlmCallerCustody","LlmCanonicalRegistry","LlmCheckpointTruncation","LlmCustodyPublication","LlmEnrollmentCredential","LlmExecutionReconciliation","LlmExecutorOffer","LlmIncarnationIssuance","LlmJoinEnqueue","LlmManifestSwitch","LlmMultiKeyRegistry","LlmPolicyContinuation","LlmPolicyPublication","LlmRecoveryCAS","LlmRegistryPublication","LlmResultProjection","LlmRouting","LlmSemanticContract","LlmSourceCustody","LlmSourceJoin","LlmSubjectAuthority","LlmWalActivation","LogicalRangeRecovery","ProtectedSignerRelease","ProviderEgressWindow","ProviderSemanticProgress","ProviderSnapshotPublication","ProviderLifecycleFootprint","ProviderReadCustody","RoutineRoutingConfig","RuntimeAdmission","SemanticGatewaySlice","SharedDomains","StreamingExecution"] [[lean_lib]] name = "DomainMigrationComposition" diff --git a/dev/proofs/lean/ProviderReadCustody.lean b/dev/proofs/lean/ProviderReadCustody.lean new file mode 100644 index 00000000..91cd055a --- /dev/null +++ b/dev/proofs/lean/ProviderReadCustody.lean @@ -0,0 +1,123 @@ +-- SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +-- +-- SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +import Std + +namespace Weaver.ProviderReadCustody + +/-- Resources denote semantic coordinates, including exact retained exposure; + native SQL snapshot isolation alone is not a shared-budget protocol. -/ +structure Access where + reads : Nat → Prop + writes : Nat → Prop + +def Compatible (a b : Access) : Prop := + ∀ key, (a.writes key → ¬ b.reads key) ∧ (b.writes key → ¬ a.reads key) ∧ ¬ (a.writes key ∧ b.writes key) + +def update (before values : Nat → Nat) (writes : Nat → Prop) [DecidablePred writes] : Nat → Nat := + fun key => if writes key then values key else before key + +theorem compatible_write_preserves_read (a b : Access) [DecidablePred a.writes] + (safe : Compatible a b) (before values : Nat → Nat) : + ∀ key, b.reads key → update before values a.writes key = before key := by + intro key read + have unchanged : ¬ a.writes key := fun write => (safe key).1 write read + simp [update, unchanged] + +def ReadsOnly (allow : (Nat → Nat) → Prop) (reads : Nat → Prop) : Prop := + ∀ before after, (∀ key, reads key → after key = before key) → (allow after ↔ allow before) + +theorem arbitrary_policy_preserved (a b : Access) [DecidablePred a.writes] + (safe : Compatible a b) (allow : (Nat → Nat) → Prop) (depends : ReadsOnly allow b.reads) + (before values : Nat → Nat) (qualified : allow before) : + allow (update before values a.writes) := by + exact (depends before _ (compatible_write_preserves_read a b safe before values)).2 qualified + +/-- Any finite interleaving of declared compatible writes preserves the read + projection. No fixed worker, family or range cardinality is assumed. -/ +inductive Steps (reader : Access) : (Nat → Nat) → (Nat → Nat) → Prop where + | refl (image) : Steps reader image image + | next {before after} (writer : Access) [DecidablePred writer.writes] + (values : Nat → Nat) (safe : Compatible writer reader) + (previous : Steps reader before after) : + Steps reader before (update after values writer.writes) + +theorem finite_interleaving_preserves_reads (steps : Steps reader before after) : + ∀ key, reader.reads key → after key = before key := by + induction steps with + | refl => intro key _; rfl + | next writer values safe _ ih => + intro key read + exact (compatible_write_preserves_read writer reader safe _ values key read).trans (ih key read) + +theorem finite_interleaving_preserves_policy (steps : Steps reader before after) + (depends : ReadsOnly allow reader.reads) (qualified : allow before) : allow after := + (depends before after (finite_interleaving_preserves_reads steps)).2 qualified + +theorem shared_writer_conflicts (a b : Access) (key : Nat) + (write : a.writes key) (read : b.reads key) : ¬ Compatible a b := by + intro safe; exact (safe key).1 write read + +theorem overlapping_writes_conflict (a b : Access) (key : Nat) + (left : a.writes key) (right : b.writes key) : ¬ Compatible a b := by + intro safe; exact (safe key).2.2 ⟨left, right⟩ + +def Eligible (candidate : Access) (older active : List Access) : Prop := + (∀ entry ∈ older, Compatible entry candidate) ∧ (∀ entry ∈ active, Compatible entry candidate) + +theorem older_conflicting_writer_blocks (candidate writer : Access) (older active : List Access) + (queued : writer ∈ older) (conflict : ¬ Compatible writer candidate) : + ¬ Eligible candidate older active := fun eligible => conflict (eligible.1 writer queued) + +theorem active_conflict_blocks (candidate writer : Access) (older active : List Access) + (leased : writer ∈ active) (conflict : ¬ Compatible writer candidate) : + ¬ Eligible candidate older active := fun eligible => conflict (eligible.2 writer leased) + +/-- Exact binding identifies the original frame, canonical read domains and plan. + Native confirmation and this current scope are independent requirements. -/ +structure Qualification where + binding : Nat + sharedRevision : Nat + originRevision : Nat + owner : Nat + +structure Transfer where + committed : Bool + issued : Qualification + actual : Qualification + revoked : Bool + used : Bool + +def Ready (t : Transfer) : Prop := t.committed = true ∧ t.issued = t.actual ∧ + t.revoked = false ∧ t.used = false + +theorem unknown_commit_blocks (t : Transfer) (unknown : t.committed = false) : ¬ Ready t := by + intro ready; exact Bool.noConfusion (unknown.symm.trans ready.1) + +theorem changed_binding_blocks (t : Transfer) (changed : t.issued.binding ≠ t.actual.binding) : + ¬ Ready t := fun ready => changed (congrArg Qualification.binding ready.2.1) + +theorem changed_shared_cut_blocks (t : Transfer) (changed : t.issued.sharedRevision ≠ t.actual.sharedRevision) : + ¬ Ready t := fun ready => changed (congrArg Qualification.sharedRevision ready.2.1) + +theorem changed_origin_cut_blocks (t : Transfer) (changed : t.issued.originRevision ≠ t.actual.originRevision) : + ¬ Ready t := fun ready => changed (congrArg Qualification.originRevision ready.2.1) + +theorem changed_owner_blocks (t : Transfer) (changed : t.issued.owner ≠ t.actual.owner) : + ¬ Ready t := fun ready => changed (congrArg Qualification.owner ready.2.1) + +#print axioms compatible_write_preserves_read +#print axioms arbitrary_policy_preserved +#print axioms finite_interleaving_preserves_reads +#print axioms finite_interleaving_preserves_policy +#print axioms overlapping_writes_conflict +#print axioms shared_writer_conflicts +#print axioms older_conflicting_writer_blocks +#print axioms active_conflict_blocks +#print axioms unknown_commit_blocks +#print axioms changed_binding_blocks +#print axioms changed_shared_cut_blocks +#print axioms changed_origin_cut_blocks +#print axioms changed_owner_blocks +end Weaver.ProviderReadCustody diff --git a/dev/proofs/quint/ProviderReadCustody.qnt b/dev/proofs/quint/ProviderReadCustody.qnt new file mode 100644 index 00000000..e7a600f5 --- /dev/null +++ b/dev/proofs/quint/ProviderReadCustody.qnt @@ -0,0 +1,64 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +module ProviderReadCustody { + pure val tickets=Set(0,1,2,3,4,5) + type State={waiting:Set[int],active:Set[int],used:Set[int],origin:int->int,exclusive:int->bool, + snapshot:int->int,version:int,held:int,failed:bool,owner:int,certificateOwner:int, + committed:bool,consumed:bool,bad:bool,certificateVersion:int,certificateOrigin:int,certificateLocal:int,originRevision:int->int,localIntent:Set[int]} + var s:State + action init=s'={waiting:Set(),active:Set(),used:Set(),origin:tickets.mapBy(_=>0), + exclusive:tickets.mapBy(_=>false),snapshot:tickets.mapBy(_=>0),version:0,held:12, + failed:false,owner:1,certificateOwner:1,committed:false,consumed:false,bad:false,certificateVersion:0,certificateOrigin:0,certificateLocal:0,originRevision:Set(0,1,2).mapBy(_=>0),localIntent:Set()} + def conflict(a:int,b:int):bool=s.exclusive.get(a) or s.exclusive.get(b) or s.origin.get(a)==s.origin.get(b) + def eligible(id:int):bool=s.waiting.forall(older=>older>=id or not(conflict(older,id))) and s.active.forall(other=>not(conflict(other,id))) + def pendingWriter:bool=s.waiting.union(s.active).exists(id=>s.exclusive.get(id)) +def requested(id:int,origin:int,exclusive:bool):State={...s,waiting:s.waiting.union(Set(id)),used:s.used.union(Set(id)),origin:s.origin.set(id,origin),exclusive:s.exclusive.set(id,exclusive)} + def fresh(id:int):bool=id==s.used.size() and not(s.used.contains(id)) and not(s.failed) + action request(id:int,origin:int,exclusive:bool):bool=all{fresh(id),s'=requested(id,origin,exclusive)} + action requestLifecycle(id:int,origin:int):bool=all{fresh(id),s'={...requested(id,origin,false),localIntent:s.localIntent.union(Set(id))}} + action grant(id:int):bool=all{s.waiting.contains(id),eligible(id),not(s.failed), + s'={...s,waiting:s.waiting.exclude(Set(id)),active:s.active.union(Set(id)),snapshot:s.snapshot.set(id,s.version)}} + action finish(id:int):bool=all{s.active.contains(id), + s'={...s,active:s.active.exclude(Set(id)),version:s.version+(if(s.exclusive.get(id))1 else 0),held:s.held+(if(s.exclusive.get(id))4 else 0),originRevision:if(s.localIntent.contains(id))s.originRevision.set(s.origin.get(id),s.originRevision.get(s.origin.get(id))+1) else s.originRevision}} + action cancel(id:int):bool=all{s.waiting.contains(id),s'={...s,waiting:s.waiting.exclude(Set(id))}} + action commitRange(id:int):bool=all{s.active.contains(id),s.certificateOwner==s.owner,s.origin.get(id)==s.certificateOrigin,not(s.exclusive.get(id)),not(s.localIntent.contains(id)),not(s.failed), + s'={...s,committed:true,certificateVersion:s.version,certificateLocal:s.originRevision.get(s.origin.get(id)),active:s.active.exclude(Set(id))}} +def pendingForFrame:bool=s.waiting.union(s.active).exists(id=>s.exclusive.get(id) or (s.localIntent.contains(id) and s.origin.get(id)==s.certificateOrigin)) + def currentCut:bool=s.certificateVersion==s.version and s.certificateLocal==s.originRevision.get(s.certificateOrigin) + action offer=all{s.committed,not(s.failed),not(pendingForFrame),currentCut,not(s.consumed),s.certificateOwner==s.owner, + s'={...s,consumed:true}} + action unsafeOffer=all{s.committed,not(s.consumed),s'= {...s,consumed:true,bad:not(currentCut) or pendingForFrame}} + action unknown=s'={...s,failed:true,committed:false} + action restart=s'={...s,owner:s.owner+1,failed:false,waiting:Set(),active:Set()} + action unsafeSharedWrite(id:int):bool=all{s.active.contains(id), + s'={...s,version:s.version+1,active:s.active.exclude(Set(id))}} + action step={nondet id=tickets.oneOf() + nondet origin=Set(0,1,2).oneOf() + nondet exclusive=Set(true,false).oneOf() + any{request(id,origin,exclusive),requestLifecycle(id,origin),grant(id),finish(id),cancel(id),commitRange(id),offer,unknown,restart}} + val safe=not(s.bad) and s.held>=12 and s.active.forall(a=>s.snapshot.get(a)==s.version and s.active.forall(b=>a==b or not(conflict(a,b)))) + action pair=init.then(request(0,0,false)).then(grant(0)).then(request(1,1,false)).then(grant(1)) + run compatibleReaderReorderingTest=init.then(request(0,0,false)).then(request(1,1,false)).then(grant(1)).then(grant(0)).expect(safe) + run distinctOriginsShareReadsTest=pair.expect(safe and s.active==Set(0,1)) + run sameOriginSerializesTest=init.then(request(0,0,false)).then(grant(0)).then(request(1,0,false)).then(grant(1).fail()) + run admissionWaitsForReadersTest=pair.then(request(2,2,true)).then(grant(2).fail()) + run writerPreventsYoungerBypassTest=init.then(request(0,0,false)).then(grant(0)).then(request(1,1,true)).then(request(2,2,false)).then(grant(2).fail()) + run writerResumesAfterReaderDrainTest=pair.then(request(2,2,true)).then(finish(0)).then(finish(1)).then(grant(2)).then(finish(2)).expect(safe and s.held==16) + run writerBlocksFinalTransferTest=init.then(request(0,0,false)).then(grant(0)).then(commitRange(0)).then(request(1,1,true)).then(offer.fail()) + run leaseAloneCannotSendTest=init.then(request(0,0,false)).then(grant(0)).then(offer.fail()) + run knownCommitAllowsOneTransferTest=init.then(request(0,0,false)).then(grant(0)).then(commitRange(0)).then(offer).then(offer.fail()) + run unknownCommitBlocksTest=init.then(request(0,0,false)).then(grant(0)).then(unknown).then(offer.fail()) + run restartRejectsOldOwnerTest=init.then(request(0,0,false)).then(grant(0)).then(commitRange(0)).then(restart).then(offer.fail()) + run cancellationRetainsReservationTest=init.then(request(0,0,false)).then(cancel(0)).expect(safe and s.held==12) + run unsafeSharedMutationCounterexampleTest=pair.then(unsafeSharedWrite(0)).expect(not(safe)) + action qualified=init.then(request(0,0,false)).then(grant(0)).then(commitRange(0)) + run committedBeforeSharedChangeTest=qualified.then(request(1,1,true)).then(grant(1)).then(finish(1)).then(offer.fail()) + run unsafeStaleSharedCutCounterexampleTest=qualified.then(request(1,1,true)).then(grant(1)).then(finish(1)).then(unsafeOffer).expect(not(safe)) + run ownLifecycleClosesPendingFrameTest=qualified.then(requestLifecycle(1,0)).then(offer.fail()) + run ownLifecycleRetiresFrameTest=qualified.then(requestLifecycle(1,0)).then(grant(1)).then(finish(1)).then(offer.fail()) + run peerLifecyclePreservesFrameTest=qualified.then(requestLifecycle(1,1)).then(grant(1)).then(finish(1)).then(offer).expect(safe) + run ownProgressPreservesFrameTest=qualified.then(request(1,0,false)).then(grant(1)).then(offer).expect(safe) run staleWorkerCannotPrepareTest=init.then(restart).then(request(0,0,false)).then(grant(0)).then(commitRange(0).fail()) + run foreignOriginCannotQualifyOriginalFrameTest=init.then(request(0,1,false)).then(grant(0)).then(commitRange(0).fail()) +} diff --git a/dev/sysml/ArchitectureViews.sysml b/dev/sysml/ArchitectureViews.sysml index eb4111fa..7c83fc8c 100644 --- a/dev/sysml/ArchitectureViews.sysml +++ b/dev/sysml/ArchitectureViews.sysml @@ -258,6 +258,7 @@ package WeaverViews { requirement semanticProgress : WeaverExecution::ProviderSemanticProgress; requirement publicationContract : WeaverExecution::ProviderSnapshotPublication; requirement lifecycleFootprint : WeaverExecution::ProviderLifecycleFootprint; + requirement readCustody : WeaverExecution::ProviderReadCustody; expose WeaverExecution::providerDeliveryJoin::changes; expose WeaverExecution::providerDeliveryJoin::validated; expose WeaverExecution::providerDeliveryJoin::publication; diff --git a/dev/sysml/WeaverExecution.sysml b/dev/sysml/WeaverExecution.sysml index 08e12edb..4c31ab74 100644 --- a/dev/sysml/WeaverExecution.sysml +++ b/dev/sysml/WeaverExecution.sysml @@ -119,14 +119,15 @@ package WeaverExecution { that transaction. Program reuse preserves the full domain join. The domain view and reservation reconciliation are scope-local. History equality, capacity, revocation, Policy and fence remain live. */ - doc /* Shared roots serialize. Independent roots may overlap under MVCC. - Qualify both with the same binary, ingress, original workload, provider, - and held-budget verification. Hold and wait intervals can overlap. - The sum of protected service demands is a lower bound on a wave - sharing one root. Cross-root time is bounded by the longest dependency - chain and can also be constrained by native writer and IO capacity. - Report wall time and sampled work separately. A diagnostic speed result - carries no authority and does not establish a production SLO. */ + doc /* Overlapping semantic writers serialize; certified provider work + may share semantic reads while writing distinct original origins. + Measure actual granted modes and reader/writer waits separately. + Only mutually conflicting protected demands form a serial service + lower bound. Compatible reads are bounded by dependency chains, + native writer/IO capacity and host scheduling, not their simple sum. + Both profiles use the same binary, original workload, ingress, + provider and held-budget verification. Hold intervals may overlap. + A diagnostic result carries no authority or production SLO claim. */ } part def SharedDomainScheduler { @@ -302,6 +303,36 @@ package WeaverExecution { reopen only on the exact fenced image and outcome. */ } + part def ProviderReadCustodyExperiment { + part grouped : ProviderSnapshotExperiment; + attribute sharedReadScopes : Integer = 12; + attribute sharedWriterScopes : Integer = 1; + assert constraint { sharedReadScopes + sharedWriterScopes == grouped.snapshotBaseScopes } + assert constraint { sharedReadScopes == grouped.lifecycle.fixedDecidingScopes - 1 + grouped.preparationGroups + grouped.snapshotQueueGroups } + doc /* In the unchanged thirteen-range burst, four lifecycle scopes and + eight range scopes use compatible read custody; only new admission + writes the shared semantic projection. Actual renewal scopes are + additional and must be reported. A mode is observed at scheduler + grant, never inferred from the phase label or chosen benchmark arm. + The thirteen frame owner/cursor checks remain independent of SQL + lease compatibility. Fewer conflicts do not prove a tail bound. */ + } + + requirement def ProviderReadCustody { + doc /* Certified provider progress and lifecycle operations read the + complete six-domain semantic footprint and write their own original + origin. Different origins may hold those shared read leases together. + Same-origin work, broad admission/settlement and global Policy/OAuth/ + migration remain conflicting writers. Earlier conflicting writers + prevent younger readers from bypassing them. No shared-budget cache + substitutes for live SQL, original claim or current Cedar checks. */ + doc /* A lease is not send authority. Known native group commit and the + current cut, unique owner, grant time and affine cursor still join at + final Tonic use. Unknown native results preserve holds and seal; native + write conflicts cannot trigger another provider invocation. WAL keeps + its global profile. Actual Turso concurrency must be positively tested. */ + } + requirement def ProviderLifecycleFootprint { doc /* Read custody and invalidation are different footprints. Admission appends original claims and changes held/history/quota projections, @@ -492,7 +523,7 @@ package WeaverExecution { part def DeliveryValidation { attribute displayName : String = "Rust / qualify group"; - attribute responsibility : String = "Pending clear; each row\nCedar + claim + domains"; + attribute responsibility : String = "Read shared; write origin\nCedar + claim + domains"; attribute glyph : String = "authorization"; attribute visualRole : String = "governance"; port closed : ~EgressWindowPort; diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index 52853457..a3e7bbdc 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -1,4 +1,5 @@ -[ {"id":"ProviderLifecycleFootprint","witnesses":[{"file":"crates/ledger/src/provider.rs","pattern":"struct OriginLifecycle"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"enum Impact"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_lifecycle"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_provider_lifecycle"},{"file":"crates/ledger/tests/unit/provider_lifecycle.rs","pattern":"fn peer_lifecycle_preserves_complete_view_but_shared_admission_does_not"},{"file":"go/dev/provider_lifecycle_test.go","pattern":"func TestProviderLifecycleCommitRecovery"},{"file":"crates/ledger/tests/unit/authority_footprint.rs","pattern":"fn local_commit_retires_whole_and_own_but_preserves_peer"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem origin_commit_retires_whole_reader","declaration":"Weaver.ProviderLifecycleFootprint.origin_commit_retires_whole_reader"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem arbitrary_cedar_predicate_preserved","declaration":"Weaver.ProviderLifecycleFootprint.arbitrary_cedar_predicate_preserved"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem shared_admission_requires_shared_invalidation","declaration":"Weaver.ProviderLifecycleFootprint.shared_admission_requires_shared_invalidation"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem peer_lifecycle_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.peer_lifecycle_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderLifecycleFootprint.qnt","pattern":"run unsafeNarrowAdmissionCounterexampleTest"}]}, +[{"id":"ProviderReadCustody","witnesses":[{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn conflicts"},{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn acquire_origin"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let shared_reads"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn compatible_origins_share_reads_but_an_older_writer_blocks_younger_readers"},{"file":"crates/ledger/tests/unit/provider_read_custody.rs","pattern":"fn shared_reads_keep_distinct_origin_native_writes_concurrent"},{"file":"go/dev/provider_read_custody_test.go","pattern":"func TestProviderReadCustodyProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderReadCustody"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem arbitrary_policy_preserved","declaration":"Weaver.ProviderReadCustody.arbitrary_policy_preserved"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem finite_interleaving_preserves_policy","declaration":"Weaver.ProviderReadCustody.finite_interleaving_preserves_policy"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem overlapping_writes_conflict","declaration":"Weaver.ProviderReadCustody.overlapping_writes_conflict"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessRetainsWriterAndSameOriginBarriers"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_binding_blocks","declaration":"Weaver.ProviderReadCustody.changed_binding_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_shared_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_shared_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_origin_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_origin_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_owner_blocks","declaration":"Weaver.ProviderReadCustody.changed_owner_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem shared_writer_conflicts","declaration":"Weaver.ProviderReadCustody.shared_writer_conflicts"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem older_conflicting_writer_blocks","declaration":"Weaver.ProviderReadCustody.older_conflicting_writer_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem read_custody_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.read_custody_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderReadCustody.qnt","pattern":"run unsafeSharedMutationCounterexampleTest"}]}, + {"id":"ProviderLifecycleFootprint","witnesses":[{"file":"crates/ledger/src/provider.rs","pattern":"struct OriginLifecycle"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"enum Impact"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_lifecycle"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_provider_lifecycle"},{"file":"crates/ledger/tests/unit/provider_lifecycle.rs","pattern":"fn peer_lifecycle_preserves_complete_view_but_shared_admission_does_not"},{"file":"go/dev/provider_lifecycle_test.go","pattern":"func TestProviderLifecycleCommitRecovery"},{"file":"crates/ledger/tests/unit/authority_footprint.rs","pattern":"fn local_commit_retires_whole_and_own_but_preserves_peer"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem origin_commit_retires_whole_reader","declaration":"Weaver.ProviderLifecycleFootprint.origin_commit_retires_whole_reader"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem arbitrary_cedar_predicate_preserved","declaration":"Weaver.ProviderLifecycleFootprint.arbitrary_cedar_predicate_preserved"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem shared_admission_requires_shared_invalidation","declaration":"Weaver.ProviderLifecycleFootprint.shared_admission_requires_shared_invalidation"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem peer_lifecycle_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.peer_lifecycle_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderLifecycleFootprint.qnt","pattern":"run unsafeNarrowAdmissionCounterexampleTest"}]}, {"id":"ProviderSnapshotPublication","witnesses":[{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn release_provider_group_for_delivery"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"struct Snapshot"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn share_qualification"},{"file":"crates/ledger/src/provider.rs","pattern":"fn begin_snapshot_validation"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn take_refresh"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem pending_close_defers_renewal","declaration":"Weaver.ProviderSnapshotPublication.pending_close_defers_renewal"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn a_request_arriving_during_qualification_cannot_trigger_a_second_native_read"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn one_snapshot_requalification_covers_every_exact_frame"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn post_staging_native_failure_cannot_publish_a_partial_snapshot"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn queue_snapshot"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func awaitDeliveryCuts"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem final_use_joins_snapshot","declaration":"Weaver.ProviderSnapshotPublication.final_use_joins_snapshot"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem published_snapshot_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.published_snapshot_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSnapshotPublication.qnt","pattern":"run ungatedArcLoadIsCounterexampleTest"}]}, {"id":"ProviderSemanticProgress","witnesses":[{"file":"crates/ledger/src/provider.rs","pattern":"struct RangeProgress"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_progress"},{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn stage_group"},{"file":"crates/ledger/tests/unit/provider_delivery.rs","pattern":"fn exact_range_progress_preserves_queued_authorization"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderSemanticProgressProperty"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_released_binding","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_released_binding"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_image","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_image"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem range_progress_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.range_progress_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSemanticProgress.qnt","pattern":"run hiddenSemanticEditIsCounterexampleTest"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"}]}, diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.00-index.org b/docs/10-19-llm-gateway/10-routing-and-inference/10.00-index.org index 24c1c8fd..5d5a8f11 100644 --- a/docs/10-19-llm-gateway/10-routing-and-inference/10.00-index.org +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.00-index.org @@ -67,3 +67,5 @@ No Gateway runtime or dependency pin is changed. - [[file:10.10-snapshot-publication.org][Published range snapshots and the final delivery boundary]] - [[file:10.11-lifecycle-footprints.org][Lifecycle write footprints and shared admission]] + +- [[file:10.12-read-custody.org][Shared read custody and final delivery latency]] diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2 b/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2 index 56458453..44c73d70 100644 --- a/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2 +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2 @@ -74,8 +74,9 @@ vars: { d2-config: { data: { figure: |json "proof0": "dev/proofs/cedar/DomainMigrationComposition.lean", "proof1": "dev/proofs/lean/ProviderEgressWindow.lean", "proof2": "dev/proofs/lean/ProviderLifecycleFootprint.lean", - "proof3": "dev/proofs/lean/ProviderSemanticProgress.lean", - "proof4": "dev/proofs/lean/ProviderSnapshotPublication.lean", + "proof3": "dev/proofs/lean/ProviderReadCustody.lean", + "proof4": "dev/proofs/lean/ProviderSemanticProgress.lean", + "proof5": "dev/proofs/lean/ProviderSnapshotPublication.lean", "sdkCapture": "dev/sysml/captures/WeaverViews-providerDeliveryJoin.json" }, "copy": {}, @@ -108,7 +109,8 @@ vars: { d2-config: { data: { figure: |json "proof1", "proof2", "proof3", - "proof4" + "proof4", + "proof5" ], "evidenceRefs": [] }, @@ -207,11 +209,11 @@ vars: { d2-config: { data: { figure: |json "modelSource": { "ref": "sdkCapture", "view": "WeaverViews::providerDeliveryJoin", - "modelHash": "3c45556818345c7270d26e7d40d6ad5d25bd2b585713bf03143e9a14a5387ed2", + "modelHash": "eff38a5a555cd875587cbd393a8aa0b12179605e7a85cbba6bae3aaf12562787", "portProjection": "owner", "labels": { "n0": "Rust / close\nRun edits / origin cut\nShared edits / shared cut", - "n1": "Rust / qualify group\nPending clear; each row\nCedar + claim + domains", + "n1": "Rust / qualify group\nRead shared; write origin\nCedar + claim + domains", "n2": "Turso / commit group\nBurn the bounded group\nPublish one qualified cut", "n3": "Rust / prepare frame\nExact bytes and next span\nReserve transport credit", "n4": "Rust / consume once\nLive cut + owner + expiry\nOne-use frame cursor", diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.svg b/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.svg index eedb39bb..7c4c9f3f 100644 --- a/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.svg +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.svg @@ -37,16 +37,16 @@ SPDX-FileComment: Weaver-authored diagram; embedded third-party fonts and marks .scene-title{font-size:26px}.scene-detail{font-size:26px}.scene-group-title{font-size:26px} @font-face{font-family:"Kalam";font-style:normal;font-weight:400;src:url(data:font/woff2;base64,d09GMgABAAAAAFdAABEAAAAAutAAAFbgAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhwbHhxkBmAAhAgIcAmXFhEICoLEDIKbMwuDQAABNgIkA4Z8BCAFhBoHIAyBGRuPoyVjnObtcUAJ1o6NinqKtpID/v+U5GQMBxq4tPTWfyK5ORyCPLtgXPc8B5G1mj4zYcfd48rweBwZy2Ttd8ZLrNPYUCieysgzGnEd4VPb1TdueM1Gd+noZrKJQWTD149d1spXP9D8kUv+MxVIx1gzOhEMY/PHxhVmGTkrn4FtI3+Sk9eqWlpWTYsmrFmZeCSvgQRA9DPjGxGPcO9fpzXzJVkyoABtC9DAsWSexMtc7QGVWPT3tquOkrQ7wM+tj1y/vbcqxqqoMXJVbMCKERFSITYotFhYGIWRdUZde3qZeufd/3cKEdLlTuLDyxVTyKkG3fwPqCEWIiQEiyDW+hPlbLphG7+BYIvZ9iSOjYQQQi4nXk0Y0K9mNF4i5qYlEiLqtn+ThTWeUZxobhFFGoV1f326bOYuz5T/JCSCNwEbskPMLTVrXAeO+tBlp9R9n911f6PMlrBXYSSRkkAZNhLFvpnHrXwGp6Ou+LzLeCskqN+tA/4HBaKFl94D6JCnog78usgOoIs0IHzulTe4/6/uFXBvWYWrvoRtFyjgkvwhCFJR+pC5Y4exR9t05YTte3Ja/bpf+DMCWQ7CklNCsCFlit27rKuCjfhCmhohs/b+kl8btWRy4rJGsbzxgKK/Oh6EQhgQ0gL/Ytz3J23KgZ8y/qBXXF+iyQHrif5qKX0gjMl4KOGiGOT59Nevbv3B1g3tcEXhJfr/m+pne98QokAuz65SwS+tbf6NlJx2cyvJObd25zZi7pvBYN4bYIAZgAQGoAJAKgxoCZyh1vwD7VkCA/GAAPUNif78IUSnzMX8CMh7jsjd3DnmfHqXPr3rOlR2575yWbiqrDqkVKgN5dr2c5A4v02aDb/1WG7lia2FEBgk7V9Nhpmde3ibPm8SkEHoGY2rMWb2v9o1ZQj7SOJ8EIAROKjMIAlPEJ56httzMqaYl3z30FgYQrCaunpIHM+fhyNSecwzr976CrIUboEzSs+CLBj2yxPEsp1gyCdd780YAX085eGjv/FRCIQQgk3GBAHg4SQCQmgcpbM2uZNxeP8GcAQ9/wh4atHH3fcVELMDbWCJqU6FXwNU2WlI5xR5jji9gZzGFGQypBWqjxcv9Ysbn4kgKmknemQj0UHuCFmFcWaIoiEmjLMjfCSM8yN8LowLI/wojIsj/CSMSyPqIYzLQ+qX+r0nV8iZXMg1ciU3cpMsssgdspGN3CV38iD3yE528kB7URgPR0xXGI9GzI5hPB4xO+2FJzSgOHuTXMiZo+6I8nVnjHY6l+HOuZzLozzZdNY6L/M219zmY+7qa13ruE5xhH22q2zc3/X8ZZ7n9cD7/7LRundvO9OS1vz8f/57/vv24sSLg6dOHjv8bOOJzWuXn50H4RAL4egOuTN6d9JX5H9EZImR/XYlEdfC/dY1140cxPGOpu7QVvfZj15MYIImI4xAeGubDthg/WGDpafvlqszps/+FPGtJfNwI8kEmq50lNaEj4SzNGpAoDc5EXTL05wM6IFfI8mn73WqFTa7zf0fVotW8QP4YtdqklNgcTdbPDskxqOhxzQsP4lohBmbccPXCpwifsnaQkX1Uea2s8qdsIZ10jt3RBHjrRDCC9vn13pODmiCvIceKHDXUjDDkhmltSOWOXmIFo1eEmqDVkkBvMqSK+dRclnnskT0l/c3RZoNI/Jpz/pdFfadFafI0YE9mTJMGl3E2QIocqEGBg+UYmI7IiCME4GsPqXazCyFPC0RUHRuld1rXmqZ+FjkHZm+sTyVhFqcC5tmXgMO5VoHaBVJOQzJecm7RzMGlTMoWgbYiJ6me0bCaB45l9AYZiVVESmGlQR8V6ihUevX1Vm/sFqJdvMaC+pIrFfwe+XRnA3MJECD6yLEjW3Gsf6EvCJ1d84mwBYsC3DNSxODqnaMHvFzrCECWa+FjUOb+LbhJsu2dfIv1o5O79mNg4+U0nNAHt9Bgub5KNZceYiVYTOcUTZzk2qfpL6AeCgg5zdLALrJu4lf1KFzWUtp9F5TPMDEb/pd6Vhjm3UTM3Xc1YgT+yaArjSIJBxrVP36XiBjIAm7e2jZNIMmq2ZYMXKlgSdWF63NIKzgzsTPqTMa8s8F9cLlVJBAXsipIuE1aAIDXeDAEHgwBQEsoQS2IIIjSNAVypUZUBDfOTCAr4EhfH+R7mGAdehJ+qRHXHyBJzDwBQ4CgYdQECASShALIiSCBKlQjo0MSihhPNezVaKSEKtcginERjG3YAKOg+Pcx6YA2g14oyhhUUpZ41xZpd2lz1wUjIec5iToQdO+ckbqc3T8WUoL4L3O6lK7CsVAFjEU8G8rgnYOh18/L59lMS1Unc+5Akq0dc4SziNyfiVdoHhQ5lyzJ4lZsWRhjsTkcApFtwhBdJ9Yi18CxNsBtqNK4+WYqdeKB3fncxYgaOT9omzrs8yFfpwYUMZCst8mjUJOkbwZTgv8nPM9ac+esethV52xNGw5UwfLEhGDHklpfS7KM52Yr0VSwV+H0feEHENviIFUUGC+DtXtlw2C8Ux8klZYVEKJLTJf0pFW9Vg1qXgx/kX8H1jwQEGyRT5ZxV2RsHup0i0aL+Ze2IZBizAjJByyUi6mBnYvQckMgBYOiB5j+zZqhIxqELyxBUrRiqxBQrJJgD1V8siytRlYcpZvFMveYRbK8YMWCbqH+Sm6rplRd9pHCArk1m3tW5SuSBNVFlJbTwfstqAe/nwPfpmxCMHeq4ybiO51GTCrxeI1hzwLTuT6OcogKWF4RFBixBdFftG+kyVp4CYc/020IxBNwBpz31IWlfZ5Rjs92V1AohgI9zJaNtkWxWxyX1MT1KghF2N3cuFVfu88OPEwS4CBFC9w9FHGfAmPnwy0pqBAKwYVVsaTLCRTfLyd8zSrUaDRSbgQRAwTEinEovhIU4hGgphhQmKFWByRb0I8EiQME5IoxJKIVEIyEqQME5IqxNKItIR0JMgYJiRTiGURMUI2EuQME5IrdDwPLDmUBDWrfJA6lHYOVBE1VBsBBCIaqNGTe0BtKBnqQsm8/kU00KCn/EJjKAWaQinQHEqBeVtToSWUCq2hVGgLpb5Gu+Ro2BD8L1BP4j3/T+VdkvZonFe6LIRAug+aOAw9l6JjEwbDpr+FBT/Q/acA1////OT89cmXICCBWvG9xlT7E5L8SOKo3f35WpHc2leDR8WCGn228EqEDMpJj/SaEohaOcqrlq8VtS4nGSApTxqgAyQFuwGJcCu80VF8vPFfBkIsFHJG/wwvqgeaD74A3Xavp8iUDKftOs7I/c2lEEeqmRsaP/u72gyPwTx+8uSln67m9aptZGG+zD1Mw+Pny737vpi6dS31rRM8ud1jij0d7scT4pHeDNt9dE8evzxe2Fcd2UN9wDP1r9IvGNCmK1REmPXITHoyw1qenVRrpVPegl9y2mSj8azyWaWzGs6qnBVwVkq9V68ep8flcf8YyF784AHf5nrN2hZtB21FW0Dbs2dKU5n6CZhk6fh1aVxu3NC4unFoHJRqnFHrG0HJgl4gAIq12Q4WeMjPJRETZ+JBbr63AUS6B/aU933Ygfyy8EvAfnCgNQ5KibMxhuC9j5GISFL+/FRMfv76v42xQ6/wp9eJ+9JSmJrrvGeDjXWG1A1R5WNZDAGksrx3EL6l6IJsBort12fxkFxmBG/b+u9L6ykIkLRMMiD7QOj3Pjpx80IHHDaPRtXNBw/3E6Tol1WFZkp0ALEs5YGAZlO0/YLN9YrLt8SobfNx11U6Pj6paPsKuRfIy6snRi/B2/oCfNPYKnhGIh/TBMXg1yhH+wA2IJWNzeNDSMErDka4H0OvM291dXH+Tk4qhJcjy2nIpVy2DqWfJKP3zNGtWP3GEetrYPtRJau9WUCPDt0IHyMiHDy5m2FL4NZhVt3qtJim7YY4bvMzKD4Nmjgl6fy8ql0rzaroWdnLuDmQzzBDXDkaBhHksbjLWDtUphcPpRAoNgeKTvaI7jJPh8o5mXmbEejTHOJx3AuaJQQ/hjQm64ygHmUjsWOKZrO8DLvuYwAOEgVZj7DD1M8xNCgZ/tDhqCskq7p+Pq4JAAo9RAuA6orSYn5G+gDaYNge2KAxvfp3KJOKLTDRJijPKYmlguakYVTsTW9bI4vACErZt2pNV+je1BwdhZeB+FuOtHyWj9uDw4rMZJgqqquI+6Pos0wAKy4f8XVSb69KQbU3u1LjeGjR10YFWHl2dxgZvXLwS3tBUdxE2ZkcZQOVCgAcqIwIq6b+d5TMQEI/ap+M8rjeYKZuHVm9ykjt6nqGe5fW1lheD33eFBEB7Ya2uNyThJKNpGxept2RXCjnYirVreHDUaR33bUJuyjK6mGmXw4yh2G+asmDhG2rjLtWv2t8h4KtbUPqcWvAViZlH1xXpl7IZA3DoRLF+oxHUzWPWHfzTE8zS/yJheW7ARKaU9BhRuH9BkRkstSCXuSuOhxhwCJyVSAXwVzUo9Pxr3jIOCNWNWPjacil3tjbzErfE0MHbO/EoB5m1K1ZGm+dmxhf1bM8ab1epLYXfsdgSDFh3RIcih+uqcn1bePEaVnXbEEyjKRxMTes3riteRQOZ5FLWkxMaYqN1SUew2czMHokapL4igZNlfibxXO9EQYEyMh3g5Kwii0UsJ6u4T8rbp6ACaIwEpDYXtGtGdAX9klHWHmkxhsUPIbgiYnExMSCfMgR0M6XA+6HQqjyhTgp61XZBsiZVkgg9GxPzSkqapwGsyqPNVTyDYteZCfonkn2MEC/uz+XixRI/08MYW62M6e6wrHUCH28L2Qu62HjpokQwgHtJGsDMphKqxXZYnJbnoGLnbA8+cuBNNc+MEJAOzW2ogsYFiMyINbCma03ny3AGHAVWR/0g0qjYog3ToI4WvPGmsO4WOoSr3kBGxuasy32y7BRhozN9lJd1fwXD1L8DuNHUDgBQ9osgPe9gsYWGjTreJXILRJRtGc76WidtUbjacJ7qa/xwTBIdpiZKz1gyftKrQCK3QYNZrMcy10uKaxMsZhxZmQYttcQ1hNKUt2ZJZHXGRQPdg+aGON0UrHKqJt0YgJuBuW9TdHyk5iMHNajAcUPkotYA8cy22CWFIwC6UQpo8mW0oWHVNtIRbHFvqbCkro+wmTDL2Z/2qe9FQJIZpH1Tn2W93xh6WR4h0aPvX8HMcN0FMigZbGwNdmBgulsR0LM8nptIh0cLh/1IPpu6ZtVQsN7Uyw2HBt3XbCTLDlqOcRVNMyAJty1lzIcs489P1Oej4+qhJFIdCx0BAJFk3GOvxG+A7jUwd+wgrCv2Taf13MGnH/3P2rTFFigWK/0LeHrkZZs3VTxO3G2QEYSwtGOyUjEsn4X6wxmEVt6JneDVW9jRwIZp+UMMFOkZlPZYCq4bbHj0SnF28TYgQy/nT5yrfBgBJjYSKKYQjm+5gmvA6icZCxSRVupi2LGTatzqShxzjD28YRnkA2vKtNOhfQg5V3X4qEcrm0Qj/Z1pWtcK/hvvlfA6UmJfJ2KIb4X6YTI8tsuHoq3Znz3A9EhYbqBtE3LSWWwitNhH7t/5JD+LpWTmcG8TOdi43FsBaHq/CNVhSPSO3gx+GV0SBfeYyMGCv3hZN7BqaOLmDlegHDFdA+YYSNtbA4bG0t0zzqRRQZkpAInz6F7iXOt50hVzqNBz4U6VgeqCrpgMrPb1etjZAZY9XI+7j/zQLAJAOVESIsxWexhXUqTWX8beJx7qH+qDSMMFZHlp5R8oVkZgIF8PDZeA3gx0Y1jZXvy+7CRu6gQukAs60yYb9tUWoFSixb4GDsIwO6gaje50DP/HW72wTD0t8UWp0EB9Wk3dsk53iZkKmO4OqM5KxSLDcextYA7R38tWwktqXjmsdtbnLnb9UfMjkvgzD43k5DLugl9Exd/0KYsT95yElTIS3Yuy0W+bq+rU5TpRpMS60jvnUDGlop+sovvYuSObyuX9+VKKWXEGjg0qJhThMw3f2MD4klorKI5sN/yjFsXH1mvLyPiuN6NJoIIUSHxbG+z+kVQFzdsGxMtNEyzAocDgxmfdEYiXAO640sqx/Ah23SFAgrfNhHltOQRayZToZjL/E/pDbLTChOHq4HyiWR1nK4snHbXn0N6xl3DFOVlmWSX3i2qtGSVFkEhx+3w7RzR5EMCUvgZa1aJ76q5r4ps+NjNl0g/OLOkszihEp5K1TDM6RUxY5pIssvtoHgk4Jzs5lYzf7DYmZ5rHZ7RCW+i4B7o5nbB/Wb06q9o28hEmmMnwk4nq8Yw29QPbdPr4A8XN6n2C2K0Q/vKip1YaPC90SWvy/NFjauut9haNrG4Vji4rspnxtuFf8UfCUAnC+INedMUMfaPgukYNJ+3NqF/QtwJIstjZdeQykPRlrG4bp9tnpOdC+FbOMe0140uT8Ju4ykRJdwfHXMl3k40rkxs7xPTto3Ew6wHQjh/CguGirBpDpgFbzkaJe2zUNIxtd9zClc82izWWLVeT72RkBIaekScVT2VF7NH1zk+ZddSbHPYG8hr9xZLs5kju9KqFDNi+Bl/W4g0gL+RYTUNQhqNYmVHo7CecQ/a2TEzd4ABeFyMQh2ESaRRPO14W+YVDx9pxfyKrjl8Ten6zSiZvtO3jL5eV7g+yVuSowwgGV4XVUqfyU2sEhPjBL++FfWHRJBja1BlTuZZYUZxRyDpDCjEeosDKNfsCLC2RVdox2ILXlPUv8gDdJFl9Itw+cHfBumW23DEIqksi3DPbahidEm/l4o1+7secdjIjWw1CDBIYCil1yy/ish7+FPpsopY6oSQzFi7/SKaqFk2f+FC02aU51ZzIVdaDjLDSBgzCdNh+sKJVF7SiJE34LgZm3uxJNIV13Vhe6y7IEKVZxplsqq0qzMWdocmHg68crgdaRlx0iOXlc30TalcxGNBm8fH45Kd7il7hzcGjmwCuyN/XX5neyF+0sdz+ivU53ABBP9OxX5yqpfPqQy2pCXN2N6pt6kER5THsfVS0ERAw+5G7JeQ04uuuMq1QQZwP8w0RpmLfR/eIYJiRd/YDn2/k7YnXkZ7+loliiq+4FdSCj3zoe+NldIf0Huyv68vPBuRHGvnyl6V09wqh7Rr8+oMHj+/fJp0Gmeq/oQUgUqvtPD0paiafrn3IYb0GDHXgBVluZAqNMHNbcC4AcThpl0DUKcyVoSFH0slItswxJjO3ZfLWdI9lnDAzE91Jnd0eDGXtqqkMzCYCTgjafGWyp5MiDJeFh50Mu8c7EyvpWh9dYGMUrdY5+EnoT9ZsnX0BlHjKKuXosJkEZl7XyvtaEMwozpancLXRSegAyoUSITJU8PvU1qTil6k4DAJuoncCui6AlyVmnV/5RZ6OOyuSD+3r4N8WCaLm71EAvCrEjHwuIdmZkxDRO23WKDjYTKjLY0gv61q2jXgQbPVf0tevmujy8qR7g4Nh/FVT9kI94skluZdV6pPzqrbq4ZEkGv6yceQTMgrCEQ0Hz7NKbT52IAf1oApUq8Wx+12vXdlfy2YW+9uIWqiwSHKXvnopMGRq34s1tPoxKJKTNhPGuwf4GNrcHekOtg8WNY/CcyIWV7G+2y7hJ29Kyfz76ftM1+siCh/aEzCRl+4qsfufoM5c4j3DQmA1/keIINprM2uX3CANw2V5v6qPJdh9c1e0eY5DPbR0LmM8bf28+kq7OP+8mlmdxta8SOEKtvSHr4ibu6OwCHE1x8BO91rKyVeXiyrrAvYx+hjhpfx6fyRmRmTFYuZG2aX7zim1mSvFxJZlye8rV5L/Ee/TocpojxX1vmSDK/Rc1IlujjsLIWY5vcdsUm16aWQkNj5tRRjEt54Zuwgm/CLhKgtRmSOR4Upo8Nnv1KIf7fOKfBfZ4308vXu0yG85EMEqQOVRT00hsJN1+wl/JkOTDbnQmLEbSKmdutb7GymsJr6HllfHqeCYtqj72xifXxwHlujz6PRpTXNIG03p122ioou2gPwwnjjlcS8QTbJtdXp1R79XbLFer2jiSRhPxnz1zQnynxVz7OGOKEoqCHm7/nyRmDunlvskkiHtmjZKPfBb+JLYsaFxdr0iFkZ+PEcbG3fHaH1zTA4aLY9w5P4kyfttrXSQOdGldOmZ2ri4mryTKS+OnVf2aF3PZvysa3CydS7x2PcW1Bd+r4hy4/do/z9SnG3Y7BXQTwWPQjwugok0nkRkWGZZKdbG1uP7Xbi2HmCtHO+oE90UxR7riJae33Bf7pLyeGkuxepU/PoBikvcy+GxHxxjxIgSU7IZ6bUhQb727+PEh9I28PuPswdH9yIEuRNBGHYFGnsH+EBo5juta04DSQdCo5BPznRaesE9tx2S5bnYTalmKCVbuJHvhnP8ywyUidErvY9frjAJ5WQBCx43N7kd90Xuy4GhBe2zMSQi1QpChWWcSZt3Gca9e4FRqD5B5bvNgZYseleSfS1ptp3Xvpo5fnU+vW7i63JjzIVNp93MP03d4Pbac9uzCfzXEub7tJ+2X9KY2MbH6f1oy7xDp3hTcCUQnxvggzlSNO+VljMasLzF/+BgDnQZg/zSMd/0jKTQlGktdcoGHkqe2PUMhzGSW+Fe5wRT24+9xrRfv6ivAww031kGvG34wb96j9BibonC8fwsdje5lhf1yTuqfCNIUjfHiUbpzf/G2Bh+SRiBNwX8dgq12E+UsJJuiarfthoCkZjSI01fk+6DXf4Y+7HvBSDxR7KIyrG2PJiUng0jPyZcPIapJWjvb69FOAQGEpZTP+lm+ID3E7EAng8/RoO3oXB7tJBu0GINAGPY1yHENXB/8TxJ6fCcCUY8jxQuPvkD7QsDG0RCFUa62nqJJTOH34Y49E00OXK3QBZTSd3YXA5vJUT9lGGFsyA/Rs1REOxcVJauwHilnGGQ7CyIxS8frcLZrohndOE2UM40wOndtBVNAAd9iHtCX+AnGeMzvDKA8wbikpCKOkg3L/l+qfuHBsesf5A0IDynFZqNqkjzv4yxUt9WhxF+qgpJV2i86bQa3GWxPkkh7KXu1Rrkg6cmlJoytN83eMmUZovvqBtc1Ai3ZhbsBigGxsTadlRleUJxD/tmpJVt57Jk606J7HA07M8q3XLN0WqnDBEeyPJ1z1hEg9/EgPRvi4z9FsU3STkf1ZS/e9U5EYnouWXC3ybSxx8u819cMzgHoyJyl7T0OTRKNPlOSc2rkkb1soX5KOYkdDi1pwUXcLRQIWx5MuuWhVpnPzPF2P/Q8bNz/z6aXfFwlB9MkS+BJfxH3Lg3WjCHhJrcd1P9HF3clmRu061caWg9K5Z8bMpUkxXNClqso1T563X6kY664vjiXuSipWnvCsqO0KrMnlELFiQlZ/h6h6Onx1n5Xz+Co0Rq/SL9mL7noXZRfQ7PzxC/Aiqy9Q4G/ALcuwm5a2Jj30bEareA79jSyLBFYsSuMfzMCj4bSzzn6lpjEZaUCP5P4lz5BME+i+mC2nxekMNpGwRbToqwhZRg+INCol1owiisW4/WV23go9DIyxpthhgySSVBLHg2B1mQAP9HU38HU34XOBOwU6EktUasYirKCFHuFOHDbpJogidkPxJkArHjcRGgnelMR2l9+F9326U4TWulF7RJn1rKt01kHYW+evATG9us6nb/2bZhvmGjmdM9Iq6mFu7qO1Y0zbIBKG/FYu2xVNhG2Q4Ap8cN78Nk3ALTZOYTEydkkEqMudofdnLleXeIt0aZSj2OYbbkzOSX2r9cN5PLYqt5XXahvk1x5JPs2EdtFFWh0VBMbNOtALEiKh+b7RfbnUI5LHCfg32YwRjq3q+z9vU3+LiSU5BQBout3VRJCI9ks6q2Fso8iU5DakS3TJvi9sT+S29pq9mjTRBpRiJBRCZFlbe2btTTMJeih1RHVcs3vTet2aV0rN53G9sKJDRgbBKvb6io0AutsY8fW9/Vt70+4/EPwSQy2tr1ZmeycLb3RubG4RteGjZWEJmI2yqmP1IN79AyatV++EptT52JK/0xHbiZgdyiCNJE8jTxbbK8wonpQ2MXPm/6T/woH4KL3gfTIV9mKGuq2rLt+Znp0X78nviyost+SXNPtNE05InUVthsN/2XHYkaw8cVWoJvIqFCtp+NGNdgvAPmjYpd4LKleIT2jI1z/7FxSxmFHDmCD4Uezb+gCWh0eVtdoz1lTcn25wVoU24CB0hHYrv35VMlnLb+8RVzxuMwk2litsZRHWW/D6aLJtHEFT7iGkZigsYkqw5EvF7+ly4um6Yj8PALWm2WGB6AZUMseBCNjFt0I8rknyeJFDwAx0/izNUtomf1+Gx444JOwZv3WdaVUQDMk+LwMUsVUCveCmZ+x1jF852aRmK9WEc8wYT64PMXCVqNVqzGA0Q9QEXC/a8C94G74myTTkJDOFs4awPgd+Sl8bdSnoeRPpFRIqY/z9qUvrIyBVQAZBQ4l2Um2USKnOAslJFOzOcrBGmFdhMaT7dzrSv2ws/GtlxeFgbN5CZX6Ky3WryF6RJs9M9cT3OxipHrtVncr6ksFycvyKrY3Xc0tj6+mX3j5X2rLWcPFnfXtpSEUWFodDC0ybvgrm57tKsR2NHPmy1UrnltaalfPBDUNq3APJJH4ZHNb9ry1oomxReZZ3Pwia6w4rC8+5aQRsu+2uWiQBXLQ7Hfc8vZb7aUJ113VdJYSquoyeP4KUmmQl0IrFzgFdSGZP2X3J342VdRXK+NhEbYhIVv7+UTXRYfwjsjwDz0VgPKWVkjd2SUl5STF/gDqk3F3B1nCI94nwCe/n8Ct7+nUtxYXLGCoGRmpzyW5QpcL2szr7l2T2KUivGbMLyGzNK242rGxfll1BeZogisNI822Cy0tTbZS3s+enS3orVDwuflqzbV5C6e/vzNiuk0OhbN4do/83hLSlOWzlRwtRGs5dKN4BahNMQMVfZ3M5+kB4/x0H+gmxdwbkbjsFzPrVXyQzxrqTryS8ciOSQKTpup7ID/joPE2zgDGUaW2HJ6KhtkcuuqYLI7OGZmuZSQWYYai2n5UFgOqZ6uhR7sR4CkeTp6Zilr7Ngh4LC5Lzdj8cQAA9g7hOWvNekXru87n4O5zFTsaBa6ZqvzEcBXlDLeS+rTBxLp9GKmOWbFa7e4vZ59dqKgTeXd3hp8TohIrhwSSeAnFaI914TACi1LlSNHaHecyguLabMD495kMzAYZ/rJXveF37KbCfkPut5ikA7Y5K/nYTayE9Ixc96nsbWgk2CjjAUdoT+s9nMqSWWPxuAk8O300FEYGQhJVK5oqT84YlNXIBLZv9tTAIPMj9MPQZqND/phwf7mxTVENoZu/CNBuyn92fGXsvtvf2QihOSC32b16scwiJ2Rn3cNxlYitPL8iabSu98Q8lh1YQLbtwYpR+mmbxU0XIlZd4yzl6sDy56z1qrMCU4hj4xsk9dGiE/w8XqT4gLErR7Ps7K43Ry+kHbN5GtWAOx9Jf+76mbswyR/PqTX3tyEubHplwGqgXTl8bPDE+UqZpDkLGKBW80+dG7KNzzoCtG6gnkoWCL6MapdnqrhUPMgKHSFQuDmCwsonzp7BZRgWYv/hdYA2PVs4J9M0lFmZ29RbfyE+QGVkyCU1e6UJ+nO1s+3O2P8zStvVTz+NA0Tyaov79qD8vyFy1fSivOEQW3t4PkQWlacU9JtkeiUxXq6KsgleJYJ3OqOfLF/flrLpY9dBjeF1YrMUSy1HLhwYLWTluB9mzpUJcvPu6JbmrMXCQE+E3abXGH/iVpjOl/mJ738evjtaaDrqQyDCZP2rA4vPxmNIo4qNjR5bREKz3OeIewNoxgMJ7+eOHSu8vQpMiU5w9JFtn6h8tfjfG0wlXIoph0kdrMT6uP1pBWSZ88c61svNhbKmGAwK/APbap3iyimt0+m9kbk3CudrtZRW/Hw9d7QGSLWEhoK79hqWRTO+fCATIObIFdrVgkpkK69vBMIZLriBlgDvY8RWDSZXVz1N2X++ivzZnJ84RGXYbd0CM7lCuKcMPxIDHZoJzJQa2Z9anzuze5XclU1j3gr0iOOWeTekDVw7L89m9BEtZSdLlfJzKx+DOXsmS19HnqY7eXRv1+v67zNGXFN3ma5PGIJTPxtqpxEbAyI35TG1eyTazrDa9LqVx7IJKNXGWmFZBVrmONPfHaI/qfsXR16h1kN/7u0XX6o9/urVgrSWf9Bie3jGlqYw3f0iwHgDV0JhnAmaKeZ2bP37Hsjyoqmj4C5edsGrmSXyY0tYGFc6V7RRtF9v6B+wO//98ROLRTC1bnnFiQe6C0I3ZqRABIqa3SYrVe+s9Mgl7jqu2o7ixzOUjPkfHfsQwk1j9pA7w0g95X3lN1ZbpHDOWSqnxoOGEjhNUjubLaHHoxZRu7j41KfH11scv0flCos7NRfVMa04yEQSBlfmyeQWEsji+yJoUFBkY4gLwICC0i6ia7+aX3Yzqkd5GIvARB8ieQalZhf3gUpFQyNK3i0JlFnD2xNa0KOijIQ8THDyBrw32dSSDALby6l59xEoFvRcT23YvEjP62j6BTLScLyFhfEXxtwIQcNRW1EfuHBnEyMeDJ8klPQdRyX3alRpuBwwaC6QVFkydpg1jvW3uudekFBI00aFWJVWiwEetvTpf5naKU7EPDy9OkBwu4/KpG87AQewySt88n5MoeR1vR6Fxe2vM01SIGAfiY1hv/ZcdsiVyTN2DZ1ts2pDUE4M10urbvUGkyJ2lsS2zTj7ql6Ircfve2Ja1qYaqVFjEDvYKU4+fNzLJsC64NAUH0FekptKNE4Ie46D9YC81RRHQQpbKkzCoxZYjTdHP9w2NUT8yTkB5G9g9KjpUizqmJG4oBV4H8JU10uzhpf1SLbvLgJ8YdZdXsUAqO2p2W5CzJH7PPdNZ0FDetZnEz0k91VdpZynBTJRL1jDQVfRSbvof1f/Z7G92brcTlWd2mGLWzjkb6Wj+PfWEfLROuazFYMUhICxVhTMzVnxrmaAL2vtSvNMKKbHNxOg+Q4zeW/izJT/k0ZBXW4HEklpqdNc79S5drhBceFyJDDmm3Yz3YmMEOqjPFW6QA+CVN6uWa6V/5JGgvTatRxa4vO7ZsVkEx5OSSclI/TyCkEE1xM0qQSMnbSrM0fWOnXSom9THnoi8iTbHBok2zryKlmVQ4E07aE9IN0SWJH4sHAyloJf0XWjWgxbq21jzkTXftVOVFLWAOxrwg+l+isUlkYup38tMEv2jDvJhCNwOlgyH6cIuxr9iSTCqcCSOdln14C+b3YJQ+yz7Zfjg5o95/wyrQ56WYGGlMzRea1H5gmHGGlmNWR483z26/wY9nf3nlnEMcfReHtpMSXySaFqN7KRHQjrcMmauGsyt1mIFPMLw/gCNrsq29/vEtkhyQ/IJGjV3YjKcRWhRnVfnv5WZc2U7uI84bl5E8yOlQA5qwn+jX3m56lOgw1wpIOpfnfPtXSS+LujY5DFkyC6sq+aKCwMCLFnD61FIoeTg30CXUZiVmXFlCz8eGVgilc4H1QRaQcD6BtQGv56d72PkOA1h6YMZlRpXv/nK8ubwzo3zSuLqn1BirL5ikVASK0xra9W1leV0psTicAsr+aAFWT/uBzVxQtGSQQQA5LCDG37pma3yP2deR7HYuWcqrJeSlDjvgABxwyozRPaQZkqx7BvM/ivUikMEzOdzZyvlZrY1ZeVZrLBaZjpM0N9uHRYAXSBjuJRWnsQ7QIwtdHzGyLQpf7pIgm5wAsfSAb7EzmoR095kshdJOStbzpW/wWBM3TNBPTXnLTrbRsADisaIygUnMS+CqDBn1tslGIxN1H0fztSdJpwz8dYz4nS3JYy0QgVcvCgMheoe95LWK6JOM3f+B9RJDWojHujQMHJaiBPRL2CkUjAaqwuGc6jsJS/7opZaRUNlkous0AYVPItiF+pLsLLNdUNRI44KzeFh8Y/y0CohD86qXeg/j7FGdb7F/Y6gT6pRGIsq79EAqUcsACU+H5RmojZGePe6ncW1Rh6bDzjpL96V1MaoIufEo6DNcrLSNV9d/xMR2BH8akmk4W3ORif5+iYch0gjJBG1myGcYn8DkehbXTYjcF8nc6czmZRA/+37fVJKN51+OmKP0/4P7FC4tnV00SwMAdKi3uPhfaZZ6mB5MEqzBipLmcY6/ddJxWd/SXIohgiZ6rDyxysBFLwTjE7VCZnS9ZMhRITAVG0UmR23sUeNiAviSvSpzRz4Qh+aUDQiz2VZuS5I6/vts3Lpgvwnk5Zc02PONSCwlcQcG4BNZN8UFYrNGWZ57araJBlWSrfBIK6b7RFaoNjZ+uHp5/vqoTRxzSVm/bn008tsT1IhG9DbpTxLZ+Ir60mXptjjSlwDavdSrVwd0ihcTBW8z6paNcOFPqCpglPE/TabXz5w0mYi3yqhFKbBRJVCXamryJqpYc1glm5URXI3va37brlWma9KUGcbU1O6GGjwOyW42dzUWFatyZblunrSjeeJ1UgagqK2Po36+pzwmhrmgIS5K4SmOsWUMnD0zuZ8U1az6ISJKXkQOj4aTnk/+AmnkaJ93jgocDKcsof3cQ5EPlH9Aw7+YEQKoysX/JL/YvT2dgYAg0jzNHkYZChaFu5uT7YuuPPp9XgQrH/z+KK3iD85OyXRTycZo1X8mqZAW4+S1RhRVovhHkVHNdN0+MU30soeTA0UNeOJsDrNMo+PmF/g/Lq3L+7KOAq5G8g3y2ZIuiyzVqiC8ZSxejT8+R+RFYfOPk7/03hlyy/3PFemET+CMeOPPzkCdlfsO+/vP35fFmf+Z+ud3wmOoZbPHXZm/pJjoGEWIV+0pUHnUngA/zdbQLvfAcPTzaEHhEZGfwLpPCfLvakrLicCcFL3zrgzZhiKdQkfFZEeIEfMA0mo4R2/dp4EIl84Exq2GdWdUTL5OMZEw32IWCBNfj9b29C5f+NX+EV7cVypglA7X6QHs0rgRbuzXKgYB+z+tDouVZ+2InFIoDIlRjuzsXA32cUuuz6HKtTHAOjj8Sq5InmUV3Fi95m5LYflzmCx5oDqNl2gto5FpeSXPDXpjrbkj2QLtGTxlQnyZxBI4GIEwgoe35jFT6GBgYQQP/djK6cdX13csHG4Y+vT9ofbhia7JsW0bxj2F9ca4elGeI7F7Q37Bl/uDGahQJUzQOqgGV4PifEEwGouvTfMYtdz0iaPWPavWIUuDADC3DYselqXYtHy1Rk/3RbudSR6j9dVJgT27Eu9kn8fJfStsqz+CYAhsXTluZRz3r2IsxEr+rZmPXHWr75kRToD+RADCbOomC4TtTe5TIfHuv3s46O5dk9f9tavGREG8+wIQF7y5puOmRT/mb6JBIOyyd9JG5HE0PwK9qasm9xeWpFeMLanNyi60b1lS1FhTkphmkTuWtBclfpYU+iuG1Sq7hYA9VA0pVi0MRDZ20uMGw+DMP78jfHr5fjQDiYfwu3M3m1zEMVsE/dyX5GAoEkM7yPz5C5lVPQ/HltvV47g+mamuz6pI1MSs/6NqUSRpJIxvUsn85yTWrhs5mZivmLj+rJB4Qi2fUkv/HVWWROGUcrA5i+FRTh2vnmEP24Tx4AiROB8TOv3BKupoD/LrCPyvGa8ESYVNZuk8EMflrooSYAupk/rYRJsxcQCHezdcCwKCSWAoAsxiG+7Fez0+MFq2yNiDgxcQCzhkdP8GpIA0+ZI6wLz7btCYuoOa3iX7B9e00j1B/PEttpWELNMT3SSGlIHPKJpx07Ksjdp1UKQRhXkKvTbt0RxJvMjOp/hgOFvywXyAgxY0rfQcvZun+nv6K9tmtqPyqIWJ6sUa74DkgDWJDuUNHPL/ZNVdQyp8CHYrODxgbaI17gYB9SPp2+QX3Ik/ye8kQqLs38su7soExis8ojteC43CUTY7FqzOBHB/LTqaIHvDbb0EkYrhUZKAYODHcD+HfjqdUlCf59d7519HxCbnq+z1g25JUnaCq3aZetN78Nso4Ml8KV135GmulYnuw+K7Lb/nMZFwOkr1rFLGxwwk07CYodTlKRioL8aArJQvNSLbMer0t1TEG/JOSFfnLc3MtC/xlFHXESR1g3zgXtReaFGOnCA4eE5kqVl7fWbZ1YJ+TEQfOaXc3XUJGr/9ctGJ7dCnkJzSgmO+j0wjLY5De7vW9RllOOJFSSz+awLif4Z4Q4rcFhXNo7hC4GY4NSulJFWncCxcWaTaQlYeRNwVW2rXXpsZvFbQh47oI4ltRcMx5guoouVPFw1f7sF+Sj0bdXTVFd7+AAupizWTNVoz9dqI9GLSHO9uIb4ln4S0de1F8zLsS7xTH02pXSq8gj3jLUkKD34+UXPNzM2h77iSkRrQAGD/uC/hXOKHalmcXQR9CidUSTzrtGYLXPUTK3Gnf4aM7KLesYtpkBWwobZCbtJzcUh3kfvIyB4cfzS0OOcy4nMii/Lje96VtcBkfbFfoEuBbiV11okEhXr0kYhJ7s8nRD4/PHGQRXoRy++5LX8pnMwss0E2xF/hPDHt0YtVpKcgphaX4VoE/QalNDQ236IN6eT+0bAQnAJ+pY4ZP16/mkGZpjvkbSZ5XfsrXnB8LzWS8wfiVfKOXghm7P7mwYUVr5EkMvBs88T5AfF/pZOCLL0jU0A0jw2CQSIdRDamWXkJCf46uXHvh4vFIHh4V0I/GcV26zEBr9jKM6YknfWRc1Fpu7LnK1I6B++QfaygI04AdwhWVMMlGUxsIbgA03xJEzMHRtJYr0H0twVHKZ2+PkYIcN2WwYHPGWyPZnUru1u3iPjPIthmVNTMn9KZIH9L6ANj0TfpGNcfLOYXhJCRHCMgGAT9WQCBbUlvz6pK5OL+6pBDVmrF6E1g3OqFLTc8spaCEsrDTFEEVuK3LknOOvfhKPXWhaYUkJ5SkCNGi0V+NbDPT506Ka3cJC+49foU5l2MY+6+W6bQTPHeIJiP7fw2Tf6ul2aE+x7Pw8HW15+3SD9S2mfDr2In4h9ZRiLARv5sMLAHIo4uEZCeYjG1uEzXIigA3JjvXHALORS0sorj+2lxgVjgHXXM2B6wTMk2D3Ky7Obefwf0lgCtZ0PRMGP3m/OXVrxCkij+M3Xhft3SbiTCvWHcnZXiyjZilxsJatX2fxL+9guFT0vX7c9PYWe/iVIFayHiKywxG9sZeyZE818Ob0lJ2srxEpYGEAknL0mn2RpgKJyu/Wm0VQBXo7mOTAHJHX/xU1u5CSq/8Pt+BpPbwwVerwX/SpmKQa2BZCtFeEcx9FbAgr4oVE+dKrvpSZRhJdGPqly2FjzgemQftaQ1kH4o6gukm6CHIvWKWQN2yvfjK5hPejYwvZprdwBfA3m/jB8EcX+9qRTVxTGPTkw+mkIQyLKGoZamahIDX+q36WMMxk4eSDsBsE1FDZ1J1xlp/Picn7fVPD44nZsYdIz0knxvViZ1I7ZRE44UfeDoGCqU4K06/MnYR84J/F6qmmQX7zg/e2cxO2ZRe8G+OHTrkljwhZt+oo8eYs4iKu+Ej38FuP890nbzvkNKPpoQu4W1zq58XZNdP8m68RqSW/1rYp2UchOEBLejr030DNn5o1ItiUppqE502hJy9eO80S9NoZh/RZSqjNT52NHIKC6Y9aZhK6vLkEGZB2hmtbqQGlN8SD5W6oqTMHZiD0TNUg5QxPfMSZbzxZ/K0Vd4X6d8TZnA+CuqfNqKdg1jypEwhSr+mqfj2TvzneJfiXix80729ikc5E/TWE17CqK6qY+lVOSrUy1oTlhTTpM9VoePhMOvttTwX3exWznPv9K9gPCSNv4WXK/xld+knTLC8kswu1lJjQQ5Bt6OkdlRF9PX+G6b2Pw1zHmfLCoTswWBSkPHsOHRoTV+eEHo4ZGVG0xmjas6ZUxhXhHTSTHQFr0TLDAHbDix5iuynft9C6erV4n9Z7OsyR/k8lY2aZeLsNOArLRE5JuUJ4elOdNPrS23s+adTM3cv3y5LurFH1aXLaW4qa5FN6THfGQmajfel2/c/TxDk+1xHjnCYnyJR3TFa3GjcFRuKfLzNgtAwFkm++EUm9jAHl+attg2NXctZy6qVTe5+RPjjtIL2F1pSc5SFjjUtQ/PmX77Zqmx8E9060J3+6qNZmuMNV7lD5GD/vMmNdRGCJzAv6QOoD/9dQ3dkiujfd0F0i0yqSrJPnf/ufwSzCfU9KnA0rXI+EzSLfFP7nRvR8ELgpt/OQ/PDRgb7+ZdYeFzDygw7eSTrq2POT3td3n5Bjo+oUIXSEXzGFAms01y/T/usbevJxY5kk5zrtUmJH0nJJ9FwfDwq7q+025ylFF3aY5uAEZw87rZ0/3eBEv1fCnJGcuMQMNAKZFqS8lLpyOIAOTh81znTIf6mi2xlhxL+7J9eTxdss7DBFgg5rvWlr+UDcfCSp7SE8qWljEX//lZes9msvhrTc+qT70oIzJIhUk71Xgp9i8gqIC8R/Yyg1hyeZpajw3htPaTi4PbPw/sv21yV6TeL5shl+228sROPukpFVlrsipyR0pD0TUYMdHL5yXmnx3w2JfU8beW1USxtvOSjPyco18ovDjj5joLlZqVROwrIbtWYQSiDr8Uf14t1zcdl/erGb51ka2TL+o+R34n+Yc2JygRrpLhi4j/5b2YHOGOjueahIdJ2SLqbjjIMdjO+tr3Pa4VaAMxOAjhNEvt9pn+Kp0iukyBw6jOh9g+Dm1aUNIGfh5nDu+6EFAG23HaaH8YrC0ti+uVL2aqHws7y9iVsSv/Y7XbV3etQ34nSzx7Ar92on+lX51Js5mYat8hGgTqbd/VOSvR1V5E1PMPqx9GZVe/UPvF2qhh3buDUvA3TvyfuLM/+ujfmub2+RVNg0llx53x1FyBaG7+2zXAKOOONfaqbW15srAj3ypBatiDHyWR8Earrhx+/0zhHz8jsOD4Wzo+sVLzOQ2tpONczBbJjf/I5OVQZ/MgHdrFK5p2tMBSXqeeVtDnPYllFbc7PrFX3y60LL8cun4u7iQn95Qb2waluXL8xayWgZ9iWcEVuMdPCfpiPWOeCV2x5cv/5a/3OPLZn1y7J8nZ7JKr0v2FrvL3UcP65vIksUYJd5ZUfvOtunWASyUg734UQ5y+y/sBz6/E7nheZJUL6vKSuYX71PZHzuR804pF8RHq29Lzti2VHJwP/tWMtRRDn1JeAARrCkkXFXlbACujEapgfwZjhpDvUWcXMBJG1S0DPBoB9clHMcRtZ/gT8p8lu6AldoM8mE4KYnC5yNHUsl4JlQj5PquTw5lDECfiqVhd/wsuQUTW16rIjCEc52/68299TiPtvvgNHh3YcP0I+goJ37OmF672jOPQF7/5F5bDqdwuTeliwnYz01V925O48ir9D+Q0jYTM+7/5O7XfAxWM/QaGwtRDnjdQ47nhp+x/D/4REp7cxtBu3WL7P4Y/r4Osfx7gGSq2Po2euOdtRcL6GNUbsIvLJrNBcDCMeHFjZ00l28BGYSUudb8i1ldVHuJwRZ2k5aE3fD2PfAqD74Anle9a4qUJqainaCkgbk5HbuVMc0BthBa2A5G9exW4nowbpG/AszdnLZYCzQTxyC5fkhsTzMblP7nnjzvjZW1uJ1vuZybiEuB+XMJlCgod8U2ETJoNvj6/PtAcBE+ER1wdX4qBs0KMgXpaIbUMHu6GROsinDWcLOkaUraIWlQe+DOEN4Y9Nudff8P6kYTXlB3yWXw5ifZfpAlaF9tLHMnoMMe3FpeRQbiNECt9kNOHWRhNzaExGykYUVTkIunuZYeHiAbmmQVnrprsBS8tJMSc6CC0xOY3EK4vv0/Gr2M6VY4MKhXYwqEk38X2Hx0lGAofPE4vPayM+wD0PBT+hiIZf24p9Zp/fAWHHwjXsYGvprXSRZQZuPr9d///gTSQuHHIswwA3EBbsg4yeSMEagfQcM6wedjvRPWyv9rsT8qT1XhXs7SGzMkorvHHyGzrmhzL0WEFJjYxuPG131Ztmr58yZAfH1kFrX7/Xf4/0EAw0SgbYdJyAKVK1Kha5bMskVm8YmvpV5R0EI8kavCfO35jqLWo/vYrjm4QpSlw6k5aW5vnq/Ai7M2FdKNA4TvHhzBZaMTyywZoFrDnNM8ySEu9DkrBGLQYiRga+EVeAO4bFKmIFwZ5hhIQ2xWOl/HlgIC3skFXLxDd4IS7rsHL97yK6oR7UYFhC8rIX/ZYkWrL1rNcC73cIwHX9iyh1zYNQtOIEkqJ29NyiubaWWFfQ7qU9LktkpW7/WtHHynYvwcTw2dfdv/t7+YXl9M4MJrE/qye+cCBHUwx6NHcwuPtE83ZPuFAkBr6vQPhGFGzcMWu+jgKb5NhczVXNOACzHm+B2YNl37vacatiTfm7bFd6hJDxwm7n+LT2FINZuukbUXwqMLMxu0B/EKlASeTTR2nJhqymo9j3u6DUZNDTyjIVgz8Mhw3BxN22M/MehEPKaL7upW8fPKm61vUXyKo0sd1CzpXCoAxB0R1A+LSoRnPYxeVA2aD+hLiBdP5OKvO+jPQ7dGTD72rU2WH7vs1D4dvyqlfB8QNdFYD4g1vEsAA1kFtMADPG5yG34mqYO7prFPdSH9kGQeIyjvuAIDbID3LQOOG4VytT5RGbOskrVpjqBw0DR3CvJ3olBu7Jje8QgSFESBhA0PfYBeI3i4f+5kGRuWyKFaLRVeOwThBG/rNAySwvnJznlG0reP0yyfdPDCDaJcYNOfuZQsAma2WIxisNwwfGTFxoV1xzyE4mp42HuNjt6ZTKIKO0QHiHEdCdStMTg2MnhKe4JPqdiowItL+eRwkNsuCo06SwxxLpmfJ+XqbJaKOZuKEAWWtXrNLN2HIAcLuQ5aF7hF+KkswQ6eDCizNyjaRGLw7mE2MZ/CsnQ3sIOPEOCUYsoc6M+cKw+CGAfVl1Gv2cYpg4wgJ1Qmdz3ZzkdnNQrI5ghRQ6NL0M1dfWYvkam84avQ3yhsujCiaVgTmVHS/C351yO/ghVofdShJOOSjnEsKXWarJFf6dhxOMcNZOMqerhtLTtoFw4VmKRnO6T1CegXsof1bN0cf4ehTBZ51z3NUy56MTIlODC8VAcODXmXhNpDQW3wxWxI1hVr6vCrThw0/92EWmCDE07DgMAmn8Q8vgwjc1bcF8673ix5PSK+JaePLmnVydT6yllY5Tpxm5UBX0bL97PnEVpwaCz1LEG7adH8N9/J+kGLwre/d/uJE/cexZ28sLZN/SRDvLeLU8I56uzcTn3/dPtw9XM6P89grmXOYBAet8B6+t4enQ5cWJcXA9Ihyjoyb+ZDEBCGZuZFpGpvE9G2sIT8j9CYVWsXD/VITa3IMVixF4WeoPGRTxgGb9CqHn2bJX71BS1BGKhmWKqOUJg0leWM02xsjqnV3IdFtkiin7qb//w6prcpkrjFhM1HtVMaGxNw26hfg4LZFlyv79aUGVHlTTeJgUrCFO3jncKx9CwUKrB2JiHGWSVc4wiN/gbZ4PeM5SFyT4HoDUdQ+rpTnl4Q0jI3MKFtgGxyd6hAcnHnM+2DoK2oKIINFe6RKajsVQm1fr9BmskcgI/VRlTPOEujPI2d0H8AZM5ro0wWBHY1VjqVX0WHv1t5KYdRtjN5LAsQSiDIQULvKzy0QKG06VdWiTXiJMRSEUp1Bq3QabgbomzhLGlUWBCexf9ASS1yCi34z26SdtbcCucpMGXc075Yzd5g8DSgJASW8gq9ERa4FehnnuAE0cWWGPPgYBLJVkDPFL0TRvEttsGpp1sugUSJf2pGHPKVeSCInOHPZ17rrRNNWeJqlHH0gDCuVbSZIW6S5Xt/stAGS7kzA7To9SLBVPKvZMhPkmuZoRmfw5H/x2GIqspX35+n22YDTrD7O7gY0dGaWXriVNKG5VYAtZCEBO9Vx1z+tT9dggpjtWcQVNGA8dMtbfTO0qZtpzVNdb901iagUOimfRP2EPYUHg8DnzDiGG51hj+7K817s/JGR5OtMm3u9OqkKr9/ylJZRaY6TXhQNSg8ClayJGY4pi5IUfezuUtdv1+wBLHfeSnFpdU3TqS/QPL03On6P23jbXL7XXrcZbiuckR7Ifhqb7AfNJGyjXY/Js6guOQu4+6ZjgYvgiocS2L4XnYZn0oRVGYumeAlfWubRgWpSid1naeBo15KndzW5bfq9C/fx/oAzftUozAFZz2TPkGF04pgSJSSTeYkQXCY3xr6rDrSzReW1JaZAj6YhlW7nOT/k8XgGRNskyWoqk8aFRVgaRHTN2mvexAhVBCd6aVYyHuGjtWotQ3HTzljf7sDl3QyBFLAYZurZOSJ1vjD8/gbE3wW5IDjkY8ckhu3n2Bu4W7ehS5raBwoab9Zrg3sDnBuqsFvJv9R2z4Odm1O1AeJ3QWqRsfhNRivrOrWhwesNjGOuAxxjT5JIiviK3QsLKtXCAL69vJdnxgncDCbPyQvoMaMeQzWgFYl/fRybEmFpmx3PTW1ME/e7TGYSozjsCid4YlPFjWS2Mr9kNg0ga8mKwbIrAAtu+UggfdCKnSfYkz2zukU4WwkXLrJlYdnliV9wBMNJyysL/i06m5ghQ3LVCE+PHLc9qABLPMe+cLTQpsdS4xkp0xIpgYA9B8elW6KFxvIenvVHzcPGCDfQnUReREZ7VzV55PEsxfA3YOwXvPMwNiNPoBOUuEDhiwIXqB70JTaHYeXtTFOIWoPbZiLF+8VRVEgHFrAsrzXdiQ8eIM8E0Te+CC2ereJay71d3q6dYJYfgirS24wkyit94V7wguOmrLsWPMprvx8x7OFSqfplayktdZJFJa1lGtIbkqUV88Pd2ndwSevF5pr2e0rQ3LZNvF+cj22TcwT9vgIf48eJMh8OytFxmuF8mBxt+q5NmmyxUxclGRHtYN60L29s7V3iK31S85RsVeYCpCX2PO+aeOwXbdmmODpsiZmE4H3dRuZrGJDmWFR4IcyzcugzsghTXNQM001cg5NgL6xrnReHfSuqMs/YcNmF1/H1wzTEWAmWQRYi8w9C6aNNhWdAhILXztGLmUtdTBoEk0WQux/iQ+9cdSMqbLI537PjQXiNIgzpxJ6SLVk+PyFQiBm3bp5mqfdP2TYpeFeI2w5XSzNbM3akrPwpnh6lXog20VbzjrKc59+JG9I7vazixI3vnZlm3QqZi7AtkMnvDTNVjYvLQ7KDXKc5usVzh9g+LoApvJLoVqIeOIIrki5YBEtwmajatIib0GNeDDWPXXVoNNuMC6cH2fxYbeD/SBM5295QYnQL+4mC4tzzyRw9qqS6qlI1dApZ8eG+yPCkRoVtr98DmMDLHY1Bpojj41yJ05CYkUt76pjOjFw2jg5bpUMg0Ag01nIX9+cdy7lM0k9g7JsUyBaJbOmJ4ROiuMofXk0mbE84aP/unqFm2sjQ3sqQ/CpIoqTEjFsfb84VKoOAOeJZHSXL0UzIaIZzUCp46mZ5MwZlJ5mbH4Pm0+C+xpVTi5u0K3QBEMCjqGt3jvLGKQj2eIKTfK9B6g5OX62hxx56GPp/8adyQnjMZYrDTsnNJX3gAZUOu46h0moXds0CRC4EHUSsvY3nt7bIKJ4/3p6/X76fHpeTglBq2EkZ1t203k8jq/z2cKOso7pkqVVBDp3jZpUuMACGtF1B4tZAsUcudqcbS3RMktFGejSPQJwtWY4TlDHiBC8di4bwgKtudP4u1z8qQTQkdhXaCpLOF+NwUlq673v5MmnJGYZu4Ut7+S81gvuoEdZMyfAsbYrH9v7ddgXUblazLjAO0M+c8brOy8AV43ABhJMIMJyzQSMJm8k4monA6fLScOgyimE05cIF32QRPcrtguINRcVWJ2lh4lglIDwFL/k/cMLKHGhjBsaOaqwm1Jl2E59JTShs7+j3QSSko4bz7inbcH5dibomCyanR+yyzEPX6rrMOQT+SX2yKv2apT+soMQ+ktaQYS2HhZ/BAzf1EScuKu4QLATtQTCkcHd3sWolvqasC3Sphj5RfmiBdNMKrzdMmTLAQyvgKgEHatoBPxrYLFnDyTAAj2QMDnADbxSejxkAwUvSdyCvl+TKtBzH7NjAh0H2rs93xSXfeqGVAgIUyQBU/xo/1EgnxoYOYdgvWGXjsF7p/sE7p6ejqNMbvSWxN6tmq8A98w6ziUASyTjcACrongTJTAZp2XKM7YSBK+ld+pleA6UTTtChPbZ1HBbz1wNNXBPJUdDpSxaWhhCt5gXpKURmWDZNZOx2yvKwNxa7YIndqESjkcMTkbmvtx6lT/j5SLnU9Lr9Th/J7Jf1f99yrDpGMYgmXeEu3sUP5rrBz6AdAowR4cwz1baLgkTMIvb0HMsg6pqrEBTc5xK5iSUbfR1dMKq4UgBxp3oZaI8CNwzPRdUCR2jAVXzMS4dTFHpv3SbP4o9J0LHzRXzR9u3UwqXlupDiQ5PjKDyM0zpW8+821L+voDyotJm6GQoiyHIp4zC5IR+C7qWWKLS0S2uS7tXw3+iQel3trYyhFFt32GP8dlZsV6bterz+i/ChuraxQsYaBBCY+TMbXdbNsU3yn3JzgaDXTOqZyv0AKgE/ll3lwybo5/cTMPYZhfMmBeXDjJD7ahqHhwJnLmi9ri9NfLB93OXVF8eBZ+SRUQERSVn4VaIJwtZY6jnoqX2DF08PTqgilapU2M78Pmg5JgagcGIPHSwMI8U37NUb+Gj/9Bj6+iZujKIEROksAB6OtfJlunS2hbklFJBee+knqMM4UfEo6qKPX08/02wbrp25ddB2pKI3RWOtICArstun4Pf/7929pNMxt94TaR/0DNYAzOZBOcYiY6hWA37mjkhxDtBvNPQ74t69njLTNees7auAwotW7NntRhls92Kgep02hZ+PlG2N/GhH8f5Wxv2Vu2hTEkVOJPFY4DVpnHhjVboyqZu6qgFiy1S3pzBt150UNu9EPdytiWjx3kFL00ArFe3KN69HzhFGpCLQa0jDv4KV0fTx9vJ0Pk7f8/d0mVuvtHyl73qCqqfvFMo4/2pIUGqy3OSrFQJfX+4fj4/zabrNt8+Cd9CWZPdkVtmi/sXFutU/LmZRtBa7hbIFKcFKWW3cr2kMOzIOESfVCN7nr8/33k4x7qYDIgUBTBFVDT0SEDfsv0QWSlbuZk3eKy7nvtWq4JSgxE68hW8VPXq0TcWwgYT8ELKkvGMHZQUb/xMXgBgn/EhPw+Yajeo5yNOV40rpwhgC3gj2jcLrfxC8PB77RldFzll6CLyKr0Ym42d7DtVqz6ntOY33zmjKHxthN947A+TbXKyOC8MB7jmkMALeutdS3ZVwS3/7oObJQZVn8y2ZwOgBiCiEyhfnXX2Q2PfGlCKPr1NMulvmqYvhIrQP3FB+3xszQlAvQl+ez8OrkHbL9P18adNuolKr3dZn283XuYf/7RH1V7dpNFDkt/f7++k4Xqdrikl44eqvjRHao6he7NjFFPMlUWtknnmcdPaQULHQDGjRMVrkxrFp7I1hknYGrBMAk8d1Y1Ba6jPFZLnPFykpG/h52zPGPT6QbovNXGxiqSAjuLtCZpDNlxRfRHQX5rFDFxNkdBnHD2NksIMt4UGN1AJ7IL1mk0gUkyHodFQQ9X1QC4960xC9n37khVP4Gaw8ERm1NhxSejO0gkGnh0IWnXZ0Ewq5r3PfSPrhoG41+PnBqe9l1jYaiGQrM+s0BI/qiBIXaWlYhXnglTt09SKWhhOluuB5qNUqe6j1ufYMDFJxlMe6ZNROPw+7Pge9gYxylWF7ouWtOarZBv32E7Wy/nLqH8OjyciIjNNyy9/EaOzz+AcoF+e4gJnBxgeisCc6tRQTuRmdjLkDJuRmfQ1A35G2eTuQJl7I5EmdRJUxEE0PQjjG45lImzc4UvUiCfVeF72uKadqarCCCjj9yhn2SeiIdGt5WQ9Z4VVKyxROC5Wuc9V0LjeF7+EwiqnV1JTJ7Iod4L5rySHR++gXtRdwjTw92cLSdSvFjECvA5PVK3sAmIy6pshTUttbD1v8AfGgA8KuT2vQkVuay7Judiva31uAqLK2iSnJgOHYFHdgRS+Urq2wUtQyWJC0rRv7IWSaWGUGBI0JytDH8yALHawZmE9lnTHySB9DEbFz68Jo/AEL6y4AvAECQZhTgqQoPU35AQo8C64pVXlJC2CZBOmT5OVRmWMYR3iNvfbu3u8022Tspu0LgnJXRmNnMCTjcArL3gv1+XE+do0SeCbzhG30oXS1DWgUF2nsB+/rnygG1qvT0mpZI5s/GdfhuuVUHA5AXbyBnz9wN5UPYmjQotXIojvaYnwcwOkJSD+1yLAFOEZB7aahTgqDvfcHk+Lal8uBcP6eccp0Kt386+P5ocHx5Lfixgh0ppcnrvccDR/FfNOKnGcpYWaIhjFm01GLoyPz9CLDNT7vcNDQN604KDcYwhZ1jRSE7Hk9D12j0iM9xmHfhdb7Qlm6PzWCirGm59gvdPb48wPfjq7PZm731sn55fIyDaCmN8XOg+LBCvCQuX2eFtCmFYE2Amb4v+aVzD9Y69GkthsZazmZhxoPhNDqW9KOr+dpkHWZxx3oIITABTJTSvt14gmmXgMm/lxPEfZdOA02TcGKYxBEt7NjAqhHmv+0b/9lUhE9abeZdN0yroNWYb6guLRsFrZDZMOxv8fqdjoKBFUDcQO8lYT3XRfl16mAZ0DnasYfsDhh8up07mOdEnUlIsqSNb0lbGX7G1wf1K3an0kMDO6dAPjty23nSct3wT3x1kZVax492T4WG6wBmtBgwEXhQ74YH0MbHL4C56lrZF2VGSO4e291hUrxEd6eSIUeUD4GtwhWQMM1XORDmlEvM9rjKas9uFUk7FJ/PxgtcVwXo90g0Eg0vjHgyGA1Ls4K1AEpJdBtBflPIpT484tAEkTp6cDteKCqtpm0ZrhNYQvvGZUl9b+X1tUy9+fhrFXV1Z06x21AULcNXhD3cUpWD5+pYonlkt6xYHEuS5mUQ2Z0Jq7YbQCNh350SIxp01ODd/eE+C4lzutYvOlp8UOJLFoBlgu+fkfwFP0efECLFE1CBHyNPUnar2ABmi1QBEzGUaLy60BYEkvzfnMpSBF0beWJGR1+EC+trI+0XOBhHO5hixdmmlZxeKtF9eKJpeqVWWdioDLGRct/EBaEBm+tHIfiiaoq0eJM7VbB7wYzhv3itNXZRq73uWEZrd/J+uPcX4er1p10x4Bbt632gIc3LPKlJcv4gIcGSrmxCPM5nciAssNoGLC1ogErKPP74QvF2G4AtvwjRPQ00+P35/vr7XL8Z3pOu+DgVkotYnG+jLHgjbPqosOP81ZQlQRubYd4BkDTdgoO0OHRsTHv0+Oeay61xaHqGg0o/mPxyKBLjXWYTEAIi2OU3/brAwB1vXaS9VYvVQ59vJUJ2pafLpg+4F2THlJuzLKcZxx0oZ80HMszpNoTbDM3Re1X4wl1W/uszpRsZWZNiqymZyx+T96Qvam579R9sdtXoTjzAA2O5px1AXlFYqNxD0nVcunw320VhvsWJdFhf728Ds8KLXiUNKLiDHrNGcomPQuhtmzd97Okl3LHb1PJRBTDBfiIJ6yF3j1TG/r+uWcmTUe9mCdbtk8AlvOx16rMpxViO9bKLZEnjBOoLbiiNXKp0dY9t9IIkjFIoShST7KhEKvQyLMso/IJgn20VJ2Mce6o0a8dC4PiodISy/9UfR+NtLqc5/ty7zs16SkSCore580IK+djUhq3GVnxuAoP+TgDM1sLxpvmVrFTcawYUM4+8Lh/3E5L1yhZ5mUneK68Z3q01YTUwu0xXtb0HqPbc1lVv0xYL1Se4YpUaYLA4nsFnyQoFLlRJrIVVAUpj/t+czkbOB5e/9pempqLBCokvP6qsRGejuwDmrTdG2d0ODDrFng8yQdDjPa21IrJkH/WR1tl8nXG74T0r1HBcDEbuwy+tV2Ep2SI/NaGbTwVwM46a4S3950Bp7zgy9P2tdVKthCM0GZ8s7+rAb7uaThF2RyPI9JjRd6GRh1LbKoXfFbO4DiWDcwm6C8qrIJoCm/oZjS0x62g3sVNDWMjh2vKOMNoH9I7c8MU7cL1Amqsnc+yf+vjtWwDOSYB6+eiJPzLN/6PNUHz36QRNxjkEdT1/S0UdaQGSFf86OQAxa/bLQ3jK6whyt1huOTPOE08CIwjvoVnFApbhJQIlqgKh+rsOxzaoZ643WHqXvFyA4eK1I/Wv2jM52Bo4yvc2H03HCTOHZT0nczsoiDUC52i7RNnSIejw8odltj+w9sHFZVcl2lBS8MTpphhwoCZDhhPrQfpGjbLVtFM8bmcGqjAxbPQderAAhdNDqclulzzzpCttvCvD9wjw7XkSao9vL1eUx3t+RIFtPRsbrtL78x6KzsZ0WZKWirkl5iybJE7FV910BGyWqX9LlTBXcUSqlANFJUu1rz1EDVOjq8CtQQqCQz61/vr40g6fDX9cMdWQwe87lqZUZFmK359LH+NLa+IsvHAoIJD5XInfRKmkPILZMAbUs0ihvpy/VUoZU/imUVWemTVTganneHiSJLjKbr09fVg0PRAgn2dpjQYBIDh9YfKM0OT8hoaSR8AuHlzws11bzHn2/N2cbcmAwCGYBwKBPwvwiUNTRXhf3b4tPZgP88P+2mEwjK06O+/a2v4ZufahHUE40ePzF2iwSIHvxbZ330hT978HHjDgC6z4ytHS2noV3Em8Z3R3JKZxRc4sqlJWHhPznKl9B0/v+MbQ/BkUevkVLT4hWHgzppfsXn10+cEXlvqxaw8QsCxMuZtcpWSb08ZcgT72NwHnmM7XFTBPqb5LbTJwiKIHo/nkU/ccPwOjcA1m5ha6uq5eF3I/Fq70n9sl1dsAXfJdJcBG2Oc57m+AnrFaLtM95P+tAnG880U/u8Mz0zlN/RBMy688V6n9bM+8oiJdqbOKVEPx8+ZuNO0Labu7e/u9qsDONoms5nPKMLmEtkkoGwxfcGySZP84hZrqvP49hDTSDKfEdHH0jYp9jcRnMguh/gayBQjYn4RxXE3gQOPyezRBzOCv68c+Rccqz3rmtLTijsM/A7iMOrF14ew96OKoTaqPENf1LyQauj46ihUj476nbnr+2nLFEnoj5/T3ojNysoPyTSH35vqRbveCU36BPhGexWvmR7OuHVLLa2T3xxvG+OL2hpCfxSn6N7XSeLYa+yzHiu+N4BszCDjHJlyyADA2XxulXNMjjLYGGWiP3L0WzZ+TcFX1s0o0olbhg6MPRPS8AvWOtBnbsD8mCwy8vnPrVPbm+FMsIZd3+cVXyMMkU8CCSMA/Znfv5Agk/aFDIXGvVCCJe+aBd8L9bDSsxfqYxK2qnKfBArV+isrOWMxt0aOakWxsVo1zMW9WrpWKzJqgeaqEfyFCpFlwVnKLCRangJ1z3LV4juv7jm3QjkV63rV0gdZ4UKkGCpWT3MuFKrytXJ49fq2k+Y44KRwl8lSIo9Pzc+USxXJlqjatZw9VoPbyLJUal9izfY6tWqhWi3fnVSZQ/1NzJfP1aUySCx/Ea1RW2qfLOZ1+6hQqQmnqQKFY+VzzLUXx8jZoo5cuVwVz8JBja3JVcprqv9v4HXt+WpNvVFfNT/DPe+i/eK1+/L8nZsj5iozFwmHT1J3C95O0szFo02of+4WUJIJNH8TlK7OYf50GPLt2Ve5hhOdcW7y8a4KKcbs0ddbvrptyJRGTiRNqdYqDfq6rM/JfQr1rz1L+v/hgFaIK26lnwHkw9Z3h5ZNde5yrgqZnlDGuUW+xv8+it/E9ZbQNgAAAA==) format('woff2')} -@font-face{font-family:"Kalam";font-style:normal;font-weight:700;src:url(data:font/woff2;base64,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) format('woff2')}{"renderer":{"package":"@deterministic-engineering/render","version":"1.0.0","icons":{"agent":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","agent-request":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","authentication":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","authorization":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","bounded-write":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","budget":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","budget-ledger":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","capture":"a647d42aa11f4e5e85d0bbf66f483f57f3c4ba3a9536362ed0eaaaae10a89cee","catalog":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","claim":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","decision":"3535642a5b613372c3fd374151ec90aafa19b64b2d33d10b19162cad07a35c7a","document":"0bf9674a401262da8a646305cab00006954721c07765b9962e0dee1c31d560f7","evidence":"0a91b169aaa644829a054cbb94194efffaf4298f2b6f8fa8c6ec2b7b413a1766","go":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","history":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","kubernetes":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","ledger":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","library":"df474fa36a74016b79236fff58a980a8c18c682d1866211776e349a0eb4b2979","message":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","model":"0cfd1f9ed3873f556ace725a7b6a251ebe75d7d976567699276f34df36b2443b","model-catalog":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","model-provider":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","obligation":"e76f4d34a7190400446c89e4e7d187762b885808a64a00c99455599d902570c5","pending":"cca7589bc3b1dcdebacb867c6836c6fc166257f05823555a268354ff9bfac00c","permission-check":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","policy":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","provider":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","publication":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","question":"dbf231e1568dc37189d5674d73c4bfc58a17eb8ada579b3f03bf2813d33c56f4","recovery":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","reference":"3814c570f79ab294252c36530de464c9364814b797afb862d9c62e728a8660fc","route-choice":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","routine":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","routing":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","rust":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","selection":"82b4ab6faf195fea0a891c35268e61c186e93e7c6a9d7967a4f6a73dbf25ae7f","stream":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","task-contract":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","telemetry":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","unknown":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","unknown-hold":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","writer":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e"}},"design":{"audience":"Gateway developers and security reviewers","medium":"GitHub at 830 CSS pixels","message":"One native outcome qualifies the group.\nRevocation closes delivery; unknown retains the hold.","questionRefs":["q1"],"requiredSubjects":["n0","n1","n2","n3","n4","n5"],"requiredRelations":[],"focalSubjects":["n4"]},"evidence":[],"layout":"model-view","presentation":{"objectRows":[["n0","n1","n2"],["n3","n4","n5"]],"notation":"objects","options":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL"},"icons":{"n0":"policy","n1":"authorization","n2":"ledger","n3":"stream","n4":"writer","n5":"stream"},"roles":{"n0":"governance","n1":"governance","n2":"ledger","n3":"semantic","n4":"execution","n5":"execution"},"edgeLabels":true,"graph":{"id":"declared-reading-order","children":[{"id":"n0","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n1","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n2","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n3","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n4","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n5","layoutOptions":{"elk.partitioning.partition":"1"}}],"layoutOptions":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.partitioning.activate":"true"}},"textColumns":22},"drawing":{"mode":"sketch","options":{"seed":29,"roughness":1.3,"strokeWidth":1.2,"fillStyle":"hachure","hachureGap":9,"fillWeight":0.6}},"fonts":[{"family":"Kalam","weight":400,"source":"@fontsource/kalam/files/kalam-latin-400-normal.woff2"},{"family":"Kalam","weight":700,"source":"@fontsource/kalam/files/kalam-latin-700-normal.woff2"}],"palette":{"background":"#F6FAF9","surface":"#FFFFFF","ink":"#163C43","muted":"#496A70","border":"#C9DDDA","accent":"#087E82","secondary":"#946044","tint":"#E1F1EC","secondaryTint":"#F4EADA","onAccent":"#FFFFFF","supported":"#237653","pending":"#986320","conflict":"#A13E54"},"inputSHA256":"7fa2e85429b63d40aeaac63eee5fa8551dcff25ff1048095d1c1d39d3e9bcf1f","model":{"subjects":[{"id":"n0","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::changes","label":"Rust / close\nRun edits / origin cut\nShared edits / shared cut"},{"id":"n1","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::validated","label":"Rust / qualify group\nPending clear; each row\nCedar + claim + domains"},{"id":"n2","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::publication","label":"Turso / commit group\nBurn the bounded group\nPublish one qualified cut"},{"id":"n3","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::staged","label":"Rust / prepare frame\nExact bytes and next span\nReserve transport credit"},{"id":"n4","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::receiver","label":"Rust / consume once\nLive cut + owner + expiry\nOne-use frame cursor"},{"id":"n5","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::tonic","label":"Tonic / accept once\nOne current Rust owner\nObserve delivery later"}],"relations":[{"id":"edge:0","src":"n0","dst":"n1","label":"closeBeforeWrite","kind":"connection","fromPort":"n0.0","toPort":"n1.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:1","src":"n2","dst":"n4","label":"exactRevision","kind":"connection","fromPort":"n2.1","toPort":"n4.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:2","src":"n3","dst":"n4","label":"inertOnly","kind":"connection","fromPort":"n3.0","toPort":"n4.1","srcArrow":"none","dstArrow":"none"},{"id":"edge:3","src":"n1","dst":"n2","label":"qualifiedManifest","kind":"connection","fromPort":"n1.1","toPort":"n2.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:4","src":"n4","dst":"n5","label":"oneOffer","kind":"connection","fromPort":"n4.2","toPort":"n5.0","srcArrow":"none","dstArrow":"none"}]},"modelSource":{"ref":"sdkCapture","modelHash":"3c45556818345c7270d26e7d40d6ad5d25bd2b585713bf03143e9a14a5387ed2","view":"WeaverViews::providerDeliveryJoin","portProjection":"owner","labels":{"n0":"Rust / close\nRun edits / origin cut\nShared edits / shared cut","n1":"Rust / qualify group\nPending clear; each row\nCedar + claim + domains","n2":"Turso / commit group\nBurn the bounded group\nPublish one qualified cut","n3":"Rust / prepare frame\nExact bytes and next span\nReserve transport credit","n4":"Rust / consume once\nLive cut + owner + expiry\nOne-use frame cursor","n5":"Tonic / accept once\nOne current Rust owner\nObserve delivery later"}},"modelTrace":{"modelHash":"3c45556818345c7270d26e7d40d6ad5d25bd2b585713bf03143e9a14a5387ed2","requestedView":"WeaverViews::providerDeliveryJoin","resolvedView":"WeaverViews::providerDeliveryJoin","renderingSHA256":"1e069227046954ec329a5a30eace9332a6c1288613939e11d45a79a65ae247c9","capturedRenderingJSON":"{\"modelHash\":\"3c45556818345c7270d26e7d40d6ad5d25bd2b585713bf03143e9a14a5387ed2\",\"requestedView\":\"WeaverViews::providerDeliveryJoin\",\"rendering\":{\"view\":\"WeaverViews::providerDeliveryJoin\",\"kind\":\"interconnection\",\"stated\":\"render asInterconnectionDiagram\",\"nodes\":[{\"id\":\"n0\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::changes\",\"nameSynthesized\":false,\"type\":\"EgressMutationBarrier\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n0.0\",\"name\":\"closed\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":519,\"startCol\":9,\"endLine\":519,\"endCol\":46}},{\"id\":\"n1\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::validated\",\"nameSynthesized\":false,\"type\":\"DeliveryValidation\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n1.0\",\"name\":\"closed\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n1.1\",\"name\":\"validated\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":520,\"startCol\":9,\"endLine\":520,\"endCol\":45}},{\"id\":\"n2\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::publication\",\"nameSynthesized\":false,\"type\":\"PublishedRangeSnapshot\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n2.0\",\"name\":\"qualified\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n2.1\",\"name\":\"preserved\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":521,\"startCol\":9,\"endLine\":521,\"endCol\":51}},{\"id\":\"n3\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::staged\",\"nameSynthesized\":false,\"type\":\"InertProviderFrame\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n3.0\",\"name\":\"stagedBytes\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":522,\"startCol\":9,\"endLine\":522,\"endCol\":42}},{\"id\":\"n4\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::receiver\",\"nameSynthesized\":false,\"type\":\"DeliveryReceiver\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n4.0\",\"name\":\"validated\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n4.1\",\"name\":\"staged\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n4.2\",\"name\":\"offer\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":523,\"startCol\":9,\"endLine\":523,\"endCol\":42}},{\"id\":\"n5\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::tonic\",\"nameSynthesized\":false,\"type\":\"ProviderEgressTransport\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n5.0\",\"name\":\"acceptedBytes\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":524,\"startCol\":9,\"endLine\":524,\"endCol\":46}}],\"edges\":[{\"from\":\"n0\",\"to\":\"n1\",\"fromPort\":\"n0.0\",\"toPort\":\"n1.0\",\"label\":\"closeBeforeWrite\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":525,\"startCol\":9,\"endLine\":525,\"endCol\":80}},{\"from\":\"n2\",\"to\":\"n4\",\"fromPort\":\"n2.1\",\"toPort\":\"n4.0\",\"label\":\"exactRevision\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":526,\"startCol\":9,\"endLine\":526,\"endCol\":86}},{\"from\":\"n3\",\"to\":\"n4\",\"fromPort\":\"n3.0\",\"toPort\":\"n4.1\",\"label\":\"inertOnly\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":527,\"startCol\":9,\"endLine\":527,\"endCol\":76}},{\"from\":\"n1\",\"to\":\"n2\",\"fromPort\":\"n1.1\",\"toPort\":\"n2.0\",\"label\":\"qualifiedManifest\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":528,\"startCol\":9,\"endLine\":528,\"endCol\":91}},{\"from\":\"n4\",\"to\":\"n5\",\"fromPort\":\"n4.2\",\"toPort\":\"n5.0\",\"label\":\"oneOffer\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":529,\"startCol\":9,\"endLine\":529,\"endCol\":75}}],\"columns\":[],\"rows\":[],\"notes\":[],\"notices\":[],\"shown\":[]}}","portProjection":"owner","nodes":[{"id":"n0","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":519,"startCol":9,"endLine":519,"endCol":46}},{"id":"n1","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":520,"startCol":9,"endLine":520,"endCol":45}},{"id":"n2","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":521,"startCol":9,"endLine":521,"endCol":51}},{"id":"n3","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":522,"startCol":9,"endLine":522,"endCol":42}},{"id":"n4","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":523,"startCol":9,"endLine":523,"endCol":42}},{"id":"n5","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":524,"startCol":9,"endLine":524,"endCol":46}}],"edges":[{"id":"edge:0","index":0,"from":"n0","to":"n1","fromPort":"n0.0","toPort":"n1.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":525,"startCol":9,"endLine":525,"endCol":80}},{"id":"edge:1","index":1,"from":"n2","to":"n4","fromPort":"n2.1","toPort":"n4.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":526,"startCol":9,"endLine":526,"endCol":86}},{"id":"edge:2","index":2,"from":"n3","to":"n4","fromPort":"n3.0","toPort":"n4.1","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":527,"startCol":9,"endLine":527,"endCol":76}},{"id":"edge:3","index":3,"from":"n1","to":"n2","fromPort":"n1.1","toPort":"n2.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":528,"startCol":9,"endLine":528,"endCol":91}},{"id":"edge:4","index":4,"from":"n4","to":"n5","fromPort":"n4.2","toPort":"n5.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":529,"startCol":9,"endLine":529,"endCol":75}}]},"view":{"source":"docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2","title":"Commit a group. Gate every frame.","purpose":"workflow","kind":"routing","question":{"subjectRefs":["n4"],"ref":"q1","text":"How can a shared snapshot stay safe during revocation?","focusRefs":["model"]},"basis":{"captureRef":"docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2#design-view","modelRefs":["Project.sysml","dev/sysml/AdmissionReaderViews.sysml","dev/sysml/ArchitectureReaderViews.sysml","dev/sysml/ArchitectureViews.sysml","dev/sysml/AssuranceReaderViews.sysml","dev/sysml/AttemptReaderViews.sysml","dev/sysml/AuthorityReaderViews.sysml","dev/sysml/ControlActivation.sysml","dev/sysml/CorrespondenceReaderView.sysml","dev/sysml/ExecutionReaderViews.sysml","dev/sysml/FloorReaderViews.sysml","dev/sysml/GatewayArchitecture.sysml","dev/sysml/PolicyEvidenceDesign.sysml","dev/sysml/ProviderRpc.sysml","dev/sysml/ReaderDesigns.sysml","dev/sysml/ResearchReaderViews.sysml","dev/sysml/StoragePersistence.sysml","dev/sysml/StreamingExecution.sysml","dev/sysml/WeaverExecution.sysml","dev/sysml/ZeroTrustRefinement.sysml"],"obligationRefs":["proof0","proof1","proof2","proof3","proof4"],"evidenceRefs":[]}},"questions":[{"subjectRefs":["n4"],"ref":"q1","text":"How can a shared snapshot stay safe during revocation?","focusRefs":["model"]}],"references":{"model":"dev/sysml/WeaverExecution.sysml","model0":"Project.sysml","model1":"dev/sysml/AdmissionReaderViews.sysml","model10":"dev/sysml/FloorReaderViews.sysml","model11":"dev/sysml/GatewayArchitecture.sysml","model12":"dev/sysml/PolicyEvidenceDesign.sysml","model13":"dev/sysml/ProviderRpc.sysml","model14":"dev/sysml/ReaderDesigns.sysml","model15":"dev/sysml/ResearchReaderViews.sysml","model16":"dev/sysml/StoragePersistence.sysml","model17":"dev/sysml/StreamingExecution.sysml","model18":"dev/sysml/WeaverExecution.sysml","model19":"dev/sysml/ZeroTrustRefinement.sysml","model2":"dev/sysml/ArchitectureReaderViews.sysml","model3":"dev/sysml/ArchitectureViews.sysml","model4":"dev/sysml/AssuranceReaderViews.sysml","model5":"dev/sysml/AttemptReaderViews.sysml","model6":"dev/sysml/AuthorityReaderViews.sysml","model7":"dev/sysml/ControlActivation.sysml","model8":"dev/sysml/CorrespondenceReaderView.sysml","model9":"dev/sysml/ExecutionReaderViews.sysml","proof0":"dev/proofs/cedar/DomainMigrationComposition.lean","proof1":"dev/proofs/lean/ProviderEgressWindow.lean","proof2":"dev/proofs/lean/ProviderLifecycleFootprint.lean","proof3":"dev/proofs/lean/ProviderSemanticProgress.lean","proof4":"dev/proofs/lean/ProviderSnapshotPublication.lean","sdkCapture":"dev/sysml/captures/WeaverViews-providerDeliveryJoin.json"},"sourceSHA256":{"dev/d2/themes/assurance.d2":"f7723f53e005a68c803a38ce5c04cd733f46f4a2688fa4b17c66f9d5b308fe24","dev/d2/themes/data.d2":"19fceb46186892da02b763217963cc3ca2a35021219c0d353fdeec84604ddaee","dev/d2/themes/flow.d2":"1f13588619d0c8087c08d8afd023c4c0efe12726711c311e623eea3872726c1f","dev/d2/themes/routing.d2":"f185df198e7435d12b17b7b57b62dfc5795597d95eb926159ee13b448727bcce","dev/d2/themes/sequence.d2":"6e39472720dccc717f984c95b79570494b6ce3828b86227629841649e6c956e6","dev/d2/themes/state.d2":"f1a35cbca0f9cbb055ea9f793ba3dfb86e5fee4e462038ef3e72b94baa61d781","dev/d2/themes/system.d2":"b2a32ec6959ca5df9103c16454c4e34b758e061f850f7de6b619bcbc5fcf17a6","dev/d2/themes/vocabulary.d2":"add21e9b87eab485e5daabf6316fea44eb56b1007b70123f24b0e32e3357f744","dev/proofs/cedar/DomainMigrationComposition.lean":"c1eea3510b34077fc22ea7e5f596c0b0cbbf0119ae56f984b1ad5ddc5fe65a64","dev/proofs/cedar/QualifiedReview.lean":"1ae16e06ad03a2906fa8c21dbeea1e3eb7700aa1e9359e64848dec65ccfd079f","dev/proofs/cedar/WeaverPolicyBridge.lean":"a9628a8123d504a34f64bf986feb4471325aa2b0ddc603d76b62632481eab67b","dev/proofs/cedar/ZeroTrustEnrichment.lean":"0c4b138843cc176c27d42d4a31177a3c12486b2d8ff124a6453e3d0922170884","dev/proofs/lean/ProviderEgressWindow.lean":"c4a15b4ccd3a6474290b71374499087dba7dac7a1fda53f3a870100ec2e768a9","dev/proofs/lean/ProviderLifecycleFootprint.lean":"4786544c8a8193c5221bda2f7cd5cf20531bd1856d88b10ae29b280f223e307c","dev/proofs/lean/ProviderRpc.lean":"e79d7639ac11220585e59e85dc5bec12b6717f7b51fb28fdcd62dc96d8fae38e","dev/proofs/lean/ProviderSemanticProgress.lean":"d32e010145a7dfcd646daeeeb4b08c0e852b9006bca404681af7e7fe10d0eaa0","dev/proofs/lean/ProviderSnapshotPublication.lean":"312c0380e334fbc5380815d882c6b5b0007747100f818becbee9c6784eeb5716","dev/proofs/lean/RuntimeAdmission.lean":"6111d4b9e93ebaa9f7cc44a55ed504c88c20c8d9de81e947a2e13b3f4a13b13c","dev/proofs/lean/SharedDomains.lean":"10eef67918986264689b09f0a6c0d53b314d7bf43b42f4b9652b403570beb58d","dev/proofs/lean/StreamingExecution.lean":"3fba798a7887a0b2ae29a7e3f0aaa3d7e2fb191e5f1f28109a4a73d28e27b776","dev/sysml/AdmissionReaderViews.sysml":"27ebc6c98ec3a1f7f9081e77a130953c3b646a1fdf6f1d6fc1fa6ed6376e9623","dev/sysml/ArchitectureReaderViews.sysml":"52ffbccbb17bd257e8ad9f4aa9f727c8ce0c00149e7d6738b82042ba06fdd0e3","dev/sysml/ArchitectureViews.sysml":"45d14e970e29ef204e500de8de94ab3a18319f2bf7e537d69ebe6138f713a14e","dev/sysml/AssuranceReaderViews.sysml":"cd99fb7e9b23e08beac265bc832a8debee0dc1e1d318b0f64d5263519270e390","dev/sysml/AttemptReaderViews.sysml":"0d87cf71e15c26566422a6ddb5945fdb8add8af0484d9d024c32b97597675e21","dev/sysml/AuthorityReaderViews.sysml":"6fa25bd3a64e7f89987caec8e4773928be2cbea0a3c943299e536ca81978316d","dev/sysml/captures/WeaverAdmissionReaderViews-beneficiaryRegistration.json":"04499e24efe1ec856cc2ef487dd18d018f0ecc85671462e4624ae785d6e1ce4b","dev/sysml/captures/WeaverAdmissionReaderViews-bootstrapInvitation.json":"bd052f79d004aa66c6b6b057e51c485b70419e041994a3ef0f9df7a56cd94e21","dev/sysml/captures/WeaverAdmissionReaderViews-callerCustody.json":"49dcf1fbb83e65666d09cdf8f9c389cb5e79a4466de5c6b1a6b062f83c25e9eb","dev/sysml/captures/WeaverAdmissionReaderViews-custodyPublication.json":"4dea2586eb9fbc092d6ec0efbf4333e476a667c308515a5831289d48f1e5343d","dev/sysml/captures/WeaverAdmissionReaderViews-enrollmentCredential.json":"99e37452ee8cb2ecf45e2e7c0c4d56f9625a34f7f6a346b0f893ee2673028542","dev/sysml/captures/WeaverAdmissionReaderViews-incarnationIssuance.json":"3bd35be32d187ef9fb4a1b7c2981bcdab75d276eb5a7ecb848330f1f419d4a71","dev/sysml/captures/WeaverAdmissionReaderViews-routineRouting.json":"9320eec5667b9ab60fc4b56bf7a8077cca4f699591df43ae8a6c4bf7a79f27ff","dev/sysml/captures/WeaverAdmissionReaderViews-sourceCustody.json":"4d6d6b376d8b061b12c3a334c6c3caedd00707959239cae49e9a18508fb8be8b","dev/sysml/captures/WeaverAdmissionReaderViews-sourceJoin.json":"2454cbfa94032bbf056eaa0dee3bbeb8bc6864a635471d013651d11988f2f98f","dev/sysml/captures/WeaverAdmissionReaderViews-subjectAuthority.json":"d97bb7e9ab14531f07b30adcf42625a3602324ceef3d93d1b5345e2b398e8263","dev/sysml/captures/WeaverArchitectureReaderViews-adapterBroker.json":"a876e33e57bbd52c0ecd63b0efe89f8303f376aa3f74ddcb38781dff18469b51","dev/sysml/captures/WeaverArchitectureReaderViews-anchorBroker.json":"9f456ed9accdddd94b311765d8e9b8da7771bb4dd25a3b4d47dc8ee55f52c733","dev/sysml/captures/WeaverArchitectureReaderViews-anchorEgress.json":"dc9fe4cc8613327473a26f03d5dfe82fa0fecb9c0506b32fea8bd9029c5aaa34","dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json":"d5ea66646d34b275e00647fc169a23b1bd700ab155a0546216bd5397871fab03","dev/sysml/captures/WeaverArchitectureReaderViews-codePolicy.json":"911b72414b876d03ffd4537853b11ff1da5a28f521f3c72da5c0cc7331e95676","dev/sysml/captures/WeaverArchitectureReaderViews-configPrefix.json":"8eb8cf6f9cbf65bb002f8ffa3497e8b43d01497740fea56b0b1d01f98f60f86a","dev/sysml/captures/WeaverArchitectureReaderViews-driverCompletion.json":"5184bbcad85bc10b924750fb0a999964a8a68878ae5a11a2a7b4b5b364d16b41","dev/sysml/captures/WeaverArchitectureReaderViews-fencing.json":"3770227e6015c758ae90797cd21187fff7d5e3ddfeff62f6e47071db943b637f","dev/sysml/captures/WeaverArchitectureReaderViews-gatePersistence.json":"96429db758d36f7038e077eebe027bb4bfb0be70c754102107d99d420db3de99","dev/sysml/captures/WeaverArchitectureReaderViews-journalLifecycle.json":"e3670e3891ec00f9291280b7791105c82330c185cf0da95fa0c95b625e4305a9","dev/sysml/captures/WeaverArchitectureReaderViews-logicalObservation.json":"ccbb19106752ff90e26727b700f52113a14adfadac99a1c9fd7ab25cd5c2c158","dev/sysml/captures/WeaverArchitectureReaderViews-manifest.json":"459cdecf7befda6d6ca94b8256a6e85af0562a4ee542420d001681acd21418d9","dev/sysml/captures/WeaverArchitectureReaderViews-migration.json":"19a8802c591a066e2d750f22849de9118fed7b23067d3460edb0d5b104138be9","dev/sysml/captures/WeaverArchitectureReaderViews-policyExecution.json":"c94dd51b1fdb94aca8fb4c8fd3b75bf6700aa555e904d676c0461fdfa9d575a6","dev/sysml/captures/WeaverArchitectureReaderViews-quorumPromises.json":"1dafc3bcbe572e0ad57397bc1c58a3a22c5f43f4c2e7bffa39120831591d10f2","dev/sysml/captures/WeaverArchitectureReaderViews-relationships.json":"49f3a30a2eb3c79b7ea90c651f2eded9aa3595b083d43e3f01df3e4fee4916ce","dev/sysml/captures/WeaverArchitectureReaderViews-settlementAnchor.json":"aac54f6f428f23545a673162c0cdc25afea928e14e24b85c851e728efafac285","dev/sysml/captures/WeaverArchitectureReaderViews-sharedBudget.json":"5593a5a6e9868d4a46297ec4772f20d96700a08cc99c19e0f1ac5f91773bf7f9","dev/sysml/captures/WeaverArchitectureReaderViews-sharedExposure.json":"02e557c5edfa0b58497f5e15354da2b0e7a76572ac1e0ceefd6e2dfae651a914","dev/sysml/captures/WeaverArchitectureReaderViews-spentState.json":"8769248ffd03df9ad5b3003ae83ff71e2a8039eb0e7bff242324152d9964ce7b","dev/sysml/captures/WeaverArchitectureReaderViews-writerSettlement.json":"33e10db472521769ac4ff201b3e721fa6fc8b19368fb57877f16f23e5b6c8c45","dev/sysml/captures/WeaverArchitectureReaderViews-zeroAssurance.json":"ea0bc966793ad36678fc690dc0d9b7e45bef6c0d3d57806494869429dd862849","dev/sysml/captures/WeaverAssuranceReaderViews-brokerQueue.json":"d1f8518678c9c8c36e3bcebb63ceb558b43786410f8411029a621bb346c8fd8e","dev/sysml/captures/WeaverAssuranceReaderViews-continuation.json":"3c1ef926be8eb3fbcb5b7a4f36b8d66d8fcf7c5504c2c54e4a4f90de72dec0e9","dev/sysml/captures/WeaverAssuranceReaderViews-deviceEvidence.json":"ad4df25c08bfc83d494b72ca7ec1cfeda7e3f57c4bfcda972e8f7cd3f2ee6a6f","dev/sysml/captures/WeaverAssuranceReaderViews-gatewayHead.json":"3d758f63c9d4dc90535298aa80d6fca3dfe198f6a9c51f35e23c1874cf7c58c5","dev/sysml/captures/WeaverAssuranceReaderViews-keySession.json":"e85e734aca17c200b6be205fca56930d50b3852c8d9a4e32dc180d2978bc7a8b","dev/sysml/captures/WeaverAssuranceReaderViews-rangeRecovery.json":"8e2d4bfbc6fd3388057d187f6d3abe7f99c8c80ad3ca26e1c3c4130cc9b8d389","dev/sysml/captures/WeaverAssuranceReaderViews-signer.json":"1d04fd69e45695c0010c23e2ed9da37bf4198335cb63755bdb587065f5bc10f5","dev/sysml/captures/WeaverAttemptReaderViews-admission.json":"288bb3aaed51572cb6b4a2e2131e1b34b45a341082bb3f854ba022d4a5096fda","dev/sysml/captures/WeaverAttemptReaderViews-outcome.json":"ba21d6881b4092b19b2a660f0f32b07598464234ec077ce8d40f292b246070f4","dev/sysml/captures/WeaverAuthorityReaderViews-attemptLedger.json":"6beb328a34e7f3b55bbb7919c3eb08cec666dc6be2ad86207d90dc717b749625","dev/sysml/captures/WeaverAuthorityReaderViews-canonical.json":"7397b46316bda6455956948bd00f8893f46a72f0f2c1854cadf641ce42c2e318","dev/sysml/captures/WeaverAuthorityReaderViews-multiKey.json":"6e7cef11b6c2df934538ba4e65bb515c2d127bf857788325394293efc9b7fb2b","dev/sysml/captures/WeaverAuthorityReaderViews-publication.json":"d98be08fa846fc8114cc4af1d47557a03e52d0c15da44877fe6e5b0278dfae86","dev/sysml/captures/WeaverAuthorityReaderViews-recoveryCAS.json":"f8a68b4c84f5776db7568fd280fd1c38077720515eb6f0ff13124e190b2bf75b","dev/sysml/captures/WeaverAuthorityReaderViews-scope.json":"92b125a292f593db4c04b60125a387a039fc337ac3a4f5cacbaaa57ee8ddf196","dev/sysml/captures/WeaverCorrespondenceReaderView-correspondence.json":"562f7f9983c4f56bfab54f51462e2253bed98aaf7bd6fbddab36ca7396c08cf1","dev/sysml/captures/WeaverExecutionReaderViews-accountCommit.json":"a00590aff4a21272cf4dd278c83e1c71a4c76c938ef4a4a87248862999b70417","dev/sysml/captures/WeaverExecutionReaderViews-admissionFloor.json":"0a47fe13c770b7881608c7e700d2caa860dcb4eecd21271378132d6c7722ef47","dev/sysml/captures/WeaverExecutionReaderViews-appendHandoff.json":"0d84875d7d5a235a25c5c5bac12a44ece098cd7dd98d89a36ba94b9fa42e0e84","dev/sysml/captures/WeaverExecutionReaderViews-checkpoint.json":"a67c2efe1400a76464e423d2ac1f64aeea052ee5e15bbc2ea9a33a55256a964a","dev/sysml/captures/WeaverExecutionReaderViews-executionEvidence.json":"f472326e0d72a3f6ec5e429e31b3efe0cca25b3ca3f2378a85150524dedfec1c","dev/sysml/captures/WeaverExecutionReaderViews-executorOffer.json":"5a567b79aeca9603c5bf4b0b3e12cedc08b3e2d0d30865be6e4ee96fc246b7a7","dev/sysml/captures/WeaverExecutionReaderViews-joinEnqueue.json":"6c52bec12f30f905cb05d5c0cf318a339ee2a1460d9174c7dd18420137cd47e6","dev/sysml/captures/WeaverExecutionReaderViews-manifestSwitch.json":"09004c8c5d2220b6f07c7093bbbca6bb26dd5cf109c1e246cda0a049bf79a060","dev/sysml/captures/WeaverExecutionReaderViews-resultProjection.json":"b3a297a46c0cea352a1764966a8617fe0a694ab0a25c711437b8c16bfab4fdb2","dev/sysml/captures/WeaverExecutionReaderViews-walActivation.json":"696165c219207691ac3e0240f8f7ba0083761089c6d49670655364b85cd4175f","dev/sysml/captures/WeaverFloorReaderViews-floorOrdering.json":"58c3404d7c1e84c17c0a41050e5588ebd6119d0bde797d75c36b6009a429404f","dev/sysml/captures/WeaverFloorReaderViews-floorRecovery.json":"bed1c9ca5d75dd698a6e8df308bd224018786a773e8efe3ab072fa791244da4c","dev/sysml/captures/WeaverResearchReaderViews-embeddedTooling.json":"45dd0569338be5e2f736797115d29c569017f8fba24f886b38be9cda0e5278b4","dev/sysml/captures/WeaverResearchReaderViews-floorTransport.json":"fbdb56bef60900927007fa5c6520d344e99848d682cc7690c7a0cdcb9937f4a0","dev/sysml/captures/WeaverResearchReaderViews-gerbilLifecycle.json":"1741aac62e80cf945309de63d5dde0054b11f8c3302bda8f04aebce25c455145","dev/sysml/captures/WeaverResearchReaderViews-gxiLifecycle.json":"09aed11e7515ece76965e2aadf577ba1a41190b583cb7c603461704f86a83f19","dev/sysml/captures/WeaverResearchReaderViews-parentReplay.json":"b00f83a1cb339bd01829b621c95c3e491e4ed8f9e13f362979ef48ec0d504c53","dev/sysml/captures/WeaverResearchReaderViews-profileBinding.json":"b5e4f9787698f14f5b1db4f866d375f8a0d2c12870178558decdd26615e7e2f7","dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json":"068636681000f55369db15c557dffe55236f228fca2662ed489a4daf24a72c3f","dev/sysml/captures/WeaverResearchReaderViews-runtimeAssets.json":"39e79818a0a1008768fa34e3bd24142374d29fd9de48c83c8759c3cb916d59d2","dev/sysml/captures/WeaverResearchReaderViews-semanticSlice.json":"218063c3c0773ca8712926545243c2d44e0306d13636915132348fb6eee10d37","dev/sysml/captures/WeaverViews-architecture.json":"cb1d25c840996da4d0c1d3b927e9fb9a636e7b4be6d330e5fc6193bb70e5b79b","dev/sysml/captures/WeaverViews-assurance.json":"6c9cb909df1134aa3baea1d129ed4f269740186d78c130513e16e36fc63aa1c6","dev/sysml/captures/WeaverViews-contractRefinement.json":"99a584b7a7ac202c054837e547d802fe402147ee3667fcc5fb74b69841ba2967","dev/sysml/captures/WeaverViews-execution.json":"8914ec28010e6869c849d32b69b756c80f5f4192d4186965c348178ac9016989","dev/sysml/captures/WeaverViews-gateway.json":"abcc5c0dd2b8ae483be7994d42fe87872eea6bae38a4447619936bc491067a02","dev/sysml/captures/WeaverViews-providerDeliveryJoin.json":"1e069227046954ec329a5a30eace9332a6c1288613939e11d45a79a65ae247c9","dev/sysml/captures/WeaverViews-providerEgressWindow.json":"c11b316d78990b8d02ffc09759c7b3c2d4333a243b6667cf82bb005cbb87d47b","dev/sysml/captures/WeaverViews-rangeRecovery.json":"5835d25e0c6c34f24dd54d11b92f85498025b33cf2191744847adb97348c11c6","dev/sysml/captures/WeaverViews-routeExecution.json":"881e66b2795823ba04fdde6cb0848851352ceb076fd0e839e4c8eee667ba0fc3","dev/sysml/captures/WeaverViews-routeSelection.json":"b35aa6bb1e46bbe66c30edfc928f49af0ba3d81d1f90e9ebbfd9a30560aa107d","dev/sysml/captures/WeaverViews-storage.json":"e737d85441f9167d86a15384009e71a2bc190913298c67219b1d45b3857a1e51","dev/sysml/captures/WeaverViews-streamAdmission.json":"48f7b17066ac2d1c5cfbc0fc9f2557301cc4b1dd1c91cec5ca38d5dfa02dd840","dev/sysml/captures/WeaverViews-zeroTrust.json":"366c70992a29e424dbe37c462d3e7f5481cc78a240f96ec1d459a4107fa28edd","dev/sysml/ControlActivation.sysml":"78bc6792c3a64ee54210720d3d88c1984b5c876d3a0647b6829bf904a811014f","dev/sysml/CorrespondenceReaderView.sysml":"24b811c00528feaab3547d5db3b7fada290ff89478ac2be0a1d252d8ea1e5828","dev/sysml/ExecutionReaderViews.sysml":"88f690ed1fed91f63f7571d14bf5d7c1c8d14ee3b8d1d17ae333dfd7a6176df3","dev/sysml/FloorReaderViews.sysml":"93401ba5b2009dd54614f7e5aff81d91a20085efbb77b3a143726ffdea16592c","dev/sysml/GatewayArchitecture.sysml":"dbec3964b7873ed0633964b05d1ba1ee828050aed35a3066858d0c38893f2642","dev/sysml/PolicyEvidenceDesign.sysml":"6a7d738b004be62e7412ea68080944f8cb6fb3aea785258efaefc2efc1c4e0e6","dev/sysml/ProviderRpc.sysml":"60a7ae2140742902a487dd29565d543591a1d080eeef37745241e142df101cc0","dev/sysml/ReaderDesigns.sysml":"4df8352980f9727b85a26533dc5ebfd67730540359d553a17d562574f3ea2529","dev/sysml/ResearchReaderViews.sysml":"cb10ed4ab79e911197834a8102e8a84986c567a358098e36d234d15b9c5acaec","dev/sysml/StoragePersistence.sysml":"b6b58b8802a557a7f3af787c2e7875be64865169ca3fd7e9973b13f6c3dc792d","dev/sysml/StreamingExecution.sysml":"d0d4d92300fba2b908ace30d9065cb2bac1d86f3b7c98219c1853a30f3110e85","dev/sysml/WeaverExecution.sysml":"9bb74725a7ede555fa9168ba1de95cc0b9e780f4769ebcdcbc5e7b659b8c6f9a","dev/sysml/ZeroTrustRefinement.sysml":"7cbec57110f03ed68469a1f49cb2046769516b09a6eb1b9433d866161bba6a82","docs/10-19-llm-gateway/10-routing-and-inference/10.02-llm-routing.d2":"513cad143cde846a9393bb5020dc4843caa1bb844204d3d0c13d1b5ada5efc70","docs/10-19-llm-gateway/10-routing-and-inference/10.05-route-execution.d2":"7c3ff8609c24983d0b27511756d8c5c04d0dc2cf5c973fc7012eaa0acda421e2","docs/10-19-llm-gateway/10-routing-and-inference/10.07-provider-egress-window.d2":"3c9c7c67296700d3b08cea62dddd5bdd011e7bafd61c2b4ecf1e38c32a94d6e7","docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2":"ae2cb959a5c54c205f8483d7d8dbf5da42fe89b64aff557789b6e9d682bcfdd2","docs/10-19-llm-gateway/11-attempts-and-failover/11.02-attempt-ledger.d2":"5438329d7af60e9596b5fe4519b04a27a7c36ce1d1dc1aa5442db6df7167cd8e","docs/10-19-llm-gateway/12-semantic-contracts/12.02-semantic-contract.d2":"8560ac03652d2dfb8aeb7797c0e3b61031e49f9a3276d3207c8758a32037c530","docs/10-19-llm-gateway/13-authoritative-scope/13.02-authoritative-scope.d2":"e5950b420b85e30891bdb2264c7fad7ccd9ec9934b6175906d592d683b3a844c","docs/10-19-llm-gateway/14-registry-publication/14.02-registry-publication.d2":"9153743fc734fb044f94a4d22175fbe963f0f15f02598143dfbd7a06cd880177","docs/10-19-llm-gateway/15-recovery-cas/15.02-recovery-cas.d2":"c5de2f6cb52b0450361b2ed0523f647bdcad1fc43d410231f91ae86aee450859","docs/10-19-llm-gateway/16-policy-publication/16.02-policy-publication.d2":"4be00575666b7ada7185a30e553b42b9c36fe9109ce89df3d0dbb4b30ac10cab","docs/10-19-llm-gateway/17-policy-continuation/17.02-policy-continuation.d2":"4108a821aba5a2de1ffebc59b9e0d9180130bb3f598ac2130d59a83e8eca571f","docs/10-19-llm-gateway/18-canonical-registry/18.02-canonical-registry.d2":"f3b44cf54b006df34b528075bbc54742963a53e2afd4cbee435f81095b59b800","docs/10-19-llm-gateway/19-multi-key-registry/19.02-multi-key-registry.d2":"c44a2569dec8ae1fab46acb1ddd58f8b468e7ea7b11136c120a6bf2b042cf8b7","docs/20-29-execution-authority/20-result-projection/20.02-result-projection.d2":"696df32a9d705c6915bcc43a33616126cdce61ce5af0ae198c0dca5bc898d645","docs/20-29-execution-authority/21-join-enqueue/21.02-join-enqueue.d2":"430f46389111827b9f0ad5c9c3193366729fffe917ef18a5bfa0ec8238f6ab02","docs/20-29-execution-authority/22-executor-offer/22.02-executor-offer.d2":"0d93c13abcc1bd79afb32e6ae8a965cc5ec3b0c30fc1958f2f212e12b5e4b65a","docs/20-29-execution-authority/23-execution-reconciliation/23.02-execution-reconciliation.d2":"14c698ad47a243d46d788ab3494b1ad22ae7f14a163140eb6b4f5e8e071c6269","docs/20-29-execution-authority/24-account-commit/24.02-account-commit.d2":"10d6a5116d2c8be77ce7f27312d9d49ad832645c6748bb7bd68bb6942055990e","docs/20-29-execution-authority/25-wal-activation/25.02-wal-activation.d2":"9ebcd14701116e583157282a1678a6f1e0fe70e1ee4b9b7e038b520d4392ce05","docs/20-29-execution-authority/26-checkpoint-truncation/26.02-checkpoint-truncation.d2":"c5c1a35a16fe9b33029169b16d4c0af113f49e665eed0074ce524fc7a15bdb77","docs/20-29-execution-authority/27-manifest-switch/27.02-manifest-switch.d2":"c4de2ef519af25b2c41194df561860ad0236b0309b3178b388204c29cebf9f41","docs/20-29-execution-authority/28-append-handoff/28.02-append-handoff.d2":"f7646793e8540ec5f1e587d5e13deaf16d166180f80107ac8f9c904ea5c9372c","docs/20-29-execution-authority/29-admission-floor/29.02-admission-floor.d2":"0b9794f3d5fdfc7dcdbb519426eecf7e6ec6cb707de5017387c9aa47208ea385","docs/30-39-assurance/31-protected-signer/31.02-protected-signer.d2":"bc787086ae26a1a6cd56e51a2b4182c86e476f13e28ed1f5d80363b1d827e013","docs/30-39-assurance/32-key-boundary/32.02-key-boundary.d2":"1b616363aa68166988cc1d09404d637da406f048b9647676ec5f42d15f1762ca","docs/30-39-assurance/33-device-isolation/33.02-device-isolation.d2":"f4b086efce29484b70d4d4b2c04dad3887976d69187c25234e734e90260a6c7c","docs/30-39-assurance/34-floor-decision/34.02-floor-decision.d2":"78e2de9f044edb41944a56c1c8c8251a9cacd3470cf73c16b87f5ba100139a04","docs/30-39-assurance/34-floor-decision/34.04-floor-recovery.d2":"296d821eae11d4b77a552ae21d91eadcddcf032a15989dd35490128397044203","docs/30-39-assurance/35-intent-continuation/35.02-intent-continuation.d2":"08475ba17d7c98911a7db912041b669d049c75315c861322f72a5b50a471df55","docs/30-39-assurance/36-gateway-head-cas/36.02-gateway-head-cas.d2":"51669df10ec208197e690f656b962b259959af5f225243b62e5ff6bbea5637a5","docs/30-39-assurance/37-broker-consumption-queue/37.02-broker-consumption-queue.d2":"1ad636df3ba980d5f25b1a330c00c8b21f152958fe7c86617736e1b1f85a1ed8","docs/30-39-assurance/38-logical-range-recovery/38.02-logical-range-recovery.d2":"8ed5e1adc741da6852d027828993a83816cadb0c7bc1732bfaf121b2a64878d3","docs/40-49-admission-coordination/40-source-join/40.02-source-join.d2":"b8815cf59a1be49a4657b6ec3857d39e6d7d39ab4bb3ed44521c71ffe0ec5cee","docs/40-49-admission-coordination/41-source-custody/41.02-source-custody.d2":"feef18f62d537d4eb0659c0f1d719218df1a3eda506c9468b59423b151550bd7","docs/40-49-admission-coordination/42-custody-publication/42.02-custody-publication.d2":"24f019e8633cc816f7488e3f65384d2dea96ac8a3685714665a47bc6144b1e5c","docs/40-49-admission-coordination/43-caller-custody/43.02-caller-custody.d2":"6352167e4d3427fd9a66befb74fb3eebf91a127c5e82ecff8312b24178d5117f","docs/40-49-admission-coordination/44-incarnation-issuance/44.02-incarnation-issuance.d2":"215f52c84c9f41c36352f8b6da8b4670f1b375672cfc9efdf6a8bd1df95c946e","docs/40-49-admission-coordination/45-bootstrap-invitation/45.02-bootstrap-invitation.d2":"9e019de8289428a97580fe66ccefc6b9d0a43c1bac07433d2f29596f4d407401","docs/40-49-admission-coordination/46-beneficiary-registration/46.02-beneficiary-registration.d2":"322b848fdd67ea88c99b509cb5d913d7a5023e327edea51f16f44816356d81ce","docs/40-49-admission-coordination/47-enrollment-credential/47.02-enrollment-credential.d2":"ea0aa0bed915bea42d3d65c8f6572f799eb63d0aee1018b75803e61ef034d303","docs/40-49-admission-coordination/48-subject-authority/48.02-subject-authority.d2":"9f707fbc6e5ba8933a0e4d9d057f013c5764afc503f819288f628d3f9709f88d","docs/40-49-admission-coordination/49-routine-routing-config/49.02-routine-routing-config.d2":"7fa18b652ba97e8fe66f402a9a85d65740db9d3ffadff7890db7d72826c498b6","docs/50-59-research-program/51-qualified-semantic-slice/51.06-semantic-gateway-slice.d2":"d63df655a635fccac3c92eded92c039a3f079c24fa2b7a2fd0dc1f3fabd3c0f5","docs/50-59-research-program/52-committed-profile-binding/52.04-committed-profile.d2":"3ea30976830c607bf8cec62cbabc4291c384bd5f368049a45777f6f981d87d6e","docs/50-59-research-program/53-gerbil-exit/53.04-gerbil-lifecycle.d2":"b7b623664edc6e86efe62eeee7f5977dc207f0cb12e40cb6f0e77e38160695de","docs/50-59-research-program/54-dynamic-gxi-exit/54.04-dynamic-lifecycle.d2":"d4d410dd8cb10de6d3526b54ac7f96731d2f2a94dd9763aad96a0926608e251c","docs/50-59-research-program/55-dynamic-gxi-paired/55.04-runtime-boundary.d2":"573b248a6b7ce2d7eee1e70a469c54e4f195c4894ec7b0f61c8406fae843eccc","docs/50-59-research-program/56-gambit-image-closure/56.04-locator-boundary.d2":"0c45ee11d269b0cab8998c7fc3432ec851b9390b7530486225134b261d8d7de8","docs/50-59-research-program/57-runtime-implementation/57.03-runtime-boundary.d2":"193d22a5bd9e4b23260334d085df8aa5ec19c349f13cd9f56eaa26fe54f7e3ac","docs/50-59-research-program/58-streaming-execution/58.03-streaming-runtime.d2":"76ea49c83b4b36af1e775f80475d40747640b80a330434bf86635e255e84ef14","docs/50-59-research-program/58-streaming-execution/58.05-range-progress-recovery.d2":"aef20c8ad7d7420a65422add6d9fb635bdbe32e42e49427d3179bf20499ae4cd","docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2":"6f4e8218ea262e35efaebaf8cc2f96345b2ef1e7e9c1a6b12b68290dd99c683d","docs/50-59-research-program/59-provider-rpc/59.21-verification-ownership.d2":"e035ae7e56ee5e6498f131ed62f4792547c1e716aa5ed29865b333f54665e8f1","docs/50-59-research-program/59-provider-rpc/59.26-semantic-execution-ecosystem.d2":"50c091b094125693e2debe73599a63405849f1f55ab3658030674692c9334e14","docs/50-59-research-program/59-provider-rpc/59.30-governance-adapter-acceptance.d2":"88cbbd45e63358bb45a58fb27f85e275b9cc9fb3d3aee6af19eabed0912545d2","docs/50-59-research-program/59-provider-rpc/59.43-floor-transport-owner.d2":"36c4d6b561332ab30deb464a92bb4c2f02ceed5c8a1ca66617f72b6086b2c555","docs/50-59-research-program/59-provider-rpc/59.44-cloud-rpc-arrow-boundaries.d2":"fe0ac2220e04f6ccea851247ecf8ae1cab4ec8c8ba8744010c478992c233ebed","docs/50-59-research-program/59-provider-rpc/59.45-slow-consumer-zero-trust.d2":"e36cf58a239a2d9f0c99789bb7484de4e26180a8f941970540f72b530a79d813","docs/50-59-research-program/59-provider-rpc/59.46-functional-security-frameworks.d2":"e541b969352e8149e71e5b539988f9955b525e5e5ba3e7e7270bd4a98fbe19f5","docs/50-59-research-program/59-provider-rpc/59.47-property-testing-framework.d2":"f66ed065dcf955a233968ca295517c642be30dad9b24e23a781fe34e4bed45d9","docs/50-59-research-program/59-provider-rpc/59.49-policy-proposal-barrier.d2":"3a8559bb22f812075d9d7de4a397978995d06c32ed22e9415f990413551aebb6","docs/50-59-research-program/59-provider-rpc/59.50-parent-contract-and-replay.d2":"2db3983f56e938c927b68077551573c8e86362da892f47890459ab7b3f929c64","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-architecture.d2":"10e92e79b69f4b0813551dd2ddadc5ad225b7b0fa8374ed7015b7f2fe66bb6e1","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-contract-refinement.d2":"204c9e20d9027b7a38bf2a964da9a7cadb92744561fa9f1eb3fa29d00f4fa386","docs/50-59-research-program/59-provider-rpc/59.52-reviewed-publication-cas.d2":"4e0998e61717d5441e242cde0dfc52198312b67b63f0ce8b0425a423d1b88a24","docs/50-59-research-program/59-provider-rpc/59.53-artifact-registry-recovery.d2":"f7083a48413d41ad99e7191281bd6e74a92b33c7cc1f4f2f9ae322bb1405088a","docs/50-59-research-program/59-provider-rpc/59.54-source-incarnation-authority.d2":"1e55c0487f01d70462e8df6b46eff9e799b0dc592c0e780c759fa602e3d84444","docs/50-59-research-program/59-provider-rpc/59.55-evidence-reviewed-publication.d2":"c66435372642f7a93ca7fc6f78c2abcbc364a4dde447d10dcc4b2b21ccc06456","docs/50-59-research-program/59-provider-rpc/59.56-runtime-assets-and-authority-floor.d2":"c675469701bb6994fed1976d1e90d01dc1cc4e416a6788f865494fa3243d32c1","docs/50-59-research-program/59-provider-rpc/59.57-schema-bound-candidate-replay.d2":"5ca15af556e0a4ba5bdf1742cf81182ad72e7f51b2eb63352b839e068a7ad7d2","docs/50-59-research-program/59-provider-rpc/59.58-independent-source-recovery.d2":"4b21999b3554be15374448f36ffbccf517b32784a65cadde0f4c1eb8308da377","docs/50-59-research-program/59-provider-rpc/59.59-retained-root-and-recovery-coverage.d2":"37fdf1d3dd01f087434a6108b43a5657d7aecf79a2b9e60638d70eb0b1a4984b","docs/50-59-research-program/59-provider-rpc/59.60-persistent-source-key-custody.d2":"d27df3a14df5d57ad725c1455c82a4ab5bad45b78acea8cd1a76e59958b710eb","docs/50-59-research-program/59-provider-rpc/59.61-authority-bound-replay-pair.d2":"bd4962775564848a90ec49439301cf0cdfbaa4018956344e809f5b318bea6ccd","docs/50-59-research-program/59-provider-rpc/59.62-burn-exposure-recovery.d2":"fab4ea6d0981d75dd4c704f302268f3c5af0898e299e8e0fb38b34d07200b22c","docs/50-59-research-program/59-provider-rpc/59.63-mrr-admission-contract.d2":"ed3c604e0d350049f00528c7117675a7db751b3d6683719b03be116bcf49d5c5","docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.d2":"7164874fdbeec99f2185e1091f759466a68a3b7d9b239db6a503f16383fce50e","docs/50-59-research-program/59-provider-rpc/59.65-turso-concurrent-admission.d2":"0ade3ea326e2066ce908129e383b7e0f371a429710ed0a0bad30ddcfd61f034e","docs/50-59-research-program/59-provider-rpc/59.66-bounded-writer-reuse.d2":"9390a3c12f06c2f33e3df99088dc39de92d3bccc971ddf5a632910515a67623e","docs/50-59-research-program/59-provider-rpc/59.67-writer-owner-lifecycle.d2":"c28559ccf38b2f3320d84bbc0ffc6133e2708081e95bff39d5ed75d064287bde","docs/50-59-research-program/59-provider-rpc/59.69-hot-path-cost-boundaries.d2":"e5789625590fab63bc3635627b7e20ac41f64b8f40cbeee84d51a85f27ab31f1","docs/50-59-research-program/59-provider-rpc/59.75-complete-entry-and-output-contract.d2":"d667501bc15d6c31d986994f641d8d38f63c1d910784e6852e596c24c4e4c7c7","docs/50-59-research-program/59-provider-rpc/59.75-package-linkage.d2":"bc655ae71cc46e0d5b7f42637b78530f262c3142394485e2a9ba31f6516a0a10","docs/50-59-research-program/59-provider-rpc/59.76-embedded-tooling-and-darwin-io.d2":"87655d7c6d81c1ab203f886930f1630003e006c0edb71f90ac3ca23a0cb91845","docs/50-59-research-program/59-provider-rpc/59.77-mrr-turso-storage.d2":"72a4dceeb20cca337276f64537d47dbbd2ac0ce359a7a63997090e6476a40c96","docs/50-59-research-program/59-provider-rpc/59.84-quint-preparation-and-completion.d2":"17f485d7c541506c42003ebba887705ea61972f00c9498aa3c0d153a33b02922","docs/architecture/08-diagram-catalog.org":"353a4296584381207513468ef291e7e1aefdcd6f9f2b854c92be90aab47577ea","docs/architecture/diagrams/00a-readme-overview.d2":"1e6119c9d5b2d8a40d3bec0c8add35e8c078dd739e46fcf45c589b8125c7c46f","docs/architecture/diagrams/00c-gateway-runtime.d2":"c1d93cc1f635803872e3349c89b5127145bdcdd2b85e9a48f83d63f0bda439da","docs/architecture/diagrams/00d-zero-trust-overview.d2":"0d3d1a5de0967db2331b9be81468cee1b7cb1d1d98966c5e541e4fc24023f2e6","docs/architecture/diagrams/01-system-boundaries.d2":"69b4622c26b18a8518d46f79db8ce281c756a16f7f1a46977272086bf4dc38e0","docs/architecture/diagrams/01-system-relationships.d2":"dde40fac8667b79a070fda14ebd892f1f1e7c1217726595179b541c855f80c2c","docs/architecture/diagrams/02-admission-sequence.d2":"97077cb16cd4457fe14092caeb4bc8cf2912d434763a08fcf350cd6a4c2b2c74","docs/architecture/diagrams/03-attempt-state.d2":"e696fc0f1d63f58100405852e88e8a7dfb1a625e43be398f3bb54bbc1d90e13a","docs/architecture/diagrams/03a-attempt-observation.d2":"6b387ec7fbcff7d5e3e129bad7ea9590afe0324800a5a13bf7a89377ad86c387","docs/architecture/diagrams/04-consume-timeout.d2":"2ccfe8d033069e0d891531f3b5afef4febf21b2722209a612454d14321cac940","docs/architecture/diagrams/05-fencing-boundaries.d2":"1103ed75ac615b1a2f8239c0321d046a5a87acfa235d5042d8a529e23acd7483","docs/architecture/diagrams/06-source-admission.d2":"4d20817291c5de93b7f97366e6cb1b4af954f22de1ebcb3012c139a4b9dbd82c","docs/architecture/diagrams/07-post-claim-outcomes.d2":"63258620c15c2f52963dcdba33b4ac82cd12aadd1c2de005cd029655493493c1","docs/architecture/diagrams/08-code-as-policy.d2":"fc2263ff1ae000055e6054b89beee60f53b9621707510354c34ef45057889676","docs/architecture/diagrams/09-claim-wins-race.d2":"9eff775ddac29c47acd2c0b69fb1ff98ba9a20943da970c2804e270979555c41","docs/architecture/diagrams/10-commit-dispatch-sequence.d2":"fa5d56c49bc3f590c88cf7c3b63e180afd2d2a39fca878d1515917077ff1687a","docs/architecture/diagrams/11-zero-trust-assurance.d2":"ea93840da2ff4bdac59349f5ad7a56cee5506600283d0c364c53275dde0b5b48","docs/architecture/diagrams/12-execution-correspondence.d2":"1dd66ee8c517fd9c6f2f4b1700aeec3e620d699fbe9eeee20df8e05a7f1decb0","docs/architecture/diagrams/13-policy-to-execution.d2":"4bb05b74c3bc0ca997c5e5035ddc949fa374db3ff49bf2104a6c9753e12be3ef","docs/architecture/diagrams/14-adapter-broker-boundary.d2":"b855fa0482a5524226354b26bc8d7ecef0daf2ab1cab54c1783eba0ff29fab01","docs/architecture/diagrams/15-stream-message-authorization.d2":"cedf1c545a853ec2a9ae51bea928b04376d192f1a4c2af117fa54f475ad541e0","docs/architecture/diagrams/16-authoritative-spent-state.d2":"201bd9fe5eb6101543d939e3d83aca646e2b07c13ff1e3c56779571a0cd1172e","docs/architecture/diagrams/17-logical-message-observation.d2":"2333ad147295ead60ed6a92dc824cf6f5769f3828eff1e0cdf58e50aace7b1e1","docs/architecture/diagrams/18-shared-identity-budget.d2":"5ab4992fd8b6a6abf518fb0bbc8c2c8ad8b920d0be74a6e734d846319252ffa7","docs/architecture/diagrams/19-finite-domains-and-migration.d2":"b72b451d0bb97de46831e4b266d8fdd22d59e7d54db99446d53549f081a008e2","docs/architecture/diagrams/20-anchor-recovery-and-egress.d2":"9479271410f1bb57f92106a1d91ec73c73872568d9fcda55cac5aa64b89e5c9f","docs/architecture/diagrams/21-composed-journal-transport-lifecycle.d2":"0fffe555ee4c2c1222c97eebd24ca9b0df91a4d3ec118300ae3b88240004c3c8","docs/architecture/diagrams/22-finite-stream-manifest.d2":"60b33eb6d06aeaa1027546a1fc9d6c07069c3cd3c7d23df8ff8d63a341afe2ea","docs/architecture/diagrams/23-driver-completion-recovery.d2":"271963db2cd881bb82e164bb1544c7bcf311e1781f20170d858ccb65a596d8f5","docs/architecture/diagrams/24-writer-settlement-closure.d2":"ea1930326b0073e7fabd8b64ef3ffea781f1aef60db0d942f9ab14f1150296e9","docs/architecture/diagrams/25-settlement-anchor-recovery.d2":"8904bfcda525de21b48ea8f2db8d12aaa27e85818ccde43fb545851dc522ba3b","docs/architecture/diagrams/26-gate-consumption-persistence.d2":"42e676634ecb40cfb2dee06db1f5497d0e58c05f30097618c3852eb946992f0d","docs/architecture/diagrams/27-anchor-commit-broker-fencing.d2":"5c2ae36987b00655bbcdba36352e03b61765739ad2f3fc80a561ff0d325a9461","docs/architecture/diagrams/28-anchor-configuration-prefix.d2":"1ac0eeb3c76f5ae0ce3565d4469e50210786c3bc53c703a1a61d519dfa075512","docs/architecture/diagrams/29-quorum-durable-promises.d2":"2e4a24c3fae49e710d5afc31d4681a9efc8c2e8af3fa58a0957ede05fe7c0255","docs/architecture/diagrams/39-shared-execution-exposure.d2":"2c08f5b3d4531a7be2aadec8f1ff9d4476495418e94e84c1ff643583ac991ce4","docs/architecture/diagrams/assets/agent-request.svg":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","docs/architecture/diagrams/assets/bounded-write.svg":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","docs/architecture/diagrams/assets/budget-ledger.svg":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","docs/architecture/diagrams/assets/components/activity.svg":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","docs/architecture/diagrams/assets/components/book-open.svg":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","docs/architecture/diagrams/assets/components/bot.svg":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","docs/architecture/diagrams/assets/components/brain.svg":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","docs/architecture/diagrams/assets/components/circle-question-mark.svg":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","docs/architecture/diagrams/assets/components/clipboard-check.svg":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","docs/architecture/diagrams/assets/components/coins.svg":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","docs/architecture/diagrams/assets/components/database.svg":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","docs/architecture/diagrams/assets/components/file-check.svg":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","docs/architecture/diagrams/assets/components/fingerprint-pattern.svg":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","docs/architecture/diagrams/assets/components/message-square.svg":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","docs/architecture/diagrams/assets/components/rotate-ccw-clock.svg":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","docs/architecture/diagrams/assets/components/rotate-ccw.svg":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","docs/architecture/diagrams/assets/components/route.svg":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","docs/architecture/diagrams/assets/components/send.svg":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e","docs/architecture/diagrams/assets/components/shield-check.svg":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","docs/architecture/diagrams/assets/components/ticket-check.svg":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","docs/architecture/diagrams/assets/components/waves-horizontal.svg":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","docs/architecture/diagrams/assets/components/workflow.svg":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","docs/architecture/diagrams/assets/go.svg":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","docs/architecture/diagrams/assets/kubernetes.svg":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","docs/architecture/diagrams/assets/model-catalog.svg":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","docs/architecture/diagrams/assets/model-provider.svg":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","docs/architecture/diagrams/assets/permission-check.svg":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","docs/architecture/diagrams/assets/route-choice.svg":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","docs/architecture/diagrams/assets/rust.svg":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","docs/architecture/diagrams/assets/task-contract.svg":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","docs/architecture/diagrams/assets/unknown-hold.svg":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","Project.sysml":"c0c96eba7c5dbce2fde3c5c0f13353acfb1291eee59bcb8eb2ee1860f527aba4"},"rendered":{"observation":{"canvas":{"x":0,"y":0,"width":980,"height":686.21875},"subjects":[{"id":"n0","role":"default","x":40,"y":311,"width":278.65625,"height":122.59375},{"id":"n1","role":"default","x":350.65625,"y":311,"width":278.671875,"height":122.609375},{"id":"n2","role":"default","x":661.328125,"y":311,"width":278.65625,"height":122.59375},{"id":"n3","role":"default","x":40,"y":511.609375,"width":278.65625,"height":122.59375},{"id":"n4","role":"default","x":350.65625,"y":511.609375,"width":278.671875,"height":122.609375},{"id":"n5","role":"default","x":661.328125,"y":511.609375,"width":278.65625,"height":122.59375}],"relations":["edge:0","edge:1","edge:2","edge:3","edge:4"],"headings":[{"role":"title","x":32,"y":32,"width":916,"height":63},{"role":"question","x":32,"y":95,"width":916,"height":56},{"role":"note","x":32,"y":167,"width":916,"height":48},{"role":"note","x":32,"y":215,"width":916,"height":48}]},"readability":{"minimumTextSize":24.14725378787879,"samples":23},"bounds":{"objects":{"x":32,"y":291,"width":916,"height":363.21875}}}}Commit a group. Gate every frame.?How can a shared snapshot stay safe during revocation?One native outcome qualifies the group.Revocation closes delivery; unknown retains the hold. +@font-face{font-family:"Kalam";font-style:normal;font-weight:700;src:url(data:font/woff2;base64,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) format('woff2')}{"renderer":{"package":"@deterministic-engineering/render","version":"1.0.0","icons":{"agent":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","agent-request":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","authentication":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","authorization":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","bounded-write":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","budget":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","budget-ledger":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","capture":"a647d42aa11f4e5e85d0bbf66f483f57f3c4ba3a9536362ed0eaaaae10a89cee","catalog":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","claim":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","decision":"3535642a5b613372c3fd374151ec90aafa19b64b2d33d10b19162cad07a35c7a","document":"0bf9674a401262da8a646305cab00006954721c07765b9962e0dee1c31d560f7","evidence":"0a91b169aaa644829a054cbb94194efffaf4298f2b6f8fa8c6ec2b7b413a1766","go":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","history":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","kubernetes":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","ledger":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","library":"df474fa36a74016b79236fff58a980a8c18c682d1866211776e349a0eb4b2979","message":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","model":"0cfd1f9ed3873f556ace725a7b6a251ebe75d7d976567699276f34df36b2443b","model-catalog":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","model-provider":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","obligation":"e76f4d34a7190400446c89e4e7d187762b885808a64a00c99455599d902570c5","pending":"cca7589bc3b1dcdebacb867c6836c6fc166257f05823555a268354ff9bfac00c","permission-check":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","policy":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","provider":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","publication":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","question":"dbf231e1568dc37189d5674d73c4bfc58a17eb8ada579b3f03bf2813d33c56f4","recovery":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","reference":"3814c570f79ab294252c36530de464c9364814b797afb862d9c62e728a8660fc","route-choice":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","routine":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","routing":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","rust":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","selection":"82b4ab6faf195fea0a891c35268e61c186e93e7c6a9d7967a4f6a73dbf25ae7f","stream":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","task-contract":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","telemetry":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","unknown":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","unknown-hold":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","writer":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e"}},"design":{"audience":"Gateway developers and security reviewers","medium":"GitHub at 830 CSS pixels","message":"One native outcome qualifies the group.\nRevocation closes delivery; unknown retains the hold.","questionRefs":["q1"],"requiredSubjects":["n0","n1","n2","n3","n4","n5"],"requiredRelations":[],"focalSubjects":["n4"]},"evidence":[],"layout":"model-view","presentation":{"objectRows":[["n0","n1","n2"],["n3","n4","n5"]],"notation":"objects","options":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL"},"icons":{"n0":"policy","n1":"authorization","n2":"ledger","n3":"stream","n4":"writer","n5":"stream"},"roles":{"n0":"governance","n1":"governance","n2":"ledger","n3":"semantic","n4":"execution","n5":"execution"},"edgeLabels":true,"graph":{"id":"declared-reading-order","children":[{"id":"n0","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n1","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n2","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n3","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n4","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n5","layoutOptions":{"elk.partitioning.partition":"1"}}],"layoutOptions":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.partitioning.activate":"true"}},"textColumns":22},"drawing":{"mode":"sketch","options":{"seed":29,"roughness":1.3,"strokeWidth":1.2,"fillStyle":"hachure","hachureGap":9,"fillWeight":0.6}},"fonts":[{"family":"Kalam","weight":400,"source":"@fontsource/kalam/files/kalam-latin-400-normal.woff2"},{"family":"Kalam","weight":700,"source":"@fontsource/kalam/files/kalam-latin-700-normal.woff2"}],"palette":{"background":"#F6FAF9","surface":"#FFFFFF","ink":"#163C43","muted":"#496A70","border":"#C9DDDA","accent":"#087E82","secondary":"#946044","tint":"#E1F1EC","secondaryTint":"#F4EADA","onAccent":"#FFFFFF","supported":"#237653","pending":"#986320","conflict":"#A13E54"},"inputSHA256":"58094e598788088833104623513cd145702a04dcaddc9f23e26017dce32cad5f","model":{"subjects":[{"id":"n0","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::changes","label":"Rust / close\nRun edits / origin cut\nShared edits / shared cut"},{"id":"n1","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::validated","label":"Rust / qualify group\nRead shared; write origin\nCedar + claim + domains"},{"id":"n2","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::publication","label":"Turso / commit group\nBurn the bounded group\nPublish one qualified cut"},{"id":"n3","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::staged","label":"Rust / prepare frame\nExact bytes and next span\nReserve transport credit"},{"id":"n4","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::receiver","label":"Rust / consume once\nLive cut + owner + expiry\nOne-use frame cursor"},{"id":"n5","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::tonic","label":"Tonic / accept once\nOne current Rust owner\nObserve delivery later"}],"relations":[{"id":"edge:0","src":"n0","dst":"n1","label":"closeBeforeWrite","kind":"connection","fromPort":"n0.0","toPort":"n1.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:1","src":"n2","dst":"n4","label":"exactRevision","kind":"connection","fromPort":"n2.1","toPort":"n4.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:2","src":"n3","dst":"n4","label":"inertOnly","kind":"connection","fromPort":"n3.0","toPort":"n4.1","srcArrow":"none","dstArrow":"none"},{"id":"edge:3","src":"n1","dst":"n2","label":"qualifiedManifest","kind":"connection","fromPort":"n1.1","toPort":"n2.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:4","src":"n4","dst":"n5","label":"oneOffer","kind":"connection","fromPort":"n4.2","toPort":"n5.0","srcArrow":"none","dstArrow":"none"}]},"modelSource":{"ref":"sdkCapture","modelHash":"eff38a5a555cd875587cbd393a8aa0b12179605e7a85cbba6bae3aaf12562787","view":"WeaverViews::providerDeliveryJoin","portProjection":"owner","labels":{"n0":"Rust / close\nRun edits / origin cut\nShared edits / shared cut","n1":"Rust / qualify group\nRead shared; write origin\nCedar + claim + domains","n2":"Turso / commit group\nBurn the bounded group\nPublish one qualified cut","n3":"Rust / prepare frame\nExact bytes and next span\nReserve transport credit","n4":"Rust / consume once\nLive cut + owner + expiry\nOne-use frame cursor","n5":"Tonic / accept once\nOne current Rust owner\nObserve delivery later"}},"modelTrace":{"modelHash":"eff38a5a555cd875587cbd393a8aa0b12179605e7a85cbba6bae3aaf12562787","requestedView":"WeaverViews::providerDeliveryJoin","resolvedView":"WeaverViews::providerDeliveryJoin","renderingSHA256":"184f54768a7516498adfd3ed388242ab764557361a0b9254f9af21b85366d7bc","capturedRenderingJSON":"{\"modelHash\":\"eff38a5a555cd875587cbd393a8aa0b12179605e7a85cbba6bae3aaf12562787\",\"requestedView\":\"WeaverViews::providerDeliveryJoin\",\"rendering\":{\"view\":\"WeaverViews::providerDeliveryJoin\",\"kind\":\"interconnection\",\"stated\":\"render asInterconnectionDiagram\",\"nodes\":[{\"id\":\"n0\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::changes\",\"nameSynthesized\":false,\"type\":\"EgressMutationBarrier\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n0.0\",\"name\":\"closed\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":550,\"startCol\":9,\"endLine\":550,\"endCol\":46}},{\"id\":\"n1\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::validated\",\"nameSynthesized\":false,\"type\":\"DeliveryValidation\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n1.0\",\"name\":\"closed\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n1.1\",\"name\":\"validated\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":551,\"startCol\":9,\"endLine\":551,\"endCol\":45}},{\"id\":\"n2\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::publication\",\"nameSynthesized\":false,\"type\":\"PublishedRangeSnapshot\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n2.0\",\"name\":\"qualified\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n2.1\",\"name\":\"preserved\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":552,\"startCol\":9,\"endLine\":552,\"endCol\":51}},{\"id\":\"n3\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::staged\",\"nameSynthesized\":false,\"type\":\"InertProviderFrame\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n3.0\",\"name\":\"stagedBytes\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":553,\"startCol\":9,\"endLine\":553,\"endCol\":42}},{\"id\":\"n4\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::receiver\",\"nameSynthesized\":false,\"type\":\"DeliveryReceiver\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n4.0\",\"name\":\"validated\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n4.1\",\"name\":\"staged\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n4.2\",\"name\":\"offer\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":554,\"startCol\":9,\"endLine\":554,\"endCol\":42}},{\"id\":\"n5\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::tonic\",\"nameSynthesized\":false,\"type\":\"ProviderEgressTransport\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n5.0\",\"name\":\"acceptedBytes\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":555,\"startCol\":9,\"endLine\":555,\"endCol\":46}}],\"edges\":[{\"from\":\"n0\",\"to\":\"n1\",\"fromPort\":\"n0.0\",\"toPort\":\"n1.0\",\"label\":\"closeBeforeWrite\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":556,\"startCol\":9,\"endLine\":556,\"endCol\":80}},{\"from\":\"n2\",\"to\":\"n4\",\"fromPort\":\"n2.1\",\"toPort\":\"n4.0\",\"label\":\"exactRevision\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":557,\"startCol\":9,\"endLine\":557,\"endCol\":86}},{\"from\":\"n3\",\"to\":\"n4\",\"fromPort\":\"n3.0\",\"toPort\":\"n4.1\",\"label\":\"inertOnly\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":558,\"startCol\":9,\"endLine\":558,\"endCol\":76}},{\"from\":\"n1\",\"to\":\"n2\",\"fromPort\":\"n1.1\",\"toPort\":\"n2.0\",\"label\":\"qualifiedManifest\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":559,\"startCol\":9,\"endLine\":559,\"endCol\":91}},{\"from\":\"n4\",\"to\":\"n5\",\"fromPort\":\"n4.2\",\"toPort\":\"n5.0\",\"label\":\"oneOffer\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":560,\"startCol\":9,\"endLine\":560,\"endCol\":75}}],\"columns\":[],\"rows\":[],\"notes\":[],\"notices\":[],\"shown\":[]}}","portProjection":"owner","nodes":[{"id":"n0","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":550,"startCol":9,"endLine":550,"endCol":46}},{"id":"n1","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":551,"startCol":9,"endLine":551,"endCol":45}},{"id":"n2","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":552,"startCol":9,"endLine":552,"endCol":51}},{"id":"n3","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":553,"startCol":9,"endLine":553,"endCol":42}},{"id":"n4","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":554,"startCol":9,"endLine":554,"endCol":42}},{"id":"n5","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":555,"startCol":9,"endLine":555,"endCol":46}}],"edges":[{"id":"edge:0","index":0,"from":"n0","to":"n1","fromPort":"n0.0","toPort":"n1.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":556,"startCol":9,"endLine":556,"endCol":80}},{"id":"edge:1","index":1,"from":"n2","to":"n4","fromPort":"n2.1","toPort":"n4.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":557,"startCol":9,"endLine":557,"endCol":86}},{"id":"edge:2","index":2,"from":"n3","to":"n4","fromPort":"n3.0","toPort":"n4.1","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":558,"startCol":9,"endLine":558,"endCol":76}},{"id":"edge:3","index":3,"from":"n1","to":"n2","fromPort":"n1.1","toPort":"n2.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":559,"startCol":9,"endLine":559,"endCol":91}},{"id":"edge:4","index":4,"from":"n4","to":"n5","fromPort":"n4.2","toPort":"n5.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":560,"startCol":9,"endLine":560,"endCol":75}}]},"view":{"source":"docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2","title":"Commit a group. Gate every frame.","purpose":"workflow","kind":"routing","question":{"subjectRefs":["n4"],"ref":"q1","text":"How can a shared snapshot stay safe during revocation?","focusRefs":["model"]},"basis":{"captureRef":"docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2#design-view","modelRefs":["Project.sysml","dev/sysml/AdmissionReaderViews.sysml","dev/sysml/ArchitectureReaderViews.sysml","dev/sysml/ArchitectureViews.sysml","dev/sysml/AssuranceReaderViews.sysml","dev/sysml/AttemptReaderViews.sysml","dev/sysml/AuthorityReaderViews.sysml","dev/sysml/ControlActivation.sysml","dev/sysml/CorrespondenceReaderView.sysml","dev/sysml/ExecutionReaderViews.sysml","dev/sysml/FloorReaderViews.sysml","dev/sysml/GatewayArchitecture.sysml","dev/sysml/PolicyEvidenceDesign.sysml","dev/sysml/ProviderRpc.sysml","dev/sysml/ReaderDesigns.sysml","dev/sysml/ResearchReaderViews.sysml","dev/sysml/StoragePersistence.sysml","dev/sysml/StreamingExecution.sysml","dev/sysml/WeaverExecution.sysml","dev/sysml/ZeroTrustRefinement.sysml"],"obligationRefs":["proof0","proof1","proof2","proof3","proof4","proof5"],"evidenceRefs":[]}},"questions":[{"subjectRefs":["n4"],"ref":"q1","text":"How can a shared snapshot stay safe during revocation?","focusRefs":["model"]}],"references":{"model":"dev/sysml/WeaverExecution.sysml","model0":"Project.sysml","model1":"dev/sysml/AdmissionReaderViews.sysml","model10":"dev/sysml/FloorReaderViews.sysml","model11":"dev/sysml/GatewayArchitecture.sysml","model12":"dev/sysml/PolicyEvidenceDesign.sysml","model13":"dev/sysml/ProviderRpc.sysml","model14":"dev/sysml/ReaderDesigns.sysml","model15":"dev/sysml/ResearchReaderViews.sysml","model16":"dev/sysml/StoragePersistence.sysml","model17":"dev/sysml/StreamingExecution.sysml","model18":"dev/sysml/WeaverExecution.sysml","model19":"dev/sysml/ZeroTrustRefinement.sysml","model2":"dev/sysml/ArchitectureReaderViews.sysml","model3":"dev/sysml/ArchitectureViews.sysml","model4":"dev/sysml/AssuranceReaderViews.sysml","model5":"dev/sysml/AttemptReaderViews.sysml","model6":"dev/sysml/AuthorityReaderViews.sysml","model7":"dev/sysml/ControlActivation.sysml","model8":"dev/sysml/CorrespondenceReaderView.sysml","model9":"dev/sysml/ExecutionReaderViews.sysml","proof0":"dev/proofs/cedar/DomainMigrationComposition.lean","proof1":"dev/proofs/lean/ProviderEgressWindow.lean","proof2":"dev/proofs/lean/ProviderLifecycleFootprint.lean","proof3":"dev/proofs/lean/ProviderReadCustody.lean","proof4":"dev/proofs/lean/ProviderSemanticProgress.lean","proof5":"dev/proofs/lean/ProviderSnapshotPublication.lean","sdkCapture":"dev/sysml/captures/WeaverViews-providerDeliveryJoin.json"},"sourceSHA256":{"dev/d2/themes/assurance.d2":"f7723f53e005a68c803a38ce5c04cd733f46f4a2688fa4b17c66f9d5b308fe24","dev/d2/themes/data.d2":"19fceb46186892da02b763217963cc3ca2a35021219c0d353fdeec84604ddaee","dev/d2/themes/flow.d2":"1f13588619d0c8087c08d8afd023c4c0efe12726711c311e623eea3872726c1f","dev/d2/themes/routing.d2":"f185df198e7435d12b17b7b57b62dfc5795597d95eb926159ee13b448727bcce","dev/d2/themes/sequence.d2":"6e39472720dccc717f984c95b79570494b6ce3828b86227629841649e6c956e6","dev/d2/themes/state.d2":"f1a35cbca0f9cbb055ea9f793ba3dfb86e5fee4e462038ef3e72b94baa61d781","dev/d2/themes/system.d2":"b2a32ec6959ca5df9103c16454c4e34b758e061f850f7de6b619bcbc5fcf17a6","dev/d2/themes/vocabulary.d2":"add21e9b87eab485e5daabf6316fea44eb56b1007b70123f24b0e32e3357f744","dev/proofs/cedar/DomainMigrationComposition.lean":"d1a5ca9740b5cbfe33db7b4f61289c5ccc9d63387c0a9bd6f95c2f04cf1d4436","dev/proofs/cedar/QualifiedReview.lean":"1ae16e06ad03a2906fa8c21dbeea1e3eb7700aa1e9359e64848dec65ccfd079f","dev/proofs/cedar/WeaverPolicyBridge.lean":"a9628a8123d504a34f64bf986feb4471325aa2b0ddc603d76b62632481eab67b","dev/proofs/cedar/ZeroTrustEnrichment.lean":"0c4b138843cc176c27d42d4a31177a3c12486b2d8ff124a6453e3d0922170884","dev/proofs/lean/ProviderEgressWindow.lean":"c4a15b4ccd3a6474290b71374499087dba7dac7a1fda53f3a870100ec2e768a9","dev/proofs/lean/ProviderLifecycleFootprint.lean":"4786544c8a8193c5221bda2f7cd5cf20531bd1856d88b10ae29b280f223e307c","dev/proofs/lean/ProviderReadCustody.lean":"67e83773a1a063852e2303512d4b75b73cd3b9a90117972aafda9ee7348e6b77","dev/proofs/lean/ProviderRpc.lean":"e79d7639ac11220585e59e85dc5bec12b6717f7b51fb28fdcd62dc96d8fae38e","dev/proofs/lean/ProviderSemanticProgress.lean":"d32e010145a7dfcd646daeeeb4b08c0e852b9006bca404681af7e7fe10d0eaa0","dev/proofs/lean/ProviderSnapshotPublication.lean":"312c0380e334fbc5380815d882c6b5b0007747100f818becbee9c6784eeb5716","dev/proofs/lean/RuntimeAdmission.lean":"6111d4b9e93ebaa9f7cc44a55ed504c88c20c8d9de81e947a2e13b3f4a13b13c","dev/proofs/lean/SharedDomains.lean":"10eef67918986264689b09f0a6c0d53b314d7bf43b42f4b9652b403570beb58d","dev/proofs/lean/StreamingExecution.lean":"3fba798a7887a0b2ae29a7e3f0aaa3d7e2fb191e5f1f28109a4a73d28e27b776","dev/sysml/AdmissionReaderViews.sysml":"27ebc6c98ec3a1f7f9081e77a130953c3b646a1fdf6f1d6fc1fa6ed6376e9623","dev/sysml/ArchitectureReaderViews.sysml":"52ffbccbb17bd257e8ad9f4aa9f727c8ce0c00149e7d6738b82042ba06fdd0e3","dev/sysml/ArchitectureViews.sysml":"036eba2c1cf65fd8e0f91272e7728fd9e61d7ff5af74e00da03f3c14472a52c8","dev/sysml/AssuranceReaderViews.sysml":"cd99fb7e9b23e08beac265bc832a8debee0dc1e1d318b0f64d5263519270e390","dev/sysml/AttemptReaderViews.sysml":"0d87cf71e15c26566422a6ddb5945fdb8add8af0484d9d024c32b97597675e21","dev/sysml/AuthorityReaderViews.sysml":"6fa25bd3a64e7f89987caec8e4773928be2cbea0a3c943299e536ca81978316d","dev/sysml/captures/WeaverAdmissionReaderViews-beneficiaryRegistration.json":"bb3fe40509cc1879a36924b5d30d17ede094dc3644eb27849fbdcdb47c29f0cf","dev/sysml/captures/WeaverAdmissionReaderViews-bootstrapInvitation.json":"0d4d7c4632fc7358facf94b4bbe12a599154bd230360453058ff5e026fe087dd","dev/sysml/captures/WeaverAdmissionReaderViews-callerCustody.json":"933ad283941b6907b0f6d57d323b3ab7003a1de543f1150aca40ef3bd3dc1ee1","dev/sysml/captures/WeaverAdmissionReaderViews-custodyPublication.json":"3097dbbedc2dbe9ba6c4fe15f8accaf4f9b8651219c5671319c782b22d7ebaf1","dev/sysml/captures/WeaverAdmissionReaderViews-enrollmentCredential.json":"b62f11b349461a0d8bfdd53056b6be2c4376baac67a1e72a85f71b1dff526503","dev/sysml/captures/WeaverAdmissionReaderViews-incarnationIssuance.json":"64c5685fe9e03b61ff4e78b0cae98b33498c394592ec91b5c8a7693e611eccf5","dev/sysml/captures/WeaverAdmissionReaderViews-routineRouting.json":"983c4d96fc1f6b467c191ad559965b11d8f49706a0d3babbb1b9f07835ddae54","dev/sysml/captures/WeaverAdmissionReaderViews-sourceCustody.json":"6c8c7fcfa6e5ec58d6e325458aef694b31cfc380c5387b878431ebde619e485d","dev/sysml/captures/WeaverAdmissionReaderViews-sourceJoin.json":"4b02fe58b62e0a4c9d805c0dd071923fcb0afd39375276f9bb77943d84e8c031","dev/sysml/captures/WeaverAdmissionReaderViews-subjectAuthority.json":"1dd45c5e633905d36c4430ce22174d101969c60b4c9a38ebb1e90618d812546f","dev/sysml/captures/WeaverArchitectureReaderViews-adapterBroker.json":"4b9da3905020fdbf324a81738fa2a76f0439d8c23442800b258ec73a559b313f","dev/sysml/captures/WeaverArchitectureReaderViews-anchorBroker.json":"2f1802ce07745d4a44d21d3cb98e09a8f5e5a4d9d4b53f4888b913201d0941f4","dev/sysml/captures/WeaverArchitectureReaderViews-anchorEgress.json":"1e2a4ccc196214ad715ab2163a8f8a10600dee723255207419dd0f6769a0f2b8","dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json":"a0bebc5e912184bfee65a3288bbc487031d4cf0f2cd3c71285f058fe7142ce03","dev/sysml/captures/WeaverArchitectureReaderViews-codePolicy.json":"f08ede8649faacabc91a177d5133e0b92d933f1c416294c4d61f04dc55cb1feb","dev/sysml/captures/WeaverArchitectureReaderViews-configPrefix.json":"ef0d65c53cf03dcbd09dcd7cefd4488b7ecf405ae51d152df843cabb41807bb1","dev/sysml/captures/WeaverArchitectureReaderViews-driverCompletion.json":"b6ceeffd98f87d7e6261e02744a8236cde3a35419908d578d175b25239372fe4","dev/sysml/captures/WeaverArchitectureReaderViews-fencing.json":"4ac01959c19f3166eee044e5c3a258930d59c0b159d95a884cdf169b79ece2f0","dev/sysml/captures/WeaverArchitectureReaderViews-gatePersistence.json":"4beba7b5cd4e620715440dc40bd5aeb4cadf96a43f596031e61e58596e3701d3","dev/sysml/captures/WeaverArchitectureReaderViews-journalLifecycle.json":"d107f9bb4fa38e4eba9768329c88a8e1bede9f4d810d8283247bc144c76178a3","dev/sysml/captures/WeaverArchitectureReaderViews-logicalObservation.json":"962193507a4c9c7e1b55232795f795f265827eb7f3538fd817c66ce992164ea8","dev/sysml/captures/WeaverArchitectureReaderViews-manifest.json":"bb5ba5357520fcc205a9fa4d5f045169e55ca5a42c13c18bab957c2c2bfee8c1","dev/sysml/captures/WeaverArchitectureReaderViews-migration.json":"a3540a49ad6a49da75c022916905d80b6f45448fc7f4c381f7af11b2b27cc3ac","dev/sysml/captures/WeaverArchitectureReaderViews-policyExecution.json":"2acf02b6dfb01193050c98c6dfb9c8d0fb318907192e008393c493518f580411","dev/sysml/captures/WeaverArchitectureReaderViews-quorumPromises.json":"3a83243e86c793b955caed914d8fc46451b52d0de361f1df57bf005f5a61a4ab","dev/sysml/captures/WeaverArchitectureReaderViews-relationships.json":"5d7b3a5dd36d4b2e4835e84e2fbbf0ce7d2667b294ac1d1707eb31319e2fc5fe","dev/sysml/captures/WeaverArchitectureReaderViews-settlementAnchor.json":"c02c9b51f69ebfe0a71dda18a6cb77000833f165e05b7ee1738934540f575854","dev/sysml/captures/WeaverArchitectureReaderViews-sharedBudget.json":"ee6dfa5160417481b932bd1512cdf61f922d700a10f8cdc749d1f075c6bc05dc","dev/sysml/captures/WeaverArchitectureReaderViews-sharedExposure.json":"b194613295f8d8be51f1640d39c9c4b94b98a3d638482b649c1894595b1543a3","dev/sysml/captures/WeaverArchitectureReaderViews-spentState.json":"cecb6f68896a1dd6cf7a46eb19406d9163f2b867a0671d000bf332e0afd229cf","dev/sysml/captures/WeaverArchitectureReaderViews-writerSettlement.json":"31be9ede3e803dee11aa87d1060670274fbfcf647216871eca88c40459d4e1c2","dev/sysml/captures/WeaverArchitectureReaderViews-zeroAssurance.json":"ff2d2b779c0656e44e093e264c0d51e0b67e7ee3a6bd2791381a78ca54ec3a3d","dev/sysml/captures/WeaverAssuranceReaderViews-brokerQueue.json":"7b0eb5ceeca912bfb67f8ec7e1b0e5873ffce143c224ab5d9ce0cee60e30e671","dev/sysml/captures/WeaverAssuranceReaderViews-continuation.json":"409bd8489db25e6cdc85d5315763c918af731ab877f23defc322c3bf79027e4b","dev/sysml/captures/WeaverAssuranceReaderViews-deviceEvidence.json":"74be93d150fd06ef18677de824014bcf16cb0975444638e8c2100045b812c5b5","dev/sysml/captures/WeaverAssuranceReaderViews-gatewayHead.json":"57640f47e1c8b8cfccb057ab8169ccd70e5f875fb6f29de245a2e4d0dfe5d30f","dev/sysml/captures/WeaverAssuranceReaderViews-keySession.json":"4214cbffe8db0eb72aa603632c021789dd7e28252f534cb36d0cce03943966fb","dev/sysml/captures/WeaverAssuranceReaderViews-rangeRecovery.json":"e9f6307a038a358326c5023eafc1cc63163f8e150e9052fce931760ee799929c","dev/sysml/captures/WeaverAssuranceReaderViews-signer.json":"6f70fdf45a86c6adccb7cc20d6d956977d4b60109040223d0a270ed39bbb9ffb","dev/sysml/captures/WeaverAttemptReaderViews-admission.json":"d596e99a10d57d963971187870b394f13902347dd63fbbd25d47a9eba262dc95","dev/sysml/captures/WeaverAttemptReaderViews-outcome.json":"f733c3a62ec92c751bed7d4af2a171159ecca791cc94a6a5bbbaf7102c666246","dev/sysml/captures/WeaverAuthorityReaderViews-attemptLedger.json":"eda5e5a9488349c8c6a7ae35f9c734d57c5a98906af45cd1803498e677d8df40","dev/sysml/captures/WeaverAuthorityReaderViews-canonical.json":"e482a9565342b97eae507fc4dced9da96a451b481c362aecf4100d9ff20894be","dev/sysml/captures/WeaverAuthorityReaderViews-multiKey.json":"edadbfe4c4b779a672f9ba10e2932f3316f2e9cb76def0824ab1720de77ab32c","dev/sysml/captures/WeaverAuthorityReaderViews-publication.json":"6b2cf4c564cdc16e5209a9ab2e501d5fad3bab5f0b0d4489cd76d59cf9ef9010","dev/sysml/captures/WeaverAuthorityReaderViews-recoveryCAS.json":"a0eb5417ae07bc68617c03cc6d15764237fb34de5991f7cc039fa3f81f115da0","dev/sysml/captures/WeaverAuthorityReaderViews-scope.json":"3f410c66badd909ed8a225cf0d855e677935d794e5ad18a693850dc11c694784","dev/sysml/captures/WeaverCorrespondenceReaderView-correspondence.json":"f95c6e9c343b767adb01a3da95e9e40bb255c0e82c99d7a94db4990d6287f09d","dev/sysml/captures/WeaverExecutionReaderViews-accountCommit.json":"4efa7c3f4336161e13fa82cd3caedd5b58f9a9c39eb908926009da3c7fc632fc","dev/sysml/captures/WeaverExecutionReaderViews-admissionFloor.json":"eae22d625eff71110531ebdc80e2c5e1b0e97d162622d2070a1c6b675e6235e1","dev/sysml/captures/WeaverExecutionReaderViews-appendHandoff.json":"d01bce1e5343581a0ec8c20c61f13f24fa800c628e52bb29234741560d43a343","dev/sysml/captures/WeaverExecutionReaderViews-checkpoint.json":"1ab5f8ec641df819977247d976f0b43dc1e64dc7be2d02dbf4ae37d4a526467f","dev/sysml/captures/WeaverExecutionReaderViews-executionEvidence.json":"a2c298c54bdaaa0208816c254c86c96d8aec30d928a9d353800bb60ff5d112eb","dev/sysml/captures/WeaverExecutionReaderViews-executorOffer.json":"599a5827ec5a194f64d391bed06f579315ae6ccbcdb5cdba8f32d9cf151cb935","dev/sysml/captures/WeaverExecutionReaderViews-joinEnqueue.json":"6c7f0bd9e64ae305668f98d8049f6751b4237fafae08d12d2cf9f5871e3457fe","dev/sysml/captures/WeaverExecutionReaderViews-manifestSwitch.json":"e12bb543a99ad8022dd55a2c6578351e336877b1512cb563eeaccef77ba82caa","dev/sysml/captures/WeaverExecutionReaderViews-resultProjection.json":"f47530cd5ed6195faa5f95771e4d22559dd143955e1c9c4ea19f6bf28c91da06","dev/sysml/captures/WeaverExecutionReaderViews-walActivation.json":"ac2ce8046f78381b21d02a52eb101526aa067fdc8c03256a59a67ebd06ea1682","dev/sysml/captures/WeaverFloorReaderViews-floorOrdering.json":"f96c5974dc67d80439db49f295718ed53403b7ff907c5e74d1d54f07c7e17c37","dev/sysml/captures/WeaverFloorReaderViews-floorRecovery.json":"8e3969a35dad50fe57b834ed48bb7baecfaf96bb149e6867563ef95942ed2f1b","dev/sysml/captures/WeaverResearchReaderViews-embeddedTooling.json":"3909e0757ea17b7b0c6fe6deb63ad54dd30b4da9f8a0a08f874c1018abd765db","dev/sysml/captures/WeaverResearchReaderViews-floorTransport.json":"2f1ca96080a750ab06f883de2133f225d4b74679286c74af24f6e1145410ad7e","dev/sysml/captures/WeaverResearchReaderViews-gerbilLifecycle.json":"f5219a0d8fced700e814276195ab8900d6e9d0bd6186dcb42401fbcb17fd1d59","dev/sysml/captures/WeaverResearchReaderViews-gxiLifecycle.json":"e16dadb9e152fdad81565022360c269cb18cc0547f8770988fc466c7c4fdcc78","dev/sysml/captures/WeaverResearchReaderViews-parentReplay.json":"f7162a3e44c6423c4721c1b04092eea53136e875f202edc626cfcb93fcdd4745","dev/sysml/captures/WeaverResearchReaderViews-profileBinding.json":"21ecc30f186aa899e1f54b7b307e443f8b16363ffc18fe77ee0e13ee94dee50b","dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json":"8896989dd0154bbc380a603d4ef5b0ea4e88874821097a3b396f2baeef152294","dev/sysml/captures/WeaverResearchReaderViews-runtimeAssets.json":"1ebf39723fec5dae93ee61cec7c83b661d3e61c133fbfa47d1c8d2227dcea8a3","dev/sysml/captures/WeaverResearchReaderViews-semanticSlice.json":"f752f776f4798f38c58dd48dc9fe1007e8bc5418ca4fcba8399a6ca5ca39b5dd","dev/sysml/captures/WeaverViews-architecture.json":"b59e3722a61358fd111b31004df8e0451ceaf5fe1a4f663f97a46c30bcba6d45","dev/sysml/captures/WeaverViews-assurance.json":"0254e9bb2f22d0502c64d063cdd39eff6e99025195a20e4a48cb0eaf4a5e0a95","dev/sysml/captures/WeaverViews-contractRefinement.json":"ef4d1ee4fe0ec4906c25372e9e2bbb6a808d6b9e88ffc070def159463b0884f3","dev/sysml/captures/WeaverViews-execution.json":"b5cfd6f2158df6268b2a9815f009b2ad1655542361f009401d71cea42e668caa","dev/sysml/captures/WeaverViews-gateway.json":"04052b561c3fdd47f10e96bd06fdf62ccfbe6a9965a5c06edd97efbc38e085d0","dev/sysml/captures/WeaverViews-providerDeliveryJoin.json":"184f54768a7516498adfd3ed388242ab764557361a0b9254f9af21b85366d7bc","dev/sysml/captures/WeaverViews-providerEgressWindow.json":"6ae1a5c56080c63329f34f9b800f6323607f5356e512a5fe9f4c478cbcf75605","dev/sysml/captures/WeaverViews-rangeRecovery.json":"b4dcc96b68358ec095c84349f43c78f354486bb223a821a34378523267393bbd","dev/sysml/captures/WeaverViews-routeExecution.json":"142a8f709e4130a34eea8f35bb879f38f88135d0e00fa47c05fb8630adaa919f","dev/sysml/captures/WeaverViews-routeSelection.json":"2a765c562fd231b25f0b8a79cec61ba344e80a153729af23cbf2402821ee6eaa","dev/sysml/captures/WeaverViews-storage.json":"ec1f839d1fb94143b4f1ca4cf4b963cfb0299a62bb99809285799eea538384ee","dev/sysml/captures/WeaverViews-streamAdmission.json":"e93c5dea6d378437c25925bf19c882938d5bf23debdefc19f86b6391d4420218","dev/sysml/captures/WeaverViews-zeroTrust.json":"b7d95b97aa07e14e5d5be4765c744eddf688b93aba34020aa57354c74f13f931","dev/sysml/ControlActivation.sysml":"78bc6792c3a64ee54210720d3d88c1984b5c876d3a0647b6829bf904a811014f","dev/sysml/CorrespondenceReaderView.sysml":"24b811c00528feaab3547d5db3b7fada290ff89478ac2be0a1d252d8ea1e5828","dev/sysml/ExecutionReaderViews.sysml":"88f690ed1fed91f63f7571d14bf5d7c1c8d14ee3b8d1d17ae333dfd7a6176df3","dev/sysml/FloorReaderViews.sysml":"93401ba5b2009dd54614f7e5aff81d91a20085efbb77b3a143726ffdea16592c","dev/sysml/GatewayArchitecture.sysml":"dbec3964b7873ed0633964b05d1ba1ee828050aed35a3066858d0c38893f2642","dev/sysml/PolicyEvidenceDesign.sysml":"6a7d738b004be62e7412ea68080944f8cb6fb3aea785258efaefc2efc1c4e0e6","dev/sysml/ProviderRpc.sysml":"60a7ae2140742902a487dd29565d543591a1d080eeef37745241e142df101cc0","dev/sysml/ReaderDesigns.sysml":"4df8352980f9727b85a26533dc5ebfd67730540359d553a17d562574f3ea2529","dev/sysml/ResearchReaderViews.sysml":"cb10ed4ab79e911197834a8102e8a84986c567a358098e36d234d15b9c5acaec","dev/sysml/StoragePersistence.sysml":"b6b58b8802a557a7f3af787c2e7875be64865169ca3fd7e9973b13f6c3dc792d","dev/sysml/StreamingExecution.sysml":"d0d4d92300fba2b908ace30d9065cb2bac1d86f3b7c98219c1853a30f3110e85","dev/sysml/WeaverExecution.sysml":"789e4924150ada9c79bb1c73ab1aba0e141a68d1e1758c01fed074cc2b6d2b82","dev/sysml/ZeroTrustRefinement.sysml":"7cbec57110f03ed68469a1f49cb2046769516b09a6eb1b9433d866161bba6a82","docs/10-19-llm-gateway/10-routing-and-inference/10.02-llm-routing.d2":"513cad143cde846a9393bb5020dc4843caa1bb844204d3d0c13d1b5ada5efc70","docs/10-19-llm-gateway/10-routing-and-inference/10.05-route-execution.d2":"7c3ff8609c24983d0b27511756d8c5c04d0dc2cf5c973fc7012eaa0acda421e2","docs/10-19-llm-gateway/10-routing-and-inference/10.07-provider-egress-window.d2":"3c9c7c67296700d3b08cea62dddd5bdd011e7bafd61c2b4ecf1e38c32a94d6e7","docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2":"46df65896ab38bc84d19b8d9e63476977fb5d74621f92918f0c3fffd9679755d","docs/10-19-llm-gateway/11-attempts-and-failover/11.02-attempt-ledger.d2":"5438329d7af60e9596b5fe4519b04a27a7c36ce1d1dc1aa5442db6df7167cd8e","docs/10-19-llm-gateway/12-semantic-contracts/12.02-semantic-contract.d2":"8560ac03652d2dfb8aeb7797c0e3b61031e49f9a3276d3207c8758a32037c530","docs/10-19-llm-gateway/13-authoritative-scope/13.02-authoritative-scope.d2":"e5950b420b85e30891bdb2264c7fad7ccd9ec9934b6175906d592d683b3a844c","docs/10-19-llm-gateway/14-registry-publication/14.02-registry-publication.d2":"9153743fc734fb044f94a4d22175fbe963f0f15f02598143dfbd7a06cd880177","docs/10-19-llm-gateway/15-recovery-cas/15.02-recovery-cas.d2":"c5de2f6cb52b0450361b2ed0523f647bdcad1fc43d410231f91ae86aee450859","docs/10-19-llm-gateway/16-policy-publication/16.02-policy-publication.d2":"4be00575666b7ada7185a30e553b42b9c36fe9109ce89df3d0dbb4b30ac10cab","docs/10-19-llm-gateway/17-policy-continuation/17.02-policy-continuation.d2":"4108a821aba5a2de1ffebc59b9e0d9180130bb3f598ac2130d59a83e8eca571f","docs/10-19-llm-gateway/18-canonical-registry/18.02-canonical-registry.d2":"f3b44cf54b006df34b528075bbc54742963a53e2afd4cbee435f81095b59b800","docs/10-19-llm-gateway/19-multi-key-registry/19.02-multi-key-registry.d2":"c44a2569dec8ae1fab46acb1ddd58f8b468e7ea7b11136c120a6bf2b042cf8b7","docs/20-29-execution-authority/20-result-projection/20.02-result-projection.d2":"696df32a9d705c6915bcc43a33616126cdce61ce5af0ae198c0dca5bc898d645","docs/20-29-execution-authority/21-join-enqueue/21.02-join-enqueue.d2":"430f46389111827b9f0ad5c9c3193366729fffe917ef18a5bfa0ec8238f6ab02","docs/20-29-execution-authority/22-executor-offer/22.02-executor-offer.d2":"0d93c13abcc1bd79afb32e6ae8a965cc5ec3b0c30fc1958f2f212e12b5e4b65a","docs/20-29-execution-authority/23-execution-reconciliation/23.02-execution-reconciliation.d2":"14c698ad47a243d46d788ab3494b1ad22ae7f14a163140eb6b4f5e8e071c6269","docs/20-29-execution-authority/24-account-commit/24.02-account-commit.d2":"10d6a5116d2c8be77ce7f27312d9d49ad832645c6748bb7bd68bb6942055990e","docs/20-29-execution-authority/25-wal-activation/25.02-wal-activation.d2":"9ebcd14701116e583157282a1678a6f1e0fe70e1ee4b9b7e038b520d4392ce05","docs/20-29-execution-authority/26-checkpoint-truncation/26.02-checkpoint-truncation.d2":"c5c1a35a16fe9b33029169b16d4c0af113f49e665eed0074ce524fc7a15bdb77","docs/20-29-execution-authority/27-manifest-switch/27.02-manifest-switch.d2":"c4de2ef519af25b2c41194df561860ad0236b0309b3178b388204c29cebf9f41","docs/20-29-execution-authority/28-append-handoff/28.02-append-handoff.d2":"f7646793e8540ec5f1e587d5e13deaf16d166180f80107ac8f9c904ea5c9372c","docs/20-29-execution-authority/29-admission-floor/29.02-admission-floor.d2":"0b9794f3d5fdfc7dcdbb519426eecf7e6ec6cb707de5017387c9aa47208ea385","docs/30-39-assurance/31-protected-signer/31.02-protected-signer.d2":"bc787086ae26a1a6cd56e51a2b4182c86e476f13e28ed1f5d80363b1d827e013","docs/30-39-assurance/32-key-boundary/32.02-key-boundary.d2":"1b616363aa68166988cc1d09404d637da406f048b9647676ec5f42d15f1762ca","docs/30-39-assurance/33-device-isolation/33.02-device-isolation.d2":"f4b086efce29484b70d4d4b2c04dad3887976d69187c25234e734e90260a6c7c","docs/30-39-assurance/34-floor-decision/34.02-floor-decision.d2":"78e2de9f044edb41944a56c1c8c8251a9cacd3470cf73c16b87f5ba100139a04","docs/30-39-assurance/34-floor-decision/34.04-floor-recovery.d2":"296d821eae11d4b77a552ae21d91eadcddcf032a15989dd35490128397044203","docs/30-39-assurance/35-intent-continuation/35.02-intent-continuation.d2":"08475ba17d7c98911a7db912041b669d049c75315c861322f72a5b50a471df55","docs/30-39-assurance/36-gateway-head-cas/36.02-gateway-head-cas.d2":"51669df10ec208197e690f656b962b259959af5f225243b62e5ff6bbea5637a5","docs/30-39-assurance/37-broker-consumption-queue/37.02-broker-consumption-queue.d2":"1ad636df3ba980d5f25b1a330c00c8b21f152958fe7c86617736e1b1f85a1ed8","docs/30-39-assurance/38-logical-range-recovery/38.02-logical-range-recovery.d2":"8ed5e1adc741da6852d027828993a83816cadb0c7bc1732bfaf121b2a64878d3","docs/40-49-admission-coordination/40-source-join/40.02-source-join.d2":"b8815cf59a1be49a4657b6ec3857d39e6d7d39ab4bb3ed44521c71ffe0ec5cee","docs/40-49-admission-coordination/41-source-custody/41.02-source-custody.d2":"feef18f62d537d4eb0659c0f1d719218df1a3eda506c9468b59423b151550bd7","docs/40-49-admission-coordination/42-custody-publication/42.02-custody-publication.d2":"24f019e8633cc816f7488e3f65384d2dea96ac8a3685714665a47bc6144b1e5c","docs/40-49-admission-coordination/43-caller-custody/43.02-caller-custody.d2":"6352167e4d3427fd9a66befb74fb3eebf91a127c5e82ecff8312b24178d5117f","docs/40-49-admission-coordination/44-incarnation-issuance/44.02-incarnation-issuance.d2":"215f52c84c9f41c36352f8b6da8b4670f1b375672cfc9efdf6a8bd1df95c946e","docs/40-49-admission-coordination/45-bootstrap-invitation/45.02-bootstrap-invitation.d2":"9e019de8289428a97580fe66ccefc6b9d0a43c1bac07433d2f29596f4d407401","docs/40-49-admission-coordination/46-beneficiary-registration/46.02-beneficiary-registration.d2":"322b848fdd67ea88c99b509cb5d913d7a5023e327edea51f16f44816356d81ce","docs/40-49-admission-coordination/47-enrollment-credential/47.02-enrollment-credential.d2":"ea0aa0bed915bea42d3d65c8f6572f799eb63d0aee1018b75803e61ef034d303","docs/40-49-admission-coordination/48-subject-authority/48.02-subject-authority.d2":"9f707fbc6e5ba8933a0e4d9d057f013c5764afc503f819288f628d3f9709f88d","docs/40-49-admission-coordination/49-routine-routing-config/49.02-routine-routing-config.d2":"7fa18b652ba97e8fe66f402a9a85d65740db9d3ffadff7890db7d72826c498b6","docs/50-59-research-program/51-qualified-semantic-slice/51.06-semantic-gateway-slice.d2":"d63df655a635fccac3c92eded92c039a3f079c24fa2b7a2fd0dc1f3fabd3c0f5","docs/50-59-research-program/52-committed-profile-binding/52.04-committed-profile.d2":"3ea30976830c607bf8cec62cbabc4291c384bd5f368049a45777f6f981d87d6e","docs/50-59-research-program/53-gerbil-exit/53.04-gerbil-lifecycle.d2":"b7b623664edc6e86efe62eeee7f5977dc207f0cb12e40cb6f0e77e38160695de","docs/50-59-research-program/54-dynamic-gxi-exit/54.04-dynamic-lifecycle.d2":"d4d410dd8cb10de6d3526b54ac7f96731d2f2a94dd9763aad96a0926608e251c","docs/50-59-research-program/55-dynamic-gxi-paired/55.04-runtime-boundary.d2":"573b248a6b7ce2d7eee1e70a469c54e4f195c4894ec7b0f61c8406fae843eccc","docs/50-59-research-program/56-gambit-image-closure/56.04-locator-boundary.d2":"0c45ee11d269b0cab8998c7fc3432ec851b9390b7530486225134b261d8d7de8","docs/50-59-research-program/57-runtime-implementation/57.03-runtime-boundary.d2":"193d22a5bd9e4b23260334d085df8aa5ec19c349f13cd9f56eaa26fe54f7e3ac","docs/50-59-research-program/58-streaming-execution/58.03-streaming-runtime.d2":"76ea49c83b4b36af1e775f80475d40747640b80a330434bf86635e255e84ef14","docs/50-59-research-program/58-streaming-execution/58.05-range-progress-recovery.d2":"aef20c8ad7d7420a65422add6d9fb635bdbe32e42e49427d3179bf20499ae4cd","docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2":"6f4e8218ea262e35efaebaf8cc2f96345b2ef1e7e9c1a6b12b68290dd99c683d","docs/50-59-research-program/59-provider-rpc/59.21-verification-ownership.d2":"e035ae7e56ee5e6498f131ed62f4792547c1e716aa5ed29865b333f54665e8f1","docs/50-59-research-program/59-provider-rpc/59.26-semantic-execution-ecosystem.d2":"50c091b094125693e2debe73599a63405849f1f55ab3658030674692c9334e14","docs/50-59-research-program/59-provider-rpc/59.30-governance-adapter-acceptance.d2":"88cbbd45e63358bb45a58fb27f85e275b9cc9fb3d3aee6af19eabed0912545d2","docs/50-59-research-program/59-provider-rpc/59.43-floor-transport-owner.d2":"36c4d6b561332ab30deb464a92bb4c2f02ceed5c8a1ca66617f72b6086b2c555","docs/50-59-research-program/59-provider-rpc/59.44-cloud-rpc-arrow-boundaries.d2":"fe0ac2220e04f6ccea851247ecf8ae1cab4ec8c8ba8744010c478992c233ebed","docs/50-59-research-program/59-provider-rpc/59.45-slow-consumer-zero-trust.d2":"e36cf58a239a2d9f0c99789bb7484de4e26180a8f941970540f72b530a79d813","docs/50-59-research-program/59-provider-rpc/59.46-functional-security-frameworks.d2":"e541b969352e8149e71e5b539988f9955b525e5e5ba3e7e7270bd4a98fbe19f5","docs/50-59-research-program/59-provider-rpc/59.47-property-testing-framework.d2":"f66ed065dcf955a233968ca295517c642be30dad9b24e23a781fe34e4bed45d9","docs/50-59-research-program/59-provider-rpc/59.49-policy-proposal-barrier.d2":"3a8559bb22f812075d9d7de4a397978995d06c32ed22e9415f990413551aebb6","docs/50-59-research-program/59-provider-rpc/59.50-parent-contract-and-replay.d2":"2db3983f56e938c927b68077551573c8e86362da892f47890459ab7b3f929c64","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-architecture.d2":"10e92e79b69f4b0813551dd2ddadc5ad225b7b0fa8374ed7015b7f2fe66bb6e1","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-contract-refinement.d2":"204c9e20d9027b7a38bf2a964da9a7cadb92744561fa9f1eb3fa29d00f4fa386","docs/50-59-research-program/59-provider-rpc/59.52-reviewed-publication-cas.d2":"4e0998e61717d5441e242cde0dfc52198312b67b63f0ce8b0425a423d1b88a24","docs/50-59-research-program/59-provider-rpc/59.53-artifact-registry-recovery.d2":"f7083a48413d41ad99e7191281bd6e74a92b33c7cc1f4f2f9ae322bb1405088a","docs/50-59-research-program/59-provider-rpc/59.54-source-incarnation-authority.d2":"1e55c0487f01d70462e8df6b46eff9e799b0dc592c0e780c759fa602e3d84444","docs/50-59-research-program/59-provider-rpc/59.55-evidence-reviewed-publication.d2":"c66435372642f7a93ca7fc6f78c2abcbc364a4dde447d10dcc4b2b21ccc06456","docs/50-59-research-program/59-provider-rpc/59.56-runtime-assets-and-authority-floor.d2":"c675469701bb6994fed1976d1e90d01dc1cc4e416a6788f865494fa3243d32c1","docs/50-59-research-program/59-provider-rpc/59.57-schema-bound-candidate-replay.d2":"5ca15af556e0a4ba5bdf1742cf81182ad72e7f51b2eb63352b839e068a7ad7d2","docs/50-59-research-program/59-provider-rpc/59.58-independent-source-recovery.d2":"4b21999b3554be15374448f36ffbccf517b32784a65cadde0f4c1eb8308da377","docs/50-59-research-program/59-provider-rpc/59.59-retained-root-and-recovery-coverage.d2":"37fdf1d3dd01f087434a6108b43a5657d7aecf79a2b9e60638d70eb0b1a4984b","docs/50-59-research-program/59-provider-rpc/59.60-persistent-source-key-custody.d2":"d27df3a14df5d57ad725c1455c82a4ab5bad45b78acea8cd1a76e59958b710eb","docs/50-59-research-program/59-provider-rpc/59.61-authority-bound-replay-pair.d2":"bd4962775564848a90ec49439301cf0cdfbaa4018956344e809f5b318bea6ccd","docs/50-59-research-program/59-provider-rpc/59.62-burn-exposure-recovery.d2":"fab4ea6d0981d75dd4c704f302268f3c5af0898e299e8e0fb38b34d07200b22c","docs/50-59-research-program/59-provider-rpc/59.63-mrr-admission-contract.d2":"ed3c604e0d350049f00528c7117675a7db751b3d6683719b03be116bcf49d5c5","docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.d2":"7164874fdbeec99f2185e1091f759466a68a3b7d9b239db6a503f16383fce50e","docs/50-59-research-program/59-provider-rpc/59.65-turso-concurrent-admission.d2":"0ade3ea326e2066ce908129e383b7e0f371a429710ed0a0bad30ddcfd61f034e","docs/50-59-research-program/59-provider-rpc/59.66-bounded-writer-reuse.d2":"9390a3c12f06c2f33e3df99088dc39de92d3bccc971ddf5a632910515a67623e","docs/50-59-research-program/59-provider-rpc/59.67-writer-owner-lifecycle.d2":"c28559ccf38b2f3320d84bbc0ffc6133e2708081e95bff39d5ed75d064287bde","docs/50-59-research-program/59-provider-rpc/59.69-hot-path-cost-boundaries.d2":"e5789625590fab63bc3635627b7e20ac41f64b8f40cbeee84d51a85f27ab31f1","docs/50-59-research-program/59-provider-rpc/59.75-complete-entry-and-output-contract.d2":"d667501bc15d6c31d986994f641d8d38f63c1d910784e6852e596c24c4e4c7c7","docs/50-59-research-program/59-provider-rpc/59.75-package-linkage.d2":"bc655ae71cc46e0d5b7f42637b78530f262c3142394485e2a9ba31f6516a0a10","docs/50-59-research-program/59-provider-rpc/59.76-embedded-tooling-and-darwin-io.d2":"87655d7c6d81c1ab203f886930f1630003e006c0edb71f90ac3ca23a0cb91845","docs/50-59-research-program/59-provider-rpc/59.77-mrr-turso-storage.d2":"72a4dceeb20cca337276f64537d47dbbd2ac0ce359a7a63997090e6476a40c96","docs/50-59-research-program/59-provider-rpc/59.84-quint-preparation-and-completion.d2":"17f485d7c541506c42003ebba887705ea61972f00c9498aa3c0d153a33b02922","docs/architecture/08-diagram-catalog.org":"353a4296584381207513468ef291e7e1aefdcd6f9f2b854c92be90aab47577ea","docs/architecture/diagrams/00a-readme-overview.d2":"1e6119c9d5b2d8a40d3bec0c8add35e8c078dd739e46fcf45c589b8125c7c46f","docs/architecture/diagrams/00c-gateway-runtime.d2":"c1d93cc1f635803872e3349c89b5127145bdcdd2b85e9a48f83d63f0bda439da","docs/architecture/diagrams/00d-zero-trust-overview.d2":"0d3d1a5de0967db2331b9be81468cee1b7cb1d1d98966c5e541e4fc24023f2e6","docs/architecture/diagrams/01-system-boundaries.d2":"69b4622c26b18a8518d46f79db8ce281c756a16f7f1a46977272086bf4dc38e0","docs/architecture/diagrams/01-system-relationships.d2":"dde40fac8667b79a070fda14ebd892f1f1e7c1217726595179b541c855f80c2c","docs/architecture/diagrams/02-admission-sequence.d2":"97077cb16cd4457fe14092caeb4bc8cf2912d434763a08fcf350cd6a4c2b2c74","docs/architecture/diagrams/03-attempt-state.d2":"e696fc0f1d63f58100405852e88e8a7dfb1a625e43be398f3bb54bbc1d90e13a","docs/architecture/diagrams/03a-attempt-observation.d2":"6b387ec7fbcff7d5e3e129bad7ea9590afe0324800a5a13bf7a89377ad86c387","docs/architecture/diagrams/04-consume-timeout.d2":"2ccfe8d033069e0d891531f3b5afef4febf21b2722209a612454d14321cac940","docs/architecture/diagrams/05-fencing-boundaries.d2":"1103ed75ac615b1a2f8239c0321d046a5a87acfa235d5042d8a529e23acd7483","docs/architecture/diagrams/06-source-admission.d2":"4d20817291c5de93b7f97366e6cb1b4af954f22de1ebcb3012c139a4b9dbd82c","docs/architecture/diagrams/07-post-claim-outcomes.d2":"63258620c15c2f52963dcdba33b4ac82cd12aadd1c2de005cd029655493493c1","docs/architecture/diagrams/08-code-as-policy.d2":"fc2263ff1ae000055e6054b89beee60f53b9621707510354c34ef45057889676","docs/architecture/diagrams/09-claim-wins-race.d2":"9eff775ddac29c47acd2c0b69fb1ff98ba9a20943da970c2804e270979555c41","docs/architecture/diagrams/10-commit-dispatch-sequence.d2":"fa5d56c49bc3f590c88cf7c3b63e180afd2d2a39fca878d1515917077ff1687a","docs/architecture/diagrams/11-zero-trust-assurance.d2":"ea93840da2ff4bdac59349f5ad7a56cee5506600283d0c364c53275dde0b5b48","docs/architecture/diagrams/12-execution-correspondence.d2":"1dd66ee8c517fd9c6f2f4b1700aeec3e620d699fbe9eeee20df8e05a7f1decb0","docs/architecture/diagrams/13-policy-to-execution.d2":"4bb05b74c3bc0ca997c5e5035ddc949fa374db3ff49bf2104a6c9753e12be3ef","docs/architecture/diagrams/14-adapter-broker-boundary.d2":"b855fa0482a5524226354b26bc8d7ecef0daf2ab1cab54c1783eba0ff29fab01","docs/architecture/diagrams/15-stream-message-authorization.d2":"cedf1c545a853ec2a9ae51bea928b04376d192f1a4c2af117fa54f475ad541e0","docs/architecture/diagrams/16-authoritative-spent-state.d2":"201bd9fe5eb6101543d939e3d83aca646e2b07c13ff1e3c56779571a0cd1172e","docs/architecture/diagrams/17-logical-message-observation.d2":"2333ad147295ead60ed6a92dc824cf6f5769f3828eff1e0cdf58e50aace7b1e1","docs/architecture/diagrams/18-shared-identity-budget.d2":"5ab4992fd8b6a6abf518fb0bbc8c2c8ad8b920d0be74a6e734d846319252ffa7","docs/architecture/diagrams/19-finite-domains-and-migration.d2":"b72b451d0bb97de46831e4b266d8fdd22d59e7d54db99446d53549f081a008e2","docs/architecture/diagrams/20-anchor-recovery-and-egress.d2":"9479271410f1bb57f92106a1d91ec73c73872568d9fcda55cac5aa64b89e5c9f","docs/architecture/diagrams/21-composed-journal-transport-lifecycle.d2":"0fffe555ee4c2c1222c97eebd24ca9b0df91a4d3ec118300ae3b88240004c3c8","docs/architecture/diagrams/22-finite-stream-manifest.d2":"60b33eb6d06aeaa1027546a1fc9d6c07069c3cd3c7d23df8ff8d63a341afe2ea","docs/architecture/diagrams/23-driver-completion-recovery.d2":"271963db2cd881bb82e164bb1544c7bcf311e1781f20170d858ccb65a596d8f5","docs/architecture/diagrams/24-writer-settlement-closure.d2":"ea1930326b0073e7fabd8b64ef3ffea781f1aef60db0d942f9ab14f1150296e9","docs/architecture/diagrams/25-settlement-anchor-recovery.d2":"8904bfcda525de21b48ea8f2db8d12aaa27e85818ccde43fb545851dc522ba3b","docs/architecture/diagrams/26-gate-consumption-persistence.d2":"42e676634ecb40cfb2dee06db1f5497d0e58c05f30097618c3852eb946992f0d","docs/architecture/diagrams/27-anchor-commit-broker-fencing.d2":"5c2ae36987b00655bbcdba36352e03b61765739ad2f3fc80a561ff0d325a9461","docs/architecture/diagrams/28-anchor-configuration-prefix.d2":"1ac0eeb3c76f5ae0ce3565d4469e50210786c3bc53c703a1a61d519dfa075512","docs/architecture/diagrams/29-quorum-durable-promises.d2":"2e4a24c3fae49e710d5afc31d4681a9efc8c2e8af3fa58a0957ede05fe7c0255","docs/architecture/diagrams/39-shared-execution-exposure.d2":"2c08f5b3d4531a7be2aadec8f1ff9d4476495418e94e84c1ff643583ac991ce4","docs/architecture/diagrams/assets/agent-request.svg":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","docs/architecture/diagrams/assets/bounded-write.svg":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","docs/architecture/diagrams/assets/budget-ledger.svg":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","docs/architecture/diagrams/assets/components/activity.svg":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","docs/architecture/diagrams/assets/components/book-open.svg":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","docs/architecture/diagrams/assets/components/bot.svg":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","docs/architecture/diagrams/assets/components/brain.svg":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","docs/architecture/diagrams/assets/components/circle-question-mark.svg":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","docs/architecture/diagrams/assets/components/clipboard-check.svg":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","docs/architecture/diagrams/assets/components/coins.svg":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","docs/architecture/diagrams/assets/components/database.svg":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","docs/architecture/diagrams/assets/components/file-check.svg":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","docs/architecture/diagrams/assets/components/fingerprint-pattern.svg":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","docs/architecture/diagrams/assets/components/message-square.svg":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","docs/architecture/diagrams/assets/components/rotate-ccw-clock.svg":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","docs/architecture/diagrams/assets/components/rotate-ccw.svg":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","docs/architecture/diagrams/assets/components/route.svg":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","docs/architecture/diagrams/assets/components/send.svg":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e","docs/architecture/diagrams/assets/components/shield-check.svg":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","docs/architecture/diagrams/assets/components/ticket-check.svg":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","docs/architecture/diagrams/assets/components/waves-horizontal.svg":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","docs/architecture/diagrams/assets/components/workflow.svg":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","docs/architecture/diagrams/assets/go.svg":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","docs/architecture/diagrams/assets/kubernetes.svg":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","docs/architecture/diagrams/assets/model-catalog.svg":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","docs/architecture/diagrams/assets/model-provider.svg":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","docs/architecture/diagrams/assets/permission-check.svg":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","docs/architecture/diagrams/assets/route-choice.svg":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","docs/architecture/diagrams/assets/rust.svg":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","docs/architecture/diagrams/assets/task-contract.svg":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","docs/architecture/diagrams/assets/unknown-hold.svg":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","Project.sysml":"c0c96eba7c5dbce2fde3c5c0f13353acfb1291eee59bcb8eb2ee1860f527aba4"},"rendered":{"observation":{"canvas":{"x":0,"y":0,"width":980,"height":686.21875},"subjects":[{"id":"n0","role":"default","x":40,"y":311,"width":278.65625,"height":122.59375},{"id":"n1","role":"default","x":350.65625,"y":311,"width":278.671875,"height":122.609375},{"id":"n2","role":"default","x":661.328125,"y":311,"width":278.65625,"height":122.59375},{"id":"n3","role":"default","x":40,"y":511.609375,"width":278.65625,"height":122.59375},{"id":"n4","role":"default","x":350.65625,"y":511.609375,"width":278.671875,"height":122.609375},{"id":"n5","role":"default","x":661.328125,"y":511.609375,"width":278.65625,"height":122.59375}],"relations":["edge:0","edge:1","edge:2","edge:3","edge:4"],"headings":[{"role":"title","x":32,"y":32,"width":916,"height":63},{"role":"question","x":32,"y":95,"width":916,"height":56},{"role":"note","x":32,"y":167,"width":916,"height":48},{"role":"note","x":32,"y":215,"width":916,"height":48}]},"readability":{"minimumTextSize":24.14725378787879,"samples":23},"bounds":{"objects":{"x":32,"y":291,"width":916,"height":363.21875}}}}Commit a group. Gate every frame.?How can a shared snapshot stay safe during revocation?One native outcome qualifies the group.Revocation closes delivery; unknown retains the hold. -Rust / closeRun edits / origin cutShared edits / shared cut +Rust / closeRun edits / origin cutShared edits / shared cut -Rust / qualify groupPending clear; each rowCedar + claim + domains +Rust / qualify groupRead shared; write originCedar + claim + domains diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.11-lifecycle-footprints.org b/docs/10-19-llm-gateway/10-routing-and-inference/10.11-lifecycle-footprints.org index 4da37961..6c199ba8 100644 --- a/docs/10-19-llm-gateway/10-routing-and-inference/10.11-lifecycle-footprints.org +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.11-lifecycle-footprints.org @@ -10,8 +10,15 @@ [[file:10.10-snapshot-publication.org][Published snapshot design and previous evidence]] [[file:10.09-provider-delivery-join.svg]] +This document records the origin-cut stage and its retained measurements. +[[file:10.12-read-custody.org][The subsequent shared-read design]] replaces its +exclusive scheduling assumption for the audited provider paths only. +The lifecycle comparison keeps both arms on exclusive read custody to isolate +its invalidation change; the separate read-custody comparison isolates scheduling. + * Complete deciding view and concrete dependency audit + A transaction's read/scheduling footprint is not its invalidation footprint. The existing scheduler still covers original origin, shared budget/history and API-key/user/tenant identities. This design narrows only the exact lifecycle diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.12-read-custody.org b/docs/10-19-llm-gateway/10-routing-and-inference/10.12-read-custody.org new file mode 100644 index 00000000..c0876d3b --- /dev/null +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.12-read-custody.org @@ -0,0 +1,256 @@ +# SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +# +# SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +#+title: Shared read custody and final delivery latency +#+language: en +#+options: toc:2 + +[[file:10.00-index.org][Routing and inference index]] +[[file:10.11-lifecycle-footprints.org][Earlier lifecycle invalidation study]] +[[file:10.09-provider-delivery-join.svg]] + +* Semantic resources and the architectural change + +The previous scheduler treated any overlap in six namespace roots as an +exclusive conflict, including transactions that only read the shared roots. +Narrowing authority invalidation alone left those readers in a serial queue. + +Read custody now retains the full original-origin, budget, history, API-key, +user and tenant read set, while audited provider operations write only their +own canonical origin lane. Distinct origins can therefore run those native +transactions concurrently even when they share budget, history or quota. +Same-origin operations remain mutually exclusive. This is not permission to +partition a shared budget by caller-supplied family labels. + +The relevant resources are semantic coordinates, rather than whole SQL tables. +For example, a peer's retained digest, reservation and plan ceiling belong to +the shared exposure projection; its dispatch marker does not. The static SQL +audit establishes that the exact classified writes cannot change the peer's +deciding projection. If a new Cedar context field exposes peer mutable run +state, that classification must be retired before publishing that field. + +| Operation | Read set | Write set | Scheduling | +|-----------+----------+-----------+------------| +| Provider consume, dispatch burn, writer acknowledgment, terminal raw usage | Complete six-root actual view | Own origin run state/target/dispatch or raw usage | Shared semantic reads; exclusive original-origin writes | +| Fresh range preparation and exact unknown-to-released CAS | Complete actual view, own cursor and exact manifest | Own origin range rows and next-event cursor | Same read custody; same-origin serialization | +| Readonly delivery renewal | Complete actual view and manifest | No shared semantic coordinate | Retains own-origin serialization; no new send capability | +| New/repeated admission | Complete actual view | Claim, held exposure, history, quote/formula and quota projections | Exclusive over every overlapping reader or writer | +| Independently signed settlement | Original reservation, formula, application ID and shared accounts | Shared holds, balances and quota deltas | Existing exclusive scope; no unknown refund | +| Policy, OAuth/witness, migration, profile, source and unclassified changes | Existing broad/global set | Semantic authority | Existing close-before-wait, commit, activate protocol | +| WAL profile | Existing global view | Immediate native transaction | Conservative global authority and writer profile | + +No mutable complete authorization snapshot is cached to avoid fresh SQL +reconciliation. Immutable prepared statements and existing bounded qualifications +remain reusable. Shared semantic writers cannot overlap a reader even when the +native engine would permit the two physical writes. + +* Protocol, fairness and final transfer + +The private =Access::OriginWrite= mode is selected only by sealed +=RangeProgress= and =OriginLifecycle= entrypoints. Generic family transactions +default to exclusive. =Scope::Domains= still carries all six exact roots; +authority closure and scheduler custody are separate contracts. + +Tickets use actual arrival order. An active conflicting lease blocks a +candidate; so does an older queued conflicting writer. A younger compatible +reader cannot repeatedly pass a waiting shared-budget writer. Disjoint work +may proceed. Cancellation removes the waiting ticket without obtaining SQL +custody or returning any reservation. Global release still advances discovery +generation, forcing roots to be checked again after a concurrent migration. + +Authority closes before scheduler waiting. A pending semantic writer therefore +closes final delivery while readers drain, including readers admitted earlier. +A read lease cannot clear a pending barrier, publish a qualification, reuse +an old owner, or consume a response cursor. + +The native outcome must be known before acknowledgment. The final Rust receiver +still checks the complete current cut, unique owner/session, exact manifest, +effective OAuth time bounds, original deadline and one-use cursor. Tonic +handoff is the local irreversible transfer; a later Go receive observation is +not proof of upstream completion or zero unknown exposure. No SQL lock spans +capacity waiting or the Rust-to-Go network transfer. + +MVCC supplies snapshot isolation and write/write conflict handling, not a +proof against application write skew. The application conflict matrix remains +necessary for shared admission and settlement. A native conflict or unknown +commit is an error, never an implicit provider retry, model substitution, +new reservation or budget refund. The existing owner-seal recovery applies. + +* Models and concrete acceptance + +| Obligation | Model | Runtime / positive evidence | +|------------+-------+-----------------------------| +| A compatible write preserves every declared read | Lean =compatible_write_preserves_read= and =arbitrary_policy_preserved= | Closed SQL read/write audit above; sealed provider entrypoints | +| A shared write cannot overlap a reader | Lean =shared_writer_conflicts=; Quint shared-writer schedules | Scheduler conflict PBT and original shared-budget/history tests | +| An older conflicting writer prevents reader bypass | Lean =older_conflicting_writer_blocks=; Quint ordered-ticket schedules | Real threaded FIFO test with two compatible readers and an older writer | +| Compatibility alone never grants final transfer | Lean =unknown_commit_blocks=; Quint unknown/restart/one-use schedules | Existing Go/TLS commit-loss, process-crash, receiver-revocation and migration injection | +| Preserved qualification joins current SPEC obligations | =read_custody_preserves_spec_final_use= imports the current =Gateway.ZeroTrust= theorem | Host must establish actual projection, current FinalUse and reachable run; no claim of verified SQL refinement | +| Real native writes coexist, rather than merely two mocked leases | Quint distinct-origin schedule is an abstraction only | Two independent Turso sessions simultaneously reach the pre-commit range cut and commit all four rows; shared hold/history remain 8/2 | +| API retries and restart cannot reuse original claims | Existing affine/finite-domain proofs | Go =TestProviderReadCustodyProperty=: concurrent TLS streams, Protobuf/Arrow, shared limits and restart replay denial | + +The Quint unsafe shared-mutation control intentionally violates the read +projection invariant when a nominal reader changes a shared coordinate. +Its ticket identities are monotonic arrival ordinals, including after worker +restart. The exploration uses 2,000 traces of 80 transitions; it is bounded +evidence, not a universal liveness proof. + +Lean proves compatibility for arbitrary finite coordinate sets and arbitrary +Policies that depend only on the declared reads. Completeness of the concrete +read set, mediation of all writers, native durability and the current SPEC +Host projection remain explicit premises. The composition uses the CURRENT +reachable run for claim affinity and shared capacity; it does not assume the +whole world equals a previously qualified world. + +* Paired measurement contract + +=BenchmarkProviderReadCustody= compares exclusive and shared read custody in +one immutable release image. Both arms retain origin-local invalidation, +four-range preparation/commit groups, identical actual SQL guards and the same +queue limits. Each bounded trace carries its actual granted access mode. The fairness +validator rejects inversions for shared writers and same-origin work, while +allowing compatible readers to pass one another. Fixture origin identities are +checked against the authoritative inspected stamp. Missing or unknown trace +modes fail validation; no old-format fallback is accepted. + +The safe test-only control can broaden conflicts; production +does not accept its environment switch. + +Each arm executes 128 streams, four in parallel, thirteen frames per stream. +All eight arms cover shared/disjoint domains and no injected pressure/six +pressure workers. Arm order alternates per wave. Preparation, frame encoding +and transport capacity limits remain fixed. + +Report scheduler wait and holding separately from native domain reads and +commit. Acknowledgment-to-Tonic, Tonic-to-Go and original enqueue-to-Go are +matched by the exact frame interval; their quantiles must not be added. +A fast local final gate does not establish submillisecond durable admission +or network delivery. No-injection is not synonymous with low host load. + +* Validation results + +The complete functional suite and both corrected eight-arm measurements pass. +This is not complete submillisecond performance qualification. +Failed diagnostic attempts remain under ignored =.cache/provider-read-custody/=. +The first native concurrency fixture incorrectly moved affine dispatch permits +to fresh sessions and correctly failed before either commit cut. The corrected +fixture keeps each permit with its deciding session; both native commits pass. +This correction does not relax the three-second observation deadline. + +The first complete eight-arm run exposed the old fairness validator's blanket +shared-domain conflict assumption. Its shared cohorts failed on legal read/read +reordering; the disjoint cohorts completed. The failure remains in +=.cache/provider-read-custody/mvcc-pair-before-access-trace.log=. The corrected +validator uses the scheduler's actual granted mode, retains writer and +same-origin negative controls, and requires a complete eight-arm rerun. + +The phase-instrumented repeat retains all 1,024 streams and 13,312 frames. +Every base candidate stream records twelve origin-write/shared-read scopes and +one exclusive admission scope; the control records thirteen exclusive scopes. +Preparation and final queue still use four native groups each. This matches +=ProviderReadCustodyExperiment=, rather than inferring concurrency from a label. + +| Shared roots | Pressure | Streams/s control / candidate | Prepare wait P99 ms/scope | Final queue wait P99 ms/scope | Rust queue-to-Go P99 ms/frame | +|--------------+----------+-------------------------------+---------------------------+------------------------------+------------------------------| +| yes | none injected | 52.97 / 101.9 | 4.533 / 0.001875 | 4.445 / 0.000625 | 0.363 / 0.713 | +| yes | six requested | 47.06 / 76.53 | 11.02 / 0.002167 | 10.98 / 0.001291 | 1.992 / 5.170 | +| no | none injected | 138.6 / 126.7 | 0.002000 / 0.002291 | 0.001875 / 0.001875 | 1.163 / 2.771 | +| no | six requested | 89.58 / 93.86 | 0.002791 / 0.004958 | 0.002292 / 0.001292 | 7.038 / 3.713 | + +| Shared roots | Pressure | Candidate shared-read wait / hold P99 ms/scope | Exclusive-class wait / hold control / candidate P99 ms/scope | Ack-to-Tonic control / candidate P99 us/frame | Tonic-to-Go control / candidate P99 us/frame | +|--------------+----------+-------------------------------------------------+------------------------------------------------------------------+---------------------------------------------+--------------------------------------------| +| yes | none injected | 3.813 / 2.915 | wait 6.746 / 6.847; hold 2.480 / 2.525 | 30 / 232 | 155 / 373 | +| yes | six requested | 4.930 / 7.013 | wait 10.91 / 22.27; hold 4.161 / 10.07 | 509 / 1521 | 1121 / 2740 | +| no | none injected | 0.002166 / 4.862 | wait 0.001959 / 0.004084; hold 3.662 / 5.394 | 511 / 901 | 731 / 975 | +| no | six requested | 0.002000 / 8.241 | wait 0.002417 / 0.001625; hold 7.946 / 11.56 | 2587 / 1830 | 5861 / 2043 | + +The candidate's exclusive class contains only admission in this base workload; +the control's exclusive class includes all thirteen base scopes. Those class +quantiles are not the same per-operation population. Shared-read wait includes +lifecycle operations waiting behind an actual pending admission writer; it is +not the prepare/queue wait alone. Do not claim all read waiting disappeared. + +Candidate final owner-turn P99 is 10.67 us in shared/no-injection and 21.54 us +under shared pressure. All four phase-instrumented cohorts have zero renewals. +Pressure workers achieve 5.722 and 4.946 CPU equivalents, not a guaranteed +six-core load. Domain-read P99 is the sum per stream before selecting the +quantile: shared/no-injection is 0.847 / 1.578 ms control/candidate; shared +pressure is 1.847 / 3.267 ms. It is not a per-query P99. + +The earlier complete repeat, before adding the read/write phase counters, +measures shared/no-injection prepare wait 4.804 / 0.002291 ms, throughput +50.29 / 96.48 streams/s and queue-to-Go 0.436 / 0.726 ms. Both complete runs +show the structural queue reduction; neither establishes universal transport +improvement. The initial failed fairness run is not used as a complete cohort. + +Parallel SQL improves shared throughput and removes unnecessary prepare/queue +serialization, but it exposes concurrent CPU, native commit and transport +service demands. The no-injection candidate queue-to-Go is submillisecond for +shared roots in both complete runs; it regresses relative to its own control. +Disjoint no-injection tails and pressured shared tails fail that target. +These regressions remain visible; no failed stream or slow sample is dropped. + +* Remaining acceptance and next architectural boundary + +The low-background requirement is still open. The early runs overlap other +repository builds. Later process samples show those compilers ending, but a +separate two-sample =top= check still observes only 44.58 and 51.57 percent idle +on the twelve-core host. That is not evidence of a low-background window. +No foreign workload was stopped; no threshold, timeout, queue bound or +concurrency was relaxed. Keep the performance qualification open. + +Further work must separate admission/lifecycle dependency waiting from the +bounded prepare/queue read phases, and measure acknowledged-owner wake, +Tonic/h2/TLS service and Go receive scheduling without moving the timestamp +past native commit. The current measurements cannot attribute every remaining +network tail to a single scheduler or transport mechanism. Do not remove the +real admission, pending writer or final-use barriers to improve a number. + +Accepted verification includes 56 ledger library tests, 129 real-Turso tests +including concurrent native pre-commit coexistence, 29 broker tests and 27 +server tests with three fixtures exercised by the Go host. The complete Go +race suite passes. Twenty-two real TLS/gRPC fault and property groups pass; +two additional actual-view/migration/independent-send groups pass, and the +four trace/fairness/concurrent-stream properties pass after the trace change. +Quint passes twenty-one named schedules and 2,000 seeded 80-transition traces. +Lean checks finite compatible interleavings and the current SPEC composition. +The diagram is generated from SysML/Design and linked above, retaining the +existing 830 px, 18 px, 5-second and 30-second checks. + +Scheme runtime integration and dependency pins are unchanged. Raw test and +failure outputs remain in ignored cache storage; generated images and the +English design/model sources remain reviewable in the repository. + +The shared fixed checkout also contains a concurrent controller/object lifecycle +study. Source-bound figure generation and the final source-model Go checks use +a Git tree inventory containing only this change, including the owned hunks of +=WeaverExecution.sysml=. The concurrent Project, lifecycle actions, model tests +and diagrams remain in the shared checkout for their owner. Runtime, real +native commits and TLS/gRPC fault tests execute in the fixed GHQ checkout. + +The first inventory-copy Go run lacked local Git inventory metadata and failed +the SPDX file-inventory test; it is retained as +=.cache/provider-read-custody/go-review-tree-metadata-failure.log=. After +supplying the existing owned tree's Git inventory, the complete uncached race +suite passes. No inventory assertion or test deadline is relaxed. The earlier +SysML reserved-name diagnostics are retained separately. + +The extended model review found an actual omission in the first read-custody +model: its final offer tracked the owner but omitted the committed shared cut. +An added old-model test reproduces an offer after an intervening shared writer +commits; the failed trace is retained as +=.cache/provider-read-custody/stale-cut-model-counterexample.log=. +The repaired model checks both shared and origin revisions at final offer, +distinguishes semantic lifecycle intents from preserving progress, and fixes +the original frame's origin and owner at qualification. Fresh read tickets +from another origin or a restarted worker cannot mint that original frame. +Pending own lifecycle changes block it; peer lifecycle and exact own progress +preserve it. This closes a model omission; Rust's existing final current-cut, +session and original-frame checks were retained throughout. + +Lean now gives the final transfer an exact qualification equality containing +original binding, shared revision, origin revision and owner, rather than +uninterpreted currentness Booleans. Changed bindings, either revision or owner +each imply that transfer is unavailable; unknown native commit remains a +separate refusal. SPEC FinalUse still supplies authorization, original scope +and global shared-exposure obligations on the current actual state. diff --git a/go/dev/provider_delivery_bench_test.go b/go/dev/provider_delivery_bench_test.go index bfd3af1a..b48b2722 100644 --- a/go/dev/provider_delivery_bench_test.go +++ b/go/dev/provider_delivery_bench_test.go @@ -47,7 +47,18 @@ type deliveryComparison struct { func BenchmarkProviderLifecycleFootprint(b *testing.B) { image := wifImage(b, true) comparison := deliveryComparison{labels: [2]string{"full-domain", "origin-cut"}, - controls: [2][]string{{"WEAVER_TEST_FULL_LIFECYCLE_INVALIDATION=1"}, nil}, queues: [2]int{4, 4}} + controls: [2][]string{{"WEAVER_TEST_FULL_LIFECYCLE_INVALIDATION=1", "WEAVER_TEST_EXCLUSIVE_PROVIDER_READS=1"}, {"WEAVER_TEST_EXCLUSIVE_PROVIDER_READS=1"}}, queues: [2]int{4, 4}} + for _, shared := range []bool{true, false} { + for _, loaded := range []bool{false, true} { + b.Run(fmt.Sprintf("shared=%t/pressure=%t", shared, loaded), func(b *testing.B) { benchmarkProviderDeliveryComparison(b, image, shared, loaded, comparison) }) + } + } +} + +func BenchmarkProviderReadCustody(b *testing.B) { + image := wifImage(b, true) + comparison := deliveryComparison{labels: [2]string{"exclusive-reads", "shared-reads"}, + controls: [2][]string{{"WEAVER_TEST_EXCLUSIVE_PROVIDER_READS=1"}, nil}, queues: [2]int{4, 4}} for _, shared := range []bool{true, false} { for _, loaded := range []bool{false, true} { b.Run(fmt.Sprintf("shared=%t/pressure=%t", shared, loaded), func(b *testing.B) { benchmarkProviderDeliveryComparison(b, image, shared, loaded, comparison) }) diff --git a/go/dev/provider_domain_program_test.go b/go/dev/provider_domain_program_test.go index 4e24850c..0ea4be61 100644 --- a/go/dev/provider_domain_program_test.go +++ b/go/dev/provider_domain_program_test.go @@ -217,7 +217,7 @@ func measureDomainEncodingWave(b *testing.B, f *fixture, plans []v1.ProviderPlan count = uint64(len(plans)) } view, err := f.admin.RPC.InspectExecutionDomains(f.admin.Context(ctx), &pb.OperationKey{Family: plan.Family}) - if err != nil || view.GetHeld() != count*plan.Ceiling || view.GetHistoryCount() != count { + if err != nil || view.GetHeld() != count*plan.Ceiling || view.GetHistoryCount() != count || view.GetStamp().GetOrigin() != plan.Family { b.Fatalf("benchmark hold/history mismatch: %v %v", view, err) } } diff --git a/go/dev/provider_range_scopes_test.go b/go/dev/provider_range_scopes_test.go index 44d7d926..15f7fd52 100644 --- a/go/dev/provider_range_scopes_test.go +++ b/go/dev/provider_range_scopes_test.go @@ -20,6 +20,7 @@ import ( ) type rangeScopeSample struct { + originWrite bool phase string family string arrival, grant uint64 @@ -66,11 +67,11 @@ func parseRangeScopes(log string) (map[string][]rangeScopeSample, error) { } for _, field := range fields[2:] { parts := strings.Split(field, ":") - if len(parts) != 5 || (parts[0] != "prepare" && parts[0] != "queue" && parts[0] != "other" && parts[0] != "revalidate") { + if len(parts) != 6 || (parts[5] != "origin" && parts[5] != "exclusive") || (parts[0] != "prepare" && parts[0] != "queue" && parts[0] != "other" && parts[0] != "revalidate") { return nil, fmt.Errorf("invalid stripe sample: %q", field) } var n [4]uint64 - for i, value := range parts[1:] { + for i, value := range parts[1:5] { n[i], err = strconv.ParseUint(value, 10, 63) if err != nil { return nil, fmt.Errorf("invalid stripe sample value: %q", value) @@ -81,7 +82,7 @@ func parseRangeScopes(log string) (map[string][]rangeScopeSample, error) { return nil, fmt.Errorf("invalid or duplicate stripe ordinal: %q", field) } seen[n[0]], seen[n[1]] = true, true - result[family] = append(result[family], rangeScopeSample{phase: parts[0], family: family, arrival: n[0], grant: n[1], wait: time.Duration(n[2]), hold: time.Duration(n[3])}) + result[family] = append(result[family], rangeScopeSample{originWrite: parts[5] == "origin", phase: parts[0], family: family, arrival: n[0], grant: n[1], wait: time.Duration(n[2]), hold: time.Duration(n[3])}) } finished[family] = final == "1" } @@ -105,7 +106,7 @@ func TestProviderScopeTraceChunksPreserveAllRecords(t *testing.T) { } fmt.Fprintf(&log, "weaver-provider-scope f %d:%d", start, final) for i := start; i < end; i++ { - fmt.Fprintf(&log, " revalidate:%d:%d:1:1", 2*i+1, 2*i+2) + fmt.Fprintf(&log, " revalidate:%d:%d:1:1:origin", 2*i+1, 2*i+2) } log.WriteByte('\n') } @@ -135,7 +136,7 @@ func TestProviderScopeTraceChunksPreserveAllRecords(t *testing.T) { func rangeScopeOvertakes(wave []rangeScopeSample, older rangeScopeSample) int { count := 0 for _, younger := range wave { - if younger.family != older.family && older.arrival < younger.arrival && younger.grant < older.grant { + if (!younger.originWrite || !older.originWrite || younger.family == older.family) && older.arrival < younger.arrival && younger.grant < older.grant { count++ } } @@ -143,20 +144,20 @@ func rangeScopeOvertakes(wave []rangeScopeSample, older rangeScopeSample) int { } func TestProviderScopeFairnessCountsArrivalGrantInversions(t *testing.T) { - property := func(seed uint64, count uint8) bool { + property := func(seed uint64, count uint8, modes uint32) bool { n := int(count%24) + 1 order := rand.New(rand.NewSource(int64(seed))).Perm(n) wave := make([]rangeScopeSample, n) for grant, family := range order { wave[family] = rangeScopeSample{ - family: strconv.Itoa(family), arrival: uint64(family + 1), grant: uint64(n + grant + 1), + originWrite: modes&(1< family { + if prior > family && (modes&(1< 0 { + b.ReportMetric(tailMillis(metric.values, 99), label+"-"+metric.name+"-p99-ms/scope") + } + b.ReportMetric(float64(len(metric.values))/float64(len(arm.streams)), label+"-"+metric.name+"-scopes/stream") + } n := float64(len(arm.streams)) b.ReportMetric(float64(len(prepareWaits))/n, label+"-preparations/stream") b.ReportMetric(tailMillis(prepareWaits, 99), label+"-prepare-wait-p99-ms/scope") diff --git a/go/internal/devrunner/benchmark_pipeline_test.go b/go/internal/devrunner/benchmark_pipeline_test.go index fa696e50..e7ed5fd6 100644 --- a/go/internal/devrunner/benchmark_pipeline_test.go +++ b/go/internal/devrunner/benchmark_pipeline_test.go @@ -98,7 +98,7 @@ func TestPublishedPipelineKeepsSchemeOutsideExecutionQualification(t *testing.T) "execution-benchmark-target": true, "execution-policy-tests": true, "execution-backend-tests": true, "execution-policy-benchmark": true, "execution-ledger-benchmark": true, "execution-provider-benchmark": true, - "execution-lifecycle-footprint-pair": true, "execution-delivery-join-pair": true, "execution-encoding-benchmark": true, "execution-range-prepare-pair": true, + "execution-read-custody-pair": true, "execution-lifecycle-footprint-pair": true, "execution-delivery-join-pair": true, "execution-encoding-benchmark": true, "execution-range-prepare-pair": true, "execution-scheduled-encoding-pair": true, "execution-contention-pair": true, "execution-provider-integration": true, "published-pipeline-benchmark": true, "execution-header-seal-pair": true, "execution-header-wait-pair": true, diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index 77383597..253f1841 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -65,6 +65,9 @@ func Plan(goBinary string) []Stage { {"provider-egress-window-lean", "elan", []string{"run", proofToolchain, "lean", "--json", "dev/proofs/lean/ProviderEgressWindow.lean"}}, {"provider-egress-promotion-quint-tests", "quint", []string{"test", "dev/proofs/quint/ProviderEgressPromotion.qnt", "--main", "ProviderEgressPromotion", "--seed", "293"}}, {"provider-egress-promotion-quint-safety", "quint", []string{"run", "dev/proofs/quint/ProviderEgressPromotion.qnt", "--main", "ProviderEgressPromotion", "--invariant", "safe", "--max-samples", "2000", "--max-steps", "80", "--seed", "293"}}, + {"provider-read-custody-tests", "quint", []string{"test", "dev/proofs/quint/ProviderReadCustody.qnt", "--main", "ProviderReadCustody", "--seed", "293"}}, + {"provider-read-custody-safety", "quint", []string{"run", "dev/proofs/quint/ProviderReadCustody.qnt", "--main", "ProviderReadCustody", "--invariant", "safe", "--max-samples", "2000", "--max-steps", "80", "--seed", "293"}}, + {"provider-read-custody-lean", "elan", []string{"run", proofToolchain, "lean", "--json", "dev/proofs/lean/ProviderReadCustody.lean"}}, {"provider-lifecycle-footprint-tests", "quint", []string{"test", "dev/proofs/quint/ProviderLifecycleFootprint.qnt", "--main", "ProviderLifecycleFootprint", "--seed", "293"}}, {"provider-lifecycle-footprint-safety", "quint", []string{"run", "dev/proofs/quint/ProviderLifecycleFootprint.qnt", "--main", "ProviderLifecycleFootprint", "--invariant", "safe", "--max-samples", "2000", "--max-steps", "80", "--seed", "293"}}, {"provider-lifecycle-footprint-lean", "elan", []string{"run", proofToolchain, "lean", "--json", "dev/proofs/lean/ProviderLifecycleFootprint.lean"}}, @@ -227,6 +230,7 @@ func Stages(mode, goBinary string) ([]Stage, error) { {"execution-encoding-benchmark", "cargo", []string{"bench", "-p", "weaver-server", "--features", "arrow", "--bench", "gateway", "--locked", "--offline", "--", "server/encoding_guard_hold", "--noplot"}}, {"execution-delivery-join-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderDeliveryJoin$", "-benchtime=1x", "-count=1", "-v"}}, {"execution-lifecycle-footprint-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderLifecycleFootprint$", "-benchtime=1x", "-count=1", "-v"}}, + {"execution-read-custody-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderReadCustody$", "-benchtime=1x", "-count=1", "-v"}}, {"execution-range-prepare-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderRangePreparationGroup$", "-benchtime=1x", "-count=1", "-v"}}, {"execution-scheduled-encoding-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderScheduledEncoding$", "-benchtime=1x", "-count=1", "-v"}}, {"execution-contention-pair", goBinary, []string{"-C", "go", "test", "-count=1", "-tags=integration", "./dev", "-run", "^TestContentionPairs$", "-v"}}, From a450c2245d1c47971f960a261c1f43eee5726921 Mon Sep 17 00:00:00 2001 From: guangtao Date: Fri, 6 Nov 2026 01:28:26 +0800 Subject: [PATCH 003/105] Shorten provider admission barriers and release Go bootstrap custody --- crates/broker/src/lib.rs | 4 +- crates/broker/src/provider/mod.rs | 2 + crates/broker/src/provider/observation.rs | 67 ++++ crates/broker/src/provider/request.rs | 45 ++- crates/broker/src/provider/response.rs | 28 +- crates/broker/src/provider/runtime.rs | 23 +- crates/broker/tests/unit/provider_dispatch.rs | 12 +- crates/broker/tests/unit/provider_request.rs | 7 +- crates/ledger/src/lib.rs | 4 +- .../ledger/src/persistence/commit_observer.rs | 5 + crates/ledger/src/persistence/mod.rs | 4 +- crates/ledger/src/persistence/scope.rs | 82 ++++- crates/ledger/src/persistence/scope_trace.rs | 11 +- crates/ledger/src/persistence/timing.rs | 2 + crates/ledger/src/provider.rs | 34 +- crates/ledger/tests/unit/provider.rs | 3 + .../tests/unit/provider_admission_turn.rs | 94 +++++ crates/ledger/tests/unit/scope_trace.rs | 2 +- crates/server/src/grpc_output.rs | 10 + crates/server/src/grpc_provider.rs | 12 + crates/server/tests/unit/provider_commit.rs | 19 +- .../cedar/DomainMigrationComposition.lean | 28 ++ dev/proofs/cedar/lakefile.toml | 2 +- dev/proofs/lean/ProviderAdmissionTurn.lean | 115 +++++++ dev/proofs/quint/ProviderAdmissionTurn.qnt | 64 ++++ dev/sysml/ArchitectureViews.sysml | 1 + dev/sysml/WeaverExecution.sysml | 49 ++- dev/sysml/runtime-trace.json | 3 +- .../10-routing-and-inference/10.00-index.org | 2 + .../10.09-provider-delivery-join.d2 | 18 +- .../10.09-provider-delivery-join.svg | 4 +- .../10.17-admission-turn.org | 321 ++++++++++++++++++ .../provider_admission_overlap_bench_test.go | 75 ++++ go/dev/provider_admission_turn_test.go | 255 ++++++++++++++ go/dev/provider_backpressure_test.go | 10 +- go/dev/provider_control_bench_test.go | 286 ++++++++++++++++ go/dev/provider_delivery_bench_test.go | 44 ++- go/dev/provider_delivery_join_test.go | 2 +- go/dev/provider_domain_program_test.go | 20 +- go/dev/provider_fixture_test.go | 7 +- go/dev/provider_range_scopes_test.go | 15 +- go/dev/provider_scheduler_bench_test.go | 40 ++- go/dev/provider_transport_phases_test.go | 72 ++++ go/internal/controlplane/deployment.go | 9 + .../devrunner/benchmark_pipeline_test.go | 2 +- go/internal/devrunner/plan.go | 6 + 46 files changed, 1822 insertions(+), 98 deletions(-) create mode 100644 crates/broker/src/provider/observation.rs create mode 100644 crates/ledger/tests/unit/provider_admission_turn.rs create mode 100644 dev/proofs/lean/ProviderAdmissionTurn.lean create mode 100644 dev/proofs/quint/ProviderAdmissionTurn.qnt create mode 100644 docs/10-19-llm-gateway/10-routing-and-inference/10.17-admission-turn.org create mode 100644 go/dev/provider_admission_overlap_bench_test.go create mode 100644 go/dev/provider_admission_turn_test.go create mode 100644 go/dev/provider_control_bench_test.go create mode 100644 go/dev/provider_transport_phases_test.go diff --git a/crates/broker/src/lib.rs b/crates/broker/src/lib.rs index 8500b978..6246393f 100644 --- a/crates/broker/src/lib.rs +++ b/crates/broker/src/lib.rs @@ -10,8 +10,8 @@ pub use broker::execute::execute; pub use broker::stream_session::StreamSession; pub use provider::{ AnthropicWifConfig, ProviderExecution, ProviderExecutionAuthority, ProviderOutput, - ProviderTransport, execute_catalog_provider, execute_catalog_provider_with_oauth, - execute_provider, + ProviderTransport, ProviderTransportPhases, TransportStage, execute_catalog_provider, + execute_catalog_provider_with_oauth, execute_provider, }; pub use transport::https::{HttpsTransport, SendObservation}; pub use transport::stream_sink::StreamTlsConfig; diff --git a/crates/broker/src/provider/mod.rs b/crates/broker/src/provider/mod.rs index 14398465..d4b0302a 100644 --- a/crates/broker/src/provider/mod.rs +++ b/crates/broker/src/provider/mod.rs @@ -5,8 +5,10 @@ //! Provider owner facade; request dispatch and output custody stay private. mod anthropic_sse; mod io_runtime; +mod observation; mod openai_sse; mod range_output; +pub use observation::{ProviderTransportPhases, TransportStage}; mod request; mod response; mod runtime; diff --git a/crates/broker/src/provider/observation.rs b/crates/broker/src/provider/observation.rs new file mode 100644 index 00000000..b2a19029 --- /dev/null +++ b/crates/broker/src/provider/observation.rs @@ -0,0 +1,67 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Per-invocation stage accounting, including failed/dropped futures. It is +//! neither a no-execution certificate nor authority to settle any reservation. +use std::{cell::Cell, time::Instant}; +/// Local elapsed time and outcome of one polled transport stage. +#[derive(Clone, Copy, Default, Debug)] +pub struct TransportStage { + pub nanos: u64, + pub attempted: bool, + pub completed: bool, +} +/// Ordered measurements for one guarded invocation; never settlement evidence. +#[derive(Clone, Copy, Default, Debug)] +pub struct ProviderTransportPhases { + pub connect: TransportStage, + pub tls: TransportStage, + pub write: TransportStage, + pub headers: TransportStage, +} +#[derive(Clone, Copy)] +pub(super) enum Stage { + Connect, + Tls, + Write, + Headers, +} +struct Measurement<'a> { + phases: &'a Cell, + stage: Stage, + entered: Instant, + completed: bool, +} +impl Drop for Measurement<'_> { + fn drop(&mut self) { + let mut phases = self.phases.get(); + let value = TransportStage { + nanos: u64::try_from(self.entered.elapsed().as_nanos()).unwrap_or(u64::MAX), + attempted: true, + completed: self.completed, + }; + match self.stage { + Stage::Connect => phases.connect = value, + Stage::Tls => phases.tls = value, + Stage::Write => phases.write = value, + Stage::Headers => phases.headers = value, + } + self.phases.set(phases); + } +} +pub(super) async fn measure( + phases: &Cell, + stage: Stage, + operation: impl std::future::Future>, +) -> Result { + let mut sample = Measurement { + phases, + stage, + entered: Instant::now(), + completed: false, + }; + let result = operation.await; + sample.completed = result.is_ok(); + result +} diff --git a/crates/broker/src/provider/request.rs b/crates/broker/src/provider/request.rs index 8f2a2b3e..0341dfb2 100644 --- a/crates/broker/src/provider/request.rs +++ b/crates/broker/src/provider/request.rs @@ -5,6 +5,7 @@ //! Immutable preparation is inert. Connect, TLS and request sealing stay guarded. use super::{ io_runtime::IoRuntime, + observation::{ProviderTransportPhases, Stage, measure}, response::{Driver, SealedRequest}, write_seal::{WRITING, WriteSeal}, }; @@ -106,7 +107,10 @@ impl PreparedRequest { self.loopback = address; self } - pub(super) fn write_and_seal(self) -> Result { + pub(super) fn write_and_seal( + self, + phases: &std::cell::Cell, + ) -> Result { require_fresh(self.expires)?; require_oauth_fresh(self.oauth_expires)?; let runtime = self.runtime.clone(); @@ -117,14 +121,29 @@ impl PreparedRequest { let stream = timeout(Duration::from_secs(3), async { #[cfg(feature = "test-loopback")] let tcp = if let Some(peer) = self.loopback { - TcpStream::connect(peer).await? + measure(phases, Stage::Connect, TcpStream::connect(peer)).await? } else { - TcpStream::connect((self.host.as_str(), self.port)).await? + measure( + phases, + Stage::Connect, + TcpStream::connect((self.host.as_str(), self.port)), + ) + .await? }; #[cfg(not(feature = "test-loopback"))] - let tcp = TcpStream::connect((self.host.as_str(), self.port)).await?; + let tcp = measure( + phases, + Stage::Connect, + TcpStream::connect((self.host.as_str(), self.port)), + ) + .await?; tcp.set_nodelay(true)?; - TlsConnector::from(self.tls).connect(name, tcp).await + measure( + phases, + Stage::Tls, + TlsConnector::from(self.tls).connect(name, tcp), + ) + .await }) .await .map_err(|_| Error::Conflict("provider connect unknown"))? @@ -139,12 +158,16 @@ impl PreparedRequest { require_fresh(self.expires)?; require_oauth_fresh(self.oauth_expires)?; let response = Box::pin(async move { sender.send_request(self.request).await }); - SealedRequest::finish_writing( - Driver::new(connection), - response, - phase, - self.runtime, - deadline, + measure( + phases, + Stage::Write, + SealedRequest::finish_writing( + Driver::new(connection), + response, + phase, + self.runtime, + deadline, + ), ) .await }) diff --git a/crates/broker/src/provider/response.rs b/crates/broker/src/provider/response.rs index cec417a4..704b5122 100644 --- a/crates/broker/src/provider/response.rs +++ b/crates/broker/src/provider/response.rs @@ -5,6 +5,7 @@ //! Owned HTTP driver: dropped on failed commit; polled for reads only afterwards. use super::{ io_runtime::IoRuntime, + observation::{ProviderTransportPhases, Stage, measure}, write_seal::{READING, SEALED, WriteSeal}, }; use bytes::Bytes; @@ -95,21 +96,28 @@ impl SealedRequest { }) } /// Only called after dispatch_provider returned success (including commit). - pub(super) fn wait_for_response_headers(mut self) -> Result { + pub(super) fn wait_for_response_headers( + mut self, + phases: &std::cell::Cell, + ) -> Result { self.phase .compare_exchange(SEALED, READING, Ordering::AcqRel, Ordering::Acquire) .map_err(|_| Error::Conflict("provider writer not sealed"))?; let response = self.runtime.wait( self.deadline, - poll_fn(|cx| { - if let Err(error) = self.driver.pump(cx) { - return Poll::Ready(Err(error)); - } - self.response - .as_mut() - .poll(cx) - .map(|r| r.map_err(|_| Error::Conflict("provider outcome unknown"))) - }), + measure( + phases, + Stage::Headers, + poll_fn(|cx| { + if let Err(error) = self.driver.pump(cx) { + return Poll::Ready(Err(error)); + } + self.response + .as_mut() + .poll(cx) + .map(|r| r.map_err(|_| Error::Conflict("provider outcome unknown"))) + }), + ), )?; if response.status() != 200 || response diff --git a/crates/broker/src/provider/runtime.rs b/crates/broker/src/provider/runtime.rs index 8e2cd624..77452924 100644 --- a/crates/broker/src/provider/runtime.rs +++ b/crates/broker/src/provider/runtime.rs @@ -212,6 +212,8 @@ impl ProviderTransport { /// Starts at most one source-bound request. The callback receives bounded batches only /// under a fresh Cedar release guard; its error leaves the release and budget unknown. pub trait ProviderOutput { + /// Bounded local diagnostics, never evidence that a send did not happen. + fn observe_transport(&self, _phases: super::ProviderTransportPhases) {} type Slot; type PreparedFrame; fn stopped(&self) -> bool; @@ -399,16 +401,21 @@ fn open_guarded( let request = transport .prepare(permit.plan(), permit.route(), permit.protocol())? .with_oauth_expiration(permit.oauth_expires()); - let sealed = ledger.dispatch_provider(permit, || { + let phases = std::cell::Cell::new(super::ProviderTransportPhases::default()); + let result = (|| { + let sealed = ledger.dispatch_provider(permit, || { + if output.stopped() { + return Err(Error::Conflict("cancelled before provider invocation")); + } + request.write_and_seal(&phases) + })?; if output.stopped() { - return Err(Error::Conflict("cancelled before provider invocation")); + return Err(Error::Conflict("cancelled after provider seal")); } - request.write_and_seal() - })?; - if output.stopped() { - return Err(Error::Conflict("cancelled after provider seal")); - } - sealed.wait_for_response_headers() + sealed.wait_for_response_headers(&phases) + })(); + output.observe_transport(phases.get()); + result } #[cfg(test)] diff --git a/crates/broker/tests/unit/provider_dispatch.rs b/crates/broker/tests/unit/provider_dispatch.rs index 66e0e381..d28b5c34 100644 --- a/crates/broker/tests/unit/provider_dispatch.rs +++ b/crates/broker/tests/unit/provider_dispatch.rs @@ -343,11 +343,17 @@ proptest::proptest! { proptest::prop_assert_eq!(endpoint.calls.load(Ordering::SeqCst),0); proptest::prop_assert_eq!(ledger.transaction_timings().transaction_hold.attempts,before.transaction_hold.attempts); if revoked {ledger.publish(Some(0),"forbid(principal,action,resource);",2).expect("new fence");} + let phases=std::cell::Cell::default(); if discarded {drop(request);} else { - let result=ledger.dispatch_provider(&permit,||request.write_and_seal()); - if revoked {proptest::prop_assert!(result.is_err());} else {let sealed=result.expect("guarded actual HTTPS seal");sealed.wait_for_response_headers().expect("headers");} + let result=ledger.dispatch_provider(&permit,||request.write_and_seal(&phases)); + if revoked {proptest::prop_assert!(result.is_err());} else {let sealed=result.expect("guarded actual HTTPS seal");sealed.wait_for_response_headers(&phases).expect("headers");} + } + for stage in [phases.get().connect,phases.get().tls,phases.get().write,phases.get().headers] { + proptest::prop_assert_eq!(stage.attempted,!revoked&&!discarded); + proptest::prop_assert_eq!(stage.completed,!revoked&&!discarded); } proptest::prop_assert_eq!(endpoint.calls.load(Ordering::SeqCst),usize::from(!revoked&&!discarded)); + proptest::prop_assert_eq!(ledger.held("f").expect("held"),4); proptest::prop_assert!(ledger.consume_provider("f","infer",&eligible).is_err()); ledger.close().expect("natural cleanup"); @@ -420,7 +426,7 @@ fn dropped_sealed_result_closes_sole_driver_without_header_read_or_refund() { .prepare(permit.plan(), permit.route(), permit.protocol()) .expect("inert request"); let sealed = ledger - .dispatch_provider(&permit, || request.write_and_seal()) + .dispatch_provider(&permit, || request.write_and_seal(&Default::default())) .expect("guard commit and seal"); // This is the same ownership drop used if the deciding commit fails or its // sealed result is lost. It is not an injected native storage-commit fault. diff --git a/crates/broker/tests/unit/provider_request.rs b/crates/broker/tests/unit/provider_request.rs index 654de5c3..931d2767 100644 --- a/crates/broker/tests/unit/provider_request.rs +++ b/crates/broker/tests/unit/provider_request.rs @@ -61,8 +61,13 @@ fn expired_anthropic_bearer_is_rejected_before_io() { .expect("inert Anthropic request"); assert!(prepared.request.headers()["authorization"].is_sensitive()); assert!(!prepared.request.headers().contains_key("x-api-key")); + let phases = std::cell::Cell::default(); assert!(matches!( - prepared.write_and_seal(), + prepared.write_and_seal(&phases), Err(weaver_contracts::Error::Denied) )); + assert!(!phases.get().connect.attempted); + assert!(!phases.get().tls.attempted); + assert!(!phases.get().write.attempted); + assert!(!phases.get().headers.attempted); } diff --git a/crates/ledger/src/lib.rs b/crates/ledger/src/lib.rs index cee0173c..0745be66 100644 --- a/crates/ledger/src/lib.rs +++ b/crates/ledger/src/lib.rs @@ -56,8 +56,8 @@ pub use provider::{ }; #[cfg(feature = "commit-observer")] pub use provider::{ - use_cached_release_programs, use_conservative_range_invalidation, use_exclusive_provider_reads, - use_full_lifecycle_invalidation, use_separate_release_reads, + use_cached_release_programs, use_conservative_range_invalidation, use_early_admission_barrier, + use_exclusive_provider_reads, use_full_lifecycle_invalidation, use_separate_release_reads, }; mod store; mod stream_catalog; diff --git a/crates/ledger/src/persistence/commit_observer.rs b/crates/ledger/src/persistence/commit_observer.rs index 8b506d7d..3b468570 100644 --- a/crates/ledger/src/persistence/commit_observer.rs +++ b/crates/ledger/src/persistence/commit_observer.rs @@ -13,6 +13,7 @@ pub enum Cut { AfterRangePrepareCommit, BeforeDeliveryCommit, AfterDeliveryCommit, + BeforeAdmissionSchedule, BeforeAdmissionCommit, AfterAdmissionCommit, BeforeLifecycleCommit, @@ -31,6 +32,10 @@ pub enum Decision { pub trait Observer: Send + Sync { /// Observe a real commit cut; native commit still owns its durable outcome. fn observe(&self, cut: Cut) -> Decision; + /// Unaccepted request after discovery, before scheduler/native custody. + fn admission_wait(&self, _family: &str) -> Decision { + Decision::Continue + } } impl crate::Ledger { /// Test-host custody only; never serialized or accepted from an RPC request. diff --git a/crates/ledger/src/persistence/mod.rs b/crates/ledger/src/persistence/mod.rs index ff5e3386..59c89381 100644 --- a/crates/ledger/src/persistence/mod.rs +++ b/crates/ledger/src/persistence/mod.rs @@ -32,6 +32,8 @@ pub use scope::ProviderScopePhase; #[cfg(not(feature = "commit-observer"))] pub(crate) use scope::ProviderScopePhase; pub use scope::{WriteScope, begin}; -pub(crate) use scope::{begin_family, begin_provider_lifecycle, begin_provider_progress}; +pub(crate) use scope::{ + begin_family, begin_provider_admission, begin_provider_lifecycle, begin_provider_progress, +}; pub use session::{LedgerCustody, Session}; pub use timing::{Timing, TransactionTimings}; diff --git a/crates/ledger/src/persistence/scope.rs b/crates/ledger/src/persistence/scope.rs index 1204cff5..bcd5a4a4 100644 --- a/crates/ledger/src/persistence/scope.rs +++ b/crates/ledger/src/persistence/scope.rs @@ -15,6 +15,7 @@ use std::{ /// Provider range phase used to label diagnostic scope observations. #[derive(Clone, Copy)] pub enum ProviderScopePhase { + Admission, Other, PrepareRange, FinalQueue, @@ -23,6 +24,7 @@ pub enum ProviderScopePhase { enum Change<'a> { Semantic, + Admission(&'a crate::provider::AdmissionRequest), Progress(&'a crate::provider::RangeProgress), Lifecycle(&'a crate::provider::OriginLifecycle), } @@ -37,6 +39,7 @@ pub struct WriteScope<'a> { poisoned: &'a AtomicBool, timings: &'a mut super::TransactionTimings, entered: Instant, + authority_entered: Instant, oauth_check: Cell, current_domain: Cell, current_pending: Cell, @@ -77,6 +80,23 @@ pub fn begin_family<'a>(session: &'a mut Session, family: &str) -> driver::Resul Change::Semantic, ) } +/// A queued execution request is not an accepted authority intent. Acquire its +/// exclusive turn and recheck root discovery before closing, then start SQL. +/// Source changes, OAuth intents and migration never use this entrypoint. +pub(crate) fn begin_provider_admission<'a>( + session: &'a mut Session, + family: &str, + proof: &crate::provider::AdmissionRequest, +) -> driver::Result> { + start( + session, + Some(family), + None, + ProviderScopePhase::Admission, + Change::Admission(proof), + ) +} + /// Read custody remains the complete domain set. Only the sealed provider /// lifecycle write set may invalidate its origin lane alone in MVCC. pub(crate) fn begin_provider_lifecycle<'a>( @@ -142,20 +162,42 @@ fn start<'a>( let close_scope = keys.as_ref().map_or(super::scheduler::Scope::All, |keys| { super::scheduler::Scope::Domains(keys.clone()) }); - let shared_reads = - !matches!(&change, Change::Semantic) && crate::provider::shared_provider_reads(); - // Close before waiting for either the scheduler or native writer. - let authority = match change { - Change::Progress(progress) => session - .owner - .authority - .close_progress(close_scope, progress)?, - Change::Lifecycle(proof) => session - .owner - .authority - .close_lifecycle(close_scope, proof)?, - Change::Semantic => session.owner.authority.close(close_scope)?, + let shared_reads = matches!(&change, Change::Progress(_) | Change::Lifecycle(_)) + && crate::provider::shared_provider_reads(); + #[cfg(any(test, feature = "commit-observer"))] + let admission_request = matches!(&change, Change::Admission(_)); + let selected_admission = + concurrent && matches!(&change, Change::Admission(proof) if proof.wait_before_close()); + let authority_entered = Instant::now(); + // Accepted source/Policy/OAuth intents close immediately, including while + // waiting. Only an unaccepted provider request may wait before closure. + let authority = if selected_admission { + None + } else { + Some(match change { + Change::Progress(proof) => session + .owner + .authority + .close_progress(close_scope.clone(), proof)?, + Change::Lifecycle(proof) => session + .owner + .authority + .close_lifecycle(close_scope.clone(), proof)?, + Change::Semantic | Change::Admission(_) => { + session.owner.authority.close(close_scope.clone())? + } + }) }; + #[cfg(any(test, feature = "commit-observer"))] + if admission_request + && let Some(observer) = &session.commit_observer + && observer.admission_wait(family.expect("provider admission family")) + != super::commit_observer::Decision::Continue + { + return Err(super::owner::error( + "unaccepted provider admission abandoned before native scheduling", + )); + } let mut owner_entered = None; let mut domains_entered = None; #[cfg(feature = "commit-observer")] @@ -167,6 +209,7 @@ fn start<'a>( ProviderScopePhase::PrepareRange | ProviderScopePhase::FinalQueue | ProviderScopePhase::RevalidateDelivery => session.range_cancelled.as_deref(), + ProviderScopePhase::Admission => session.range_cancelled.as_deref(), ProviderScopePhase::Other => None, }; #[cfg(feature = "commit-observer")] @@ -213,6 +256,13 @@ fn start<'a>( } (false, _) => None, }; + let (authority, authority_entered) = match authority { + Some(authority) => (authority, authority_entered), + None => { + let entered = Instant::now(); + (session.owner.authority.close(close_scope)?, entered) + } + }; let parallel = concurrent && family.is_some(); // The mutable Session borrow provides exclusive custody for the whole scope. let native = super::timing::measure(&mut session.timings.transaction_begin, || { @@ -234,6 +284,7 @@ fn start<'a>( poisoned: &session.poisoned, timings: &mut session.timings, entered: Instant::now(), + authority_entered, oauth_check: Cell::default(), current_domain: Cell::default(), current_pending: Cell::default(), @@ -503,6 +554,9 @@ impl Drop for WriteScope<'_> { total.nanos = total.nanos.saturating_add(sample.nanos); } self.authority.settle_drop(); + self.timings + .authority_span + .record(self.authority_entered.elapsed()); drop(self.grant.take()); if let Some(entered) = self.domains_entered { self.timings.domain_hold.record(entered.elapsed()); @@ -512,7 +566,7 @@ impl Drop for WriteScope<'_> { } #[cfg(feature = "commit-observer")] if let Some(trace) = self.scope_trace.take() { - trace.record(); + trace.record(self.authority_entered.elapsed()); } } } diff --git a/crates/ledger/src/persistence/scope_trace.rs b/crates/ledger/src/persistence/scope_trace.rs index 8169d2fa..1d6f4e0a 100644 --- a/crates/ledger/src/persistence/scope_trace.rs +++ b/crates/ledger/src/persistence/scope_trace.rs @@ -30,6 +30,8 @@ pub struct ProviderScopeSample { pub grant: u64, pub wait: Duration, pub hold: Duration, + /// Authority-intent lifetime; preserved progress does not close readers. + pub authority_span: Duration, } impl Arrival { @@ -80,13 +82,14 @@ impl Trace { for sample in &self.samples { let phase = match sample.phase { ProviderScopePhase::Other => "other", + ProviderScopePhase::Admission => "admit", ProviderScopePhase::PrepareRange => "prepare", ProviderScopePhase::FinalQueue => "queue", ProviderScopePhase::RevalidateDelivery => "revalidate", }; let _ = write!( line, - " {phase}:{}:{}:{}:{}:{}", + " {phase}:{}:{}:{}:{}:{}:{}", sample.arrival, sample.grant, sample.wait.as_nanos(), @@ -95,7 +98,8 @@ impl Trace { "origin" } else { "exclusive" - } + }, + sample.authority_span.as_nanos() ); } eprintln!("{line}"); @@ -113,9 +117,10 @@ impl Trace { } } impl Granted<'_> { - pub(super) fn record(self) { + pub(super) fn record(self, authority_span: Duration) { self.trace.record(ProviderScopeSample { phase: self.arrival.phase, + authority_span, origin_write: self.arrival.origin_write, arrival: self.arrival.order, grant: self.order, diff --git a/crates/ledger/src/persistence/timing.rs b/crates/ledger/src/persistence/timing.rs index 523c2086..0157c6e3 100644 --- a/crates/ledger/src/persistence/timing.rs +++ b/crates/ledger/src/persistence/timing.rs @@ -27,6 +27,7 @@ pub struct TransactionTimings { pub owner_gate_wait: Timing, pub domain_keys: Timing, pub domain_wait: Timing, + pub authority_span: Timing, pub transaction_begin: Timing, pub owner_gate_hold: Timing, pub domain_hold: Timing, @@ -83,6 +84,7 @@ impl TransactionTimings { owner_gate_wait: delta(self.owner_gate_wait, earlier.owner_gate_wait), domain_keys: delta(self.domain_keys, earlier.domain_keys), domain_wait: delta(self.domain_wait, earlier.domain_wait), + authority_span: delta(self.authority_span, earlier.authority_span), transaction_begin: delta(self.transaction_begin, earlier.transaction_begin), owner_gate_hold: delta(self.owner_gate_hold, earlier.owner_gate_hold), domain_hold: delta(self.domain_hold, earlier.domain_hold), diff --git a/crates/ledger/src/provider.rs b/crates/ledger/src/provider.rs index 1df641b9..5a94af9d 100644 --- a/crates/ledger/src/provider.rs +++ b/crates/ledger/src/provider.rs @@ -22,6 +22,32 @@ use weaver_contracts::{ pub(crate) struct RangeProgress { _sealed: (), } +/// Unaccepted execution request. It cannot mutate shared facts or expose an +/// authoritative outcome before the scheduler selects its writer turn. +pub(crate) struct AdmissionRequest { + _sealed: (), +} +#[cfg(feature = "commit-observer")] +thread_local! { + static EARLY_ADMISSION_BARRIER: std::cell::Cell = const { std::cell::Cell::new(false) }; +} +/// Safe same-image control retaining closure while an admission request waits. +#[cfg(feature = "commit-observer")] +pub fn use_early_admission_barrier(early: bool) { + EARLY_ADMISSION_BARRIER.set(early); +} +impl AdmissionRequest { + pub(crate) fn wait_before_close(&self) -> bool { + #[cfg(feature = "commit-observer")] + { + !EARLY_ADMISSION_BARRIER.get() + } + #[cfg(not(feature = "commit-observer"))] + { + true + } + } +} /// Sealed write-set obligation: only run state/target, dispatch marker or raw /// terminal usage changes; no reservation, history, quota or publication write. pub(crate) struct OriginLifecycle { @@ -186,8 +212,12 @@ impl Ledger { let publication = self.connection.prepare_provider_publication(&plan.family); let original = self.connection.prepare_provider_original(&plan.family); self.connection.prepare_provider_domain(); - let tx = - crate::persistence::begin_family(&mut self.connection, &plan.family).map_err(db)?; + let tx = crate::persistence::begin_provider_admission( + &mut self.connection, + &plan.family, + &AdmissionRequest { _sealed: () }, + ) + .map_err(db)?; tx.check_provider_oauth(prepared.as_ref())?; let new_claim = match receipt(&tx, &plan.family, &plan.node)? { Some(old) if old.digest != digest => { diff --git a/crates/ledger/tests/unit/provider.rs b/crates/ledger/tests/unit/provider.rs index c845a14c..1ea1530e 100644 --- a/crates/ledger/tests/unit/provider.rs +++ b/crates/ledger/tests/unit/provider.rs @@ -891,3 +891,6 @@ mod lifecycle; #[path = "provider_read_custody.rs"] mod read_custody; + +#[path = "provider_admission_turn.rs"] +mod admission_turn; diff --git a/crates/ledger/tests/unit/provider_admission_turn.rs b/crates/ledger/tests/unit/provider_admission_turn.rs new file mode 100644 index 00000000..12ddd581 --- /dev/null +++ b/crates/ledger/tests/unit/provider_admission_turn.rs @@ -0,0 +1,94 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +use super::fixture_nodes; +use proptest::{prop_assert_eq, proptest, test_runner::Config}; +use std::{ + collections::BTreeSet, + sync::{ + Arc, + atomic::{AtomicBool, Ordering}, + mpsc, + }, + task::{Context, Poll, Waker}, + thread, + time::{Duration, Instant}, +}; +use weaver_contracts::{DomainBinding, Task}; +use weaver_ledger::{ + DeliveryCursor, Ledger, + persistence::{self, Journal, Session}, +}; + +proptest! { + #![proptest_config(Config::with_cases(8))] + #[test] + fn queued_unaccepted_admission_preserves_old_frame_and_original_hold( + early in proptest::bool::ANY, cancel in proptest::bool::ANY, + ) { + let directory=tempfile::tempdir().expect("store"); + let path=directory.path().join("selected.db"); + let storage=Session::open_with_journal(&path,Journal::Mvcc).expect("MVCC"); + let (mut own,mut plan)=fixture_nodes(&path,&["infer","second"]); + let policy=super::POLICY.replace("context.family == \"f\"","[\"f\",\"peer\"].contains(context.family)") + .replace("context.node == \"infer\"","[\"infer\",\"second\"].contains(context.node)"); + own.publish_typed(Some(0),&policy,super::SCHEMA,2).expect("shared source"); + plan.revision=1;plan.fence=2; + let mut peer=plan.clone();peer.family="peer".into(); + let mut candidate=peer.clone();candidate.node="second".into(); + let record:String=persistence::one(&storage,"SELECT record FROM tasks WHERE family='f'",(),|r|r.get(0)).expect("original"); + let mut task:Task=serde_json::from_str(&record).expect("typed original");task.family="peer".into(); + for p in [&peer,&candidate] { task.stream_contracts.insert(p.node.clone(),p.digest().expect("bound original")); } + own.register_task_domains(&task,&DomainBinding{origin:"peer-origin".into(),budget:"f".into(),history:"f".into(),budget_limit:8},None).expect("shared roots"); + own.enqueue_provider(&plan).expect("original hold");own.enqueue_provider(&peer).expect("peer hold"); + let eligible=BTreeSet::from(["primary".into()]); + let permit=own.consume_provider("f","infer",&eligible).expect("original consume"); + own.dispatch_provider(&permit,||Ok(())).expect("original invocation"); + let release=own.prepare_provider_release(&permit,"frame","protobuf",1).expect("exact range"); + let mut delivery=None; + own.release_provider_for_delivery(&permit,release,"protobuf",|_,d|{delivery=Some(d.split());Ok(())}).expect("known native qualification"); + let (producer,frame)=delivery.expect("frame"); + producer.acknowledge(Instant::now()+Duration::from_secs(2)).expect("ack"); + let mut cursor=DeliveryCursor::new(&plan).expect("unique owner"); + let mut holder=Ledger::open(&path).expect("peer worker"); + let peer_permit=holder.consume_provider("peer","infer",&eligible).expect("peer consume"); + let (entered,held)=mpsc::channel();let(resume,drain)=mpsc::channel(); + let (queued,waiting)=mpsc::channel(); + let aborted=Arc::new(AtomicBool::new(false)); + let accepted=thread::scope(|threads| { + let active=threads.spawn(move || holder.dispatch_provider(&peer_permit,||{ + entered.send(()).expect("native read custody"); + drain.recv_timeout(Duration::from_secs(2)).expect("bounded release"); + Ok(()) + })); + held.recv_timeout(Duration::from_secs(2)).expect("peer effect active"); + let cancelled=aborted.clone();let path=&path; + let contender=threads.spawn(move || { + let mut request=Ledger::open(path).expect("request worker"); + let announced=AtomicBool::new(false); + let deadline=Instant::now()+Duration::from_secs(2); + request.set_provider_range_cancellation(move || { + if !announced.swap(true,Ordering::Relaxed) { queued.send(()).expect("registered scheduler request"); } + cancelled.load(Ordering::Relaxed)||Instant::now()>=deadline + }); + weaver_ledger::use_early_admission_barrier(early); + let result=request.enqueue_provider(&candidate); + weaver_ledger::use_early_admission_barrier(false); + result + }); + waiting.recv_timeout(Duration::from_secs(1)).expect("actual queued ticket"); + let observed=matches!(cursor.poll(&frame,&Context::from_waker(Waker::noop()),&mut Some(())),Poll::Ready(Ok(()))); + if cancel { aborted.store(true,Ordering::Relaxed); } + resume.send(()).expect("drain peer"); + active.join().expect("peer joined").expect("peer committed"); + assert!(contender.join().expect("request joined").is_err(),"full original budget must reject or cancel"); + observed + }); + prop_assert_eq!(accepted,!early); + let actual=own.execution_domains("f").expect("actual original"); + prop_assert_eq!((actual.held,actual.history_count),(8,2)); + prop_assert_eq!(own.provider_receipt("peer","second").expect("no admission outcome").is_none(),true); + prop_assert_eq!(own.consume_provider("f","infer",&eligible).is_err(),true); + } +} diff --git a/crates/ledger/tests/unit/scope_trace.rs b/crates/ledger/tests/unit/scope_trace.rs index 4da47519..94d6a200 100644 --- a/crates/ledger/tests/unit/scope_trace.rs +++ b/crates/ledger/tests/unit/scope_trace.rs @@ -13,7 +13,7 @@ proptest! { for ordinal in 0..count { trace.record(ProviderScopeSample {origin_write: ordinal % 2 == 0, phase: ProviderScopePhase::RevalidateDelivery, arrival: ordinal as u64*2+1, grant: ordinal as u64*2+2, - wait: Duration::ZERO, hold: Duration::ZERO}); + wait: Duration::ZERO, authority_span: Duration::ZERO, hold: Duration::ZERO}); prop_assert!(trace.samples.len() <= CAPACITY); prop_assert_eq!(trace.flushed + trace.samples.len(), ordinal+1); } diff --git a/crates/server/src/grpc_output.rs b/crates/server/src/grpc_output.rs index 70efa9a9..01a9a631 100644 --- a/crates/server/src/grpc_output.rs +++ b/crates/server/src/grpc_output.rs @@ -15,6 +15,7 @@ use weaver_contracts::{Error, ProviderEvent, ProviderRoute, Result}; thread_local! { static HANDOFFS: std::cell::RefCell> = const { std::cell::RefCell::new(Vec::new()) }; static DELIVERIES: std::cell::RefCell> = const { std::cell::RefCell::new(Vec::new()) }; + static TRANSPORT: std::cell::Cell> = const { std::cell::Cell::new(None) }; static ENCODING_NANOS: std::cell::Cell = const { std::cell::Cell::new(0) }; } @@ -33,6 +34,11 @@ pub(crate) fn take_deliveries() -> Vec { DELIVERIES.with(|rows| std::mem::take(&mut *rows.borrow_mut())) } +#[cfg(test)] +pub(crate) fn take_transport() -> Option { + TRANSPORT.with(|phases| phases.take()) +} + /// Only Output constructs the packet. Other server owners cannot inspect or /// modify its bytes before the deciding receiver consumes the proof. pub(crate) struct InertFrame { @@ -75,6 +81,10 @@ pub(crate) struct PreparedFrame { rows: usize, } impl ProviderOutput for Output { + #[cfg(test)] + fn observe_transport(&self, phases: weaver_broker::ProviderTransportPhases) { + TRANSPORT.with(|slot| slot.set(Some(phases))); + } type PreparedFrame = PreparedFrame; type Slot = mpsc::OwnedPermit>; #[cfg(test)] diff --git a/crates/server/src/grpc_provider.rs b/crates/server/src/grpc_provider.rs index aa35e8e9..bab9ee61 100644 --- a/crates/server/src/grpc_provider.rs +++ b/crates/server/src/grpc_provider.rs @@ -92,6 +92,8 @@ impl Gateway { std::env::var("WEAVER_TEST_SEPARATE_RELEASE_READS").as_deref() == Ok("1"), ); #[cfg(test)] + weaver_ledger::use_early_admission_barrier(std::env::var_os("WEAVER_TEST_EARLY_ADMISSION_BARRIER").is_some()); + #[cfg(test)] weaver_ledger::use_exclusive_provider_reads( std::env::var_os("WEAVER_TEST_EXCLUSIVE_PROVIDER_READS").is_some(), ); @@ -117,6 +119,7 @@ impl Gateway { #[cfg(test)] { crate::grpc_output::take_encoding_nanos(); + crate::grpc_output::take_transport(); crate::grpc_output::take_handoffs(); crate::grpc_output::take_deliveries(); } @@ -143,6 +146,7 @@ impl Gateway { weaver_ledger::use_fresh_provider_domain_plan(false); weaver_ledger::use_separate_release_reads(false); weaver_ledger::use_cached_release_programs(false); + weaver_ledger::use_early_admission_barrier(false); weaver_ledger::use_exclusive_provider_reads(false); weaver_ledger::use_full_lifecycle_invalidation(false); weaver_ledger::use_conservative_range_invalidation(false); @@ -199,6 +203,14 @@ impl Gateway { if trace_scopes { eprintln!("weaver-provider-encode {} {}", plan.family, crate::grpc_output::take_encoding_nanos()); use std::fmt::Write; + if let Some(phases) = crate::grpc_output::take_transport() { + let mut line = format!("weaver-provider-transport {}", plan.family); + for stage in [phases.connect, phases.tls, phases.write, phases.headers] { + let _ = write!(line, " {}:{}:{}", stage.nanos, u8::from(stage.attempted), u8::from(stage.completed)); + } + eprintln!("{line}"); + } + ledger.finish_provider_scope_trace(); let mut handoff = format!("weaver-provider-handoff {}", plan.family); for (sequence, time) in crate::grpc_output::take_handoffs() { diff --git a/crates/server/tests/unit/provider_commit.rs b/crates/server/tests/unit/provider_commit.rs index 6daf6d6b..962d74ea 100644 --- a/crates/server/tests/unit/provider_commit.rs +++ b/crates/server/tests/unit/provider_commit.rs @@ -25,6 +25,16 @@ struct CommitObserver { static OBSERVER: OnceLock> = OnceLock::new(); impl Observer for CommitObserver { + fn admission_wait(&self, family: &str) -> Decision { + if self.selected == Cut::BeforeAdmissionSchedule + && std::env::var("WEAVER_TEST_ADMISSION_FAMILY").as_deref() == Ok(family) + { + self.observe(Cut::BeforeAdmissionSchedule) + } else { + Decision::Continue + } + } + fn observe(&self, cut: Cut) -> Decision { if cut == Cut::AfterDeliveryCommit && matches!( @@ -81,7 +91,9 @@ impl Observer for CommitObserver { Cut::BeforeRangePrepareCommit | Cut::AfterRangePrepareCommit => durable_range_marker(), Cut::BeforeDeliveryCommit | Cut::AfterDeliveryCommit => durable_delivery_marker(), Cut::BeforeLifecycleCommit | Cut::AfterLifecycleCommit => lifecycle_marker(), - Cut::BeforeAdmissionCommit | Cut::AfterAdmissionCommit => admission_marker(), + Cut::BeforeAdmissionSchedule + | Cut::BeforeAdmissionCommit + | Cut::AfterAdmissionCommit => admission_marker(), _ => durable_marker(), }; socket @@ -221,6 +233,7 @@ fn serve_observed_gateway() { Ok("prepare-after") => Cut::AfterRangePrepareCommit, Ok("lifecycle-before") => Cut::BeforeLifecycleCommit, Ok("lifecycle-after") => Cut::AfterLifecycleCommit, + Ok("admission-queued") => Cut::BeforeAdmissionSchedule, Ok("admission-before") => Cut::BeforeAdmissionCommit, Ok("admission-after") => Cut::AfterAdmissionCommit, Ok("delivery-before") => Cut::BeforeDeliveryCommit, @@ -239,7 +252,9 @@ fn serve_observed_gateway() { Cut::BeforeDeliveryCommit | Cut::AfterDeliveryCommit => durable_delivery_marker(), Cut::BeforeLifecycleCommit | Cut::AfterLifecycleCommit => lifecycle_marker(), - Cut::BeforeAdmissionCommit | Cut::AfterAdmissionCommit => admission_marker(), + Cut::BeforeAdmissionSchedule + | Cut::BeforeAdmissionCommit + | Cut::AfterAdmissionCommit => admission_marker(), _ => durable_marker(), } ) diff --git a/dev/proofs/cedar/DomainMigrationComposition.lean b/dev/proofs/cedar/DomainMigrationComposition.lean index 6e155cc6..d4323beb 100644 --- a/dev/proofs/cedar/DomainMigrationComposition.lean +++ b/dev/proofs/cedar/DomainMigrationComposition.lean @@ -2,6 +2,7 @@ -- -- SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 +import ProviderAdmissionTurn import ProviderReadCustody import ProviderLifecycleFootprint import ProviderSnapshotPublication @@ -267,4 +268,31 @@ theorem staged_policy_excludes_actual_effect {Key : Type} [DecidableEq Key] #print axioms staged_policy_excludes_actual_effect +/-- Waiting for a native writer turn is not a source-accepted semantic change. + Compose on the same actual state; this does not license an accepted pending + source intent or mutation between qualification and final delivery. -/ +theorem queued_admission_preserves_spec_final_use + (use : Gateway.ZeroTrust.FinalUse proposal) + (events : GatewayHeadCAS.Run c owner GatewayHeadCAS.initial use.actual) + (queued : Weaver.ProviderAdmissionTurn.State GatewayHeadCAS.State) + (same : queued.actual = use.actual) (requests : List Nat) : + (Gateway.ZeroTrust.specialize proposal (reachableDomain c)).required effect + (Weaver.ProviderAdmissionTurn.enqueueAll queued requests).actual ∧ + (∀ account, booked c (Weaver.ProviderAdmissionTurn.enqueueAll queued requests).actual.base account ≤ c.capacity account) ∧ + (∀ key, ((Weaver.ProviderAdmissionTurn.enqueueAll queued requests).actual.base.messages key).claims ≤ 1 ∧ + ((Weaver.ProviderAdmissionTurn.enqueueAll queued requests).actual.base.messages key).sends ≤ 1) ∧ + original.Refines prepared.profile := by + have unchanged : (Weaver.ProviderAdmissionTurn.enqueueAll queued requests).actual = use.actual := by + have step (s : Weaver.ProviderAdmissionTurn.State GatewayHeadCAS.State) : + (Weaver.ProviderAdmissionTurn.enqueueAll s requests).actual = s.actual := by + induction requests generalizing s with + | nil => rfl + | cons id rest ih => + simpa only [Weaver.ProviderAdmissionTurn.enqueueAll, List.foldl_cons] using + (ih (Weaver.ProviderAdmissionTurn.enqueue s id)).trans (Weaver.ProviderAdmissionTurn.queue_preserves_actual s id) + exact (step queued).trans same + simpa only [unchanged] using gateway_final_use_preserves_domain_contract use events + +#print axioms queued_admission_preserves_spec_final_use + end Weaver.DomainMigrationComposition diff --git a/dev/proofs/cedar/lakefile.toml b/dev/proofs/cedar/lakefile.toml index 15b3e376..b031eec9 100644 --- a/dev/proofs/cedar/lakefile.toml +++ b/dev/proofs/cedar/lakefile.toml @@ -46,7 +46,7 @@ roots = ["AnchorBrokerCommit","AnchorReconfiguration","AnchoredRecoveryAndEgress [[lean_lib]] name = "ExecutionResearch" srcDir = "../lean" -roots = ["BrokerConsumptionQueue","CommittedSemanticProfile","DeviceIsolationRecovery","DynamicImageCustody","DynamicImportBoundary","DynamicLoaderPublication","DynamicPairedEvidence","FencedIntentContinuation","FloorIntentDecision","GambitLocatorClosure","GatewayHeadCAS","GerbilExitQualification","KeyBoundaryQueue","LlmAccountCommit","LlmAdmissionFloor","LlmAppendHandoff","LlmAttemptLedger","LlmAuthoritativeScope","LlmBeneficiaryRegistration","LlmBootstrapInvitation","LlmCallerCustody","LlmCanonicalRegistry","LlmCheckpointTruncation","LlmCustodyPublication","LlmEnrollmentCredential","LlmExecutionReconciliation","LlmExecutorOffer","LlmIncarnationIssuance","LlmJoinEnqueue","LlmManifestSwitch","LlmMultiKeyRegistry","LlmPolicyContinuation","LlmPolicyPublication","LlmRecoveryCAS","LlmRegistryPublication","LlmResultProjection","LlmRouting","LlmSemanticContract","LlmSourceCustody","LlmSourceJoin","LlmSubjectAuthority","LlmWalActivation","LogicalRangeRecovery","ProtectedSignerRelease","ProviderEgressWindow","ProviderSemanticProgress","ProviderSnapshotPublication","ProviderLifecycleFootprint","ProviderReadCustody","RoutineRoutingConfig","RuntimeAdmission","SemanticGatewaySlice","SharedDomains","StreamingExecution"] +roots = ["BrokerConsumptionQueue","CommittedSemanticProfile","DeviceIsolationRecovery","DynamicImageCustody","DynamicImportBoundary","DynamicLoaderPublication","DynamicPairedEvidence","FencedIntentContinuation","FloorIntentDecision","GambitLocatorClosure","GatewayHeadCAS","GerbilExitQualification","KeyBoundaryQueue","LlmAccountCommit","LlmAdmissionFloor","LlmAppendHandoff","LlmAttemptLedger","LlmAuthoritativeScope","LlmBeneficiaryRegistration","LlmBootstrapInvitation","LlmCallerCustody","LlmCanonicalRegistry","LlmCheckpointTruncation","LlmCustodyPublication","LlmEnrollmentCredential","LlmExecutionReconciliation","LlmExecutorOffer","LlmIncarnationIssuance","LlmJoinEnqueue","LlmManifestSwitch","LlmMultiKeyRegistry","LlmPolicyContinuation","LlmPolicyPublication","LlmRecoveryCAS","LlmRegistryPublication","LlmResultProjection","LlmRouting","LlmSemanticContract","LlmSourceCustody","LlmSourceJoin","LlmSubjectAuthority","LlmWalActivation","LogicalRangeRecovery","ProtectedSignerRelease","ProviderEgressWindow","ProviderSemanticProgress","ProviderSnapshotPublication","ProviderLifecycleFootprint","ProviderReadCustody","ProviderAdmissionTurn","RoutineRoutingConfig","RuntimeAdmission","SemanticGatewaySlice","SharedDomains","StreamingExecution"] [[lean_lib]] name = "DomainMigrationComposition" diff --git a/dev/proofs/lean/ProviderAdmissionTurn.lean b/dev/proofs/lean/ProviderAdmissionTurn.lean new file mode 100644 index 00000000..fe20ebc0 --- /dev/null +++ b/dev/proofs/lean/ProviderAdmissionTurn.lean @@ -0,0 +1,115 @@ +-- SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +-- +-- SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +import Std + +namespace Weaver.ProviderAdmissionTurn + +/-- A queue entry has no native claim/reservation, outcome acknowledgment or + published semantic intent. Source Policy/OAuth intents use the early barrier. -/ +structure State (Image : Type) where + actual : Image + queued : List Nat + granted : Bool + closed : Bool + hardPending : Bool + known : Bool + failed : Bool + +def enqueue (s : State I) (id : Nat) : State I := {s with queued := s.queued ++ [id]} + +def CanOffer (s : State I) (qualified : I) : Prop := + s.known = true ∧ s.failed = false ∧ s.closed = false ∧ + s.hardPending = false ∧ qualified = s.actual + +theorem queue_preserves_actual (s : State I) (id : Nat) : + (enqueue s id).actual = s.actual := rfl + +theorem queue_preserves_arbitrary_requirement (s : State I) (id : Nat) (required : I → Prop) : + required (enqueue s id).actual ↔ required s.actual := Iff.rfl + +theorem queue_preserves_final_offer (s : State I) (id : Nat) (qualified : I) : + CanOffer (enqueue s id) qualified ↔ CanOffer s qualified := Iff.rfl + +/-- The selected writer may not start a native mutation before closure. -/ +def MayMutate (s : State I) : Prop := s.granted = true ∧ s.closed = true + +theorem open_writer_cannot_mutate (s : State I) (isOpen : s.closed = false) : + ¬ MayMutate s := by + intro guard + exact Bool.noConfusion (isOpen.symm.trans guard.2) + +theorem accepted_hard_intent_blocks (s : State I) (qualified : I) + (pending : s.hardPending = true) : ¬ CanOffer s qualified := by + intro offered + exact Bool.noConfusion (pending.symm.trans offered.2.2.2.1) + +theorem unknown_outcome_blocks (s : State I) (qualified : I) (unknown : s.known = false) : + ¬ CanOffer s qualified := by + intro offered + exact Bool.noConfusion (unknown.symm.trans offered.1) + +theorem changed_image_blocks (s : State I) (qualified : I) (changed : qualified ≠ s.actual) : + ¬ CanOffer s qualified := fun offered => changed offered.2.2.2.2 + +/-- Conditional barrier accounting, not an OS/transport latency theorem. The + native service bound and fair scheduling remain measured host premises. -/ +theorem selection_removes_queue_from_closed_interval (queue service : Nat) : + service ≤ queue + service := Nat.le_add_left service queue + +def enqueueAll (s : State I) (ids : List Nat) : State I := + ids.foldl enqueue s + +theorem finite_queue_preserves_final_offer (ids : List Nat) (s : State I) (qualified : I) : + CanOffer (enqueueAll s ids) qualified ↔ CanOffer s qualified := by + induction ids generalizing s with + | nil => rfl + | cons id rest ih => + simpa only [enqueueAll, List.foldl_cons] using + (ih (enqueue s id)).trans (queue_preserves_final_offer s id qualified) + +/-- Serving without a bootstrap-only source channel requires known activation. + Runtime catalogue selection retains source custody. Closing a socket is not + publication success or proof that any unfinished source command rolled back. + Failure cleanup may close its socket without activating ingress. -/ +structure SourceChannel (Image : Type) where + actual : Image + activated : Bool + known : Bool + runtimeSource : Bool + sourceOpen : Bool + +def MayServeWithoutSource (s : SourceChannel I) : Prop := + s.activated = true ∧ s.known = true ∧ s.runtimeSource = false + +def closeSource (s : SourceChannel I) : SourceChannel I := {s with sourceOpen := false} + +theorem runtime_catalog_requires_source (s : SourceChannel I) (runtime : s.runtimeSource = true) : + ¬ MayServeWithoutSource s := by + intro allowed + exact Bool.noConfusion (runtime.symm.trans allowed.2.2) + +theorem unknown_activation_blocks_source_handoff (s : SourceChannel I) (unknown : s.known = false) : + ¬ MayServeWithoutSource s := by + intro allowed + exact Bool.noConfusion (unknown.symm.trans allowed.2.1) + +theorem bootstrap_source_close_preserves_actual (s : SourceChannel I) + (_knownActivation : MayServeWithoutSource s) (required : I → Prop) : + required (closeSource s).actual ↔ required s.actual := Iff.rfl + +#print axioms runtime_catalog_requires_source +#print axioms unknown_activation_blocks_source_handoff +#print axioms bootstrap_source_close_preserves_actual + +#print axioms queue_preserves_actual +#print axioms queue_preserves_arbitrary_requirement +#print axioms queue_preserves_final_offer +#print axioms open_writer_cannot_mutate +#print axioms accepted_hard_intent_blocks +#print axioms unknown_outcome_blocks +#print axioms changed_image_blocks +#print axioms selection_removes_queue_from_closed_interval +#print axioms finite_queue_preserves_final_offer +end Weaver.ProviderAdmissionTurn diff --git a/dev/proofs/quint/ProviderAdmissionTurn.qnt b/dev/proofs/quint/ProviderAdmissionTurn.qnt new file mode 100644 index 00000000..da0ef474 --- /dev/null +++ b/dev/proofs/quint/ProviderAdmissionTurn.qnt @@ -0,0 +1,64 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +module ProviderAdmissionTurn { + type State={queued:Set[int],used:Set[int],active:Set[int],closed:bool,hard:bool,reader:bool, + image:int,qualified:int,owner:int,issuedOwner:int,known:bool,failed:bool, + held:int,claims:int,history:int,consumed:bool,bad:bool,sourceOpen:bool,runtimeSource:bool,sourceKnown:bool,serving:bool} + var s:State + action init=s'={queued:Set(),used:Set(),active:Set(),closed:false,hard:false,reader:true, + image:0,qualified:0,owner:1,issuedOwner:1,known:true,failed:false, + held:4,claims:1,history:1,consumed:false,bad:false,sourceOpen:true,runtimeSource:false,sourceKnown:true,serving:true} + action enqueue(id:int):bool=all{not(s.failed),not(s.used.contains(id)), + s'={...s,queued:s.queued.union(Set(id)),used:s.used.union(Set(id))}} + action grant(id:int):bool=all{s.queued.contains(id),s.active==Set(),not(s.reader),not(s.failed), + s'={...s,queued:s.queued.exclude(Set(id)),active:Set(id)}} + action close=all{not(s.active==Set()),not(s.failed),s'={...s,closed:true}} + action commit=all{not(s.active==Set()),s.closed,not(s.failed),s.held+4<=12, + s'={...s,image:s.image+1,held:s.held+4,claims:s.claims+1,history:s.history+1,active:Set(),closed:false}} + action reject=all{not(s.active==Set()),s'={...s,active:Set(),closed:false}} + action cancel(id:int):bool=all{s.queued.contains(id),s'={...s,queued:s.queued.exclude(Set(id))}} + action drain=all{s.reader,s'={...s,reader:false}} + action hardIntent=s'={...s,hard:true} + action publishHard=all{s.hard,s.active==Set(),not(s.reader), + s'={...s,hard:false,image:s.image+1}} + action refresh=all{not(s.closed),not(s.hard),not(s.failed),s.owner==s.issuedOwner,s'={...s,qualified:s.image}} + def ready:bool=s.known and not(s.failed) and not(s.closed) and not(s.hard) and + s.serving and s.owner==s.issuedOwner and s.qualified==s.image and not(s.consumed) + action offer=all{ready,s'={...s,consumed:true}} + action loseOutcome(applied:bool):bool=all{s.closed,not(s.active==Set()),s.held+4<=12, + s'={...s,known:false,failed:true,active:Set(),closed:true,image:s.image+(if(applied)1 else 0), + held:s.held+(if(applied)4 else 0),claims:s.claims+(if(applied)1 else 0),history:s.history+(if(applied)1 else 0)}} + action restart=s'={...s,owner:s.owner+1,queued:Set(),active:Set(),reader:false} + action eagerQueue(id:int):bool=all{not(s.used.contains(id)),s'={...s,queued:s.queued.union(Set(id)),used:s.used.union(Set(id)),closed:true}} + action unsafeWrite=all{not(s.active==Set()),not(s.closed),s'={...s,bad:true}} + action runtimeSelection=all{s.sourceOpen,s'={...s,runtimeSource:true}} + action unknownActivation=all{s.sourceOpen,s'={...s,sourceKnown:false,serving:false}} + action closeBootstrapSource=all{s.sourceOpen,not(s.runtimeSource),s.sourceKnown,s'={...s,sourceOpen:false}} + action cleanupSource=all{not(s.serving),s'={...s,sourceOpen:false}} + action unsafeSourceClose=all{s.runtimeSource,s'={...s,sourceOpen:false}} + action step={nondet id=Set(0,1,2,3).oneOf() + nondet applied=Set(true,false).oneOf() + any{enqueue(id),grant(id),close,commit,reject,cancel(id),drain,hardIntent,publishHard,refresh,offer,loseOutcome(applied),restart,runtimeSelection,unknownActivation,closeBootstrapSource,cleanupSource}} + val safe=(s.serving implies s.sourceKnown) and ((s.serving and s.runtimeSource) implies s.sourceOpen) and not(s.bad) and s.held>=4 and s.held<=12 and s.claims==s.history and s.claims>=1 + run queuedAdmissionDoesNotCloseFrameTest=init.then(enqueue(0)).then(enqueue(1)).then(offer).expect(safe) + run eagerQueueBlocksOldFrameCounterexampleTest=init.then(eagerQueue(0)).then(offer.fail()) + run selectedBeforeCloseStillCannotWriteTest=init.then(drain).then(enqueue(0)).then(grant(0)).then(commit.fail()) + run unclosedWriteCounterexampleTest=init.then(drain).then(enqueue(0)).then(grant(0)).then(unsafeWrite).expect(not(safe)) + run closedWriterBlocksFrameTest=init.then(drain).then(enqueue(0)).then(grant(0)).then(close).then(offer.fail()) + run committedWriterRetiresOldFrameTest=init.then(drain).then(enqueue(0)).then(grant(0)).then(close).then(commit).then(offer.fail()) + run pendingPolicyBlocksQueuedRequestAndFrameTest=init.then(enqueue(0)).then(hardIntent).then(offer.fail()) + run queuedCancellationHasNoReservationTest=init.then(enqueue(0)).then(cancel(0)).then(offer).expect(safe and s.held==4 and s.claims==1) + run rollbackKeepsOriginalImageTest=init.then(drain).then(enqueue(0)).then(grant(0)).then(close).then(reject).then(offer).expect(safe and s.held==4) + run lostCommittedResponseKeepsHoldTest=init.then(drain).then(enqueue(0)).then(grant(0)).then(close).then(loseOutcome(true)).expect(safe and s.held==8) + run unknownAbsentOutcomeStillBlocksTest=init.then(drain).then(enqueue(0)).then(grant(0)).then(close).then(loseOutcome(false)).then(offer.fail()) + run oldOwnerCannotOfferTest=init.then(restart).then(offer.fail()) + run committedRefreshUsesCurrentViewTest=init.then(drain).then(enqueue(0)).then(grant(0)).then(close).then(commit).then(refresh).then(offer).expect(safe) + run lostOutcomeCannotOfferTest=init.then(drain).then(enqueue(0)).then(grant(0)).then(close).then(loseOutcome(true)).then(offer.fail()) run knownBootstrapSourceCloseKeepsQualifiedFrameTest=init.then(closeBootstrapSource).then(offer).expect(safe and s.held==4) + run runtimeCatalogMustRetainSourceTest=init.then(runtimeSelection).then(closeBootstrapSource.fail()) + run unknownBootstrapCannotCloseSourceTest=init.then(unknownActivation).then(closeBootstrapSource.fail()) + run prematureSourceCloseCounterexampleTest=init.then(runtimeSelection).then(unsafeSourceClose).expect(not(safe)) + run failedBootstrapCleanupDoesNotActivateIngressTest=init.then(unknownActivation).then(cleanupSource).then(offer.fail()) + +} diff --git a/dev/sysml/ArchitectureViews.sysml b/dev/sysml/ArchitectureViews.sysml index 7c83fc8c..70715c32 100644 --- a/dev/sysml/ArchitectureViews.sysml +++ b/dev/sysml/ArchitectureViews.sysml @@ -259,6 +259,7 @@ package WeaverViews { requirement publicationContract : WeaverExecution::ProviderSnapshotPublication; requirement lifecycleFootprint : WeaverExecution::ProviderLifecycleFootprint; requirement readCustody : WeaverExecution::ProviderReadCustody; + requirement admissionTurn : WeaverExecution::ProviderAdmissionTurn; expose WeaverExecution::providerDeliveryJoin::changes; expose WeaverExecution::providerDeliveryJoin::validated; expose WeaverExecution::providerDeliveryJoin::publication; diff --git a/dev/sysml/WeaverExecution.sysml b/dev/sysml/WeaverExecution.sysml index 4c31ab74..0584c2a7 100644 --- a/dev/sysml/WeaverExecution.sysml +++ b/dev/sysml/WeaverExecution.sysml @@ -303,6 +303,53 @@ package WeaverExecution { reopen only on the exact fenced image and outcome. */ } + requirement def ProviderAdmissionTurn { + doc /* A pending execution request has no accepted authority outcome, + native claim, reservation or semantic publication. It waits in the + existing bounded runtime lane and conflicting-writer FIFO without + closing old frame authority. Once its exclusive writer turn and + domain discovery generation are current, close the entire semantic + footprint before BEGIN or any native mutation. A queued request is + not a source-accepted Policy/OAuth/witness intent. Those intents, + settlement, migration and all unclassified writers close immediately. + WAL retains the existing eager global closure. */ + doc /* Known commit invalidates the affected image and activates the + exact new outcome; unknown commit seals and retains original holds. + Cancellation before native admission creates no claim or refund. + A crash after known queued admission can resume only the original + non-invoked operation; consumed/partially-written sends cannot replay. + Receiver owner, cut, one-use cursor, expiry and pending barriers + remain live at final Tonic delivery. */ + doc /* Separate scheduler wait, native hold and authority-closed lifetime. + Selected closure excludes unaccepted queue residence, not native + service, hard-source barriers or transport latency. TCP connect, TLS + handshake and request write/seal remain inside the invocation guard; + response-header wait follows seal. Stage timing is diagnostic and + can never certify non-execution or authorize budget release. */ + doc /* Go retains source-channel custody through known bootstrap activation. + Static published routing then closes the bootstrap-only source channel + before serving ingress. Runtime catalogue selection retains it. Unknown + activation never becomes readiness. Connection release changes no + authority view, claim, hold, publication or pending-intent outcome. */ + } + + part def ProviderAdmissionOverlapExperiment { + attribute responseFrames : Integer = 64; + attribute maximumGroupFrames : Integer = 4; + attribute minimumGroups : Integer = 16; + attribute oldFramesBeforeOffering : Integer = 1; + attribute laterRequests : Integer = 3; + attribute streamsPerArm : Integer = 128; + assert constraint { minimumGroups * maximumGroupFrames == responseFrames } + doc /* Additional scenario, not a replacement for the frozen thirteen-frame + wave. Offer three real requests after receiving the first old frame. + Opportunistic collect_buffered may stop at an input boundary; sixteen + is a lower bound, not an exact group count. Observe every prepare and + queue group and require matching counts within [minimumGroups, + responseFrames]. Do not erase actual renewals, shorten the stream or + change per-frame final authorization to satisfy a performance target. */ + } + part def ProviderReadCustodyExperiment { part grouped : ProviderSnapshotExperiment; attribute sharedReadScopes : Integer = 12; @@ -483,7 +530,7 @@ package WeaverExecution { } part def EgressMutationBarrier { attribute displayName : String = "Rust / close"; - attribute responsibility : String = "Run edits / origin cut\nShared edits / shared cut"; + attribute responsibility : String = "Queued request / no cut\nAccepted edit / close first"; attribute glyph : String = "policy"; attribute visualRole : String = "governance"; port closed : EgressWindowPort; diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index a3e7bbdc..4386daaa 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -1,4 +1,5 @@ -[{"id":"ProviderReadCustody","witnesses":[{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn conflicts"},{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn acquire_origin"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let shared_reads"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn compatible_origins_share_reads_but_an_older_writer_blocks_younger_readers"},{"file":"crates/ledger/tests/unit/provider_read_custody.rs","pattern":"fn shared_reads_keep_distinct_origin_native_writes_concurrent"},{"file":"go/dev/provider_read_custody_test.go","pattern":"func TestProviderReadCustodyProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderReadCustody"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem arbitrary_policy_preserved","declaration":"Weaver.ProviderReadCustody.arbitrary_policy_preserved"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem finite_interleaving_preserves_policy","declaration":"Weaver.ProviderReadCustody.finite_interleaving_preserves_policy"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem overlapping_writes_conflict","declaration":"Weaver.ProviderReadCustody.overlapping_writes_conflict"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessRetainsWriterAndSameOriginBarriers"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_binding_blocks","declaration":"Weaver.ProviderReadCustody.changed_binding_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_shared_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_shared_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_origin_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_origin_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_owner_blocks","declaration":"Weaver.ProviderReadCustody.changed_owner_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem shared_writer_conflicts","declaration":"Weaver.ProviderReadCustody.shared_writer_conflicts"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem older_conflicting_writer_blocks","declaration":"Weaver.ProviderReadCustody.older_conflicting_writer_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem read_custody_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.read_custody_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderReadCustody.qnt","pattern":"run unsafeSharedMutationCounterexampleTest"}]}, +[{"id":"ProviderAdmissionTurn","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let selected_admission"},{"file":"crates/ledger/src/provider.rs","pattern":"struct AdmissionRequest"},{"file":"crates/ledger/tests/unit/provider_admission_turn.rs","pattern":"fn queued_unaccepted_admission_preserves_old_frame_and_original_hold"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionTurnProperty"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionCommitRecovery"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderAdmissionTurn"},{"file":"crates/broker/src/provider/request.rs","pattern":"Stage::Tls"},{"file":"go/dev/provider_transport_phases_test.go","pattern":"func reportProviderTransport"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run eagerQueueBlocksOldFrameCounterexampleTest"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem queue_preserves_arbitrary_requirement","declaration":"Weaver.ProviderAdmissionTurn.queue_preserves_arbitrary_requirement"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem finite_queue_preserves_final_offer","declaration":"Weaver.ProviderAdmissionTurn.finite_queue_preserves_final_offer"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem open_writer_cannot_mutate","declaration":"Weaver.ProviderAdmissionTurn.open_writer_cannot_mutate"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem accepted_hard_intent_blocks","declaration":"Weaver.ProviderAdmissionTurn.accepted_hard_intent_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_outcome_blocks","declaration":"Weaver.ProviderAdmissionTurn.unknown_outcome_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem changed_image_blocks","declaration":"Weaver.ProviderAdmissionTurn.changed_image_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem queued_admission_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.queued_admission_preserves_spec_final_use"},{"file":"go/internal/controlplane/deployment.go","pattern":"if gateway.source == nil"},{"file":"go/dev/provider_control_bench_test.go","pattern":"func TestProviderGoControlMeasuredChain"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem runtime_catalog_requires_source","declaration":"Weaver.ProviderAdmissionTurn.runtime_catalog_requires_source"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_activation_blocks_source_handoff","declaration":"Weaver.ProviderAdmissionTurn.unknown_activation_blocks_source_handoff"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem bootstrap_source_close_preserves_actual","declaration":"Weaver.ProviderAdmissionTurn.bootstrap_source_close_preserves_actual"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run failedBootstrapCleanupDoesNotActivateIngressTest"},{"file":"go/dev/provider_admission_overlap_bench_test.go","pattern":"func BenchmarkProviderAdmissionOverlap"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn collect_buffered"}]}, + {"id":"ProviderReadCustody","witnesses":[{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn conflicts"},{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn acquire_origin"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let shared_reads"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn compatible_origins_share_reads_but_an_older_writer_blocks_younger_readers"},{"file":"crates/ledger/tests/unit/provider_read_custody.rs","pattern":"fn shared_reads_keep_distinct_origin_native_writes_concurrent"},{"file":"go/dev/provider_read_custody_test.go","pattern":"func TestProviderReadCustodyProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderReadCustody"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem arbitrary_policy_preserved","declaration":"Weaver.ProviderReadCustody.arbitrary_policy_preserved"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem finite_interleaving_preserves_policy","declaration":"Weaver.ProviderReadCustody.finite_interleaving_preserves_policy"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem overlapping_writes_conflict","declaration":"Weaver.ProviderReadCustody.overlapping_writes_conflict"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessRetainsWriterAndSameOriginBarriers"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_binding_blocks","declaration":"Weaver.ProviderReadCustody.changed_binding_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_shared_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_shared_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_origin_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_origin_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_owner_blocks","declaration":"Weaver.ProviderReadCustody.changed_owner_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem shared_writer_conflicts","declaration":"Weaver.ProviderReadCustody.shared_writer_conflicts"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem older_conflicting_writer_blocks","declaration":"Weaver.ProviderReadCustody.older_conflicting_writer_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem read_custody_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.read_custody_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderReadCustody.qnt","pattern":"run unsafeSharedMutationCounterexampleTest"}]}, {"id":"ProviderLifecycleFootprint","witnesses":[{"file":"crates/ledger/src/provider.rs","pattern":"struct OriginLifecycle"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"enum Impact"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_lifecycle"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_provider_lifecycle"},{"file":"crates/ledger/tests/unit/provider_lifecycle.rs","pattern":"fn peer_lifecycle_preserves_complete_view_but_shared_admission_does_not"},{"file":"go/dev/provider_lifecycle_test.go","pattern":"func TestProviderLifecycleCommitRecovery"},{"file":"crates/ledger/tests/unit/authority_footprint.rs","pattern":"fn local_commit_retires_whole_and_own_but_preserves_peer"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem origin_commit_retires_whole_reader","declaration":"Weaver.ProviderLifecycleFootprint.origin_commit_retires_whole_reader"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem arbitrary_cedar_predicate_preserved","declaration":"Weaver.ProviderLifecycleFootprint.arbitrary_cedar_predicate_preserved"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem shared_admission_requires_shared_invalidation","declaration":"Weaver.ProviderLifecycleFootprint.shared_admission_requires_shared_invalidation"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem peer_lifecycle_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.peer_lifecycle_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderLifecycleFootprint.qnt","pattern":"run unsafeNarrowAdmissionCounterexampleTest"}]}, {"id":"ProviderSnapshotPublication","witnesses":[{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn release_provider_group_for_delivery"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"struct Snapshot"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn share_qualification"},{"file":"crates/ledger/src/provider.rs","pattern":"fn begin_snapshot_validation"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn take_refresh"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem pending_close_defers_renewal","declaration":"Weaver.ProviderSnapshotPublication.pending_close_defers_renewal"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn a_request_arriving_during_qualification_cannot_trigger_a_second_native_read"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn one_snapshot_requalification_covers_every_exact_frame"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn post_staging_native_failure_cannot_publish_a_partial_snapshot"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn queue_snapshot"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func awaitDeliveryCuts"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem final_use_joins_snapshot","declaration":"Weaver.ProviderSnapshotPublication.final_use_joins_snapshot"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem published_snapshot_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.published_snapshot_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSnapshotPublication.qnt","pattern":"run ungatedArcLoadIsCounterexampleTest"}]}, diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.00-index.org b/docs/10-19-llm-gateway/10-routing-and-inference/10.00-index.org index 5d5a8f11..a9b91483 100644 --- a/docs/10-19-llm-gateway/10-routing-and-inference/10.00-index.org +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.00-index.org @@ -69,3 +69,5 @@ No Gateway runtime or dependency pin is changed. - [[file:10.11-lifecycle-footprints.org][Lifecycle write footprints and shared admission]] - [[file:10.12-read-custody.org][Shared read custody and final delivery latency]] + +- [[file:10.17-admission-turn.org][10.17 Provider admission turn and transport lifetime]] diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2 b/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2 index 44c73d70..fd2d88ee 100644 --- a/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2 +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2 @@ -72,11 +72,12 @@ vars: { d2-config: { data: { figure: |json "model8": "dev/sysml/CorrespondenceReaderView.sysml", "model9": "dev/sysml/ExecutionReaderViews.sysml", "proof0": "dev/proofs/cedar/DomainMigrationComposition.lean", - "proof1": "dev/proofs/lean/ProviderEgressWindow.lean", - "proof2": "dev/proofs/lean/ProviderLifecycleFootprint.lean", - "proof3": "dev/proofs/lean/ProviderReadCustody.lean", - "proof4": "dev/proofs/lean/ProviderSemanticProgress.lean", - "proof5": "dev/proofs/lean/ProviderSnapshotPublication.lean", + "proof1": "dev/proofs/lean/ProviderAdmissionTurn.lean", + "proof2": "dev/proofs/lean/ProviderEgressWindow.lean", + "proof3": "dev/proofs/lean/ProviderLifecycleFootprint.lean", + "proof4": "dev/proofs/lean/ProviderReadCustody.lean", + "proof5": "dev/proofs/lean/ProviderSemanticProgress.lean", + "proof6": "dev/proofs/lean/ProviderSnapshotPublication.lean", "sdkCapture": "dev/sysml/captures/WeaverViews-providerDeliveryJoin.json" }, "copy": {}, @@ -110,7 +111,8 @@ vars: { d2-config: { data: { figure: |json "proof2", "proof3", "proof4", - "proof5" + "proof5", + "proof6" ], "evidenceRefs": [] }, @@ -209,10 +211,10 @@ vars: { d2-config: { data: { figure: |json "modelSource": { "ref": "sdkCapture", "view": "WeaverViews::providerDeliveryJoin", - "modelHash": "eff38a5a555cd875587cbd393a8aa0b12179605e7a85cbba6bae3aaf12562787", + "modelHash": "c637cf09173a79f88860780ded6bda42ff9f1a58e1ba64f11cfaaa253593938b", "portProjection": "owner", "labels": { - "n0": "Rust / close\nRun edits / origin cut\nShared edits / shared cut", + "n0": "Rust / close\nQueued request / no cut\nAccepted edit / close first", "n1": "Rust / qualify group\nRead shared; write origin\nCedar + claim + domains", "n2": "Turso / commit group\nBurn the bounded group\nPublish one qualified cut", "n3": "Rust / prepare frame\nExact bytes and next span\nReserve transport credit", diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.svg b/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.svg index 7c4c9f3f..8c00ac98 100644 --- a/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.svg +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.svg @@ -37,12 +37,12 @@ SPDX-FileComment: Weaver-authored diagram; embedded third-party fonts and marks .scene-title{font-size:26px}.scene-detail{font-size:26px}.scene-group-title{font-size:26px} @font-face{font-family:"Kalam";font-style:normal;font-weight:400;src:url(data:font/woff2;base64,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) format('woff2')} -@font-face{font-family:"Kalam";font-style:normal;font-weight:700;src:url(data:font/woff2;base64,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) format('woff2')}{"renderer":{"package":"@deterministic-engineering/render","version":"1.0.0","icons":{"agent":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","agent-request":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","authentication":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","authorization":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","bounded-write":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","budget":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","budget-ledger":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","capture":"a647d42aa11f4e5e85d0bbf66f483f57f3c4ba3a9536362ed0eaaaae10a89cee","catalog":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","claim":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","decision":"3535642a5b613372c3fd374151ec90aafa19b64b2d33d10b19162cad07a35c7a","document":"0bf9674a401262da8a646305cab00006954721c07765b9962e0dee1c31d560f7","evidence":"0a91b169aaa644829a054cbb94194efffaf4298f2b6f8fa8c6ec2b7b413a1766","go":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","history":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","kubernetes":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","ledger":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","library":"df474fa36a74016b79236fff58a980a8c18c682d1866211776e349a0eb4b2979","message":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","model":"0cfd1f9ed3873f556ace725a7b6a251ebe75d7d976567699276f34df36b2443b","model-catalog":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","model-provider":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","obligation":"e76f4d34a7190400446c89e4e7d187762b885808a64a00c99455599d902570c5","pending":"cca7589bc3b1dcdebacb867c6836c6fc166257f05823555a268354ff9bfac00c","permission-check":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","policy":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","provider":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","publication":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","question":"dbf231e1568dc37189d5674d73c4bfc58a17eb8ada579b3f03bf2813d33c56f4","recovery":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","reference":"3814c570f79ab294252c36530de464c9364814b797afb862d9c62e728a8660fc","route-choice":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","routine":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","routing":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","rust":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","selection":"82b4ab6faf195fea0a891c35268e61c186e93e7c6a9d7967a4f6a73dbf25ae7f","stream":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","task-contract":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","telemetry":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","unknown":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","unknown-hold":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","writer":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e"}},"design":{"audience":"Gateway developers and security reviewers","medium":"GitHub at 830 CSS pixels","message":"One native outcome qualifies the group.\nRevocation closes delivery; unknown retains the hold.","questionRefs":["q1"],"requiredSubjects":["n0","n1","n2","n3","n4","n5"],"requiredRelations":[],"focalSubjects":["n4"]},"evidence":[],"layout":"model-view","presentation":{"objectRows":[["n0","n1","n2"],["n3","n4","n5"]],"notation":"objects","options":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL"},"icons":{"n0":"policy","n1":"authorization","n2":"ledger","n3":"stream","n4":"writer","n5":"stream"},"roles":{"n0":"governance","n1":"governance","n2":"ledger","n3":"semantic","n4":"execution","n5":"execution"},"edgeLabels":true,"graph":{"id":"declared-reading-order","children":[{"id":"n0","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n1","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n2","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n3","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n4","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n5","layoutOptions":{"elk.partitioning.partition":"1"}}],"layoutOptions":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.partitioning.activate":"true"}},"textColumns":22},"drawing":{"mode":"sketch","options":{"seed":29,"roughness":1.3,"strokeWidth":1.2,"fillStyle":"hachure","hachureGap":9,"fillWeight":0.6}},"fonts":[{"family":"Kalam","weight":400,"source":"@fontsource/kalam/files/kalam-latin-400-normal.woff2"},{"family":"Kalam","weight":700,"source":"@fontsource/kalam/files/kalam-latin-700-normal.woff2"}],"palette":{"background":"#F6FAF9","surface":"#FFFFFF","ink":"#163C43","muted":"#496A70","border":"#C9DDDA","accent":"#087E82","secondary":"#946044","tint":"#E1F1EC","secondaryTint":"#F4EADA","onAccent":"#FFFFFF","supported":"#237653","pending":"#986320","conflict":"#A13E54"},"inputSHA256":"58094e598788088833104623513cd145702a04dcaddc9f23e26017dce32cad5f","model":{"subjects":[{"id":"n0","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::changes","label":"Rust / close\nRun edits / origin cut\nShared edits / shared cut"},{"id":"n1","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::validated","label":"Rust / qualify group\nRead shared; write origin\nCedar + claim + domains"},{"id":"n2","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::publication","label":"Turso / commit group\nBurn the bounded group\nPublish one qualified cut"},{"id":"n3","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::staged","label":"Rust / prepare frame\nExact bytes and next span\nReserve transport credit"},{"id":"n4","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::receiver","label":"Rust / consume once\nLive cut + owner + expiry\nOne-use frame cursor"},{"id":"n5","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::tonic","label":"Tonic / accept once\nOne current Rust owner\nObserve delivery later"}],"relations":[{"id":"edge:0","src":"n0","dst":"n1","label":"closeBeforeWrite","kind":"connection","fromPort":"n0.0","toPort":"n1.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:1","src":"n2","dst":"n4","label":"exactRevision","kind":"connection","fromPort":"n2.1","toPort":"n4.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:2","src":"n3","dst":"n4","label":"inertOnly","kind":"connection","fromPort":"n3.0","toPort":"n4.1","srcArrow":"none","dstArrow":"none"},{"id":"edge:3","src":"n1","dst":"n2","label":"qualifiedManifest","kind":"connection","fromPort":"n1.1","toPort":"n2.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:4","src":"n4","dst":"n5","label":"oneOffer","kind":"connection","fromPort":"n4.2","toPort":"n5.0","srcArrow":"none","dstArrow":"none"}]},"modelSource":{"ref":"sdkCapture","modelHash":"eff38a5a555cd875587cbd393a8aa0b12179605e7a85cbba6bae3aaf12562787","view":"WeaverViews::providerDeliveryJoin","portProjection":"owner","labels":{"n0":"Rust / close\nRun edits / origin cut\nShared edits / shared cut","n1":"Rust / qualify group\nRead shared; write origin\nCedar + claim + domains","n2":"Turso / commit group\nBurn the bounded group\nPublish one qualified cut","n3":"Rust / prepare frame\nExact bytes and next span\nReserve transport credit","n4":"Rust / consume once\nLive cut + owner + expiry\nOne-use frame cursor","n5":"Tonic / accept once\nOne current Rust owner\nObserve delivery later"}},"modelTrace":{"modelHash":"eff38a5a555cd875587cbd393a8aa0b12179605e7a85cbba6bae3aaf12562787","requestedView":"WeaverViews::providerDeliveryJoin","resolvedView":"WeaverViews::providerDeliveryJoin","renderingSHA256":"184f54768a7516498adfd3ed388242ab764557361a0b9254f9af21b85366d7bc","capturedRenderingJSON":"{\"modelHash\":\"eff38a5a555cd875587cbd393a8aa0b12179605e7a85cbba6bae3aaf12562787\",\"requestedView\":\"WeaverViews::providerDeliveryJoin\",\"rendering\":{\"view\":\"WeaverViews::providerDeliveryJoin\",\"kind\":\"interconnection\",\"stated\":\"render asInterconnectionDiagram\",\"nodes\":[{\"id\":\"n0\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::changes\",\"nameSynthesized\":false,\"type\":\"EgressMutationBarrier\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n0.0\",\"name\":\"closed\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":550,\"startCol\":9,\"endLine\":550,\"endCol\":46}},{\"id\":\"n1\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::validated\",\"nameSynthesized\":false,\"type\":\"DeliveryValidation\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n1.0\",\"name\":\"closed\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n1.1\",\"name\":\"validated\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":551,\"startCol\":9,\"endLine\":551,\"endCol\":45}},{\"id\":\"n2\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::publication\",\"nameSynthesized\":false,\"type\":\"PublishedRangeSnapshot\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n2.0\",\"name\":\"qualified\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n2.1\",\"name\":\"preserved\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":552,\"startCol\":9,\"endLine\":552,\"endCol\":51}},{\"id\":\"n3\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::staged\",\"nameSynthesized\":false,\"type\":\"InertProviderFrame\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n3.0\",\"name\":\"stagedBytes\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":553,\"startCol\":9,\"endLine\":553,\"endCol\":42}},{\"id\":\"n4\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::receiver\",\"nameSynthesized\":false,\"type\":\"DeliveryReceiver\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n4.0\",\"name\":\"validated\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n4.1\",\"name\":\"staged\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n4.2\",\"name\":\"offer\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":554,\"startCol\":9,\"endLine\":554,\"endCol\":42}},{\"id\":\"n5\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::tonic\",\"nameSynthesized\":false,\"type\":\"ProviderEgressTransport\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n5.0\",\"name\":\"acceptedBytes\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":555,\"startCol\":9,\"endLine\":555,\"endCol\":46}}],\"edges\":[{\"from\":\"n0\",\"to\":\"n1\",\"fromPort\":\"n0.0\",\"toPort\":\"n1.0\",\"label\":\"closeBeforeWrite\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":556,\"startCol\":9,\"endLine\":556,\"endCol\":80}},{\"from\":\"n2\",\"to\":\"n4\",\"fromPort\":\"n2.1\",\"toPort\":\"n4.0\",\"label\":\"exactRevision\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":557,\"startCol\":9,\"endLine\":557,\"endCol\":86}},{\"from\":\"n3\",\"to\":\"n4\",\"fromPort\":\"n3.0\",\"toPort\":\"n4.1\",\"label\":\"inertOnly\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":558,\"startCol\":9,\"endLine\":558,\"endCol\":76}},{\"from\":\"n1\",\"to\":\"n2\",\"fromPort\":\"n1.1\",\"toPort\":\"n2.0\",\"label\":\"qualifiedManifest\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":559,\"startCol\":9,\"endLine\":559,\"endCol\":91}},{\"from\":\"n4\",\"to\":\"n5\",\"fromPort\":\"n4.2\",\"toPort\":\"n5.0\",\"label\":\"oneOffer\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":560,\"startCol\":9,\"endLine\":560,\"endCol\":75}}],\"columns\":[],\"rows\":[],\"notes\":[],\"notices\":[],\"shown\":[]}}","portProjection":"owner","nodes":[{"id":"n0","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":550,"startCol":9,"endLine":550,"endCol":46}},{"id":"n1","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":551,"startCol":9,"endLine":551,"endCol":45}},{"id":"n2","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":552,"startCol":9,"endLine":552,"endCol":51}},{"id":"n3","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":553,"startCol":9,"endLine":553,"endCol":42}},{"id":"n4","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":554,"startCol":9,"endLine":554,"endCol":42}},{"id":"n5","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":555,"startCol":9,"endLine":555,"endCol":46}}],"edges":[{"id":"edge:0","index":0,"from":"n0","to":"n1","fromPort":"n0.0","toPort":"n1.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":556,"startCol":9,"endLine":556,"endCol":80}},{"id":"edge:1","index":1,"from":"n2","to":"n4","fromPort":"n2.1","toPort":"n4.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":557,"startCol":9,"endLine":557,"endCol":86}},{"id":"edge:2","index":2,"from":"n3","to":"n4","fromPort":"n3.0","toPort":"n4.1","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":558,"startCol":9,"endLine":558,"endCol":76}},{"id":"edge:3","index":3,"from":"n1","to":"n2","fromPort":"n1.1","toPort":"n2.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":559,"startCol":9,"endLine":559,"endCol":91}},{"id":"edge:4","index":4,"from":"n4","to":"n5","fromPort":"n4.2","toPort":"n5.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":560,"startCol":9,"endLine":560,"endCol":75}}]},"view":{"source":"docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2","title":"Commit a group. Gate every frame.","purpose":"workflow","kind":"routing","question":{"subjectRefs":["n4"],"ref":"q1","text":"How can a shared snapshot stay safe during revocation?","focusRefs":["model"]},"basis":{"captureRef":"docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2#design-view","modelRefs":["Project.sysml","dev/sysml/AdmissionReaderViews.sysml","dev/sysml/ArchitectureReaderViews.sysml","dev/sysml/ArchitectureViews.sysml","dev/sysml/AssuranceReaderViews.sysml","dev/sysml/AttemptReaderViews.sysml","dev/sysml/AuthorityReaderViews.sysml","dev/sysml/ControlActivation.sysml","dev/sysml/CorrespondenceReaderView.sysml","dev/sysml/ExecutionReaderViews.sysml","dev/sysml/FloorReaderViews.sysml","dev/sysml/GatewayArchitecture.sysml","dev/sysml/PolicyEvidenceDesign.sysml","dev/sysml/ProviderRpc.sysml","dev/sysml/ReaderDesigns.sysml","dev/sysml/ResearchReaderViews.sysml","dev/sysml/StoragePersistence.sysml","dev/sysml/StreamingExecution.sysml","dev/sysml/WeaverExecution.sysml","dev/sysml/ZeroTrustRefinement.sysml"],"obligationRefs":["proof0","proof1","proof2","proof3","proof4","proof5"],"evidenceRefs":[]}},"questions":[{"subjectRefs":["n4"],"ref":"q1","text":"How can a shared snapshot stay safe during revocation?","focusRefs":["model"]}],"references":{"model":"dev/sysml/WeaverExecution.sysml","model0":"Project.sysml","model1":"dev/sysml/AdmissionReaderViews.sysml","model10":"dev/sysml/FloorReaderViews.sysml","model11":"dev/sysml/GatewayArchitecture.sysml","model12":"dev/sysml/PolicyEvidenceDesign.sysml","model13":"dev/sysml/ProviderRpc.sysml","model14":"dev/sysml/ReaderDesigns.sysml","model15":"dev/sysml/ResearchReaderViews.sysml","model16":"dev/sysml/StoragePersistence.sysml","model17":"dev/sysml/StreamingExecution.sysml","model18":"dev/sysml/WeaverExecution.sysml","model19":"dev/sysml/ZeroTrustRefinement.sysml","model2":"dev/sysml/ArchitectureReaderViews.sysml","model3":"dev/sysml/ArchitectureViews.sysml","model4":"dev/sysml/AssuranceReaderViews.sysml","model5":"dev/sysml/AttemptReaderViews.sysml","model6":"dev/sysml/AuthorityReaderViews.sysml","model7":"dev/sysml/ControlActivation.sysml","model8":"dev/sysml/CorrespondenceReaderView.sysml","model9":"dev/sysml/ExecutionReaderViews.sysml","proof0":"dev/proofs/cedar/DomainMigrationComposition.lean","proof1":"dev/proofs/lean/ProviderEgressWindow.lean","proof2":"dev/proofs/lean/ProviderLifecycleFootprint.lean","proof3":"dev/proofs/lean/ProviderReadCustody.lean","proof4":"dev/proofs/lean/ProviderSemanticProgress.lean","proof5":"dev/proofs/lean/ProviderSnapshotPublication.lean","sdkCapture":"dev/sysml/captures/WeaverViews-providerDeliveryJoin.json"},"sourceSHA256":{"dev/d2/themes/assurance.d2":"f7723f53e005a68c803a38ce5c04cd733f46f4a2688fa4b17c66f9d5b308fe24","dev/d2/themes/data.d2":"19fceb46186892da02b763217963cc3ca2a35021219c0d353fdeec84604ddaee","dev/d2/themes/flow.d2":"1f13588619d0c8087c08d8afd023c4c0efe12726711c311e623eea3872726c1f","dev/d2/themes/routing.d2":"f185df198e7435d12b17b7b57b62dfc5795597d95eb926159ee13b448727bcce","dev/d2/themes/sequence.d2":"6e39472720dccc717f984c95b79570494b6ce3828b86227629841649e6c956e6","dev/d2/themes/state.d2":"f1a35cbca0f9cbb055ea9f793ba3dfb86e5fee4e462038ef3e72b94baa61d781","dev/d2/themes/system.d2":"b2a32ec6959ca5df9103c16454c4e34b758e061f850f7de6b619bcbc5fcf17a6","dev/d2/themes/vocabulary.d2":"add21e9b87eab485e5daabf6316fea44eb56b1007b70123f24b0e32e3357f744","dev/proofs/cedar/DomainMigrationComposition.lean":"d1a5ca9740b5cbfe33db7b4f61289c5ccc9d63387c0a9bd6f95c2f04cf1d4436","dev/proofs/cedar/QualifiedReview.lean":"1ae16e06ad03a2906fa8c21dbeea1e3eb7700aa1e9359e64848dec65ccfd079f","dev/proofs/cedar/WeaverPolicyBridge.lean":"a9628a8123d504a34f64bf986feb4471325aa2b0ddc603d76b62632481eab67b","dev/proofs/cedar/ZeroTrustEnrichment.lean":"0c4b138843cc176c27d42d4a31177a3c12486b2d8ff124a6453e3d0922170884","dev/proofs/lean/ProviderEgressWindow.lean":"c4a15b4ccd3a6474290b71374499087dba7dac7a1fda53f3a870100ec2e768a9","dev/proofs/lean/ProviderLifecycleFootprint.lean":"4786544c8a8193c5221bda2f7cd5cf20531bd1856d88b10ae29b280f223e307c","dev/proofs/lean/ProviderReadCustody.lean":"67e83773a1a063852e2303512d4b75b73cd3b9a90117972aafda9ee7348e6b77","dev/proofs/lean/ProviderRpc.lean":"e79d7639ac11220585e59e85dc5bec12b6717f7b51fb28fdcd62dc96d8fae38e","dev/proofs/lean/ProviderSemanticProgress.lean":"d32e010145a7dfcd646daeeeb4b08c0e852b9006bca404681af7e7fe10d0eaa0","dev/proofs/lean/ProviderSnapshotPublication.lean":"312c0380e334fbc5380815d882c6b5b0007747100f818becbee9c6784eeb5716","dev/proofs/lean/RuntimeAdmission.lean":"6111d4b9e93ebaa9f7cc44a55ed504c88c20c8d9de81e947a2e13b3f4a13b13c","dev/proofs/lean/SharedDomains.lean":"10eef67918986264689b09f0a6c0d53b314d7bf43b42f4b9652b403570beb58d","dev/proofs/lean/StreamingExecution.lean":"3fba798a7887a0b2ae29a7e3f0aaa3d7e2fb191e5f1f28109a4a73d28e27b776","dev/sysml/AdmissionReaderViews.sysml":"27ebc6c98ec3a1f7f9081e77a130953c3b646a1fdf6f1d6fc1fa6ed6376e9623","dev/sysml/ArchitectureReaderViews.sysml":"52ffbccbb17bd257e8ad9f4aa9f727c8ce0c00149e7d6738b82042ba06fdd0e3","dev/sysml/ArchitectureViews.sysml":"036eba2c1cf65fd8e0f91272e7728fd9e61d7ff5af74e00da03f3c14472a52c8","dev/sysml/AssuranceReaderViews.sysml":"cd99fb7e9b23e08beac265bc832a8debee0dc1e1d318b0f64d5263519270e390","dev/sysml/AttemptReaderViews.sysml":"0d87cf71e15c26566422a6ddb5945fdb8add8af0484d9d024c32b97597675e21","dev/sysml/AuthorityReaderViews.sysml":"6fa25bd3a64e7f89987caec8e4773928be2cbea0a3c943299e536ca81978316d","dev/sysml/captures/WeaverAdmissionReaderViews-beneficiaryRegistration.json":"bb3fe40509cc1879a36924b5d30d17ede094dc3644eb27849fbdcdb47c29f0cf","dev/sysml/captures/WeaverAdmissionReaderViews-bootstrapInvitation.json":"0d4d7c4632fc7358facf94b4bbe12a599154bd230360453058ff5e026fe087dd","dev/sysml/captures/WeaverAdmissionReaderViews-callerCustody.json":"933ad283941b6907b0f6d57d323b3ab7003a1de543f1150aca40ef3bd3dc1ee1","dev/sysml/captures/WeaverAdmissionReaderViews-custodyPublication.json":"3097dbbedc2dbe9ba6c4fe15f8accaf4f9b8651219c5671319c782b22d7ebaf1","dev/sysml/captures/WeaverAdmissionReaderViews-enrollmentCredential.json":"b62f11b349461a0d8bfdd53056b6be2c4376baac67a1e72a85f71b1dff526503","dev/sysml/captures/WeaverAdmissionReaderViews-incarnationIssuance.json":"64c5685fe9e03b61ff4e78b0cae98b33498c394592ec91b5c8a7693e611eccf5","dev/sysml/captures/WeaverAdmissionReaderViews-routineRouting.json":"983c4d96fc1f6b467c191ad559965b11d8f49706a0d3babbb1b9f07835ddae54","dev/sysml/captures/WeaverAdmissionReaderViews-sourceCustody.json":"6c8c7fcfa6e5ec58d6e325458aef694b31cfc380c5387b878431ebde619e485d","dev/sysml/captures/WeaverAdmissionReaderViews-sourceJoin.json":"4b02fe58b62e0a4c9d805c0dd071923fcb0afd39375276f9bb77943d84e8c031","dev/sysml/captures/WeaverAdmissionReaderViews-subjectAuthority.json":"1dd45c5e633905d36c4430ce22174d101969c60b4c9a38ebb1e90618d812546f","dev/sysml/captures/WeaverArchitectureReaderViews-adapterBroker.json":"4b9da3905020fdbf324a81738fa2a76f0439d8c23442800b258ec73a559b313f","dev/sysml/captures/WeaverArchitectureReaderViews-anchorBroker.json":"2f1802ce07745d4a44d21d3cb98e09a8f5e5a4d9d4b53f4888b913201d0941f4","dev/sysml/captures/WeaverArchitectureReaderViews-anchorEgress.json":"1e2a4ccc196214ad715ab2163a8f8a10600dee723255207419dd0f6769a0f2b8","dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json":"a0bebc5e912184bfee65a3288bbc487031d4cf0f2cd3c71285f058fe7142ce03","dev/sysml/captures/WeaverArchitectureReaderViews-codePolicy.json":"f08ede8649faacabc91a177d5133e0b92d933f1c416294c4d61f04dc55cb1feb","dev/sysml/captures/WeaverArchitectureReaderViews-configPrefix.json":"ef0d65c53cf03dcbd09dcd7cefd4488b7ecf405ae51d152df843cabb41807bb1","dev/sysml/captures/WeaverArchitectureReaderViews-driverCompletion.json":"b6ceeffd98f87d7e6261e02744a8236cde3a35419908d578d175b25239372fe4","dev/sysml/captures/WeaverArchitectureReaderViews-fencing.json":"4ac01959c19f3166eee044e5c3a258930d59c0b159d95a884cdf169b79ece2f0","dev/sysml/captures/WeaverArchitectureReaderViews-gatePersistence.json":"4beba7b5cd4e620715440dc40bd5aeb4cadf96a43f596031e61e58596e3701d3","dev/sysml/captures/WeaverArchitectureReaderViews-journalLifecycle.json":"d107f9bb4fa38e4eba9768329c88a8e1bede9f4d810d8283247bc144c76178a3","dev/sysml/captures/WeaverArchitectureReaderViews-logicalObservation.json":"962193507a4c9c7e1b55232795f795f265827eb7f3538fd817c66ce992164ea8","dev/sysml/captures/WeaverArchitectureReaderViews-manifest.json":"bb5ba5357520fcc205a9fa4d5f045169e55ca5a42c13c18bab957c2c2bfee8c1","dev/sysml/captures/WeaverArchitectureReaderViews-migration.json":"a3540a49ad6a49da75c022916905d80b6f45448fc7f4c381f7af11b2b27cc3ac","dev/sysml/captures/WeaverArchitectureReaderViews-policyExecution.json":"2acf02b6dfb01193050c98c6dfb9c8d0fb318907192e008393c493518f580411","dev/sysml/captures/WeaverArchitectureReaderViews-quorumPromises.json":"3a83243e86c793b955caed914d8fc46451b52d0de361f1df57bf005f5a61a4ab","dev/sysml/captures/WeaverArchitectureReaderViews-relationships.json":"5d7b3a5dd36d4b2e4835e84e2fbbf0ce7d2667b294ac1d1707eb31319e2fc5fe","dev/sysml/captures/WeaverArchitectureReaderViews-settlementAnchor.json":"c02c9b51f69ebfe0a71dda18a6cb77000833f165e05b7ee1738934540f575854","dev/sysml/captures/WeaverArchitectureReaderViews-sharedBudget.json":"ee6dfa5160417481b932bd1512cdf61f922d700a10f8cdc749d1f075c6bc05dc","dev/sysml/captures/WeaverArchitectureReaderViews-sharedExposure.json":"b194613295f8d8be51f1640d39c9c4b94b98a3d638482b649c1894595b1543a3","dev/sysml/captures/WeaverArchitectureReaderViews-spentState.json":"cecb6f68896a1dd6cf7a46eb19406d9163f2b867a0671d000bf332e0afd229cf","dev/sysml/captures/WeaverArchitectureReaderViews-writerSettlement.json":"31be9ede3e803dee11aa87d1060670274fbfcf647216871eca88c40459d4e1c2","dev/sysml/captures/WeaverArchitectureReaderViews-zeroAssurance.json":"ff2d2b779c0656e44e093e264c0d51e0b67e7ee3a6bd2791381a78ca54ec3a3d","dev/sysml/captures/WeaverAssuranceReaderViews-brokerQueue.json":"7b0eb5ceeca912bfb67f8ec7e1b0e5873ffce143c224ab5d9ce0cee60e30e671","dev/sysml/captures/WeaverAssuranceReaderViews-continuation.json":"409bd8489db25e6cdc85d5315763c918af731ab877f23defc322c3bf79027e4b","dev/sysml/captures/WeaverAssuranceReaderViews-deviceEvidence.json":"74be93d150fd06ef18677de824014bcf16cb0975444638e8c2100045b812c5b5","dev/sysml/captures/WeaverAssuranceReaderViews-gatewayHead.json":"57640f47e1c8b8cfccb057ab8169ccd70e5f875fb6f29de245a2e4d0dfe5d30f","dev/sysml/captures/WeaverAssuranceReaderViews-keySession.json":"4214cbffe8db0eb72aa603632c021789dd7e28252f534cb36d0cce03943966fb","dev/sysml/captures/WeaverAssuranceReaderViews-rangeRecovery.json":"e9f6307a038a358326c5023eafc1cc63163f8e150e9052fce931760ee799929c","dev/sysml/captures/WeaverAssuranceReaderViews-signer.json":"6f70fdf45a86c6adccb7cc20d6d956977d4b60109040223d0a270ed39bbb9ffb","dev/sysml/captures/WeaverAttemptReaderViews-admission.json":"d596e99a10d57d963971187870b394f13902347dd63fbbd25d47a9eba262dc95","dev/sysml/captures/WeaverAttemptReaderViews-outcome.json":"f733c3a62ec92c751bed7d4af2a171159ecca791cc94a6a5bbbaf7102c666246","dev/sysml/captures/WeaverAuthorityReaderViews-attemptLedger.json":"eda5e5a9488349c8c6a7ae35f9c734d57c5a98906af45cd1803498e677d8df40","dev/sysml/captures/WeaverAuthorityReaderViews-canonical.json":"e482a9565342b97eae507fc4dced9da96a451b481c362aecf4100d9ff20894be","dev/sysml/captures/WeaverAuthorityReaderViews-multiKey.json":"edadbfe4c4b779a672f9ba10e2932f3316f2e9cb76def0824ab1720de77ab32c","dev/sysml/captures/WeaverAuthorityReaderViews-publication.json":"6b2cf4c564cdc16e5209a9ab2e501d5fad3bab5f0b0d4489cd76d59cf9ef9010","dev/sysml/captures/WeaverAuthorityReaderViews-recoveryCAS.json":"a0eb5417ae07bc68617c03cc6d15764237fb34de5991f7cc039fa3f81f115da0","dev/sysml/captures/WeaverAuthorityReaderViews-scope.json":"3f410c66badd909ed8a225cf0d855e677935d794e5ad18a693850dc11c694784","dev/sysml/captures/WeaverCorrespondenceReaderView-correspondence.json":"f95c6e9c343b767adb01a3da95e9e40bb255c0e82c99d7a94db4990d6287f09d","dev/sysml/captures/WeaverExecutionReaderViews-accountCommit.json":"4efa7c3f4336161e13fa82cd3caedd5b58f9a9c39eb908926009da3c7fc632fc","dev/sysml/captures/WeaverExecutionReaderViews-admissionFloor.json":"eae22d625eff71110531ebdc80e2c5e1b0e97d162622d2070a1c6b675e6235e1","dev/sysml/captures/WeaverExecutionReaderViews-appendHandoff.json":"d01bce1e5343581a0ec8c20c61f13f24fa800c628e52bb29234741560d43a343","dev/sysml/captures/WeaverExecutionReaderViews-checkpoint.json":"1ab5f8ec641df819977247d976f0b43dc1e64dc7be2d02dbf4ae37d4a526467f","dev/sysml/captures/WeaverExecutionReaderViews-executionEvidence.json":"a2c298c54bdaaa0208816c254c86c96d8aec30d928a9d353800bb60ff5d112eb","dev/sysml/captures/WeaverExecutionReaderViews-executorOffer.json":"599a5827ec5a194f64d391bed06f579315ae6ccbcdb5cdba8f32d9cf151cb935","dev/sysml/captures/WeaverExecutionReaderViews-joinEnqueue.json":"6c7f0bd9e64ae305668f98d8049f6751b4237fafae08d12d2cf9f5871e3457fe","dev/sysml/captures/WeaverExecutionReaderViews-manifestSwitch.json":"e12bb543a99ad8022dd55a2c6578351e336877b1512cb563eeaccef77ba82caa","dev/sysml/captures/WeaverExecutionReaderViews-resultProjection.json":"f47530cd5ed6195faa5f95771e4d22559dd143955e1c9c4ea19f6bf28c91da06","dev/sysml/captures/WeaverExecutionReaderViews-walActivation.json":"ac2ce8046f78381b21d02a52eb101526aa067fdc8c03256a59a67ebd06ea1682","dev/sysml/captures/WeaverFloorReaderViews-floorOrdering.json":"f96c5974dc67d80439db49f295718ed53403b7ff907c5e74d1d54f07c7e17c37","dev/sysml/captures/WeaverFloorReaderViews-floorRecovery.json":"8e3969a35dad50fe57b834ed48bb7baecfaf96bb149e6867563ef95942ed2f1b","dev/sysml/captures/WeaverResearchReaderViews-embeddedTooling.json":"3909e0757ea17b7b0c6fe6deb63ad54dd30b4da9f8a0a08f874c1018abd765db","dev/sysml/captures/WeaverResearchReaderViews-floorTransport.json":"2f1ca96080a750ab06f883de2133f225d4b74679286c74af24f6e1145410ad7e","dev/sysml/captures/WeaverResearchReaderViews-gerbilLifecycle.json":"f5219a0d8fced700e814276195ab8900d6e9d0bd6186dcb42401fbcb17fd1d59","dev/sysml/captures/WeaverResearchReaderViews-gxiLifecycle.json":"e16dadb9e152fdad81565022360c269cb18cc0547f8770988fc466c7c4fdcc78","dev/sysml/captures/WeaverResearchReaderViews-parentReplay.json":"f7162a3e44c6423c4721c1b04092eea53136e875f202edc626cfcb93fcdd4745","dev/sysml/captures/WeaverResearchReaderViews-profileBinding.json":"21ecc30f186aa899e1f54b7b307e443f8b16363ffc18fe77ee0e13ee94dee50b","dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json":"8896989dd0154bbc380a603d4ef5b0ea4e88874821097a3b396f2baeef152294","dev/sysml/captures/WeaverResearchReaderViews-runtimeAssets.json":"1ebf39723fec5dae93ee61cec7c83b661d3e61c133fbfa47d1c8d2227dcea8a3","dev/sysml/captures/WeaverResearchReaderViews-semanticSlice.json":"f752f776f4798f38c58dd48dc9fe1007e8bc5418ca4fcba8399a6ca5ca39b5dd","dev/sysml/captures/WeaverViews-architecture.json":"b59e3722a61358fd111b31004df8e0451ceaf5fe1a4f663f97a46c30bcba6d45","dev/sysml/captures/WeaverViews-assurance.json":"0254e9bb2f22d0502c64d063cdd39eff6e99025195a20e4a48cb0eaf4a5e0a95","dev/sysml/captures/WeaverViews-contractRefinement.json":"ef4d1ee4fe0ec4906c25372e9e2bbb6a808d6b9e88ffc070def159463b0884f3","dev/sysml/captures/WeaverViews-execution.json":"b5cfd6f2158df6268b2a9815f009b2ad1655542361f009401d71cea42e668caa","dev/sysml/captures/WeaverViews-gateway.json":"04052b561c3fdd47f10e96bd06fdf62ccfbe6a9965a5c06edd97efbc38e085d0","dev/sysml/captures/WeaverViews-providerDeliveryJoin.json":"184f54768a7516498adfd3ed388242ab764557361a0b9254f9af21b85366d7bc","dev/sysml/captures/WeaverViews-providerEgressWindow.json":"6ae1a5c56080c63329f34f9b800f6323607f5356e512a5fe9f4c478cbcf75605","dev/sysml/captures/WeaverViews-rangeRecovery.json":"b4dcc96b68358ec095c84349f43c78f354486bb223a821a34378523267393bbd","dev/sysml/captures/WeaverViews-routeExecution.json":"142a8f709e4130a34eea8f35bb879f38f88135d0e00fa47c05fb8630adaa919f","dev/sysml/captures/WeaverViews-routeSelection.json":"2a765c562fd231b25f0b8a79cec61ba344e80a153729af23cbf2402821ee6eaa","dev/sysml/captures/WeaverViews-storage.json":"ec1f839d1fb94143b4f1ca4cf4b963cfb0299a62bb99809285799eea538384ee","dev/sysml/captures/WeaverViews-streamAdmission.json":"e93c5dea6d378437c25925bf19c882938d5bf23debdefc19f86b6391d4420218","dev/sysml/captures/WeaverViews-zeroTrust.json":"b7d95b97aa07e14e5d5be4765c744eddf688b93aba34020aa57354c74f13f931","dev/sysml/ControlActivation.sysml":"78bc6792c3a64ee54210720d3d88c1984b5c876d3a0647b6829bf904a811014f","dev/sysml/CorrespondenceReaderView.sysml":"24b811c00528feaab3547d5db3b7fada290ff89478ac2be0a1d252d8ea1e5828","dev/sysml/ExecutionReaderViews.sysml":"88f690ed1fed91f63f7571d14bf5d7c1c8d14ee3b8d1d17ae333dfd7a6176df3","dev/sysml/FloorReaderViews.sysml":"93401ba5b2009dd54614f7e5aff81d91a20085efbb77b3a143726ffdea16592c","dev/sysml/GatewayArchitecture.sysml":"dbec3964b7873ed0633964b05d1ba1ee828050aed35a3066858d0c38893f2642","dev/sysml/PolicyEvidenceDesign.sysml":"6a7d738b004be62e7412ea68080944f8cb6fb3aea785258efaefc2efc1c4e0e6","dev/sysml/ProviderRpc.sysml":"60a7ae2140742902a487dd29565d543591a1d080eeef37745241e142df101cc0","dev/sysml/ReaderDesigns.sysml":"4df8352980f9727b85a26533dc5ebfd67730540359d553a17d562574f3ea2529","dev/sysml/ResearchReaderViews.sysml":"cb10ed4ab79e911197834a8102e8a84986c567a358098e36d234d15b9c5acaec","dev/sysml/StoragePersistence.sysml":"b6b58b8802a557a7f3af787c2e7875be64865169ca3fd7e9973b13f6c3dc792d","dev/sysml/StreamingExecution.sysml":"d0d4d92300fba2b908ace30d9065cb2bac1d86f3b7c98219c1853a30f3110e85","dev/sysml/WeaverExecution.sysml":"789e4924150ada9c79bb1c73ab1aba0e141a68d1e1758c01fed074cc2b6d2b82","dev/sysml/ZeroTrustRefinement.sysml":"7cbec57110f03ed68469a1f49cb2046769516b09a6eb1b9433d866161bba6a82","docs/10-19-llm-gateway/10-routing-and-inference/10.02-llm-routing.d2":"513cad143cde846a9393bb5020dc4843caa1bb844204d3d0c13d1b5ada5efc70","docs/10-19-llm-gateway/10-routing-and-inference/10.05-route-execution.d2":"7c3ff8609c24983d0b27511756d8c5c04d0dc2cf5c973fc7012eaa0acda421e2","docs/10-19-llm-gateway/10-routing-and-inference/10.07-provider-egress-window.d2":"3c9c7c67296700d3b08cea62dddd5bdd011e7bafd61c2b4ecf1e38c32a94d6e7","docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2":"46df65896ab38bc84d19b8d9e63476977fb5d74621f92918f0c3fffd9679755d","docs/10-19-llm-gateway/11-attempts-and-failover/11.02-attempt-ledger.d2":"5438329d7af60e9596b5fe4519b04a27a7c36ce1d1dc1aa5442db6df7167cd8e","docs/10-19-llm-gateway/12-semantic-contracts/12.02-semantic-contract.d2":"8560ac03652d2dfb8aeb7797c0e3b61031e49f9a3276d3207c8758a32037c530","docs/10-19-llm-gateway/13-authoritative-scope/13.02-authoritative-scope.d2":"e5950b420b85e30891bdb2264c7fad7ccd9ec9934b6175906d592d683b3a844c","docs/10-19-llm-gateway/14-registry-publication/14.02-registry-publication.d2":"9153743fc734fb044f94a4d22175fbe963f0f15f02598143dfbd7a06cd880177","docs/10-19-llm-gateway/15-recovery-cas/15.02-recovery-cas.d2":"c5de2f6cb52b0450361b2ed0523f647bdcad1fc43d410231f91ae86aee450859","docs/10-19-llm-gateway/16-policy-publication/16.02-policy-publication.d2":"4be00575666b7ada7185a30e553b42b9c36fe9109ce89df3d0dbb4b30ac10cab","docs/10-19-llm-gateway/17-policy-continuation/17.02-policy-continuation.d2":"4108a821aba5a2de1ffebc59b9e0d9180130bb3f598ac2130d59a83e8eca571f","docs/10-19-llm-gateway/18-canonical-registry/18.02-canonical-registry.d2":"f3b44cf54b006df34b528075bbc54742963a53e2afd4cbee435f81095b59b800","docs/10-19-llm-gateway/19-multi-key-registry/19.02-multi-key-registry.d2":"c44a2569dec8ae1fab46acb1ddd58f8b468e7ea7b11136c120a6bf2b042cf8b7","docs/20-29-execution-authority/20-result-projection/20.02-result-projection.d2":"696df32a9d705c6915bcc43a33616126cdce61ce5af0ae198c0dca5bc898d645","docs/20-29-execution-authority/21-join-enqueue/21.02-join-enqueue.d2":"430f46389111827b9f0ad5c9c3193366729fffe917ef18a5bfa0ec8238f6ab02","docs/20-29-execution-authority/22-executor-offer/22.02-executor-offer.d2":"0d93c13abcc1bd79afb32e6ae8a965cc5ec3b0c30fc1958f2f212e12b5e4b65a","docs/20-29-execution-authority/23-execution-reconciliation/23.02-execution-reconciliation.d2":"14c698ad47a243d46d788ab3494b1ad22ae7f14a163140eb6b4f5e8e071c6269","docs/20-29-execution-authority/24-account-commit/24.02-account-commit.d2":"10d6a5116d2c8be77ce7f27312d9d49ad832645c6748bb7bd68bb6942055990e","docs/20-29-execution-authority/25-wal-activation/25.02-wal-activation.d2":"9ebcd14701116e583157282a1678a6f1e0fe70e1ee4b9b7e038b520d4392ce05","docs/20-29-execution-authority/26-checkpoint-truncation/26.02-checkpoint-truncation.d2":"c5c1a35a16fe9b33029169b16d4c0af113f49e665eed0074ce524fc7a15bdb77","docs/20-29-execution-authority/27-manifest-switch/27.02-manifest-switch.d2":"c4de2ef519af25b2c41194df561860ad0236b0309b3178b388204c29cebf9f41","docs/20-29-execution-authority/28-append-handoff/28.02-append-handoff.d2":"f7646793e8540ec5f1e587d5e13deaf16d166180f80107ac8f9c904ea5c9372c","docs/20-29-execution-authority/29-admission-floor/29.02-admission-floor.d2":"0b9794f3d5fdfc7dcdbb519426eecf7e6ec6cb707de5017387c9aa47208ea385","docs/30-39-assurance/31-protected-signer/31.02-protected-signer.d2":"bc787086ae26a1a6cd56e51a2b4182c86e476f13e28ed1f5d80363b1d827e013","docs/30-39-assurance/32-key-boundary/32.02-key-boundary.d2":"1b616363aa68166988cc1d09404d637da406f048b9647676ec5f42d15f1762ca","docs/30-39-assurance/33-device-isolation/33.02-device-isolation.d2":"f4b086efce29484b70d4d4b2c04dad3887976d69187c25234e734e90260a6c7c","docs/30-39-assurance/34-floor-decision/34.02-floor-decision.d2":"78e2de9f044edb41944a56c1c8c8251a9cacd3470cf73c16b87f5ba100139a04","docs/30-39-assurance/34-floor-decision/34.04-floor-recovery.d2":"296d821eae11d4b77a552ae21d91eadcddcf032a15989dd35490128397044203","docs/30-39-assurance/35-intent-continuation/35.02-intent-continuation.d2":"08475ba17d7c98911a7db912041b669d049c75315c861322f72a5b50a471df55","docs/30-39-assurance/36-gateway-head-cas/36.02-gateway-head-cas.d2":"51669df10ec208197e690f656b962b259959af5f225243b62e5ff6bbea5637a5","docs/30-39-assurance/37-broker-consumption-queue/37.02-broker-consumption-queue.d2":"1ad636df3ba980d5f25b1a330c00c8b21f152958fe7c86617736e1b1f85a1ed8","docs/30-39-assurance/38-logical-range-recovery/38.02-logical-range-recovery.d2":"8ed5e1adc741da6852d027828993a83816cadb0c7bc1732bfaf121b2a64878d3","docs/40-49-admission-coordination/40-source-join/40.02-source-join.d2":"b8815cf59a1be49a4657b6ec3857d39e6d7d39ab4bb3ed44521c71ffe0ec5cee","docs/40-49-admission-coordination/41-source-custody/41.02-source-custody.d2":"feef18f62d537d4eb0659c0f1d719218df1a3eda506c9468b59423b151550bd7","docs/40-49-admission-coordination/42-custody-publication/42.02-custody-publication.d2":"24f019e8633cc816f7488e3f65384d2dea96ac8a3685714665a47bc6144b1e5c","docs/40-49-admission-coordination/43-caller-custody/43.02-caller-custody.d2":"6352167e4d3427fd9a66befb74fb3eebf91a127c5e82ecff8312b24178d5117f","docs/40-49-admission-coordination/44-incarnation-issuance/44.02-incarnation-issuance.d2":"215f52c84c9f41c36352f8b6da8b4670f1b375672cfc9efdf6a8bd1df95c946e","docs/40-49-admission-coordination/45-bootstrap-invitation/45.02-bootstrap-invitation.d2":"9e019de8289428a97580fe66ccefc6b9d0a43c1bac07433d2f29596f4d407401","docs/40-49-admission-coordination/46-beneficiary-registration/46.02-beneficiary-registration.d2":"322b848fdd67ea88c99b509cb5d913d7a5023e327edea51f16f44816356d81ce","docs/40-49-admission-coordination/47-enrollment-credential/47.02-enrollment-credential.d2":"ea0aa0bed915bea42d3d65c8f6572f799eb63d0aee1018b75803e61ef034d303","docs/40-49-admission-coordination/48-subject-authority/48.02-subject-authority.d2":"9f707fbc6e5ba8933a0e4d9d057f013c5764afc503f819288f628d3f9709f88d","docs/40-49-admission-coordination/49-routine-routing-config/49.02-routine-routing-config.d2":"7fa18b652ba97e8fe66f402a9a85d65740db9d3ffadff7890db7d72826c498b6","docs/50-59-research-program/51-qualified-semantic-slice/51.06-semantic-gateway-slice.d2":"d63df655a635fccac3c92eded92c039a3f079c24fa2b7a2fd0dc1f3fabd3c0f5","docs/50-59-research-program/52-committed-profile-binding/52.04-committed-profile.d2":"3ea30976830c607bf8cec62cbabc4291c384bd5f368049a45777f6f981d87d6e","docs/50-59-research-program/53-gerbil-exit/53.04-gerbil-lifecycle.d2":"b7b623664edc6e86efe62eeee7f5977dc207f0cb12e40cb6f0e77e38160695de","docs/50-59-research-program/54-dynamic-gxi-exit/54.04-dynamic-lifecycle.d2":"d4d410dd8cb10de6d3526b54ac7f96731d2f2a94dd9763aad96a0926608e251c","docs/50-59-research-program/55-dynamic-gxi-paired/55.04-runtime-boundary.d2":"573b248a6b7ce2d7eee1e70a469c54e4f195c4894ec7b0f61c8406fae843eccc","docs/50-59-research-program/56-gambit-image-closure/56.04-locator-boundary.d2":"0c45ee11d269b0cab8998c7fc3432ec851b9390b7530486225134b261d8d7de8","docs/50-59-research-program/57-runtime-implementation/57.03-runtime-boundary.d2":"193d22a5bd9e4b23260334d085df8aa5ec19c349f13cd9f56eaa26fe54f7e3ac","docs/50-59-research-program/58-streaming-execution/58.03-streaming-runtime.d2":"76ea49c83b4b36af1e775f80475d40747640b80a330434bf86635e255e84ef14","docs/50-59-research-program/58-streaming-execution/58.05-range-progress-recovery.d2":"aef20c8ad7d7420a65422add6d9fb635bdbe32e42e49427d3179bf20499ae4cd","docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2":"6f4e8218ea262e35efaebaf8cc2f96345b2ef1e7e9c1a6b12b68290dd99c683d","docs/50-59-research-program/59-provider-rpc/59.21-verification-ownership.d2":"e035ae7e56ee5e6498f131ed62f4792547c1e716aa5ed29865b333f54665e8f1","docs/50-59-research-program/59-provider-rpc/59.26-semantic-execution-ecosystem.d2":"50c091b094125693e2debe73599a63405849f1f55ab3658030674692c9334e14","docs/50-59-research-program/59-provider-rpc/59.30-governance-adapter-acceptance.d2":"88cbbd45e63358bb45a58fb27f85e275b9cc9fb3d3aee6af19eabed0912545d2","docs/50-59-research-program/59-provider-rpc/59.43-floor-transport-owner.d2":"36c4d6b561332ab30deb464a92bb4c2f02ceed5c8a1ca66617f72b6086b2c555","docs/50-59-research-program/59-provider-rpc/59.44-cloud-rpc-arrow-boundaries.d2":"fe0ac2220e04f6ccea851247ecf8ae1cab4ec8c8ba8744010c478992c233ebed","docs/50-59-research-program/59-provider-rpc/59.45-slow-consumer-zero-trust.d2":"e36cf58a239a2d9f0c99789bb7484de4e26180a8f941970540f72b530a79d813","docs/50-59-research-program/59-provider-rpc/59.46-functional-security-frameworks.d2":"e541b969352e8149e71e5b539988f9955b525e5e5ba3e7e7270bd4a98fbe19f5","docs/50-59-research-program/59-provider-rpc/59.47-property-testing-framework.d2":"f66ed065dcf955a233968ca295517c642be30dad9b24e23a781fe34e4bed45d9","docs/50-59-research-program/59-provider-rpc/59.49-policy-proposal-barrier.d2":"3a8559bb22f812075d9d7de4a397978995d06c32ed22e9415f990413551aebb6","docs/50-59-research-program/59-provider-rpc/59.50-parent-contract-and-replay.d2":"2db3983f56e938c927b68077551573c8e86362da892f47890459ab7b3f929c64","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-architecture.d2":"10e92e79b69f4b0813551dd2ddadc5ad225b7b0fa8374ed7015b7f2fe66bb6e1","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-contract-refinement.d2":"204c9e20d9027b7a38bf2a964da9a7cadb92744561fa9f1eb3fa29d00f4fa386","docs/50-59-research-program/59-provider-rpc/59.52-reviewed-publication-cas.d2":"4e0998e61717d5441e242cde0dfc52198312b67b63f0ce8b0425a423d1b88a24","docs/50-59-research-program/59-provider-rpc/59.53-artifact-registry-recovery.d2":"f7083a48413d41ad99e7191281bd6e74a92b33c7cc1f4f2f9ae322bb1405088a","docs/50-59-research-program/59-provider-rpc/59.54-source-incarnation-authority.d2":"1e55c0487f01d70462e8df6b46eff9e799b0dc592c0e780c759fa602e3d84444","docs/50-59-research-program/59-provider-rpc/59.55-evidence-reviewed-publication.d2":"c66435372642f7a93ca7fc6f78c2abcbc364a4dde447d10dcc4b2b21ccc06456","docs/50-59-research-program/59-provider-rpc/59.56-runtime-assets-and-authority-floor.d2":"c675469701bb6994fed1976d1e90d01dc1cc4e416a6788f865494fa3243d32c1","docs/50-59-research-program/59-provider-rpc/59.57-schema-bound-candidate-replay.d2":"5ca15af556e0a4ba5bdf1742cf81182ad72e7f51b2eb63352b839e068a7ad7d2","docs/50-59-research-program/59-provider-rpc/59.58-independent-source-recovery.d2":"4b21999b3554be15374448f36ffbccf517b32784a65cadde0f4c1eb8308da377","docs/50-59-research-program/59-provider-rpc/59.59-retained-root-and-recovery-coverage.d2":"37fdf1d3dd01f087434a6108b43a5657d7aecf79a2b9e60638d70eb0b1a4984b","docs/50-59-research-program/59-provider-rpc/59.60-persistent-source-key-custody.d2":"d27df3a14df5d57ad725c1455c82a4ab5bad45b78acea8cd1a76e59958b710eb","docs/50-59-research-program/59-provider-rpc/59.61-authority-bound-replay-pair.d2":"bd4962775564848a90ec49439301cf0cdfbaa4018956344e809f5b318bea6ccd","docs/50-59-research-program/59-provider-rpc/59.62-burn-exposure-recovery.d2":"fab4ea6d0981d75dd4c704f302268f3c5af0898e299e8e0fb38b34d07200b22c","docs/50-59-research-program/59-provider-rpc/59.63-mrr-admission-contract.d2":"ed3c604e0d350049f00528c7117675a7db751b3d6683719b03be116bcf49d5c5","docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.d2":"7164874fdbeec99f2185e1091f759466a68a3b7d9b239db6a503f16383fce50e","docs/50-59-research-program/59-provider-rpc/59.65-turso-concurrent-admission.d2":"0ade3ea326e2066ce908129e383b7e0f371a429710ed0a0bad30ddcfd61f034e","docs/50-59-research-program/59-provider-rpc/59.66-bounded-writer-reuse.d2":"9390a3c12f06c2f33e3df99088dc39de92d3bccc971ddf5a632910515a67623e","docs/50-59-research-program/59-provider-rpc/59.67-writer-owner-lifecycle.d2":"c28559ccf38b2f3320d84bbc0ffc6133e2708081e95bff39d5ed75d064287bde","docs/50-59-research-program/59-provider-rpc/59.69-hot-path-cost-boundaries.d2":"e5789625590fab63bc3635627b7e20ac41f64b8f40cbeee84d51a85f27ab31f1","docs/50-59-research-program/59-provider-rpc/59.75-complete-entry-and-output-contract.d2":"d667501bc15d6c31d986994f641d8d38f63c1d910784e6852e596c24c4e4c7c7","docs/50-59-research-program/59-provider-rpc/59.75-package-linkage.d2":"bc655ae71cc46e0d5b7f42637b78530f262c3142394485e2a9ba31f6516a0a10","docs/50-59-research-program/59-provider-rpc/59.76-embedded-tooling-and-darwin-io.d2":"87655d7c6d81c1ab203f886930f1630003e006c0edb71f90ac3ca23a0cb91845","docs/50-59-research-program/59-provider-rpc/59.77-mrr-turso-storage.d2":"72a4dceeb20cca337276f64537d47dbbd2ac0ce359a7a63997090e6476a40c96","docs/50-59-research-program/59-provider-rpc/59.84-quint-preparation-and-completion.d2":"17f485d7c541506c42003ebba887705ea61972f00c9498aa3c0d153a33b02922","docs/architecture/08-diagram-catalog.org":"353a4296584381207513468ef291e7e1aefdcd6f9f2b854c92be90aab47577ea","docs/architecture/diagrams/00a-readme-overview.d2":"1e6119c9d5b2d8a40d3bec0c8add35e8c078dd739e46fcf45c589b8125c7c46f","docs/architecture/diagrams/00c-gateway-runtime.d2":"c1d93cc1f635803872e3349c89b5127145bdcdd2b85e9a48f83d63f0bda439da","docs/architecture/diagrams/00d-zero-trust-overview.d2":"0d3d1a5de0967db2331b9be81468cee1b7cb1d1d98966c5e541e4fc24023f2e6","docs/architecture/diagrams/01-system-boundaries.d2":"69b4622c26b18a8518d46f79db8ce281c756a16f7f1a46977272086bf4dc38e0","docs/architecture/diagrams/01-system-relationships.d2":"dde40fac8667b79a070fda14ebd892f1f1e7c1217726595179b541c855f80c2c","docs/architecture/diagrams/02-admission-sequence.d2":"97077cb16cd4457fe14092caeb4bc8cf2912d434763a08fcf350cd6a4c2b2c74","docs/architecture/diagrams/03-attempt-state.d2":"e696fc0f1d63f58100405852e88e8a7dfb1a625e43be398f3bb54bbc1d90e13a","docs/architecture/diagrams/03a-attempt-observation.d2":"6b387ec7fbcff7d5e3e129bad7ea9590afe0324800a5a13bf7a89377ad86c387","docs/architecture/diagrams/04-consume-timeout.d2":"2ccfe8d033069e0d891531f3b5afef4febf21b2722209a612454d14321cac940","docs/architecture/diagrams/05-fencing-boundaries.d2":"1103ed75ac615b1a2f8239c0321d046a5a87acfa235d5042d8a529e23acd7483","docs/architecture/diagrams/06-source-admission.d2":"4d20817291c5de93b7f97366e6cb1b4af954f22de1ebcb3012c139a4b9dbd82c","docs/architecture/diagrams/07-post-claim-outcomes.d2":"63258620c15c2f52963dcdba33b4ac82cd12aadd1c2de005cd029655493493c1","docs/architecture/diagrams/08-code-as-policy.d2":"fc2263ff1ae000055e6054b89beee60f53b9621707510354c34ef45057889676","docs/architecture/diagrams/09-claim-wins-race.d2":"9eff775ddac29c47acd2c0b69fb1ff98ba9a20943da970c2804e270979555c41","docs/architecture/diagrams/10-commit-dispatch-sequence.d2":"fa5d56c49bc3f590c88cf7c3b63e180afd2d2a39fca878d1515917077ff1687a","docs/architecture/diagrams/11-zero-trust-assurance.d2":"ea93840da2ff4bdac59349f5ad7a56cee5506600283d0c364c53275dde0b5b48","docs/architecture/diagrams/12-execution-correspondence.d2":"1dd66ee8c517fd9c6f2f4b1700aeec3e620d699fbe9eeee20df8e05a7f1decb0","docs/architecture/diagrams/13-policy-to-execution.d2":"4bb05b74c3bc0ca997c5e5035ddc949fa374db3ff49bf2104a6c9753e12be3ef","docs/architecture/diagrams/14-adapter-broker-boundary.d2":"b855fa0482a5524226354b26bc8d7ecef0daf2ab1cab54c1783eba0ff29fab01","docs/architecture/diagrams/15-stream-message-authorization.d2":"cedf1c545a853ec2a9ae51bea928b04376d192f1a4c2af117fa54f475ad541e0","docs/architecture/diagrams/16-authoritative-spent-state.d2":"201bd9fe5eb6101543d939e3d83aca646e2b07c13ff1e3c56779571a0cd1172e","docs/architecture/diagrams/17-logical-message-observation.d2":"2333ad147295ead60ed6a92dc824cf6f5769f3828eff1e0cdf58e50aace7b1e1","docs/architecture/diagrams/18-shared-identity-budget.d2":"5ab4992fd8b6a6abf518fb0bbc8c2c8ad8b920d0be74a6e734d846319252ffa7","docs/architecture/diagrams/19-finite-domains-and-migration.d2":"b72b451d0bb97de46831e4b266d8fdd22d59e7d54db99446d53549f081a008e2","docs/architecture/diagrams/20-anchor-recovery-and-egress.d2":"9479271410f1bb57f92106a1d91ec73c73872568d9fcda55cac5aa64b89e5c9f","docs/architecture/diagrams/21-composed-journal-transport-lifecycle.d2":"0fffe555ee4c2c1222c97eebd24ca9b0df91a4d3ec118300ae3b88240004c3c8","docs/architecture/diagrams/22-finite-stream-manifest.d2":"60b33eb6d06aeaa1027546a1fc9d6c07069c3cd3c7d23df8ff8d63a341afe2ea","docs/architecture/diagrams/23-driver-completion-recovery.d2":"271963db2cd881bb82e164bb1544c7bcf311e1781f20170d858ccb65a596d8f5","docs/architecture/diagrams/24-writer-settlement-closure.d2":"ea1930326b0073e7fabd8b64ef3ffea781f1aef60db0d942f9ab14f1150296e9","docs/architecture/diagrams/25-settlement-anchor-recovery.d2":"8904bfcda525de21b48ea8f2db8d12aaa27e85818ccde43fb545851dc522ba3b","docs/architecture/diagrams/26-gate-consumption-persistence.d2":"42e676634ecb40cfb2dee06db1f5497d0e58c05f30097618c3852eb946992f0d","docs/architecture/diagrams/27-anchor-commit-broker-fencing.d2":"5c2ae36987b00655bbcdba36352e03b61765739ad2f3fc80a561ff0d325a9461","docs/architecture/diagrams/28-anchor-configuration-prefix.d2":"1ac0eeb3c76f5ae0ce3565d4469e50210786c3bc53c703a1a61d519dfa075512","docs/architecture/diagrams/29-quorum-durable-promises.d2":"2e4a24c3fae49e710d5afc31d4681a9efc8c2e8af3fa58a0957ede05fe7c0255","docs/architecture/diagrams/39-shared-execution-exposure.d2":"2c08f5b3d4531a7be2aadec8f1ff9d4476495418e94e84c1ff643583ac991ce4","docs/architecture/diagrams/assets/agent-request.svg":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","docs/architecture/diagrams/assets/bounded-write.svg":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","docs/architecture/diagrams/assets/budget-ledger.svg":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","docs/architecture/diagrams/assets/components/activity.svg":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","docs/architecture/diagrams/assets/components/book-open.svg":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","docs/architecture/diagrams/assets/components/bot.svg":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","docs/architecture/diagrams/assets/components/brain.svg":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","docs/architecture/diagrams/assets/components/circle-question-mark.svg":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","docs/architecture/diagrams/assets/components/clipboard-check.svg":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","docs/architecture/diagrams/assets/components/coins.svg":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","docs/architecture/diagrams/assets/components/database.svg":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","docs/architecture/diagrams/assets/components/file-check.svg":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","docs/architecture/diagrams/assets/components/fingerprint-pattern.svg":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","docs/architecture/diagrams/assets/components/message-square.svg":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","docs/architecture/diagrams/assets/components/rotate-ccw-clock.svg":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","docs/architecture/diagrams/assets/components/rotate-ccw.svg":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","docs/architecture/diagrams/assets/components/route.svg":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","docs/architecture/diagrams/assets/components/send.svg":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e","docs/architecture/diagrams/assets/components/shield-check.svg":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","docs/architecture/diagrams/assets/components/ticket-check.svg":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","docs/architecture/diagrams/assets/components/waves-horizontal.svg":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","docs/architecture/diagrams/assets/components/workflow.svg":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","docs/architecture/diagrams/assets/go.svg":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","docs/architecture/diagrams/assets/kubernetes.svg":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","docs/architecture/diagrams/assets/model-catalog.svg":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","docs/architecture/diagrams/assets/model-provider.svg":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","docs/architecture/diagrams/assets/permission-check.svg":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","docs/architecture/diagrams/assets/route-choice.svg":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","docs/architecture/diagrams/assets/rust.svg":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","docs/architecture/diagrams/assets/task-contract.svg":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","docs/architecture/diagrams/assets/unknown-hold.svg":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","Project.sysml":"c0c96eba7c5dbce2fde3c5c0f13353acfb1291eee59bcb8eb2ee1860f527aba4"},"rendered":{"observation":{"canvas":{"x":0,"y":0,"width":980,"height":686.21875},"subjects":[{"id":"n0","role":"default","x":40,"y":311,"width":278.65625,"height":122.59375},{"id":"n1","role":"default","x":350.65625,"y":311,"width":278.671875,"height":122.609375},{"id":"n2","role":"default","x":661.328125,"y":311,"width":278.65625,"height":122.59375},{"id":"n3","role":"default","x":40,"y":511.609375,"width":278.65625,"height":122.59375},{"id":"n4","role":"default","x":350.65625,"y":511.609375,"width":278.671875,"height":122.609375},{"id":"n5","role":"default","x":661.328125,"y":511.609375,"width":278.65625,"height":122.59375}],"relations":["edge:0","edge:1","edge:2","edge:3","edge:4"],"headings":[{"role":"title","x":32,"y":32,"width":916,"height":63},{"role":"question","x":32,"y":95,"width":916,"height":56},{"role":"note","x":32,"y":167,"width":916,"height":48},{"role":"note","x":32,"y":215,"width":916,"height":48}]},"readability":{"minimumTextSize":24.14725378787879,"samples":23},"bounds":{"objects":{"x":32,"y":291,"width":916,"height":363.21875}}}}Commit a group. Gate every frame.?How can a shared snapshot stay safe during revocation?One native outcome qualifies the group.Revocation closes delivery; unknown retains the hold. +@font-face{font-family:"Kalam";font-style:normal;font-weight:700;src:url(data:font/woff2;base64,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) format('woff2')}{"renderer":{"package":"@deterministic-engineering/render","version":"1.0.0","icons":{"agent":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","agent-request":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","authentication":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","authorization":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","bounded-write":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","budget":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","budget-ledger":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","capture":"a647d42aa11f4e5e85d0bbf66f483f57f3c4ba3a9536362ed0eaaaae10a89cee","catalog":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","claim":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","decision":"3535642a5b613372c3fd374151ec90aafa19b64b2d33d10b19162cad07a35c7a","document":"0bf9674a401262da8a646305cab00006954721c07765b9962e0dee1c31d560f7","evidence":"0a91b169aaa644829a054cbb94194efffaf4298f2b6f8fa8c6ec2b7b413a1766","go":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","history":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","kubernetes":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","ledger":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","library":"df474fa36a74016b79236fff58a980a8c18c682d1866211776e349a0eb4b2979","message":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","model":"0cfd1f9ed3873f556ace725a7b6a251ebe75d7d976567699276f34df36b2443b","model-catalog":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","model-provider":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","obligation":"e76f4d34a7190400446c89e4e7d187762b885808a64a00c99455599d902570c5","pending":"cca7589bc3b1dcdebacb867c6836c6fc166257f05823555a268354ff9bfac00c","permission-check":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","policy":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","provider":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","publication":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","question":"dbf231e1568dc37189d5674d73c4bfc58a17eb8ada579b3f03bf2813d33c56f4","recovery":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","reference":"3814c570f79ab294252c36530de464c9364814b797afb862d9c62e728a8660fc","route-choice":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","routine":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","routing":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","rust":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","selection":"82b4ab6faf195fea0a891c35268e61c186e93e7c6a9d7967a4f6a73dbf25ae7f","stream":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","task-contract":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","telemetry":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","unknown":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","unknown-hold":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","writer":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e"}},"design":{"audience":"Gateway developers and security reviewers","medium":"GitHub at 830 CSS pixels","message":"One native outcome qualifies the group.\nRevocation closes delivery; unknown retains the hold.","questionRefs":["q1"],"requiredSubjects":["n0","n1","n2","n3","n4","n5"],"requiredRelations":[],"focalSubjects":["n4"]},"evidence":[],"layout":"model-view","presentation":{"objectRows":[["n0","n1","n2"],["n3","n4","n5"]],"notation":"objects","options":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL"},"icons":{"n0":"policy","n1":"authorization","n2":"ledger","n3":"stream","n4":"writer","n5":"stream"},"roles":{"n0":"governance","n1":"governance","n2":"ledger","n3":"semantic","n4":"execution","n5":"execution"},"edgeLabels":true,"graph":{"id":"declared-reading-order","children":[{"id":"n0","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n1","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n2","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n3","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n4","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n5","layoutOptions":{"elk.partitioning.partition":"1"}}],"layoutOptions":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.partitioning.activate":"true"}},"textColumns":22},"drawing":{"mode":"sketch","options":{"seed":29,"roughness":1.3,"strokeWidth":1.2,"fillStyle":"hachure","hachureGap":9,"fillWeight":0.6}},"fonts":[{"family":"Kalam","weight":400,"source":"@fontsource/kalam/files/kalam-latin-400-normal.woff2"},{"family":"Kalam","weight":700,"source":"@fontsource/kalam/files/kalam-latin-700-normal.woff2"}],"palette":{"background":"#F6FAF9","surface":"#FFFFFF","ink":"#163C43","muted":"#496A70","border":"#C9DDDA","accent":"#087E82","secondary":"#946044","tint":"#E1F1EC","secondaryTint":"#F4EADA","onAccent":"#FFFFFF","supported":"#237653","pending":"#986320","conflict":"#A13E54"},"inputSHA256":"cfbb9725f5151d4bb0033fc22daeaabba34c0410f687c77065c8862556a44d55","model":{"subjects":[{"id":"n0","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::changes","label":"Rust / close\nQueued request / no cut\nAccepted edit / close first"},{"id":"n1","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::validated","label":"Rust / qualify group\nRead shared; write origin\nCedar + claim + domains"},{"id":"n2","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::publication","label":"Turso / commit group\nBurn the bounded group\nPublish one qualified cut"},{"id":"n3","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::staged","label":"Rust / prepare frame\nExact bytes and next span\nReserve transport credit"},{"id":"n4","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::receiver","label":"Rust / consume once\nLive cut + owner + expiry\nOne-use frame cursor"},{"id":"n5","type":"part","sourceName":"WeaverExecution::providerDeliveryJoin::tonic","label":"Tonic / accept once\nOne current Rust owner\nObserve delivery later"}],"relations":[{"id":"edge:0","src":"n0","dst":"n1","label":"closeBeforeWrite","kind":"connection","fromPort":"n0.0","toPort":"n1.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:1","src":"n2","dst":"n4","label":"exactRevision","kind":"connection","fromPort":"n2.1","toPort":"n4.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:2","src":"n3","dst":"n4","label":"inertOnly","kind":"connection","fromPort":"n3.0","toPort":"n4.1","srcArrow":"none","dstArrow":"none"},{"id":"edge:3","src":"n1","dst":"n2","label":"qualifiedManifest","kind":"connection","fromPort":"n1.1","toPort":"n2.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:4","src":"n4","dst":"n5","label":"oneOffer","kind":"connection","fromPort":"n4.2","toPort":"n5.0","srcArrow":"none","dstArrow":"none"}]},"modelSource":{"ref":"sdkCapture","modelHash":"c637cf09173a79f88860780ded6bda42ff9f1a58e1ba64f11cfaaa253593938b","view":"WeaverViews::providerDeliveryJoin","portProjection":"owner","labels":{"n0":"Rust / close\nQueued request / no cut\nAccepted edit / close first","n1":"Rust / qualify group\nRead shared; write origin\nCedar + claim + domains","n2":"Turso / commit group\nBurn the bounded group\nPublish one qualified cut","n3":"Rust / prepare frame\nExact bytes and next span\nReserve transport credit","n4":"Rust / consume once\nLive cut + owner + expiry\nOne-use frame cursor","n5":"Tonic / accept once\nOne current Rust owner\nObserve delivery later"}},"modelTrace":{"modelHash":"c637cf09173a79f88860780ded6bda42ff9f1a58e1ba64f11cfaaa253593938b","requestedView":"WeaverViews::providerDeliveryJoin","resolvedView":"WeaverViews::providerDeliveryJoin","renderingSHA256":"74fa1b5e5efbcdf87298b4bcf11c65d109fa9bd5042b1949ff5bd0951ef35989","capturedRenderingJSON":"{\"modelHash\":\"c637cf09173a79f88860780ded6bda42ff9f1a58e1ba64f11cfaaa253593938b\",\"requestedView\":\"WeaverViews::providerDeliveryJoin\",\"rendering\":{\"view\":\"WeaverViews::providerDeliveryJoin\",\"kind\":\"interconnection\",\"stated\":\"render asInterconnectionDiagram\",\"nodes\":[{\"id\":\"n0\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::changes\",\"nameSynthesized\":false,\"type\":\"EgressMutationBarrier\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n0.0\",\"name\":\"closed\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":597,\"startCol\":9,\"endLine\":597,\"endCol\":46}},{\"id\":\"n1\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::validated\",\"nameSynthesized\":false,\"type\":\"DeliveryValidation\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n1.0\",\"name\":\"closed\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n1.1\",\"name\":\"validated\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":598,\"startCol\":9,\"endLine\":598,\"endCol\":45}},{\"id\":\"n2\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::publication\",\"nameSynthesized\":false,\"type\":\"PublishedRangeSnapshot\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n2.0\",\"name\":\"qualified\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n2.1\",\"name\":\"preserved\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":599,\"startCol\":9,\"endLine\":599,\"endCol\":51}},{\"id\":\"n3\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::staged\",\"nameSynthesized\":false,\"type\":\"InertProviderFrame\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n3.0\",\"name\":\"stagedBytes\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":600,\"startCol\":9,\"endLine\":600,\"endCol\":42}},{\"id\":\"n4\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::receiver\",\"nameSynthesized\":false,\"type\":\"DeliveryReceiver\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n4.0\",\"name\":\"validated\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n4.1\",\"name\":\"staged\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"},{\"id\":\"n4.2\",\"name\":\"offer\",\"type\":\"EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":601,\"startCol\":9,\"endLine\":601,\"endCol\":42}},{\"id\":\"n5\",\"kind\":\"part\",\"name\":\"WeaverExecution::providerDeliveryJoin::tonic\",\"nameSynthesized\":false,\"type\":\"ProviderEgressTransport\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n5.0\",\"name\":\"acceptedBytes\",\"type\":\"~EgressWindowPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":602,\"startCol\":9,\"endLine\":602,\"endCol\":46}}],\"edges\":[{\"from\":\"n0\",\"to\":\"n1\",\"fromPort\":\"n0.0\",\"toPort\":\"n1.0\",\"label\":\"closeBeforeWrite\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":603,\"startCol\":9,\"endLine\":603,\"endCol\":80}},{\"from\":\"n2\",\"to\":\"n4\",\"fromPort\":\"n2.1\",\"toPort\":\"n4.0\",\"label\":\"exactRevision\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":604,\"startCol\":9,\"endLine\":604,\"endCol\":86}},{\"from\":\"n3\",\"to\":\"n4\",\"fromPort\":\"n3.0\",\"toPort\":\"n4.1\",\"label\":\"inertOnly\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":605,\"startCol\":9,\"endLine\":605,\"endCol\":76}},{\"from\":\"n1\",\"to\":\"n2\",\"fromPort\":\"n1.1\",\"toPort\":\"n2.0\",\"label\":\"qualifiedManifest\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":606,\"startCol\":9,\"endLine\":606,\"endCol\":91}},{\"from\":\"n4\",\"to\":\"n5\",\"fromPort\":\"n4.2\",\"toPort\":\"n5.0\",\"label\":\"oneOffer\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/WeaverExecution.sysml\",\"startLine\":607,\"startCol\":9,\"endLine\":607,\"endCol\":75}}],\"columns\":[],\"rows\":[],\"notes\":[],\"notices\":[],\"shown\":[]}}","portProjection":"owner","nodes":[{"id":"n0","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":597,"startCol":9,"endLine":597,"endCol":46}},{"id":"n1","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":598,"startCol":9,"endLine":598,"endCol":45}},{"id":"n2","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":599,"startCol":9,"endLine":599,"endCol":51}},{"id":"n3","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":600,"startCol":9,"endLine":600,"endCol":42}},{"id":"n4","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":601,"startCol":9,"endLine":601,"endCol":42}},{"id":"n5","parent":"","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":602,"startCol":9,"endLine":602,"endCol":46}}],"edges":[{"id":"edge:0","index":0,"from":"n0","to":"n1","fromPort":"n0.0","toPort":"n1.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":603,"startCol":9,"endLine":603,"endCol":80}},{"id":"edge:1","index":1,"from":"n2","to":"n4","fromPort":"n2.1","toPort":"n4.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":604,"startCol":9,"endLine":604,"endCol":86}},{"id":"edge:2","index":2,"from":"n3","to":"n4","fromPort":"n3.0","toPort":"n4.1","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":605,"startCol":9,"endLine":605,"endCol":76}},{"id":"edge:3","index":3,"from":"n1","to":"n2","fromPort":"n1.1","toPort":"n2.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":606,"startCol":9,"endLine":606,"endCol":91}},{"id":"edge:4","index":4,"from":"n4","to":"n5","fromPort":"n4.2","toPort":"n5.0","kind":"connection","origin":{"file":"dev/sysml/WeaverExecution.sysml","startLine":607,"startCol":9,"endLine":607,"endCol":75}}]},"view":{"source":"docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2","title":"Commit a group. Gate every frame.","purpose":"workflow","kind":"routing","question":{"subjectRefs":["n4"],"ref":"q1","text":"How can a shared snapshot stay safe during revocation?","focusRefs":["model"]},"basis":{"captureRef":"docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2#design-view","modelRefs":["Project.sysml","dev/sysml/AdmissionReaderViews.sysml","dev/sysml/ArchitectureReaderViews.sysml","dev/sysml/ArchitectureViews.sysml","dev/sysml/AssuranceReaderViews.sysml","dev/sysml/AttemptReaderViews.sysml","dev/sysml/AuthorityReaderViews.sysml","dev/sysml/ControlActivation.sysml","dev/sysml/CorrespondenceReaderView.sysml","dev/sysml/ExecutionReaderViews.sysml","dev/sysml/FloorReaderViews.sysml","dev/sysml/GatewayArchitecture.sysml","dev/sysml/PolicyEvidenceDesign.sysml","dev/sysml/ProviderRpc.sysml","dev/sysml/ReaderDesigns.sysml","dev/sysml/ResearchReaderViews.sysml","dev/sysml/StoragePersistence.sysml","dev/sysml/StreamingExecution.sysml","dev/sysml/WeaverExecution.sysml","dev/sysml/ZeroTrustRefinement.sysml"],"obligationRefs":["proof0","proof1","proof2","proof3","proof4","proof5","proof6"],"evidenceRefs":[]}},"questions":[{"subjectRefs":["n4"],"ref":"q1","text":"How can a shared snapshot stay safe during revocation?","focusRefs":["model"]}],"references":{"model":"dev/sysml/WeaverExecution.sysml","model0":"Project.sysml","model1":"dev/sysml/AdmissionReaderViews.sysml","model10":"dev/sysml/FloorReaderViews.sysml","model11":"dev/sysml/GatewayArchitecture.sysml","model12":"dev/sysml/PolicyEvidenceDesign.sysml","model13":"dev/sysml/ProviderRpc.sysml","model14":"dev/sysml/ReaderDesigns.sysml","model15":"dev/sysml/ResearchReaderViews.sysml","model16":"dev/sysml/StoragePersistence.sysml","model17":"dev/sysml/StreamingExecution.sysml","model18":"dev/sysml/WeaverExecution.sysml","model19":"dev/sysml/ZeroTrustRefinement.sysml","model2":"dev/sysml/ArchitectureReaderViews.sysml","model3":"dev/sysml/ArchitectureViews.sysml","model4":"dev/sysml/AssuranceReaderViews.sysml","model5":"dev/sysml/AttemptReaderViews.sysml","model6":"dev/sysml/AuthorityReaderViews.sysml","model7":"dev/sysml/ControlActivation.sysml","model8":"dev/sysml/CorrespondenceReaderView.sysml","model9":"dev/sysml/ExecutionReaderViews.sysml","proof0":"dev/proofs/cedar/DomainMigrationComposition.lean","proof1":"dev/proofs/lean/ProviderAdmissionTurn.lean","proof2":"dev/proofs/lean/ProviderEgressWindow.lean","proof3":"dev/proofs/lean/ProviderLifecycleFootprint.lean","proof4":"dev/proofs/lean/ProviderReadCustody.lean","proof5":"dev/proofs/lean/ProviderSemanticProgress.lean","proof6":"dev/proofs/lean/ProviderSnapshotPublication.lean","sdkCapture":"dev/sysml/captures/WeaverViews-providerDeliveryJoin.json"},"sourceSHA256":{"dev/d2/themes/assurance.d2":"f7723f53e005a68c803a38ce5c04cd733f46f4a2688fa4b17c66f9d5b308fe24","dev/d2/themes/data.d2":"19fceb46186892da02b763217963cc3ca2a35021219c0d353fdeec84604ddaee","dev/d2/themes/flow.d2":"1f13588619d0c8087c08d8afd023c4c0efe12726711c311e623eea3872726c1f","dev/d2/themes/routing.d2":"f185df198e7435d12b17b7b57b62dfc5795597d95eb926159ee13b448727bcce","dev/d2/themes/sequence.d2":"6e39472720dccc717f984c95b79570494b6ce3828b86227629841649e6c956e6","dev/d2/themes/state.d2":"f1a35cbca0f9cbb055ea9f793ba3dfb86e5fee4e462038ef3e72b94baa61d781","dev/d2/themes/system.d2":"b2a32ec6959ca5df9103c16454c4e34b758e061f850f7de6b619bcbc5fcf17a6","dev/d2/themes/vocabulary.d2":"add21e9b87eab485e5daabf6316fea44eb56b1007b70123f24b0e32e3357f744","dev/proofs/cedar/DomainMigrationComposition.lean":"97c2564f79b3ad81b538d763e70727d4505995019d8a96d401bb738486b190e9","dev/proofs/cedar/QualifiedReview.lean":"1ae16e06ad03a2906fa8c21dbeea1e3eb7700aa1e9359e64848dec65ccfd079f","dev/proofs/cedar/WeaverPolicyBridge.lean":"a9628a8123d504a34f64bf986feb4471325aa2b0ddc603d76b62632481eab67b","dev/proofs/cedar/ZeroTrustEnrichment.lean":"0c4b138843cc176c27d42d4a31177a3c12486b2d8ff124a6453e3d0922170884","dev/proofs/lean/ProviderAdmissionTurn.lean":"9b30418066f14197ad601d0f439a7326c7940a5f67785353c37f2ac044801bf4","dev/proofs/lean/ProviderEgressWindow.lean":"c4a15b4ccd3a6474290b71374499087dba7dac7a1fda53f3a870100ec2e768a9","dev/proofs/lean/ProviderLifecycleFootprint.lean":"4786544c8a8193c5221bda2f7cd5cf20531bd1856d88b10ae29b280f223e307c","dev/proofs/lean/ProviderReadCustody.lean":"67e83773a1a063852e2303512d4b75b73cd3b9a90117972aafda9ee7348e6b77","dev/proofs/lean/ProviderRpc.lean":"e79d7639ac11220585e59e85dc5bec12b6717f7b51fb28fdcd62dc96d8fae38e","dev/proofs/lean/ProviderSemanticProgress.lean":"d32e010145a7dfcd646daeeeb4b08c0e852b9006bca404681af7e7fe10d0eaa0","dev/proofs/lean/ProviderSnapshotPublication.lean":"312c0380e334fbc5380815d882c6b5b0007747100f818becbee9c6784eeb5716","dev/proofs/lean/RuntimeAdmission.lean":"6111d4b9e93ebaa9f7cc44a55ed504c88c20c8d9de81e947a2e13b3f4a13b13c","dev/proofs/lean/SharedDomains.lean":"10eef67918986264689b09f0a6c0d53b314d7bf43b42f4b9652b403570beb58d","dev/proofs/lean/StreamingExecution.lean":"3fba798a7887a0b2ae29a7e3f0aaa3d7e2fb191e5f1f28109a4a73d28e27b776","dev/sysml/AdmissionReaderViews.sysml":"27ebc6c98ec3a1f7f9081e77a130953c3b646a1fdf6f1d6fc1fa6ed6376e9623","dev/sysml/ArchitectureReaderViews.sysml":"52ffbccbb17bd257e8ad9f4aa9f727c8ce0c00149e7d6738b82042ba06fdd0e3","dev/sysml/ArchitectureViews.sysml":"e5b5dbbd27acfba0bd5d5b52e45990b99471d88da0e814ec13fb7ab23d752d4b","dev/sysml/AssuranceReaderViews.sysml":"cd99fb7e9b23e08beac265bc832a8debee0dc1e1d318b0f64d5263519270e390","dev/sysml/AttemptReaderViews.sysml":"0d87cf71e15c26566422a6ddb5945fdb8add8af0484d9d024c32b97597675e21","dev/sysml/AuthorityReaderViews.sysml":"6fa25bd3a64e7f89987caec8e4773928be2cbea0a3c943299e536ca81978316d","dev/sysml/captures/WeaverAdmissionReaderViews-beneficiaryRegistration.json":"f36007a0698684ea5f2283bd17065f7d95e1dcd2bcc949ea68bf5c610810a3bc","dev/sysml/captures/WeaverAdmissionReaderViews-bootstrapInvitation.json":"ffef415d572d39a813e0072c5e20e0b3eeb1b8d3187cf784707e46ebbe1c58ec","dev/sysml/captures/WeaverAdmissionReaderViews-callerCustody.json":"8b910f8eb72f6556c9b0cf9f883000156953c3fa8d76f8968f8eb6b0ef2ba909","dev/sysml/captures/WeaverAdmissionReaderViews-custodyPublication.json":"9f658b008b9c79111be8cf52689419ba18b2c89f310a6fcb01e588ac5137e225","dev/sysml/captures/WeaverAdmissionReaderViews-enrollmentCredential.json":"873143a415443fd07ce1a6802344af6137d28824a6d6f9ad3a5886615fa621f6","dev/sysml/captures/WeaverAdmissionReaderViews-incarnationIssuance.json":"97f9f23bd48b48d93c01fb71c0f205a77d085ad26b8c838f89fafaf77ebd0ad3","dev/sysml/captures/WeaverAdmissionReaderViews-routineRouting.json":"e9e8b724864e39ad1e9f766efab2c2a7e879649975c71fa766708761fd8fb37f","dev/sysml/captures/WeaverAdmissionReaderViews-sourceCustody.json":"6e9aa869102cc878f131e6b405d84475da81b34cc27c1012ddb3e5c466d2a433","dev/sysml/captures/WeaverAdmissionReaderViews-sourceJoin.json":"e33f7b5e979570f70f7b6f6884c08d20a2038ecba0d1fc616cca466148656d8e","dev/sysml/captures/WeaverAdmissionReaderViews-subjectAuthority.json":"a5ab2c594694f704aacc076a2c30564ff9d57f022048fb5a29f48a9fb13081ef","dev/sysml/captures/WeaverArchitectureReaderViews-adapterBroker.json":"4926391e28c2f3cddbd17fcea7091fb753737cbedb62fd978be659e58f4a2966","dev/sysml/captures/WeaverArchitectureReaderViews-anchorBroker.json":"3ca3529f4294770a6cd99a5f782d5c41c8ab74e8e095eaa955df5d83b2e41aa9","dev/sysml/captures/WeaverArchitectureReaderViews-anchorEgress.json":"8bb022cbdfb6dc083d9a1dbb9a7af6803f88725df308e75188549015538c8bcc","dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json":"12cfa6bda4d8cf42bda9c0ef2dd85d3c622122aa2c95b7138bf2a72e799b8182","dev/sysml/captures/WeaverArchitectureReaderViews-codePolicy.json":"0a31e69f905bc2866609f4a44d906fcb0f8ee19444cccaaac82c481a44c6a163","dev/sysml/captures/WeaverArchitectureReaderViews-configPrefix.json":"c5e3ef30ad7dabc4f97388c9e7c9e918f894fb6932c19c7d2a1ead46d7cf7ba1","dev/sysml/captures/WeaverArchitectureReaderViews-driverCompletion.json":"3efb21fbf0195669c0bf8952c004dfb75fbf1289ac3e5dec4a2e83a6b2a965a7","dev/sysml/captures/WeaverArchitectureReaderViews-fencing.json":"524fd105fc93858f8b67466f476c6a82fd363889b208e7bf9b1be232211be926","dev/sysml/captures/WeaverArchitectureReaderViews-gatePersistence.json":"7ca4849c8e1f2769809d57e7f855f71caeace13cd2aec4fc752cbfd00cc9c477","dev/sysml/captures/WeaverArchitectureReaderViews-journalLifecycle.json":"94b245b915a17c8599267d1c6c0045de9347acaca59588823d688ffbec52698b","dev/sysml/captures/WeaverArchitectureReaderViews-logicalObservation.json":"72230a3f4e465af3bda275761bbe45ab0cbfcb47e318a1f025f23a68aad61ddc","dev/sysml/captures/WeaverArchitectureReaderViews-manifest.json":"380095511dce3ddfba8bea0c9842c8611e2f7b8e0542362f2a3789f98aae83c8","dev/sysml/captures/WeaverArchitectureReaderViews-migration.json":"45b00e3e077851860ace691c061a48f2e603e500eca4a5fb5ba3d3f1322fd3a2","dev/sysml/captures/WeaverArchitectureReaderViews-policyExecution.json":"7b3c387a065d86897987a1d38790c58c8aa6f5fb37c97693db27992a26cc4e99","dev/sysml/captures/WeaverArchitectureReaderViews-quorumPromises.json":"87a7b1d3764d18c0e935864bebf7f542b086e570e6671ce71d7bc492912f3904","dev/sysml/captures/WeaverArchitectureReaderViews-relationships.json":"9d6437dd78721b737331b0ab68eca8d4a36000150410374b3e6b39909f7efa7c","dev/sysml/captures/WeaverArchitectureReaderViews-settlementAnchor.json":"8de6da3519314c54e6fa99a65266e82829f4522d01620a96f1b5c42049a98713","dev/sysml/captures/WeaverArchitectureReaderViews-sharedBudget.json":"67235b2110acbaf97b82d8850df827479d47da3ae700b108905dc46933583d10","dev/sysml/captures/WeaverArchitectureReaderViews-sharedExposure.json":"a9395cf03fcdb4c82c5639afea251ea0de505fd10df8205fcac521caf70c5e13","dev/sysml/captures/WeaverArchitectureReaderViews-spentState.json":"819c6e97ab2ce794f707af23470b8182fa3fd22d1a1d91da69d4faa345df724f","dev/sysml/captures/WeaverArchitectureReaderViews-writerSettlement.json":"bbadd045af278fba72dfa2d8f207ea6740b93eaf6f6417e930f617ed76848eb6","dev/sysml/captures/WeaverArchitectureReaderViews-zeroAssurance.json":"6a8d4144076295353411f6ffa8ea4226dd507751b1edbd770f7a7197b3420cad","dev/sysml/captures/WeaverAssuranceReaderViews-brokerQueue.json":"054546ffda20c1beb2103280b8c6eb83fde8b9453ed9dfbd5c9a9925075a1262","dev/sysml/captures/WeaverAssuranceReaderViews-continuation.json":"3df6fefc7270013fe2f9e3ca104edab32502bd0d99491a5a371e5ce4ef32cfaf","dev/sysml/captures/WeaverAssuranceReaderViews-deviceEvidence.json":"6c831a12484bf38457d3b11c4df29794430288cb6576176e4647a4de81b1732e","dev/sysml/captures/WeaverAssuranceReaderViews-gatewayHead.json":"21fbadc94437eccabd6e9c4c5572136ff077bdb4caeaa6e7e7e13bf34892c2b2","dev/sysml/captures/WeaverAssuranceReaderViews-keySession.json":"caa295dcf3537655441cfb9851b76c5f1f1ca3b501b87728768176a16de95280","dev/sysml/captures/WeaverAssuranceReaderViews-rangeRecovery.json":"f6b56c7452abce37363e6bca34f6a135ae82dc19bfdba290c89e4ce840230e6b","dev/sysml/captures/WeaverAssuranceReaderViews-signer.json":"419b7a9f693c6817dd0b6b85db6dbdfab275c34d90ca546d1b65cbdfb129f87d","dev/sysml/captures/WeaverAttemptReaderViews-admission.json":"fa594beaa6f3ff601c9a79d9b2ab09da599d0b825172c8c4233575c79b289b63","dev/sysml/captures/WeaverAttemptReaderViews-outcome.json":"35240f053206a96eb6f15d71b9be0983907b95d58d863556b95e5460b1da8832","dev/sysml/captures/WeaverAuthorityReaderViews-attemptLedger.json":"df956a35a2786088f2be90c0d103fbb73526f8234513aea899a476faf2a23385","dev/sysml/captures/WeaverAuthorityReaderViews-canonical.json":"7e988c391575d5af5fe2eab27496dbcbbe97f71c060be0100cbd550cd6240563","dev/sysml/captures/WeaverAuthorityReaderViews-multiKey.json":"f8a9a873a73103da078c56624cae4c4eaf5717fcadb867fef13e7b6bd4c4ab76","dev/sysml/captures/WeaverAuthorityReaderViews-publication.json":"4e38e2b7b6ef99e93852288c5b878159bc95a70dd701dd052c4a6e1a4f13579e","dev/sysml/captures/WeaverAuthorityReaderViews-recoveryCAS.json":"f734aeac59f75bd3fdb8101e81c04556c0071156215b9c2c1c6b185e26a20d15","dev/sysml/captures/WeaverAuthorityReaderViews-scope.json":"031e6bb7db97b5fa454d91b80f358ceb77eb06ca38a659ed0e342f9eaf999494","dev/sysml/captures/WeaverCorrespondenceReaderView-correspondence.json":"cbe0b55284a21ccc94e90faa11bac8e9a3423fe6181379e73c0bbc88daddc771","dev/sysml/captures/WeaverExecutionReaderViews-accountCommit.json":"47bf75e02b2ffb4b76ecc2976f9e69efc54857f761b3b45060a4c327c4c86598","dev/sysml/captures/WeaverExecutionReaderViews-admissionFloor.json":"02a0847d39312dd0d5cece466f4cba429febfaf612662b5dada76dc288ec146e","dev/sysml/captures/WeaverExecutionReaderViews-appendHandoff.json":"6659f686bf021607a39d865fe1efedf1df6f2b90b13f49397472e5f287adb3bf","dev/sysml/captures/WeaverExecutionReaderViews-checkpoint.json":"895c7fd697490a69c0bb874241b08471afd04531a25f276f5d397b842b2f6f91","dev/sysml/captures/WeaverExecutionReaderViews-executionEvidence.json":"68d5914eef000eb6d9d059699d50f2e6626bf49733114cdd5d7c06404c133e75","dev/sysml/captures/WeaverExecutionReaderViews-executorOffer.json":"0b8b5144ed0d552214aac9d70431edcf14f5f7b0db1dbaf441a2d2e8cfa4e03b","dev/sysml/captures/WeaverExecutionReaderViews-joinEnqueue.json":"83e4342f4834fea5af3761b1a903af431d64bbcc171dd095913da0a622d576a2","dev/sysml/captures/WeaverExecutionReaderViews-manifestSwitch.json":"a9868da7d1b38f3d828a303bca6bb3c1536e526d98427fff852c49dfa9a5ce55","dev/sysml/captures/WeaverExecutionReaderViews-resultProjection.json":"3eb6bbd1bd79f38da926de49e82f98fda8c56fd2386032c7d07cc8db75245eba","dev/sysml/captures/WeaverExecutionReaderViews-walActivation.json":"04405fc492f392fb5db4969dee6301e68537ecf93508b74ad3894a9c08fdb519","dev/sysml/captures/WeaverFloorReaderViews-floorOrdering.json":"306e70722e44ea24c57aa8fc38bf07a51ac8d8480d99b0620bf7d688b86c423b","dev/sysml/captures/WeaverFloorReaderViews-floorRecovery.json":"6c5d02a6a2f7d721e2a3cea707a071767cde136f8a7df04fa1eb533d5333a322","dev/sysml/captures/WeaverResearchReaderViews-embeddedTooling.json":"af5fcdf8428d8e36486a846c0300e929be2c2089fb489cc4f05cb78d9b5d7ecd","dev/sysml/captures/WeaverResearchReaderViews-floorTransport.json":"d0c046f04d68953284e0e33fe1c35ff5bbd427553d4b7b30ad41fc65578bfb6d","dev/sysml/captures/WeaverResearchReaderViews-gerbilLifecycle.json":"20bbbd6a7db4b55e8ad5043a80b865d6855caa552078c9c2fae24ec6d8dee28b","dev/sysml/captures/WeaverResearchReaderViews-gxiLifecycle.json":"2988bce1c154a815fab710a2f5cef0bffb4dc293499b7c358d20b7d475689fcc","dev/sysml/captures/WeaverResearchReaderViews-parentReplay.json":"06c57dfa59b2f5da52eb90c49ecb02b26f28b2cbbb3fef0faabd57d10c16da15","dev/sysml/captures/WeaverResearchReaderViews-profileBinding.json":"ce69268f65f752a749fa4bef924c078a1a175d65dbd36bb158d98a45818327de","dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json":"4caa32079b2a58909d9331e4124073a959b62ae1bc0a3f57737071da975d146e","dev/sysml/captures/WeaverResearchReaderViews-runtimeAssets.json":"5c8611d19ed5902e77fdfe5c30297c485da9ac25bda57092566e1a93d72a2404","dev/sysml/captures/WeaverResearchReaderViews-semanticSlice.json":"053da32f5a59408316755a0e404d4b3804b72b1f74b2143744e8e803c87f472f","dev/sysml/captures/WeaverViews-architecture.json":"6693d3a73a34e668e5045a49fd73209756a65bb910ef0e92ba8a1865ddff34b5","dev/sysml/captures/WeaverViews-assurance.json":"32aefbca11ca410fe69cd34f73647852d0d60c5511fb9c772c14c8af8325b9db","dev/sysml/captures/WeaverViews-contractRefinement.json":"79696ae4b5c479127794a047484f2f8cb26dd15fd6bf8c65b592939254ceef92","dev/sysml/captures/WeaverViews-execution.json":"01a099cbe9e01a16d23a805f5700582f49cda3796f3f6ae0f3c70d51d62f56a3","dev/sysml/captures/WeaverViews-gateway.json":"d3193b75c98f2612313877701307774dad4a170250a3d4a8ccc7d513548ff631","dev/sysml/captures/WeaverViews-providerDeliveryJoin.json":"74fa1b5e5efbcdf87298b4bcf11c65d109fa9bd5042b1949ff5bd0951ef35989","dev/sysml/captures/WeaverViews-providerEgressWindow.json":"bbf55f9ccfe1034d5b120f0d1fb0ced1a37b3060d59bf71b412d62053a26fefd","dev/sysml/captures/WeaverViews-rangeRecovery.json":"50ca2b441431723d696cf1d5bc8d412bb5e39c9aa8a20622f8cb3c42c0c56f3e","dev/sysml/captures/WeaverViews-routeExecution.json":"6828fe1d359df8351af07d347ffdf1b2e9c3abc7d890c1ebbfb687c2584ab9cf","dev/sysml/captures/WeaverViews-routeSelection.json":"05c0db7e80b0acebc225a10550f44502fea5150722d2a980c4ad92baf37c7ebd","dev/sysml/captures/WeaverViews-storage.json":"fb7cf1791862581c32901d8ebdb3f2f826662afb99a77eba3d695b40bfa4fbe3","dev/sysml/captures/WeaverViews-streamAdmission.json":"4c7a94ce30323b7b388fe388d41752bda0971370f724163c2949c38ca1d80c8f","dev/sysml/captures/WeaverViews-zeroTrust.json":"fba4f4af30b9f23282a9ef7d0e8c44c1b2149bdbecdab7174188ab461fff17d4","dev/sysml/ControlActivation.sysml":"78bc6792c3a64ee54210720d3d88c1984b5c876d3a0647b6829bf904a811014f","dev/sysml/CorrespondenceReaderView.sysml":"24b811c00528feaab3547d5db3b7fada290ff89478ac2be0a1d252d8ea1e5828","dev/sysml/ExecutionReaderViews.sysml":"88f690ed1fed91f63f7571d14bf5d7c1c8d14ee3b8d1d17ae333dfd7a6176df3","dev/sysml/FloorReaderViews.sysml":"93401ba5b2009dd54614f7e5aff81d91a20085efbb77b3a143726ffdea16592c","dev/sysml/GatewayArchitecture.sysml":"dbec3964b7873ed0633964b05d1ba1ee828050aed35a3066858d0c38893f2642","dev/sysml/PolicyEvidenceDesign.sysml":"6a7d738b004be62e7412ea68080944f8cb6fb3aea785258efaefc2efc1c4e0e6","dev/sysml/ProviderRpc.sysml":"60a7ae2140742902a487dd29565d543591a1d080eeef37745241e142df101cc0","dev/sysml/ReaderDesigns.sysml":"4df8352980f9727b85a26533dc5ebfd67730540359d553a17d562574f3ea2529","dev/sysml/ResearchReaderViews.sysml":"cb10ed4ab79e911197834a8102e8a84986c567a358098e36d234d15b9c5acaec","dev/sysml/StoragePersistence.sysml":"b6b58b8802a557a7f3af787c2e7875be64865169ca3fd7e9973b13f6c3dc792d","dev/sysml/StreamingExecution.sysml":"d0d4d92300fba2b908ace30d9065cb2bac1d86f3b7c98219c1853a30f3110e85","dev/sysml/WeaverExecution.sysml":"e76e7c0c3995d880a12ed20935d34effc6e8c01e206367a690187970f432cea7","dev/sysml/ZeroTrustRefinement.sysml":"7cbec57110f03ed68469a1f49cb2046769516b09a6eb1b9433d866161bba6a82","docs/10-19-llm-gateway/10-routing-and-inference/10.02-llm-routing.d2":"513cad143cde846a9393bb5020dc4843caa1bb844204d3d0c13d1b5ada5efc70","docs/10-19-llm-gateway/10-routing-and-inference/10.05-route-execution.d2":"7c3ff8609c24983d0b27511756d8c5c04d0dc2cf5c973fc7012eaa0acda421e2","docs/10-19-llm-gateway/10-routing-and-inference/10.07-provider-egress-window.d2":"3c9c7c67296700d3b08cea62dddd5bdd011e7bafd61c2b4ecf1e38c32a94d6e7","docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2":"80b85a1f845c440259a93a52b33fae42f5373f985b6dd24d1fcef2c798e5ccf4","docs/10-19-llm-gateway/11-attempts-and-failover/11.02-attempt-ledger.d2":"5438329d7af60e9596b5fe4519b04a27a7c36ce1d1dc1aa5442db6df7167cd8e","docs/10-19-llm-gateway/12-semantic-contracts/12.02-semantic-contract.d2":"8560ac03652d2dfb8aeb7797c0e3b61031e49f9a3276d3207c8758a32037c530","docs/10-19-llm-gateway/13-authoritative-scope/13.02-authoritative-scope.d2":"e5950b420b85e30891bdb2264c7fad7ccd9ec9934b6175906d592d683b3a844c","docs/10-19-llm-gateway/14-registry-publication/14.02-registry-publication.d2":"9153743fc734fb044f94a4d22175fbe963f0f15f02598143dfbd7a06cd880177","docs/10-19-llm-gateway/15-recovery-cas/15.02-recovery-cas.d2":"c5de2f6cb52b0450361b2ed0523f647bdcad1fc43d410231f91ae86aee450859","docs/10-19-llm-gateway/16-policy-publication/16.02-policy-publication.d2":"4be00575666b7ada7185a30e553b42b9c36fe9109ce89df3d0dbb4b30ac10cab","docs/10-19-llm-gateway/17-policy-continuation/17.02-policy-continuation.d2":"4108a821aba5a2de1ffebc59b9e0d9180130bb3f598ac2130d59a83e8eca571f","docs/10-19-llm-gateway/18-canonical-registry/18.02-canonical-registry.d2":"f3b44cf54b006df34b528075bbc54742963a53e2afd4cbee435f81095b59b800","docs/10-19-llm-gateway/19-multi-key-registry/19.02-multi-key-registry.d2":"c44a2569dec8ae1fab46acb1ddd58f8b468e7ea7b11136c120a6bf2b042cf8b7","docs/20-29-execution-authority/20-result-projection/20.02-result-projection.d2":"696df32a9d705c6915bcc43a33616126cdce61ce5af0ae198c0dca5bc898d645","docs/20-29-execution-authority/21-join-enqueue/21.02-join-enqueue.d2":"430f46389111827b9f0ad5c9c3193366729fffe917ef18a5bfa0ec8238f6ab02","docs/20-29-execution-authority/22-executor-offer/22.02-executor-offer.d2":"0d93c13abcc1bd79afb32e6ae8a965cc5ec3b0c30fc1958f2f212e12b5e4b65a","docs/20-29-execution-authority/23-execution-reconciliation/23.02-execution-reconciliation.d2":"14c698ad47a243d46d788ab3494b1ad22ae7f14a163140eb6b4f5e8e071c6269","docs/20-29-execution-authority/24-account-commit/24.02-account-commit.d2":"10d6a5116d2c8be77ce7f27312d9d49ad832645c6748bb7bd68bb6942055990e","docs/20-29-execution-authority/25-wal-activation/25.02-wal-activation.d2":"9ebcd14701116e583157282a1678a6f1e0fe70e1ee4b9b7e038b520d4392ce05","docs/20-29-execution-authority/26-checkpoint-truncation/26.02-checkpoint-truncation.d2":"c5c1a35a16fe9b33029169b16d4c0af113f49e665eed0074ce524fc7a15bdb77","docs/20-29-execution-authority/27-manifest-switch/27.02-manifest-switch.d2":"c4de2ef519af25b2c41194df561860ad0236b0309b3178b388204c29cebf9f41","docs/20-29-execution-authority/28-append-handoff/28.02-append-handoff.d2":"f7646793e8540ec5f1e587d5e13deaf16d166180f80107ac8f9c904ea5c9372c","docs/20-29-execution-authority/29-admission-floor/29.02-admission-floor.d2":"0b9794f3d5fdfc7dcdbb519426eecf7e6ec6cb707de5017387c9aa47208ea385","docs/30-39-assurance/31-protected-signer/31.02-protected-signer.d2":"bc787086ae26a1a6cd56e51a2b4182c86e476f13e28ed1f5d80363b1d827e013","docs/30-39-assurance/32-key-boundary/32.02-key-boundary.d2":"1b616363aa68166988cc1d09404d637da406f048b9647676ec5f42d15f1762ca","docs/30-39-assurance/33-device-isolation/33.02-device-isolation.d2":"f4b086efce29484b70d4d4b2c04dad3887976d69187c25234e734e90260a6c7c","docs/30-39-assurance/34-floor-decision/34.02-floor-decision.d2":"78e2de9f044edb41944a56c1c8c8251a9cacd3470cf73c16b87f5ba100139a04","docs/30-39-assurance/34-floor-decision/34.04-floor-recovery.d2":"296d821eae11d4b77a552ae21d91eadcddcf032a15989dd35490128397044203","docs/30-39-assurance/35-intent-continuation/35.02-intent-continuation.d2":"08475ba17d7c98911a7db912041b669d049c75315c861322f72a5b50a471df55","docs/30-39-assurance/36-gateway-head-cas/36.02-gateway-head-cas.d2":"51669df10ec208197e690f656b962b259959af5f225243b62e5ff6bbea5637a5","docs/30-39-assurance/37-broker-consumption-queue/37.02-broker-consumption-queue.d2":"1ad636df3ba980d5f25b1a330c00c8b21f152958fe7c86617736e1b1f85a1ed8","docs/30-39-assurance/38-logical-range-recovery/38.02-logical-range-recovery.d2":"8ed5e1adc741da6852d027828993a83816cadb0c7bc1732bfaf121b2a64878d3","docs/40-49-admission-coordination/40-source-join/40.02-source-join.d2":"b8815cf59a1be49a4657b6ec3857d39e6d7d39ab4bb3ed44521c71ffe0ec5cee","docs/40-49-admission-coordination/41-source-custody/41.02-source-custody.d2":"feef18f62d537d4eb0659c0f1d719218df1a3eda506c9468b59423b151550bd7","docs/40-49-admission-coordination/42-custody-publication/42.02-custody-publication.d2":"24f019e8633cc816f7488e3f65384d2dea96ac8a3685714665a47bc6144b1e5c","docs/40-49-admission-coordination/43-caller-custody/43.02-caller-custody.d2":"6352167e4d3427fd9a66befb74fb3eebf91a127c5e82ecff8312b24178d5117f","docs/40-49-admission-coordination/44-incarnation-issuance/44.02-incarnation-issuance.d2":"215f52c84c9f41c36352f8b6da8b4670f1b375672cfc9efdf6a8bd1df95c946e","docs/40-49-admission-coordination/45-bootstrap-invitation/45.02-bootstrap-invitation.d2":"9e019de8289428a97580fe66ccefc6b9d0a43c1bac07433d2f29596f4d407401","docs/40-49-admission-coordination/46-beneficiary-registration/46.02-beneficiary-registration.d2":"322b848fdd67ea88c99b509cb5d913d7a5023e327edea51f16f44816356d81ce","docs/40-49-admission-coordination/47-enrollment-credential/47.02-enrollment-credential.d2":"ea0aa0bed915bea42d3d65c8f6572f799eb63d0aee1018b75803e61ef034d303","docs/40-49-admission-coordination/48-subject-authority/48.02-subject-authority.d2":"9f707fbc6e5ba8933a0e4d9d057f013c5764afc503f819288f628d3f9709f88d","docs/40-49-admission-coordination/49-routine-routing-config/49.02-routine-routing-config.d2":"7fa18b652ba97e8fe66f402a9a85d65740db9d3ffadff7890db7d72826c498b6","docs/50-59-research-program/51-qualified-semantic-slice/51.06-semantic-gateway-slice.d2":"d63df655a635fccac3c92eded92c039a3f079c24fa2b7a2fd0dc1f3fabd3c0f5","docs/50-59-research-program/52-committed-profile-binding/52.04-committed-profile.d2":"3ea30976830c607bf8cec62cbabc4291c384bd5f368049a45777f6f981d87d6e","docs/50-59-research-program/53-gerbil-exit/53.04-gerbil-lifecycle.d2":"b7b623664edc6e86efe62eeee7f5977dc207f0cb12e40cb6f0e77e38160695de","docs/50-59-research-program/54-dynamic-gxi-exit/54.04-dynamic-lifecycle.d2":"d4d410dd8cb10de6d3526b54ac7f96731d2f2a94dd9763aad96a0926608e251c","docs/50-59-research-program/55-dynamic-gxi-paired/55.04-runtime-boundary.d2":"573b248a6b7ce2d7eee1e70a469c54e4f195c4894ec7b0f61c8406fae843eccc","docs/50-59-research-program/56-gambit-image-closure/56.04-locator-boundary.d2":"0c45ee11d269b0cab8998c7fc3432ec851b9390b7530486225134b261d8d7de8","docs/50-59-research-program/57-runtime-implementation/57.03-runtime-boundary.d2":"193d22a5bd9e4b23260334d085df8aa5ec19c349f13cd9f56eaa26fe54f7e3ac","docs/50-59-research-program/58-streaming-execution/58.03-streaming-runtime.d2":"76ea49c83b4b36af1e775f80475d40747640b80a330434bf86635e255e84ef14","docs/50-59-research-program/58-streaming-execution/58.05-range-progress-recovery.d2":"aef20c8ad7d7420a65422add6d9fb635bdbe32e42e49427d3179bf20499ae4cd","docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2":"6f4e8218ea262e35efaebaf8cc2f96345b2ef1e7e9c1a6b12b68290dd99c683d","docs/50-59-research-program/59-provider-rpc/59.21-verification-ownership.d2":"e035ae7e56ee5e6498f131ed62f4792547c1e716aa5ed29865b333f54665e8f1","docs/50-59-research-program/59-provider-rpc/59.26-semantic-execution-ecosystem.d2":"50c091b094125693e2debe73599a63405849f1f55ab3658030674692c9334e14","docs/50-59-research-program/59-provider-rpc/59.30-governance-adapter-acceptance.d2":"88cbbd45e63358bb45a58fb27f85e275b9cc9fb3d3aee6af19eabed0912545d2","docs/50-59-research-program/59-provider-rpc/59.43-floor-transport-owner.d2":"36c4d6b561332ab30deb464a92bb4c2f02ceed5c8a1ca66617f72b6086b2c555","docs/50-59-research-program/59-provider-rpc/59.44-cloud-rpc-arrow-boundaries.d2":"fe0ac2220e04f6ccea851247ecf8ae1cab4ec8c8ba8744010c478992c233ebed","docs/50-59-research-program/59-provider-rpc/59.45-slow-consumer-zero-trust.d2":"e36cf58a239a2d9f0c99789bb7484de4e26180a8f941970540f72b530a79d813","docs/50-59-research-program/59-provider-rpc/59.46-functional-security-frameworks.d2":"e541b969352e8149e71e5b539988f9955b525e5e5ba3e7e7270bd4a98fbe19f5","docs/50-59-research-program/59-provider-rpc/59.47-property-testing-framework.d2":"f66ed065dcf955a233968ca295517c642be30dad9b24e23a781fe34e4bed45d9","docs/50-59-research-program/59-provider-rpc/59.49-policy-proposal-barrier.d2":"3a8559bb22f812075d9d7de4a397978995d06c32ed22e9415f990413551aebb6","docs/50-59-research-program/59-provider-rpc/59.50-parent-contract-and-replay.d2":"2db3983f56e938c927b68077551573c8e86362da892f47890459ab7b3f929c64","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-architecture.d2":"10e92e79b69f4b0813551dd2ddadc5ad225b7b0fa8374ed7015b7f2fe66bb6e1","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-contract-refinement.d2":"204c9e20d9027b7a38bf2a964da9a7cadb92744561fa9f1eb3fa29d00f4fa386","docs/50-59-research-program/59-provider-rpc/59.52-reviewed-publication-cas.d2":"4e0998e61717d5441e242cde0dfc52198312b67b63f0ce8b0425a423d1b88a24","docs/50-59-research-program/59-provider-rpc/59.53-artifact-registry-recovery.d2":"f7083a48413d41ad99e7191281bd6e74a92b33c7cc1f4f2f9ae322bb1405088a","docs/50-59-research-program/59-provider-rpc/59.54-source-incarnation-authority.d2":"1e55c0487f01d70462e8df6b46eff9e799b0dc592c0e780c759fa602e3d84444","docs/50-59-research-program/59-provider-rpc/59.55-evidence-reviewed-publication.d2":"c66435372642f7a93ca7fc6f78c2abcbc364a4dde447d10dcc4b2b21ccc06456","docs/50-59-research-program/59-provider-rpc/59.56-runtime-assets-and-authority-floor.d2":"c675469701bb6994fed1976d1e90d01dc1cc4e416a6788f865494fa3243d32c1","docs/50-59-research-program/59-provider-rpc/59.57-schema-bound-candidate-replay.d2":"5ca15af556e0a4ba5bdf1742cf81182ad72e7f51b2eb63352b839e068a7ad7d2","docs/50-59-research-program/59-provider-rpc/59.58-independent-source-recovery.d2":"4b21999b3554be15374448f36ffbccf517b32784a65cadde0f4c1eb8308da377","docs/50-59-research-program/59-provider-rpc/59.59-retained-root-and-recovery-coverage.d2":"37fdf1d3dd01f087434a6108b43a5657d7aecf79a2b9e60638d70eb0b1a4984b","docs/50-59-research-program/59-provider-rpc/59.60-persistent-source-key-custody.d2":"d27df3a14df5d57ad725c1455c82a4ab5bad45b78acea8cd1a76e59958b710eb","docs/50-59-research-program/59-provider-rpc/59.61-authority-bound-replay-pair.d2":"bd4962775564848a90ec49439301cf0cdfbaa4018956344e809f5b318bea6ccd","docs/50-59-research-program/59-provider-rpc/59.62-burn-exposure-recovery.d2":"fab4ea6d0981d75dd4c704f302268f3c5af0898e299e8e0fb38b34d07200b22c","docs/50-59-research-program/59-provider-rpc/59.63-mrr-admission-contract.d2":"ed3c604e0d350049f00528c7117675a7db751b3d6683719b03be116bcf49d5c5","docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.d2":"7164874fdbeec99f2185e1091f759466a68a3b7d9b239db6a503f16383fce50e","docs/50-59-research-program/59-provider-rpc/59.65-turso-concurrent-admission.d2":"0ade3ea326e2066ce908129e383b7e0f371a429710ed0a0bad30ddcfd61f034e","docs/50-59-research-program/59-provider-rpc/59.66-bounded-writer-reuse.d2":"9390a3c12f06c2f33e3df99088dc39de92d3bccc971ddf5a632910515a67623e","docs/50-59-research-program/59-provider-rpc/59.67-writer-owner-lifecycle.d2":"c28559ccf38b2f3320d84bbc0ffc6133e2708081e95bff39d5ed75d064287bde","docs/50-59-research-program/59-provider-rpc/59.69-hot-path-cost-boundaries.d2":"e5789625590fab63bc3635627b7e20ac41f64b8f40cbeee84d51a85f27ab31f1","docs/50-59-research-program/59-provider-rpc/59.75-complete-entry-and-output-contract.d2":"d667501bc15d6c31d986994f641d8d38f63c1d910784e6852e596c24c4e4c7c7","docs/50-59-research-program/59-provider-rpc/59.75-package-linkage.d2":"bc655ae71cc46e0d5b7f42637b78530f262c3142394485e2a9ba31f6516a0a10","docs/50-59-research-program/59-provider-rpc/59.76-embedded-tooling-and-darwin-io.d2":"87655d7c6d81c1ab203f886930f1630003e006c0edb71f90ac3ca23a0cb91845","docs/50-59-research-program/59-provider-rpc/59.77-mrr-turso-storage.d2":"72a4dceeb20cca337276f64537d47dbbd2ac0ce359a7a63997090e6476a40c96","docs/50-59-research-program/59-provider-rpc/59.84-quint-preparation-and-completion.d2":"17f485d7c541506c42003ebba887705ea61972f00c9498aa3c0d153a33b02922","docs/architecture/08-diagram-catalog.org":"353a4296584381207513468ef291e7e1aefdcd6f9f2b854c92be90aab47577ea","docs/architecture/diagrams/00a-readme-overview.d2":"1e6119c9d5b2d8a40d3bec0c8add35e8c078dd739e46fcf45c589b8125c7c46f","docs/architecture/diagrams/00c-gateway-runtime.d2":"c1d93cc1f635803872e3349c89b5127145bdcdd2b85e9a48f83d63f0bda439da","docs/architecture/diagrams/00d-zero-trust-overview.d2":"0d3d1a5de0967db2331b9be81468cee1b7cb1d1d98966c5e541e4fc24023f2e6","docs/architecture/diagrams/01-system-boundaries.d2":"69b4622c26b18a8518d46f79db8ce281c756a16f7f1a46977272086bf4dc38e0","docs/architecture/diagrams/01-system-relationships.d2":"dde40fac8667b79a070fda14ebd892f1f1e7c1217726595179b541c855f80c2c","docs/architecture/diagrams/02-admission-sequence.d2":"97077cb16cd4457fe14092caeb4bc8cf2912d434763a08fcf350cd6a4c2b2c74","docs/architecture/diagrams/03-attempt-state.d2":"e696fc0f1d63f58100405852e88e8a7dfb1a625e43be398f3bb54bbc1d90e13a","docs/architecture/diagrams/03a-attempt-observation.d2":"6b387ec7fbcff7d5e3e129bad7ea9590afe0324800a5a13bf7a89377ad86c387","docs/architecture/diagrams/04-consume-timeout.d2":"2ccfe8d033069e0d891531f3b5afef4febf21b2722209a612454d14321cac940","docs/architecture/diagrams/05-fencing-boundaries.d2":"1103ed75ac615b1a2f8239c0321d046a5a87acfa235d5042d8a529e23acd7483","docs/architecture/diagrams/06-source-admission.d2":"4d20817291c5de93b7f97366e6cb1b4af954f22de1ebcb3012c139a4b9dbd82c","docs/architecture/diagrams/07-post-claim-outcomes.d2":"63258620c15c2f52963dcdba33b4ac82cd12aadd1c2de005cd029655493493c1","docs/architecture/diagrams/08-code-as-policy.d2":"fc2263ff1ae000055e6054b89beee60f53b9621707510354c34ef45057889676","docs/architecture/diagrams/09-claim-wins-race.d2":"9eff775ddac29c47acd2c0b69fb1ff98ba9a20943da970c2804e270979555c41","docs/architecture/diagrams/10-commit-dispatch-sequence.d2":"fa5d56c49bc3f590c88cf7c3b63e180afd2d2a39fca878d1515917077ff1687a","docs/architecture/diagrams/11-zero-trust-assurance.d2":"ea93840da2ff4bdac59349f5ad7a56cee5506600283d0c364c53275dde0b5b48","docs/architecture/diagrams/12-execution-correspondence.d2":"1dd66ee8c517fd9c6f2f4b1700aeec3e620d699fbe9eeee20df8e05a7f1decb0","docs/architecture/diagrams/13-policy-to-execution.d2":"4bb05b74c3bc0ca997c5e5035ddc949fa374db3ff49bf2104a6c9753e12be3ef","docs/architecture/diagrams/14-adapter-broker-boundary.d2":"b855fa0482a5524226354b26bc8d7ecef0daf2ab1cab54c1783eba0ff29fab01","docs/architecture/diagrams/15-stream-message-authorization.d2":"cedf1c545a853ec2a9ae51bea928b04376d192f1a4c2af117fa54f475ad541e0","docs/architecture/diagrams/16-authoritative-spent-state.d2":"201bd9fe5eb6101543d939e3d83aca646e2b07c13ff1e3c56779571a0cd1172e","docs/architecture/diagrams/17-logical-message-observation.d2":"2333ad147295ead60ed6a92dc824cf6f5769f3828eff1e0cdf58e50aace7b1e1","docs/architecture/diagrams/18-shared-identity-budget.d2":"5ab4992fd8b6a6abf518fb0bbc8c2c8ad8b920d0be74a6e734d846319252ffa7","docs/architecture/diagrams/19-finite-domains-and-migration.d2":"b72b451d0bb97de46831e4b266d8fdd22d59e7d54db99446d53549f081a008e2","docs/architecture/diagrams/20-anchor-recovery-and-egress.d2":"9479271410f1bb57f92106a1d91ec73c73872568d9fcda55cac5aa64b89e5c9f","docs/architecture/diagrams/21-composed-journal-transport-lifecycle.d2":"0fffe555ee4c2c1222c97eebd24ca9b0df91a4d3ec118300ae3b88240004c3c8","docs/architecture/diagrams/22-finite-stream-manifest.d2":"60b33eb6d06aeaa1027546a1fc9d6c07069c3cd3c7d23df8ff8d63a341afe2ea","docs/architecture/diagrams/23-driver-completion-recovery.d2":"271963db2cd881bb82e164bb1544c7bcf311e1781f20170d858ccb65a596d8f5","docs/architecture/diagrams/24-writer-settlement-closure.d2":"ea1930326b0073e7fabd8b64ef3ffea781f1aef60db0d942f9ab14f1150296e9","docs/architecture/diagrams/25-settlement-anchor-recovery.d2":"8904bfcda525de21b48ea8f2db8d12aaa27e85818ccde43fb545851dc522ba3b","docs/architecture/diagrams/26-gate-consumption-persistence.d2":"42e676634ecb40cfb2dee06db1f5497d0e58c05f30097618c3852eb946992f0d","docs/architecture/diagrams/27-anchor-commit-broker-fencing.d2":"5c2ae36987b00655bbcdba36352e03b61765739ad2f3fc80a561ff0d325a9461","docs/architecture/diagrams/28-anchor-configuration-prefix.d2":"1ac0eeb3c76f5ae0ce3565d4469e50210786c3bc53c703a1a61d519dfa075512","docs/architecture/diagrams/29-quorum-durable-promises.d2":"2e4a24c3fae49e710d5afc31d4681a9efc8c2e8af3fa58a0957ede05fe7c0255","docs/architecture/diagrams/39-shared-execution-exposure.d2":"2c08f5b3d4531a7be2aadec8f1ff9d4476495418e94e84c1ff643583ac991ce4","docs/architecture/diagrams/assets/agent-request.svg":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","docs/architecture/diagrams/assets/bounded-write.svg":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","docs/architecture/diagrams/assets/budget-ledger.svg":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","docs/architecture/diagrams/assets/components/activity.svg":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","docs/architecture/diagrams/assets/components/book-open.svg":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","docs/architecture/diagrams/assets/components/bot.svg":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","docs/architecture/diagrams/assets/components/brain.svg":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","docs/architecture/diagrams/assets/components/circle-question-mark.svg":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","docs/architecture/diagrams/assets/components/clipboard-check.svg":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","docs/architecture/diagrams/assets/components/coins.svg":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","docs/architecture/diagrams/assets/components/database.svg":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","docs/architecture/diagrams/assets/components/file-check.svg":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","docs/architecture/diagrams/assets/components/fingerprint-pattern.svg":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","docs/architecture/diagrams/assets/components/message-square.svg":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","docs/architecture/diagrams/assets/components/rotate-ccw-clock.svg":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","docs/architecture/diagrams/assets/components/rotate-ccw.svg":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","docs/architecture/diagrams/assets/components/route.svg":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","docs/architecture/diagrams/assets/components/send.svg":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e","docs/architecture/diagrams/assets/components/shield-check.svg":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","docs/architecture/diagrams/assets/components/ticket-check.svg":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","docs/architecture/diagrams/assets/components/waves-horizontal.svg":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","docs/architecture/diagrams/assets/components/workflow.svg":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","docs/architecture/diagrams/assets/go.svg":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","docs/architecture/diagrams/assets/kubernetes.svg":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","docs/architecture/diagrams/assets/model-catalog.svg":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","docs/architecture/diagrams/assets/model-provider.svg":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","docs/architecture/diagrams/assets/permission-check.svg":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","docs/architecture/diagrams/assets/route-choice.svg":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","docs/architecture/diagrams/assets/rust.svg":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","docs/architecture/diagrams/assets/task-contract.svg":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","docs/architecture/diagrams/assets/unknown-hold.svg":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","Project.sysml":"c0c96eba7c5dbce2fde3c5c0f13353acfb1291eee59bcb8eb2ee1860f527aba4"},"rendered":{"observation":{"canvas":{"x":0,"y":0,"width":980,"height":686.21875},"subjects":[{"id":"n0","role":"default","x":40,"y":311,"width":278.65625,"height":122.59375},{"id":"n1","role":"default","x":350.65625,"y":311,"width":278.671875,"height":122.609375},{"id":"n2","role":"default","x":661.328125,"y":311,"width":278.65625,"height":122.59375},{"id":"n3","role":"default","x":40,"y":511.609375,"width":278.65625,"height":122.59375},{"id":"n4","role":"default","x":350.65625,"y":511.609375,"width":278.671875,"height":122.609375},{"id":"n5","role":"default","x":661.328125,"y":511.609375,"width":278.65625,"height":122.59375}],"relations":["edge:0","edge:1","edge:2","edge:3","edge:4"],"headings":[{"role":"title","x":32,"y":32,"width":916,"height":63},{"role":"question","x":32,"y":95,"width":916,"height":56},{"role":"note","x":32,"y":167,"width":916,"height":48},{"role":"note","x":32,"y":215,"width":916,"height":48}]},"readability":{"minimumTextSize":24.14725378787879,"samples":23},"bounds":{"objects":{"x":32,"y":291,"width":916,"height":363.21875}}}}Commit a group. Gate every frame.?How can a shared snapshot stay safe during revocation?One native outcome qualifies the group.Revocation closes delivery; unknown retains the hold. -Rust / closeRun edits / origin cutShared edits / shared cut +Rust / closeQueued request / no cutAccepted edit / close first diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.17-admission-turn.org b/docs/10-19-llm-gateway/10-routing-and-inference/10.17-admission-turn.org new file mode 100644 index 00000000..afc55891 --- /dev/null +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.17-admission-turn.org @@ -0,0 +1,321 @@ +# SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +# +# SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +#+title: 10.17 Provider admission turn and transport lifetime + +* Reading scope + +[[file:10.09-provider-delivery-join.svg]] + +An execution request waiting for a writer turn is not an accepted Policy or +OAuth change. Separating these lifetimes reduces avoidable interruption of an +already qualified response. It does not make source revocation asynchronous, +remove per-frame final-use checks, or turn uncertain sends into refundable work. +The companion [[file:10.12-read-custody.org][read custody design]] retains the +complete six-root read footprint and conflicting-writer FIFO. + +* Queue, close, commit and activate + +| Entry | Waiting state | Native mutation and activation | +|-------+---------------+--------------------------------| +| New provider request | No reservation, claim, accepted result or source intent | Obtain exclusive domain turn; recheck root discovery; close full footprint; begin transaction; fresh checks and original claim/reservation CAS; known commit activates the new image | +| Accepted source Policy, OAuth or witness intent | Immediate pending barrier, including while waiting | Existing close/commit/activate protocol; late publication or confirmation cannot resurrect an old permit | +| Domain migration or unclassified write | Immediate closure | Full native scope and current generation; no new reduced footprint | +| Certified origin lifecycle or range progress | Existing compatible read custody | Existing origin-only or preserved invalidation, with real shared reads | +| WAL profile | Existing eager global closure | Existing global writer and recovery protocol | + +Only the provider admission module constructs the sealed =AdmissionRequest=. +An arbitrary caller cannot request delayed closure for a Policy change. Domain +keys discovered before waiting are hints: the selected writer must compare the +scheduler generation and re-read roots when necessary, before closing and +starting SQL. A migration mismatch rejects the request without granting send +power. The source transaction still checks pending publication, OAuth witness, +current Cedar, original task/claim, history and shared exposure. + +Cancellation while unaccepted removes a request without releasing any budget: +there was no new reservation. Known rollback restores the prior image. Unknown +commit seals the affected authority and retains the original reservation. +After restart a known queued operation that has never consumed invocation may +resume under its original identity and digest. A consumed invocation, partial +request write, or uncertain send cannot be retried through a new operation, +provider, model or SDK retry. + +* Transport lifetime + +| Stage | Guard ownership | Diagnostic | +|-------+-----------------+------------| +| Immutable request preparation and credential refresh | Before deciding invocation scope; no network request capability | Separate from native service | +| TCP connection and TLS handshake | Inside the current invocation guard | Attempted/completed state and monotonic elapsed time, including dropped futures | +| HTTP handshake and request write/seal | Inside the same guard | Request-seal elapsed time | +| Response-header wait | After writer seal and the native outcome protocol | Header elapsed time, independent of TCP/TLS/write | +| Streaming response | Existing bounded range preparation, commit and final receiver gate | Per-scope wait/hold/closed time; exact owner/cut/cursor at Tonic | + +Transport timing has no settlement authority. An unattempted stage or failed +handshake is not a no-execution certificate. Timing is collected locally and +emitted by the test owner after the deciding operation, not by doing diagnostic +I/O inside the writer guard. No connection pooling, off-guard connection grant, +new transport retry or changed TLS trust root is introduced by this change. + +* Models and implementation obligations + +=ProviderAdmissionTurn.lean= proves that arbitrary finite unaccepted queues +preserve the exact actual image, any requirement on that image and final-offer +enabledness. It separately proves that open writers cannot mutate and that +accepted hard intents, changed images and unknown outcomes block final offer. +Its service-versus-queue arithmetic is conditional accounting, not an operating +system latency bound or an unconditional liveness theorem. + +=DomainMigrationComposition.queued_admission_preserves_spec_final_use= composes +with the existing cedar-poo-spec Gateway.ZeroTrust final-use theorem on the +same actual state. It retains original profile refinement, finite per-message +affinity and every account capacity. The Host still owns projection fidelity, +complete write mediation, durable recovery and the actual final transport +handoff; this theorem is not a verified SQL or Rust refinement. + +=ProviderAdmissionTurn.qnt= exercises the early-closure blocking counterexample, +mutation before close, native known commit, hard pending barriers, cancellation, +rollback, lost outcomes, owner restart and current refresh. Its finite state +space and sampled schedules do not establish unbounded fairness. + +The Rust native PBT holds an actual same-domain native lifecycle scope while a +second admission registers a conflicting ticket. The old frame remains usable +only under selected closure; original holds/claims/history survive rejection or +cancellation. Go/TLS tests additionally pause before native scheduling and at +native admission commit boundaries, kill the process, lose the commit response, +restart and retry the original SDK operation. The pre-scheduling pause is not +reported as a registered scheduler ticket; the native PBT covers that boundary. + +* Performance admission + +Keep the frozen pair: one release image, MVCC, four streams per wave, thirteen +frames per stream, 128 completed streams per arm, shared/disjoint roots and +none-injected/controlled pressure. Alternate arm order. The early barrier is a +test-only control; selected closure is the MVCC provider default. Report all +frames, receipts, original reservations and provider invocation counts. + +Measure scheduler residence, native scope hold and authority-closed lifetime +separately. In the early control closure includes ticket waiting; in the selected +arm it starts after the writer grant and root recheck. Do not subtract unrelated +P99 values, omit revalidation scopes, relabel a closed-loop wave as open-loop +capacity, or interpret none-injected load as a certified idle host. + +The ready-frame target remains below one millisecond. Source-pending intervals, +provider waits, socket backpressure and native admission service must remain +visible rather than disappear through a new timestamp. Throughput, tails and +low-background eligibility require measured evidence in the specified envelope. +No dependency pin or Scheme runtime is changed here. + +* Go control-plane measurement boundary + +=BenchmarkProviderGoControlPair= activates both arms through the existing Go +bootstrap and reviewed publication RPCs. Four task owners each declare 32 +original nodes, within the existing one-task bundle and 64-plan bounds. The +publication identity is shared, not replaced per owner. Direct Rust ingress +and Go routing/relay ingress then execute the same four-way, 128-operation +workload against separate stores using the same Rust image. Protobuf single +rows and Arrow four-row batches are separate, fixed cohorts. + +For the shared cohort, existing whole-domain migration binds the four roots +before measurement. Capacity remains the minimum of the original capacities; +each original root starts with the common total bound, without increasing it +during migration. Every receipt and the total original held/history projection +are checked after the timed waves. The Go binary uses its normal optimized +build in benchmarks; functional Go control tests retain the race instrument. + +Report cold owner activation as four individual samples, not a P99 from four +observations. Report warm request latency, receive/decode cost and complete +streams per second for each ingress arm. Do not subtract their P99 values as a +causal estimate of relay time. This additional fixture uses configured provider +API credentials and the existing synthetic independent review fixture; it is +not a production WIF or SPEC Delta-producer qualification. Existing dual-hop +OAuth, real SPEC review and recovery acceptance remain separate gates. + +The initial four-owner fixture exposed retained bootstrap source connections: +the fixed Rust source listener admits four connections, and the independent +source observer plus four static Go owners exhausted that capacity. The fourth +owner timed out at the unchanged fifteen-second readiness bound. The fix is in +Go deployment ownership: after known activation, a Gateway with no runtime +source reader closes its bootstrap-only connection before serving ingress. +Deferred current-catalog selection retains the source connection. Failure +cleanup still closes sockets; it neither activates ingress nor resolves an +unknown publication outcome. No connection limit or deadline is increased. + +Lean distinguishes permission to serve without source custody from error-path +socket cleanup. Quint checks that unknown activation cannot serve even after +cleanup, and that runtime catalog selection cannot lose its source channel +while serving. The real four-process test requires the closure phase marker, +then executes both independent and migrated shared-domain streams; existing +runtime catalog and lost-publication/restart tests remain required controls. + +* Measured acceptance and remaining performance gates + +The functional acceptance passed 38 Go/TLS test groups with the race detector, +130 ledger integration/property tests, 29 broker tests and 27 server tests. The +three ignored server fixtures were launched through real Go integration paths. +The additional bounded-wait native admission property passed after its cleanup +bound was made explicit. Standard Go package/race tests passed on the owned +source image. Positive SPEC proof closure passed with 70 modules and 3,980 +reported theorems; the twelve new local theorem audits report no axioms. The +Quint suite passed nineteen named tests and 2,000 sampled eighty-step schedules. +The selected Library figure passed Chromium checks at 830 CSS pixels with the +existing 18 px, five-second and thirty-second gates. + +The first admission recovery test incorrectly expected a missing operation to +return =NotFound=. The existing Inspect RPC maps missing operations to +=FailedPrecondition=. The corrected test requires that exact contract, an +independent committed row count of zero, zero held/history projections and zero +provider invocations. The failed run is retained; no production denial was +reclassified as successful execution. + +Within each complete matrix, all arms use the same optimized Rust test image +and normal Go control binary, with current machine concurrency (twelve CPUs). Preparation and +compilation are outside samples. Each ten-cohort matrix completed 2,560 original +operations, 54,784 transport frames and 59,392 normalized events, with exact +provider counts, receipts and retained reservations checked. No backup call or +automatic redispatch is permitted. + +** Frozen thirteen-frame admission pair + +Values below are P99 milliseconds except throughput. =None injected= describes +the benchmark pressure switch, not a certified idle host. + +| Roots / pressure | Closed interval: early / selected | Queue-to-Go: early / selected | Complete/s: early / selected | +|------------------+-----------------------------------+-------------------------------+-----------------------------| +| Shared / none injected | 10.50 / 4.342 | 0.977 / 0.808 | 94.27 / 95.78 | +| Shared / controlled | 25.97 / 8.416 | 5.852 / 3.288 | 58.98 / 66.27 | +| Disjoint / none injected | 24.82 / 17.81 | 2.634 / 4.621 | 105.0 / 96.84 | +| Disjoint / controlled | 5.404 / 10.69 | 2.823 / 3.120 | 102.9 / 105.8 | + +There were no receiver requalifications in this wave-shaped cohort. It does not +by itself demonstrate how later admissions interrupt an already active stream. +Closure duration is measured from that scope's actual close entry through scope +completion, including queue residence in the early control. Its known-success +samples do not bound the lifetime of a sealed unknown outcome. + +** Admission while an old stream is active + +The additional cohort uses sixty-four frames per operation. After the old +stream's first received frame, three new requests become offered without any +fault pause or synthetic commit result. Both arms retain the same real native +FIFO, TLS, source evidence and final per-frame cursor gate. + +| Pressure | Closed interval: early / selected | Queue-to-Go: early / selected | Receiver renewals: early / selected | Complete/s: early / selected | +|----------+-----------------------------------+-------------------------------+------------------------------------+-----------------------------| +| None injected | 14.85 / 9.549 | 4.526 / 4.042 | 21 / 20 | 31.84 / 31.82 | +| Controlled | 26.87 / 11.10 | 9.951 / 8.555 | 27 / 27 | 20.43 / 20.62 | + +An initial measurement rejected seventeen preparation/queue groups because it +assumed =ceil(64 / 4) = 16= was an exact count. The source =collect_buffered= +coalesces only already buffered events; an input boundary may yield a short +group. The additional cohort now checks equal observed preparation/queue counts +within the existing four-frame maximum's bounds, retains every renewal scope, +and reports the actual counts (17.00 groups per stream in both final arms). +The original thirteen-frame exact-count gates are unchanged. The failed +seventeen-group observation remains in the cache evidence. + +With no injected pressure, selected closure measured 740 microseconds from +acknowledgment to Tonic at aggregate P99, while its final owner turn was much +shorter. Its queue-to-Go P99 still exceeded four milliseconds. Under pressure, +the final owner turn was 16.04 microseconds, but acknowledgment-to-Tonic was +4.684 milliseconds and Tonic-to-Go was 3.968 milliseconds at their respective +P99s. These are different distributions and cannot be added or subtracted to +reconstruct another percentile. Required renewals remained tens of milliseconds +within their small subset and were not removed from the overall frame cohort. + +** Actual Go routing/relay path + +Both arms activate through Go; the direct arm then calls Rust ingress and the +relay arm calls Go ingress. Each has four task owners and 128 original nodes, +so its growing shared history differs from the fresh per-wave domains above. + +| Roots / encoding | Queue-to-client P99 ms: direct / Go | Complete/s: direct / Go | +|------------------+------------------------------------+------------------------| +| Disjoint / Protobuf one row | 4.136 / 6.238 | 81.51 / 86.31 | +| Disjoint / Arrow four rows | 4.993 / 3.530 | 94.11 / 93.84 | +| Shared / Protobuf one row | 2.809 / 4.850 | 54.04 / 55.73 | +| Shared / Arrow four rows | 6.461 / 5.925 | 62.52 / 58.24 | + +Frame observations retain all per-family stream groups. They are joined by +wave only because this fixture permits one in-flight node per family and waits +for its EOF before the next wave. A generic concurrent same-family stream must +use an explicit operation identity rather than infer this ordering. + +** Promotion boundary and next architecture work + +The general sub-millisecond performance gate remains open. The first matrix +had one passing frozen queue-to-Go cohort; the final matrix below has more +passing cohorts but retains pressure and disjoint-Protobuf failures. Run-to-run +variation prohibits a universal latency or throughput improvement claim. +Host samples around the first pair showed roughly 59--66 percent idle CPU, +with an unrelated Gerbil process and desktop load present. This is not the +requested qualified low-background envelope. No external process was stopped. + +The next work must separate three mechanisms before changing authority: + +1. Keep actual history-domain size, offered admission rate and stream length in + the workload model. The current =domains/evidence.rs= reconciliation path enumerates + budget/history origins, verifies member exposure and reads retained history; + its work grows with the domain rather than only with the current range. + Replacing that reconciliation with an authoritative projection requires an + inductive commit/recovery invariant covering every writer and unknown result. +2. Separate a ready receiver's scheduling/transport-credit delay from its short + final authority turn and from mandatory renewal. Neither Arrow batching nor + moving a timer boundary establishes a faster last handoff. +3. Qualify the same image in a measured quiet-host envelope and a bounded offered + load. The frozen wave is not an open-loop capacity test. Preserve all failed, + canceled, timed-out and unknown operations in the admitted workload. + +No fast profile is promoted by these measurements. TCP/TLS remains guarded, +accepted Policy/OAuth intents retain their immediate barrier, and unknown +reservations remain held. Evidence and failure logs live under the ignored +=.cache/provider-admission-turn/= directory, not in tracked proof directories. + +Admission now has its own =admit= trace phase: one admission and four other +fixed scopes retain the original five-scope base. All authority intent handles +report a span; preserved progress does not itself close a reader. The dedicated +admission-closed metric selects the actual admission phase rather than inferring +it from an exclusive scheduler lease. Earlier raw logs used an aggregate closed +label for intent spans; the tables above use the single genuine admission +barrier in each stream, not that aggregate. + +** Final complete matrix after diagnostic phase clarification + +The whole matrix was repeated after separating =admit= from the other four +fixed phases and correcting intent-span naming. Authorization logic, workloads, +limits and dependency pins were not weakened. The second matrix's image is +identical across its ten cohorts; the first matrix remains retained as a +separate image/reference, not merged into a favorable percentile population. +Both accepted matrices together account for 5,120 original operations, 109,568 +transport frames and 118,784 normalized events, excluding the failed shape audit. + +| Native cohort | Admission barrier P99 ms: early / selected | Queue-to-Go P99 ms: early / selected | Complete/s: early / selected | +|---------------+--------------------------------------------+------------------------------------+-----------------------------| +| 13 frames / shared / none injected | 9.533 / 2.735 | 0.520 / 0.497 | 102.9 / 104.4 | +| 13 frames / shared / controlled | 10.74 / 5.343 | 2.372 / 2.834 | 79.79 / 77.39 | +| 13 frames / disjoint / none injected | 3.907 / 2.845 | 0.531 / 0.553 | 148.8 / 149.8 | +| 13 frames / disjoint / controlled | 7.989 / 4.731 | 2.370 / 3.261 | 109.7 / 108.8 | +| 64 frames / later admissions / none injected | 8.579 / 2.756 | 0.848 / 0.548 | 37.84 / 37.67 | +| 64 frames / later admissions / controlled | 12.92 / 4.805 | 6.669 / 4.096 | 28.42 / 28.14 | + +In the sixty-four-frame pair, renewal counts were 18/13 without injected +pressure and 33/22 under pressure. Selected final-owner-turn P99 was 9.208 and +12.42 microseconds respectively. Renewal-subset acknowledgment-to-Tonic P99 was +9.507 and 16.084 milliseconds; aggregate frame P99 does not erase those slower +but necessary current-view decisions. Actual preparation/queue groups remained +17.00 per stream in both arms. + +| Go routing cohort | Queue-to-client P99 ms: direct / Go | Complete/s: direct / Go | +|-------------------+------------------------------------+------------------------| +| Disjoint / Protobuf one row | 3.215 / 4.438 | 129.1 / 117.3 | +| Disjoint / Arrow four rows | 0.555 / 0.698 | 179.0 / 179.7 | +| Shared / Protobuf one row | 0.594 / 0.832 | 71.60 / 71.43 | +| Shared / Arrow four rows | 0.598 / 0.887 | 103.1 / 103.1 | + +The final pre-run host samples reported 84.69--85.56 percent idle CPU; later +post-run samples reported 61.40--65.98 percent idle. Those boundary samples are +not a sustained quiet-host or offered-load certificate. The large improvement +between whole matrices is not attributed to renaming diagnostics. Report both +runs, the remaining reversals, pressure cases and mandatory renewal subset. +P0/P1 implementation and functional verification are accepted locally; broad +P2 latency promotion remains unaccepted and the PR remains a draft. diff --git a/go/dev/provider_admission_overlap_bench_test.go b/go/dev/provider_admission_overlap_bench_test.go new file mode 100644 index 00000000..fdbc9d89 --- /dev/null +++ b/go/dev/provider_admission_overlap_bench_test.go @@ -0,0 +1,75 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build integration && !windows + +package dev + +import ( + "context" + "fmt" + "testing" + "time" + + pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" + v1 "github.com/HardenedLinux/weaver/go/api/v1" +) + +// This is an additional cohort, not a replacement for the frozen 13-frame pair. +// Three admissions become offered only after the first old frame is received. +// Native scheduling, TLS, currentness and commits remain real and unpaused. +func BenchmarkProviderAdmissionOverlap(b *testing.B) { + image := wifImage(b, true) + comparison := deliveryComparison{staggered: true, labels: [2]string{"early-close", "selected-close"}, controls: [2][]string{{"WEAVER_TEST_EARLY_ADMISSION_BARRIER=1"}, nil}} + for _, loaded := range []bool{false, true} { + b.Run(fmt.Sprintf("shared=true/pressure=%t/ranges=64", loaded), func(b *testing.B) { benchmarkProviderDeliveryComparison(b, image, true, loaded, comparison) }) + } +} + +func measureAdmissionOverlapWave(b *testing.B, f *fixture, plans []v1.ProviderPlan, ranges int) ([]domainStreamSample, time.Duration) { + b.Helper() + ctx, cancel := context.WithTimeout(b.Context(), 12*time.Second) + defer cancel() + first := make(chan struct{}) + type result struct { + sample domainStreamSample + events int + err error + } + results := make(chan result, len(plans)) + began := time.Now() + for i, plan := range plans { + go func() { + if i != 0 { + select { + case <-first: + case <-ctx.Done(): + results <- result{err: ctx.Err()} + return + } + } + at := time.Now() + var onFirst func() + if i == 0 { + onFirst = func() { close(first) } + } + n, timing, err := readDomainProgramStreamObserved(ctx, f.client, plan, pb.Encoding_PROTOBUF, 1, onFirst) + if err == nil && timing.frames != ranges { + err = fmt.Errorf("missing overlap frames: %d", timing.frames) + } + results <- result{domainStreamSample{family: plan.Family, latency: time.Since(at), transport: timing}, n, err} + }() + } + var streams []domainStreamSample + for range plans { + r := <-results + if r.err != nil || r.events != ranges { + b.Fatal("actual admission overlap did not complete", r.events, r.err) + } + streams = append(streams, r.sample) + } + wall := time.Since(began) + verifyDomainProgramWave(b, ctx, f, plans, ranges, true) + return streams, wall +} diff --git a/go/dev/provider_admission_turn_test.go b/go/dev/provider_admission_turn_test.go new file mode 100644 index 00000000..bcd77291 --- /dev/null +++ b/go/dev/provider_admission_turn_test.go @@ -0,0 +1,255 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build integration && !windows + +package dev + +import ( + "context" + "math/rand" + "sync/atomic" + "testing" + "testing/quick" + "time" + + pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func TestProviderAdmissionTurnGate(t *testing.T) { + for _, mode := range []string{"early", "selected", "revoke"} { + t.Run(mode, func(t *testing.T) { checkAdmissionTurn(t, mode) }) + } +} +func TestProviderAdmissionTurnProperty(t *testing.T) { + property := func(early, revoke bool) bool { + mode := "selected" + if early { + mode = "early" + } + if revoke { + mode = "revoke" + } + checkAdmissionTurn(t, mode) + return true + } + if err := quick.Check(property, &quick.Config{MaxCount: 4, Rand: rand.New(rand.NewSource(293))}); err != nil { + t.Fatal(err) + } +} +func checkAdmissionTurn(t *testing.T, mode string) { + t.Helper() + controller := observeCommit(t) + env := []string{"WEAVER_STORAGE_JOURNAL=mvcc", "WEAVER_TEST_COMMIT_SOCKET=" + controller.path, + "WEAVER_TEST_COMMIT_CUT=admission-queued", "WEAVER_TEST_ADMISSION_FAMILY=right", "WEAVER_TEST_RECEIVER_PAUSE=1"} + if mode == "early" { + env = append(env, "WEAVER_TEST_EARLY_ADMISSION_BARRIER=1") + } + f := fixtureWithInvocation(t, burstProviderSSE(13), false, observedServer(t), + []string{"--exact", "provider_commit_tests::serve_observed_gateway", "--ignored", "--nocapture"}, env) + ctx, cancel := context.WithTimeout(t.Context(), 12*time.Second) + defer cancel() + controller.await(t, ctx, "Boot", 0) + plans := boundProviderPlans(t, f, 8) + first := make(chan struct{}, 1) + leftDone := make(chan error, 1) + rightDone := make(chan error, 1) + var rows atomic.Int64 + go func() { + _, err := f.client.Execute(ctx, plans[0], pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { + if rows.Add(1) == 1 { + first <- struct{}{} + } + return nil + }) + leftDone <- err + }() + receiver := controller.await(t, ctx, "BeforeReceiverHandoff", 0) + go func() { + _, err := f.client.Execute(ctx, plans[1], pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }) + rightDone <- err + }() + waiting := controller.await(t, ctx, "BeforeAdmissionSchedule", 1) + view, err := f.admin.RPC.InspectExecutionDomains(f.admin.Context(ctx), &pb.OperationKey{Family: "left"}) + if err != nil || view.GetHeld() != 4 || view.GetHistoryCount() != 1 { + t.Fatal("unaccepted request changed shared evidence", view, err) + } + if mode == "revoke" { + parent := uint64(1) + r, err := f.admin.RPC.PublishAuthority(f.admin.Context(ctx), &pb.PublishRequest{OperationId: "revoke-queued-admission", ExpectedRevision: &parent, Fence: 3, Policy: "forbid(principal,action,resource);", Schema: f.schema}) + if err != nil || r.GetOutcome() != pb.PublicationOutcome_COMMITTED { + t.Fatal("hard source change", r, err) + } + } + resumeCommit(t, receiver, 'c') + if mode == "selected" { + select { + case <-first: + case <-time.After(300 * time.Millisecond): + t.Fatal("unaccepted request blocked a qualified old frame") + } + if f.primary.Load() != 1 { + t.Fatal("new request called a provider before admission") + } + } else { + select { + case <-first: + t.Fatal("closed or revoked frame escaped") + case <-time.After(40 * time.Millisecond): + } + } + resumeCommit(t, waiting, 'c') + left, right := <-leftDone, <-rightDone + if mode == "revoke" { + if left == nil || right == nil || rows.Load() != 0 || f.primary.Load() != 1 { + t.Fatal("revocation crossed final use", left, right, rows.Load(), f.primary.Load()) + } + } else if left != nil || right != nil || rows.Load() != 13 || f.primary.Load() != 2 { + t.Fatal("authorized streams failed", left, right, rows.Load(), f.primary.Load()) + } + f.stop(t) + f.start(t) + marker := 1 + held, history, calls := uint64(4), uint64(1), int64(1) + if mode != "revoke" { + marker = 2 + held = 8 + history = 2 + calls = 2 + } + controller.await(t, ctx, "Boot", marker) + view, err = f.admin.RPC.InspectExecutionDomains(f.admin.Context(ctx), &pb.OperationKey{Family: "left"}) + if err != nil || view.GetHeld() != held || view.GetHistoryCount() != history { + t.Fatal("restart changed original exposure", view, err) + } + for i, plan := range plans { + retry := make(chan error, 1) + go func() { + _, err := f.client.Execute(ctx, plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }) + retry <- err + }() + if i == 1 { + pause := controller.await(t, ctx, "BeforeAdmissionSchedule", marker) + resumeCommit(t, pause, 'c') + } + if err := <-retry; err == nil { + t.Fatal("SDK retry reopened an original claim") + } + } + if f.primary.Load() != calls || f.backup.Load() != 0 { + t.Fatal("restart duplicated/substituted execution") + } + f.stop(t) +} + +func TestProviderAdmissionCommitRecovery(t *testing.T) { + for _, journal := range []string{"wal", "mvcc"} { + for _, mode := range []string{"control", "rollback-before", "crash-before", "lost-after", "crash-after"} { + t.Run(journal+"/"+mode, func(t *testing.T) { checkAdmissionRecovery(t, journal, mode) }) + } + } +} +func checkAdmissionRecovery(t *testing.T, journal, mode string) { + t.Helper() + before := mode == "rollback-before" || mode == "crash-before" + cut, phase, marker := "admission-after", "AfterAdmissionCommit", 1 + if before { + cut, phase, marker = "admission-before", "BeforeAdmissionCommit", 0 + } + controller := observeCommit(t) + f := fixtureWithInvocation(t, completeSSE, false, observedServer(t), + []string{"--exact", "provider_commit_tests::serve_observed_gateway", "--ignored", "--nocapture"}, + []string{"WEAVER_STORAGE_JOURNAL=" + journal, "WEAVER_TEST_COMMIT_SOCKET=" + controller.path, "WEAVER_TEST_COMMIT_CUT=" + cut}) + ctx, cancel := context.WithTimeout(t.Context(), 12*time.Second) + defer cancel() + controller.await(t, ctx, "Boot", 0) + done := make(chan error, 1) + go func() { + _, err := f.client.Execute(ctx, f.plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }) + done <- err + }() + event := controller.await(t, ctx, phase, marker) + switch mode { + case "control": + resumeCommit(t, event, 'c') + case "rollback-before": + resumeCommit(t, event, 'r') + case "lost-after": + resumeCommit(t, event, 'l') + default: + if err := f.child.Process.Kill(); err != nil { + t.Fatal(err) + } + select { + case <-f.exited: + case <-ctx.Done(): + t.Fatal("injected crash did not finish") + } + f.child = nil + f.client.Connection.Close() + f.admin.Connection.Close() + event.socket.Close() + } + err := <-done + if (err == nil) != (mode == "control") { + t.Fatal("unexpected admission result", mode, err) + } + if f.child != nil { + assertNoFaultWorkerUnwind(t, f) + f.stop(t) + } + f.start(t) + controller.await(t, ctx, "Boot", marker) + key := &pb.OperationKey{Family: f.plan.Family, Node: f.plan.Node} + receipt, err := f.client.RPC.Inspect(f.client.Context(ctx), key) + if before { + if status.Code(err) != codes.FailedPrecondition { + t.Fatal("missing original operation did not follow the Inspect contract", receipt, err) + } + view, viewErr := f.admin.RPC.InspectExecutionDomains(f.admin.Context(ctx), &pb.OperationKey{Family: f.plan.Family}) + if viewErr != nil || view.GetHeld() != 0 || view.GetHistoryCount() != 0 || f.primary.Load() != 0 { + t.Fatal("uncommitted admission left a hold, history or invocation", view, viewErr) + } + } else if err != nil || receipt.GetHeld() != 4 || receipt.GetState() != map[bool]string{true: "complete", false: "queued"}[mode == "control"] { + t.Fatal("admission outcome or original hold lost", receipt, err) + } + if mode != "control" { + // No invoke consumption exists yet: resume exactly the original queued + // operation, retaining its digest and reservation, rather than a new key. + if before { + retry := make(chan error, 1) + go func() { + _, err := f.client.Execute(ctx, f.plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }) + retry <- err + }() + pause := controller.await(t, ctx, phase, 0) + resumeCommit(t, pause, 'c') + if err := <-retry; err != nil { + t.Fatal("known absent original did not resume", err) + } + } else { + // Idempotent enqueue still commits its existing plan once. Confirm + // that exact after-commit cut before permitting the first invoke. + retry := make(chan error, 1) + go func() { + _, err := f.client.Execute(ctx, f.plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }) + retry <- err + }() + pause := controller.await(t, ctx, phase, 1) + resumeCommit(t, pause, 'c') + if err := <-retry; err != nil { + t.Fatal("queued original did not resume", err) + } + } + } + if f.primary.Load() != 1 || f.backup.Load() != 0 || inspect(t, f).Held != 4 { + t.Fatal("recovery duplicated send or released original hold") + } + if _, err := f.client.Execute(ctx, f.plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }); err == nil { + t.Fatal("completed original replayed") + } + f.stop(t) +} diff --git a/go/dev/provider_backpressure_test.go b/go/dev/provider_backpressure_test.go index 79571549..37c1378e 100644 --- a/go/dev/provider_backpressure_test.go +++ b/go/dev/provider_backpressure_test.go @@ -46,7 +46,15 @@ func observedServer(t testing.TB) string { var stderr bytes.Buffer cmd.Stderr = &stderr var err error - observedBuild.binary, err = buildCargoExecutable(cmd, cargoTarget{Name: "weaver_server", Kind: "lib", Test: true}) + built, err := buildCargoExecutable(cmd, cargoTarget{Name: "weaver_server", Kind: "lib", Test: true}) + if err == nil { + observedBuild.binary = filepath.Join(filepath.Dir(serverBinary), "weaver-observed") + var digest string + digest, err = publishProviderImage(built, observedBuild.binary) + if err == nil { + t.Logf("observed provider image sha256=%s", digest) + } + } if err != nil { observedBuild.err = fmt.Errorf("observed test build: %w: %s", err, stderr.String()) } diff --git a/go/dev/provider_control_bench_test.go b/go/dev/provider_control_bench_test.go new file mode 100644 index 00000000..739381c8 --- /dev/null +++ b/go/dev/provider_control_bench_test.go @@ -0,0 +1,286 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build integration && !windows + +package dev + +import ( + "context" + "fmt" + "os" + "path/filepath" + "strings" + "testing" + "time" + + pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" + v1 "github.com/HardenedLinux/weaver/go/api/v1" + "github.com/HardenedLinux/weaver/go/internal/config" +) + +type controlFrameSample struct { + family string + wave int + received map[uint64]int64 +} +type controlBenchArm struct { + frames []controlFrameSample + + f *fixture + control [4]*controlProcess + plans [4][]v1.ProviderPlan + activation []time.Duration + latency, recv, decode []time.Duration + wall time.Duration +} + +// Four independently bootstrapped task owners each expose 32 distinct original +// nodes. Both arms activate through Go; only the measured request path differs. +// Cold activation stays separate from the 128 warm, exactly-once operations. +func BenchmarkProviderGoControlPair(b *testing.B) { + image := wifImage(b, true) + for _, shared := range []bool{false, true} { + for _, encoding := range []pb.Encoding{pb.Encoding_PROTOBUF, pb.Encoding_ARROW_IPC} { + rows := uint32(1) + if encoding == pb.Encoding_ARROW_IPC { + rows = 4 + } + b.Run(fmt.Sprintf("shared=%t/encoding=%s/rows=%d", shared, encoding, rows), func(b *testing.B) { + b.StopTimer() + var arms [2]*controlBenchArm + for i := range arms { + arms[i] = newControlBenchArm(b, image, 32*b.N, shared) + } + b.StartTimer() + for wave := range 32 * b.N { + for _, i := range []int{wave % 2, 1 - wave%2} { + arm := arms[i] + began := time.Now() + type result struct { + owner int + events int + transport domainStreamTransport + latency time.Duration + err error + } + results := make(chan result, 4) + start := make(chan struct{}) + for owner := range 4 { + go func() { + client := arm.f.client + if i == 1 { + client = arm.control[owner].client + } + ctx, cancel := context.WithTimeout(b.Context(), 12*time.Second) + defer cancel() + <-start + at := time.Now() + n, timing, err := readDomainProgramStreamWithClient(ctx, client, arm.plans[owner][wave], encoding, rows) + results <- result{owner, n, timing, time.Since(at), err} + }() + } + close(start) + for range 4 { + r := <-results + if r.err != nil || r.events != 13 || r.transport.frames != (13+int(rows)-1)/int(rows) { + b.Fatalf("control stream completion: %+v", r) + } + arm.frames = append(arm.frames, controlFrameSample{arm.plans[r.owner][wave].Family, wave, r.transport.received}) + arm.latency = append(arm.latency, r.latency) + arm.recv = append(arm.recv, r.transport.recv) + arm.decode = append(arm.decode, r.transport.decode) + } + arm.wall += time.Since(began) + } + } + b.StopTimer() + b.ReportMetric(0, "ns/op") + for i, label := range []string{"direct-rust", "go-control"} { + arm := arms[i] + verifyControlBenchArm(b, arm, shared) + b.ReportMetric(float64(len(arm.latency))/arm.wall.Seconds(), label+"-complete/s") + b.ReportMetric(tailMillis(arm.latency, 99), label+"-stream-p99-ms") + b.ReportMetric(tailMillis(controlFrameLatencies(b, arm), 99), label+"-rust-queue-to-client-p99-ms/frame") + b.ReportMetric(tailMillis(arm.recv, 99), label+"-grpc-recv-p99-ms/stream") + b.ReportMetric(tailMillis(arm.decode, 99), label+"-decode-p99-ms/stream") + for j, duration := range arm.activation { + b.ReportMetric(float64(duration.Nanoseconds())/1e6, fmt.Sprintf("%s-cold-owner%d-ms", label, j)) + } + for _, owner := range arm.control { + owner.stop(b) + } + arm.f.stop(b) + } + }) + } + } +} + +func newControlBenchArm(t testing.TB, image string, nodes int, shared bool) *controlBenchArm { + t.Helper() + if nodes > 64 { + t.Fatal("frozen control benchmark supports at most 64 nodes per task; use -benchtime=1x") + } + f := providerFixture(t, burstProviderSSE(13), false, image, []string{"--exact", "grpc_config::serve_wif_gateway", "--ignored", "--nocapture"}, []string{"WEAVER_STORAGE_JOURNAL=mvcc", "WEAVER_TEST_PROVIDER_SCOPE_TRACE=1"}, providerProfile(), nil, nil) + arm := &controlBenchArm{f: f} + families := []string{"controlbench-0", "controlbench-1", "controlbench-2", "controlbench-3"} + parent := uint64(0) + policy := f.policy + ` +permit(principal == Weaver::Principal::"alice", action in [Weaver::Action::"admitProvider", Weaver::Action::"invokeProvider", Weaver::Action::"emitProvider"], resource) +when { ["controlbench-0","controlbench-1","controlbench-2","controlbench-3"].contains(context.family) && context.profile == "p" && context.model == "model-a" && context.profile_digest != "" && context.protocol == "openai.chat-text-sse.v1" && context.output_token_limit <= 4096 && context.message_count <= 64 && context.sequence < 4096 && ["protobuf","arrow"].contains(context.format) };` + publication := v1.Publication{OperationID: "control-benchmark-activation", ExpectedRevision: &parent, Fence: 2, Policy: policy, Schema: f.schema} + for i, family := range families { + first := f.plan + first.Family, first.Node, first.Revision, first.Fence = family, "node-0", 1, 2 + task := profileTask(t, first, *providerProfile()) + task.Budget = uint64(16 * nodes) + plans := []v1.ProviderPlan{first} + for j := 1; j < nodes; j++ { + plan := first + plan.Node = fmt.Sprintf("node-%d", j) + digest, err := plan.Digest() + if err != nil { + t.Fatal(err) + } + task.Nodes = append(task.Nodes, plan.Node) + task.BodyDigests[plan.Node] = task.BodyDigests[first.Node] + task.StreamContracts[plan.Node] = digest + task.NodeCostBounds[plan.Node] = 4 + plans = append(plans, plan) + } + bundle := config.Bundle{Governance: config.Governance{Schema: "agentic-ai-lab.loop-governor.v1", Family: family, OpenNodes: task.Nodes}, Tasks: []v1.Task{task}, Plans: plans, Publication: publication} + if err := bundle.Validate(); err != nil { + t.Fatal(err) + } + path := writeControlBundle(t, f, bundle, "json") + owner := newControlProcess(t, f, path) + at := time.Now() + owner.start(t) + startupLog, err := os.ReadFile(filepath.Join(owner.directory, "control.log")) + if err != nil || !strings.Contains(string(startupLog), "phase=bootstrap-source-channel-closed") { + t.Fatal("static Go owner retained bootstrap source custody", err) + } + arm.activation = append(arm.activation, time.Since(at)) + arm.control[i] = owner + arm.plans[i] = plans + } + if shared { + ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second) + defer cancel() + for _, from := range families[1:] { + view, err := f.admin.RPC.InspectExecutionDomains(f.admin.Context(ctx), &pb.OperationKey{Family: families[0]}) + if err != nil { + t.Fatal(err) + } + stamp := view.GetStamp() + receipt, err := f.admin.RPC.MigrateExecutionDomains(f.admin.Context(ctx), &pb.DomainMigration{OperationId: "benchmark-union-" + from, BudgetFrom: from, BudgetTo: stamp.GetBudgetRoot(), HistoryFrom: from, HistoryTo: stamp.GetHistoryRoot(), BudgetFromEpoch: 1, BudgetToEpoch: stamp.GetBudgetEpoch(), HistoryFromEpoch: 1, HistoryToEpoch: stamp.GetHistoryEpoch()}) + if err != nil || !receipt.GetCommitted() { + t.Fatal("benchmark shared domain binding", receipt, err) + } + } + } + return arm +} +func verifyControlBenchArm(t testing.TB, arm *controlBenchArm, shared bool) { + t.Helper() + ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second) + defer cancel() + total := 0 + for _, plans := range arm.plans { + for _, plan := range plans { + receipt, err := arm.f.client.RPC.Inspect(arm.f.client.Context(ctx), &pb.OperationKey{Family: plan.Family, Node: plan.Node}) + digest, digestErr := plan.Digest() + if err != nil || digestErr != nil || receipt.GetState() != "complete" || receipt.GetEvents() != 13 || receipt.GetDigest() != digest || receipt.GetReserved() != 4 || receipt.GetHeld() != uint64(4*len(plans)) || receipt.GetTarget() != "primary" { + t.Fatal("control benchmark original receipt", receipt, err, digestErr) + } + total++ + } + count := uint64(len(plans)) + if shared { + count *= 4 + } + view, err := arm.f.admin.RPC.InspectExecutionDomains(arm.f.admin.Context(ctx), &pb.OperationKey{Family: plans[0].Family}) + if err != nil || view.GetHeld() != 4*count || view.GetHistoryCount() != count { + t.Fatal("control benchmark shared exposure", view, err) + } + } + if arm.f.primary.Load() != int64(total) || arm.f.backup.Load() != 0 || arm.f.denied.Load() != 0 { + t.Fatal("control benchmark duplicated/substituted provider invocation") + } +} + +func TestProviderGoControlMeasuredChain(t *testing.T) { + image := filepath.Join(t.TempDir(), "weaver-control-chain") + if _, err := publishProviderImage(observedServer(t), image); err != nil { + t.Fatal(err) + } + for _, shared := range []bool{false, true} { + t.Run(fmt.Sprintf("shared=%t", shared), func(t *testing.T) { + arm := newControlBenchArm(t, image, 2, shared) + for wave := range 2 { + for owner := range 4 { + ctx, cancel := context.WithTimeout(t.Context(), 12*time.Second) + n, timing, err := readDomainProgramStreamWithClient(ctx, arm.control[owner].client, arm.plans[owner][wave], pb.Encoding_ARROW_IPC, 4) + arm.frames = append(arm.frames, controlFrameSample{arm.plans[owner][wave].Family, wave, timing.received}) + cancel() + if err != nil || n != 13 || timing.frames != 4 { + t.Fatal("real Go routing / Rust streaming chain", n, timing, err) + } + } + } + verifyControlBenchArm(t, arm, shared) + controlFrameLatencies(t, arm) + for _, owner := range arm.control { + owner.stop(t) + } + arm.f.stop(t) + }) + } +} + +func controlFrameLatencies(t testing.TB, arm *controlBenchArm) []time.Duration { + t.Helper() + groups := providerHandoffGroups(t, arm.f) + if len(groups) != len(arm.plans) { + t.Fatal("missing native handoff family") + } + total := 0 + for _, plans := range arm.plans { + if len(groups[plans[0].Family]) != len(plans) { + t.Fatal("missing or duplicate native handoff group") + } + total += len(plans) + } + if len(arm.frames) != total { + t.Fatal("missing received stream observation") + } + var latencies []time.Duration + seen := map[string]map[int]bool{} + for _, stream := range arm.frames { + rows := groups[stream.family] + if stream.wave < 0 || stream.wave >= len(rows) { + t.Fatal("foreign handoff ordinal") + } + if seen[stream.family] == nil { + seen[stream.family] = map[int]bool{} + } + if seen[stream.family][stream.wave] { + t.Fatal("duplicate received stream") + } + seen[stream.family][stream.wave] = true + stamps := rows[stream.wave] + if len(stamps) != len(stream.received) { + t.Fatal("missing native or client frame") + } + for sequence, received := range stream.received { + staged, ok := stamps[sequence] + if !ok || received < staged { + t.Fatal("unjoinable native queue to client observation") + } + latencies = append(latencies, time.Duration(received-staged)) + } + } + return latencies +} diff --git a/go/dev/provider_delivery_bench_test.go b/go/dev/provider_delivery_bench_test.go index b48b2722..8912265f 100644 --- a/go/dev/provider_delivery_bench_test.go +++ b/go/dev/provider_delivery_bench_test.go @@ -39,9 +39,10 @@ func benchmarkProviderDeliveryJoin(b *testing.B, image string, shared, loaded bo } type deliveryComparison struct { - labels [2]string - controls [2][]string - queues [2]int + staggered bool + labels [2]string + controls [2][]string + queues [2]int } func BenchmarkProviderLifecycleFootprint(b *testing.B) { @@ -66,10 +67,27 @@ func BenchmarkProviderReadCustody(b *testing.B) { } } +func BenchmarkProviderAdmissionTurn(b *testing.B) { + image := wifImage(b, true) + comparison := deliveryComparison{labels: [2]string{"early-close", "selected-close"}, + controls: [2][]string{{"WEAVER_TEST_EARLY_ADMISSION_BARRIER=1"}, nil}, queues: [2]int{4, 4}} + for _, shared := range []bool{true, false} { + for _, loaded := range []bool{false, true} { + b.Run(fmt.Sprintf("shared=%t/pressure=%t", shared, loaded), func(b *testing.B) { + benchmarkProviderDeliveryComparison(b, image, shared, loaded, comparison) + }) + } + } +} + func benchmarkProviderDeliveryComparison(b *testing.B, image string, shared, loaded bool, comparison deliveryComparison) { b.Helper() b.StopTimer() - const ranges, parallel, samples = 13, 4, 128 + const parallel, samples = 4, 128 + ranges := 13 + if comparison.staggered { + ranges = 64 + } var arms [2]providerTailArm for i := range arms { env := []string{"WEAVER_STORAGE_JOURNAL=mvcc", "WEAVER_TEST_PROVIDER_TAIL=1", "WEAVER_TEST_PROVIDER_SCOPE_TRACE=1"} @@ -85,7 +103,13 @@ func benchmarkProviderDeliveryComparison(b *testing.B, image string, shared, loa for _, i := range []int{wave % 2, 1 - wave%2} { arm := &arms[i] plans := registerDomainProgramWave(b, arm.fixture, wave, parallel, shared) - streams, wall := measureDomainProgramWave(b, arm.fixture, plans, ranges, shared) + var streams []domainStreamSample + var wall time.Duration + if comparison.staggered { + streams, wall = measureAdmissionOverlapWave(b, arm.fixture, plans, ranges) + } else { + streams, wall = measureDomainProgramWave(b, arm.fixture, plans, ranges, shared) + } arm.streams = append(arm.streams, streams...) arm.wall += wall } @@ -99,8 +123,16 @@ func benchmarkProviderDeliveryComparison(b *testing.B, image string, shared, loa for i, label := range comparison.labels { arm := &arms[i] reportProviderTailArm(b, arm, label) + reportProviderTransport(b, arm, label) queues := comparison.queues[i] - reportScheduledEncoding(b, arm, label, ranges, (ranges+3)/4, queues, shared) + if comparison.staggered { + queues = 0 + } + preparations := (ranges + 3) / 4 + if comparison.staggered { + preparations = 0 + } + reportScheduledEncoding(b, arm, label, ranges, preparations, queues, shared) reportDeliveryJoin(b, arm, label) arm.fixture.stop(b) } diff --git a/go/dev/provider_delivery_join_test.go b/go/dev/provider_delivery_join_test.go index c017f0ad..e6f7abea 100644 --- a/go/dev/provider_delivery_join_test.go +++ b/go/dev/provider_delivery_join_test.go @@ -290,7 +290,7 @@ func TestProviderSemanticProgressProperty(t *testing.T) { for _, scope := range readRangeScopes(t, f)[f.plan.Family] { counts[scope.phase]++ } - if counts["prepare"] < ((rows+3)/4) || counts["prepare"] > rows || counts["queue"] != counts["prepare"] || counts["revalidate"] != 0 || counts["other"] != 5 { + if counts["prepare"] < ((rows+3)/4) || counts["prepare"] > rows || counts["queue"] != counts["prepare"] || counts["revalidate"] != 0 || counts["other"] != 4 || counts["admit"] != 1 { t.Fatal("native decisions did not match exact opportunistic manifests", counts, rows) } } diff --git a/go/dev/provider_domain_program_test.go b/go/dev/provider_domain_program_test.go index 0ea4be61..ee4de8aa 100644 --- a/go/dev/provider_domain_program_test.go +++ b/go/dev/provider_domain_program_test.go @@ -200,6 +200,12 @@ func measureDomainEncodingWave(b *testing.B, f *fixture, plans []v1.ProviderPlan latencies = append(latencies, r.domainStreamSample) } wall := time.Since(began) + verifyDomainProgramWave(b, ctx, f, plans, ranges, shared) + return latencies, wall +} + +func verifyDomainProgramWave(b testing.TB, ctx context.Context, f *fixture, plans []v1.ProviderPlan, ranges int, shared bool) { + b.Helper() // Inspect uses its own bounded observation lane. Verify all receipts // sequentially after the timed stream calls have reached EOF. for _, plan := range plans { @@ -221,7 +227,6 @@ func measureDomainEncodingWave(b *testing.B, f *fixture, plans []v1.ProviderPlan b.Fatalf("benchmark hold/history mismatch: %v %v", view, err) } } - return latencies, wall } type domainStreamTransport struct { @@ -231,8 +236,16 @@ type domainStreamTransport struct { } func readDomainProgramStream(ctx context.Context, f *fixture, plan v1.ProviderPlan, encoding pb.Encoding, rows uint32) (int, domainStreamTransport, error) { + return readDomainProgramStreamWithClient(ctx, f.client, plan, encoding, rows) +} + +func readDomainProgramStreamWithClient(ctx context.Context, client *gatewayclient.Client, plan v1.ProviderPlan, encoding pb.Encoding, rows uint32) (int, domainStreamTransport, error) { + return readDomainProgramStreamObserved(ctx, client, plan, encoding, rows, nil) +} + +func readDomainProgramStreamObserved(ctx context.Context, client *gatewayclient.Client, plan v1.ProviderPlan, encoding pb.Encoding, rows uint32, onFirst func()) (int, domainStreamTransport, error) { timing := domainStreamTransport{received: make(map[uint64]int64)} - stream, err := f.client.RPC.ExecuteProvider(f.client.Context(ctx), &pb.ProviderRequest{ + stream, err := client.RPC.ExecuteProvider(client.Context(ctx), &pb.ProviderRequest{ Plan: gatewayclient.Plan(plan), Encoding: encoding, BatchRows: rows, }) if err != nil { @@ -263,6 +276,9 @@ func readDomainProgramStream(ctx context.Context, f *fixture, plan v1.ProviderPl return next, timing, fmt.Errorf("invalid benchmark frame at %d", next) } timing.received[events[0].GetSequence()] = received.UnixNano() + if next == 0 && onFirst != nil { + onFirst() + } for _, event := range events { if done || event.GetSequence() != uint64(next) { return next, timing, fmt.Errorf("invalid benchmark event at %d", next) diff --git a/go/dev/provider_fixture_test.go b/go/dev/provider_fixture_test.go index c954d1ee..3b52e0ad 100644 --- a/go/dev/provider_fixture_test.go +++ b/go/dev/provider_fixture_test.go @@ -86,7 +86,12 @@ func TestMain(m *testing.M) { } fmt.Fprintf(os.Stderr, "test-owned provider image sha256=%s profile=%s\n", digest, profile) controlBinary = filepath.Join(directory, "weaver-control") - controlBuild := exec.Command(filepath.Join(runtime.GOROOT(), "bin/go"), "-C", "go", "build", "-race", "-o", controlBinary, "./cmd/weaver-control") + controlArgs := []string{"-C", "go", "build", "-mod=readonly"} + if benchmark == "" { + controlArgs = append(controlArgs, "-race") + } + controlArgs = append(controlArgs, "-o", controlBinary, "./cmd/weaver-control") + controlBuild := exec.Command(filepath.Join(runtime.GOROOT(), "bin/go"), controlArgs...) controlBuild.Dir, controlBuild.Stdout, controlBuild.Stderr = repo, os.Stderr, os.Stderr if err := controlBuild.Run(); err != nil { os.RemoveAll(directory) diff --git a/go/dev/provider_range_scopes_test.go b/go/dev/provider_range_scopes_test.go index 15f7fd52..d3b2a608 100644 --- a/go/dev/provider_range_scopes_test.go +++ b/go/dev/provider_range_scopes_test.go @@ -25,6 +25,7 @@ type rangeScopeSample struct { family string arrival, grant uint64 wait, hold time.Duration + authoritySpan time.Duration } func BenchmarkProviderSharedRangeScopes(b *testing.B) { @@ -67,7 +68,7 @@ func parseRangeScopes(log string) (map[string][]rangeScopeSample, error) { } for _, field := range fields[2:] { parts := strings.Split(field, ":") - if len(parts) != 6 || (parts[5] != "origin" && parts[5] != "exclusive") || (parts[0] != "prepare" && parts[0] != "queue" && parts[0] != "other" && parts[0] != "revalidate") { + if len(parts) != 7 || (parts[5] != "origin" && parts[5] != "exclusive") || (parts[0] != "admit" && parts[0] != "prepare" && parts[0] != "queue" && parts[0] != "other" && parts[0] != "revalidate") { return nil, fmt.Errorf("invalid stripe sample: %q", field) } var n [4]uint64 @@ -77,12 +78,16 @@ func parseRangeScopes(log string) (map[string][]rangeScopeSample, error) { return nil, fmt.Errorf("invalid stripe sample value: %q", value) } } + span, err := strconv.ParseInt(parts[6], 10, 64) + if err != nil || span < 0 { + return nil, fmt.Errorf("invalid authority span: %q", field) + } previous := result[family] if n[0] == 0 || n[0] >= n[1] || seen[n[0]] || seen[n[1]] || (len(previous) > 0 && n[0] <= previous[len(previous)-1].grant) { return nil, fmt.Errorf("invalid or duplicate stripe ordinal: %q", field) } seen[n[0]], seen[n[1]] = true, true - result[family] = append(result[family], rangeScopeSample{originWrite: parts[5] == "origin", phase: parts[0], family: family, arrival: n[0], grant: n[1], wait: time.Duration(n[2]), hold: time.Duration(n[3])}) + result[family] = append(result[family], rangeScopeSample{authoritySpan: time.Duration(span), originWrite: parts[5] == "origin", phase: parts[0], family: family, arrival: n[0], grant: n[1], wait: time.Duration(n[2]), hold: time.Duration(n[3])}) } finished[family] = final == "1" } @@ -106,7 +111,7 @@ func TestProviderScopeTraceChunksPreserveAllRecords(t *testing.T) { } fmt.Fprintf(&log, "weaver-provider-scope f %d:%d", start, final) for i := start; i < end; i++ { - fmt.Fprintf(&log, " revalidate:%d:%d:1:1:origin", 2*i+1, 2*i+2) + fmt.Fprintf(&log, " revalidate:%d:%d:1:1:origin:1", 2*i+1, 2*i+2) } log.WriteByte('\n') } @@ -216,11 +221,11 @@ func reportProviderRangeScopes(b *testing.B, arm *providerTailArm, name string, var wait time.Duration for _, scope := range trace { counts[scope.phase]++ - if scope.phase != "other" { + if scope.phase != "other" && scope.phase != "admit" { wait += scope.wait } } - if counts["prepare"] != ranges || counts["queue"] != ranges || counts["other"] != 5 { + if counts["prepare"] != ranges || counts["queue"] != ranges || counts["other"] != 4 || counts["admit"] != 1 { b.Fatalf("%s unexpected range scope counts for %s: %v", name, stream.family, counts) } waves[wave] = append(waves[wave], trace...) diff --git a/go/dev/provider_scheduler_bench_test.go b/go/dev/provider_scheduler_bench_test.go index a7cd76d7..c2a2a9de 100644 --- a/go/dev/provider_scheduler_bench_test.go +++ b/go/dev/provider_scheduler_bench_test.go @@ -86,13 +86,14 @@ func benchmarkProviderScheduledEncoding(b *testing.B, image string, shared, load func reportScheduledEncoding(b *testing.B, arm *providerTailArm, label string, ranges, preparations, queues int, shared bool) { b.Helper() - b.ReportMetric(float64(queues), label+"-queue-transactions/stream") + // Positive counts retain the frozen exact shape. Zero requests actual + // bounded groups for a separate IO-sensitive overlap cohort. encodes := providerEncodingObservations(b, arm.fixture) handoffs := providerHandoffs(b, arm.fixture) scopes := readRangeScopes(b, arm.fixture) waves := make(map[string][]rangeScopeSample) var frames, payload int - var readWaits, readHolds, exclusiveWaits, exclusiveHolds, queueWaits []time.Duration + var readWaits, readHolds, exclusiveWaits, exclusiveHolds, queueWaits, spans, admissionClosed []time.Duration var receives, decodes, encodesByStream, queueToRecv, scopeWaits, prepareWaits []time.Duration for _, stream := range arm.streams { encode, ok := encodes[stream.family] @@ -102,6 +103,10 @@ func reportScheduledEncoding(b *testing.B, arm *providerTailArm, label string, r counts := make(map[string]int) for _, scope := range scopes[stream.family] { counts[scope.phase]++ + spans = append(spans, scope.authoritySpan) + if scope.phase == "admit" { + admissionClosed = append(admissionClosed, scope.authoritySpan) + } scopeWaits = append(scopeWaits, scope.wait) if scope.originWrite { readWaits = append(readWaits, scope.wait) @@ -118,8 +123,10 @@ func reportScheduledEncoding(b *testing.B, arm *providerTailArm, label string, r } } prepared := counts["prepare"] - if counts["other"] != 5 || counts["queue"] != queues || prepared < (ranges+3)/4 || prepared > ranges || - (preparations > 0 && prepared != preparations) { + queued := counts["queue"] + if counts["other"] != 4 || counts["admit"] != 1 || (queues > 0 && queued != queues) || prepared < (ranges+3)/4 || prepared > ranges || + (preparations > 0 && prepared != preparations) || + (queues == 0 && (queued != prepared || queued < (ranges+3)/4 || queued > ranges)) { b.Fatalf("%s unexpected phases for %s: %v", label, stream.family, counts) } sent := handoffs[stream.family] @@ -156,7 +163,7 @@ func reportScheduledEncoding(b *testing.B, arm *providerTailArm, label string, r }{ {"shared-read-wait", readWaits}, {"shared-read-hold", readHolds}, {"exclusive-wait", exclusiveWaits}, {"exclusive-hold", exclusiveHolds}, - {"queue-wait", queueWaits}, + {"queue-wait", queueWaits}, {"authority-span", spans}, {"admission-closed", admissionClosed}, } { if len(metric.values) > 0 { b.ReportMetric(tailMillis(metric.values, 99), label+"-"+metric.name+"-p99-ms/scope") @@ -164,6 +171,7 @@ func reportScheduledEncoding(b *testing.B, arm *providerTailArm, label string, r b.ReportMetric(float64(len(metric.values))/float64(len(arm.streams)), label+"-"+metric.name+"-scopes/stream") } n := float64(len(arm.streams)) + b.ReportMetric(float64(len(queueWaits))/n, label+"-queue-transactions/stream") b.ReportMetric(float64(len(prepareWaits))/n, label+"-preparations/stream") b.ReportMetric(tailMillis(prepareWaits, 99), label+"-prepare-wait-p99-ms/scope") b.ReportMetric(float64(frames)/n, label+"-frames/stream") @@ -199,19 +207,35 @@ func providerEncodingObservations(b *testing.B, f *fixture) map[string]time.Dura } func providerHandoffs(b *testing.B, f *fixture) map[string]map[uint64]int64 { + b.Helper() + groups := providerHandoffGroups(b, f) + result := make(map[string]map[uint64]int64, len(groups)) + for family, rows := range groups { + if len(rows) != 1 { + b.Fatalf("duplicate single-stream family handoff: %s", family) + } + result[family] = rows[0] + } + return result +} + +// Native output emits one complete group per stream. Multiple nodes in a family +// are retained, not overwritten. Callers must establish their ordering before +// joining observations; the control benchmark permits one node/family/wave. +func providerHandoffGroups(b testing.TB, f *fixture) map[string][]map[uint64]int64 { b.Helper() log, err := os.ReadFile(filepath.Join(f.directory, "server.log")) if err != nil { b.Fatal(err) } - result := make(map[string]map[uint64]int64) + result := make(map[string][]map[uint64]int64) for _, line := range strings.Split(string(log), "\n") { raw, ok := strings.CutPrefix(line, "weaver-provider-handoff ") if !ok { continue } fields := strings.Fields(raw) - if len(fields) < 2 || result[fields[0]] != nil { + if len(fields) < 2 { b.Fatalf("invalid handoff observation: %q", raw) } stamps := make(map[uint64]int64) @@ -224,7 +248,7 @@ func providerHandoffs(b *testing.B, f *fixture) map[string]map[uint64]int64 { } stamps[seq] = nanos } - result[fields[0]] = stamps + result[fields[0]] = append(result[fields[0]], stamps) } return result } diff --git a/go/dev/provider_transport_phases_test.go b/go/dev/provider_transport_phases_test.go new file mode 100644 index 00000000..c91297e2 --- /dev/null +++ b/go/dev/provider_transport_phases_test.go @@ -0,0 +1,72 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build integration && !windows + +package dev + +import ( + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + "testing" + "time" +) + +// Stage observations account for polled failures as well as successes. They are +// diagnostics only: zero bytes or a missing stage never release a reservation. +func providerTransportPhases(b testing.TB, f *fixture) map[string][4]time.Duration { + b.Helper() + raw, err := os.ReadFile(filepath.Join(f.directory, "server.log")) + if err != nil { + b.Fatal(err) + } + result := map[string][4]time.Duration{} + for _, line := range strings.Split(string(raw), "\n") { + tail, ok := strings.CutPrefix(line, "weaver-provider-transport ") + if !ok { + continue + } + fields := strings.Fields(tail) + if len(fields) != 5 { + b.Fatalf("invalid transport observation: %q", line) + } + if _, duplicate := result[fields[0]]; duplicate { + b.Fatalf("duplicate transport observation: %q", line) + } + var phases [4]time.Duration + for i, field := range fields[1:] { + parts := strings.Split(field, ":") + if len(parts) != 3 || parts[1] != "1" || parts[2] != "1" { + b.Fatalf("unfinished transport in successful cohort: %q", line) + } + n, err := strconv.ParseInt(parts[0], 10, 64) + if err != nil || n < 0 { + b.Fatalf("invalid stage: %q", field) + } + phases[i] = time.Duration(n) + } + result[fields[0]] = phases + } + return result +} +func reportProviderTransport(b *testing.B, arm *providerTailArm, label string) { + b.Helper() + phases := providerTransportPhases(b, arm.fixture) + var samples [4][]time.Duration + for _, stream := range arm.streams { + row, ok := phases[stream.family] + if !ok { + b.Fatalf("missing transport for %s", stream.family) + } + for i, n := range row { + samples[i] = append(samples[i], n) + } + } + for i, name := range []string{"tcp", "tls", "request-seal", "response-headers"} { + b.ReportMetric(tailMillis(samples[i], 99), fmt.Sprintf("%s-%s-p99-ms/invoke", label, name)) + } +} diff --git a/go/internal/controlplane/deployment.go b/go/internal/controlplane/deployment.go index 8a23fc2d..8ec1cd06 100644 --- a/go/internal/controlplane/deployment.go +++ b/go/internal/controlplane/deployment.go @@ -195,6 +195,15 @@ func RunFromEnv(ctx context.Context) error { if err != nil { return err } + // Static published routing has no runtime source reads. Return its scarce + // authenticated connection after known activation, before serving ingress. + // A deferred catalogue keeps source custody; bootstrap errors return above. + if gateway.source == nil { + if err := source.Connection.Close(); err != nil { + return err + } + trace("bootstrap-source-channel-closed") + } gateway.oauthRelay = oauthRelay trace("authority-reconciled") server, err := NewServer(gateway, &tls.Config{Certificates: []tls.Certificate{serverKey}, ClientCAs: clientRoots, ClientAuth: tls.RequireAndVerifyClientCert}, leaf, token) diff --git a/go/internal/devrunner/benchmark_pipeline_test.go b/go/internal/devrunner/benchmark_pipeline_test.go index e7ed5fd6..b3e43a28 100644 --- a/go/internal/devrunner/benchmark_pipeline_test.go +++ b/go/internal/devrunner/benchmark_pipeline_test.go @@ -98,7 +98,7 @@ func TestPublishedPipelineKeepsSchemeOutsideExecutionQualification(t *testing.T) "execution-benchmark-target": true, "execution-policy-tests": true, "execution-backend-tests": true, "execution-policy-benchmark": true, "execution-ledger-benchmark": true, "execution-provider-benchmark": true, - "execution-read-custody-pair": true, "execution-lifecycle-footprint-pair": true, "execution-delivery-join-pair": true, "execution-encoding-benchmark": true, "execution-range-prepare-pair": true, + "execution-go-control-pair": true, "execution-admission-overlap-pair": true, "execution-admission-turn-pair": true, "execution-read-custody-pair": true, "execution-lifecycle-footprint-pair": true, "execution-delivery-join-pair": true, "execution-encoding-benchmark": true, "execution-range-prepare-pair": true, "execution-scheduled-encoding-pair": true, "execution-contention-pair": true, "execution-provider-integration": true, "published-pipeline-benchmark": true, "execution-header-seal-pair": true, "execution-header-wait-pair": true, diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index 253f1841..66a59b80 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -65,6 +65,9 @@ func Plan(goBinary string) []Stage { {"provider-egress-window-lean", "elan", []string{"run", proofToolchain, "lean", "--json", "dev/proofs/lean/ProviderEgressWindow.lean"}}, {"provider-egress-promotion-quint-tests", "quint", []string{"test", "dev/proofs/quint/ProviderEgressPromotion.qnt", "--main", "ProviderEgressPromotion", "--seed", "293"}}, {"provider-egress-promotion-quint-safety", "quint", []string{"run", "dev/proofs/quint/ProviderEgressPromotion.qnt", "--main", "ProviderEgressPromotion", "--invariant", "safe", "--max-samples", "2000", "--max-steps", "80", "--seed", "293"}}, + {"provider-admission-turn-tests", "quint", []string{"test", "dev/proofs/quint/ProviderAdmissionTurn.qnt", "--main", "ProviderAdmissionTurn", "--seed", "293"}}, + {"provider-admission-turn-safety", "quint", []string{"run", "dev/proofs/quint/ProviderAdmissionTurn.qnt", "--main", "ProviderAdmissionTurn", "--invariant", "safe", "--max-samples", "2000", "--max-steps", "80", "--seed", "293"}}, + {"provider-admission-turn-lean", "elan", []string{"run", proofToolchain, "lean", "--json", "dev/proofs/lean/ProviderAdmissionTurn.lean"}}, {"provider-read-custody-tests", "quint", []string{"test", "dev/proofs/quint/ProviderReadCustody.qnt", "--main", "ProviderReadCustody", "--seed", "293"}}, {"provider-read-custody-safety", "quint", []string{"run", "dev/proofs/quint/ProviderReadCustody.qnt", "--main", "ProviderReadCustody", "--invariant", "safe", "--max-samples", "2000", "--max-steps", "80", "--seed", "293"}}, {"provider-read-custody-lean", "elan", []string{"run", proofToolchain, "lean", "--json", "dev/proofs/lean/ProviderReadCustody.lean"}}, @@ -231,6 +234,9 @@ func Stages(mode, goBinary string) ([]Stage, error) { {"execution-delivery-join-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderDeliveryJoin$", "-benchtime=1x", "-count=1", "-v"}}, {"execution-lifecycle-footprint-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderLifecycleFootprint$", "-benchtime=1x", "-count=1", "-v"}}, {"execution-read-custody-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderReadCustody$", "-benchtime=1x", "-count=1", "-v"}}, + {"execution-admission-turn-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderAdmissionTurn$", "-benchtime=1x", "-count=1", "-v"}}, + {"execution-admission-overlap-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderAdmissionOverlap$", "-benchtime=1x", "-count=1", "-v"}}, + {"execution-go-control-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderGoControlPair$", "-benchtime=1x", "-count=1", "-v"}}, {"execution-range-prepare-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderRangePreparationGroup$", "-benchtime=1x", "-count=1", "-v"}}, {"execution-scheduled-encoding-pair", goBinary, []string{"-C", "go", "test", "-mod=readonly", "-tags=integration", "./dev", "-run", "^$", "-bench", "^BenchmarkProviderScheduledEncoding$", "-benchtime=1x", "-count=1", "-v"}}, {"execution-contention-pair", goBinary, []string{"-C", "go", "test", "-count=1", "-tags=integration", "./dev", "-run", "^TestContentionPairs$", "-v"}}, From 39587cf6ff41bc71452bb210b66d2ee51ac58aa7 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 18:17:38 +0800 Subject: [PATCH 004/105] Provision Scheme SDK and bound verification phases in CI --- .github/workflows/verify-suite.yml | 40 +++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 3d966463..f218e2a7 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -24,12 +24,14 @@ jobs: verify: name: ${{ inputs.label }} runs-on: ${{ inputs.runner }} - timeout-minutes: 45 + # Keep time for the receipt upload after a phase hits its own limit. + timeout-minutes: 65 env: GOTOOLCHAIN: local WEAVER_VERIFY_SUITE: ${{ inputs.suite }} steps: - name: Check out committed source + timeout-minutes: 2 uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 with: persist-credentials: false @@ -38,38 +40,68 @@ jobs: /* !/dev/proofs/evidence/ !/dev/specs/evidence/ + - name: Record tested revision + timeout-minutes: 1 + env: + PR_HEAD: ${{ github.event.pull_request.head.sha || github.sha }} + run: | + checkout_sha=$(git rev-parse HEAD) + test "$checkout_sha" = "$GITHUB_SHA" + mkdir -p .cache/verification + printf 'head=%s\ncheckout=%s\n' "$PR_HEAD" "$checkout_sha" > .cache/verification/ci-source.txt - name: Prepare deterministic toolchain + timeout-minutes: 10 uses: ./.github/actions/prepare-toolchain - name: Fetch locked Rust and Go dependencies + timeout-minutes: 4 run: go -C go run ./cmd/weaver-dev -clean-source bootstrap-build - name: Prepare Cedar and Lean proof dependencies if: inputs.suite == 'check-policy' + timeout-minutes: 8 run: go -C go run ./cmd/weaver-dev -clean-source bootstrap-proofs - name: Prepare published Scheme SDK - if: inputs.suite == 'check-scheme' + if: contains(fromJSON('["check-rust", "check-go", "check-scheme", "bench"]'), inputs.suite) + timeout-minutes: 5 uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@838af1ab4e6c0c8177fed176efba448c694012b5 with: release-root: ${{ runner.temp }}/gerbil-sdk + - name: Prepare macOS Scheme build watchdog + if: inputs.suite == 'check-scheme' && runner.os == 'macOS' + timeout-minutes: 4 + env: + HOMEBREW_NO_AUTO_UPDATE: '1' + run: | + brew install coreutils + echo "$(brew --prefix coreutils)/libexec/gnubin" >> "$GITHUB_PATH" - name: Install declared Scheme dependencies if: inputs.suite == 'check-scheme' + timeout-minutes: 12 env: GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil - run: gerbil deps --install + run: | + command -v timeout + gerbil deps --install - name: Verify declared suite if: inputs.suite != 'check-scheme' + timeout-minutes: 30 run: go -C go run ./cmd/weaver-dev -clean-source "$WEAVER_VERIFY_SUITE" - name: Verify Scheme modules, Cedar FFI and streaming recovery if: inputs.suite == 'check-scheme' + timeout-minutes: 20 env: GERBIL_GXI: ${{ env.GERBIL_PREFIX }}/bin/gxi GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil run: go -C go run ./cmd/weaver-dev -clean-source check-scheme - name: Publish latest structured result if: always() + timeout-minutes: 2 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: ${{ inputs.suite }}-${{ runner.os }}-${{ runner.arch }}-${{ github.sha }} - path: .cache/verification/latest-* + path: | + .cache/verification/ci-source.txt + .cache/verification/latest-* + .cache/spec-qualification/**/spec-exact-delta-qualification.log include-hidden-files: true if-no-files-found: warn retention-days: 7 From 421f6980f827b4ecdef62e39c6ddcad18a6a0715 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 18:29:55 +0800 Subject: [PATCH 005/105] Model and publish structured CI verification artifacts --- .github/workflows/verify-suite.yml | 73 ++++++++++++++++--- Project.sysml | 45 ++++++++++++ .../59-provider-rpc/59.22-parallel-ci.org | 50 +++++++++++-- go/dev/ci_test.go | 36 +++++++++ go/internal/devrunner/retention.go | 6 +- .../devrunner/spec_proof_integration_test.go | 60 +++++++-------- go/internal/devrunner/spec_qualification.go | 43 +++++++++-- 7 files changed, 257 insertions(+), 56 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index f218e2a7..c56a7f14 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -31,6 +31,7 @@ jobs: WEAVER_VERIFY_SUITE: ${{ inputs.suite }} steps: - name: Check out committed source + id: checkout timeout-minutes: 2 uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 with: @@ -40,32 +41,35 @@ jobs: /* !/dev/proofs/evidence/ !/dev/specs/evidence/ - - name: Record tested revision + - name: Verify tested revision + id: source timeout-minutes: 1 - env: - PR_HEAD: ${{ github.event.pull_request.head.sha || github.sha }} run: | checkout_sha=$(git rev-parse HEAD) test "$checkout_sha" = "$GITHUB_SHA" - mkdir -p .cache/verification - printf 'head=%s\ncheckout=%s\n' "$PR_HEAD" "$checkout_sha" > .cache/verification/ci-source.txt + printf 'revision=%s\n' "$checkout_sha" >> "$GITHUB_OUTPUT" - name: Prepare deterministic toolchain + id: toolchain timeout-minutes: 10 uses: ./.github/actions/prepare-toolchain - name: Fetch locked Rust and Go dependencies + id: bootstrap_build timeout-minutes: 4 run: go -C go run ./cmd/weaver-dev -clean-source bootstrap-build - name: Prepare Cedar and Lean proof dependencies + id: bootstrap_proofs if: inputs.suite == 'check-policy' timeout-minutes: 8 run: go -C go run ./cmd/weaver-dev -clean-source bootstrap-proofs - name: Prepare published Scheme SDK + id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@838af1ab4e6c0c8177fed176efba448c694012b5 with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog + id: scheme_watchdog if: inputs.suite == 'check-scheme' && runner.os == 'macOS' timeout-minutes: 4 env: @@ -74,6 +78,7 @@ jobs: brew install coreutils echo "$(brew --prefix coreutils)/libexec/gnubin" >> "$GITHUB_PATH" - name: Install declared Scheme dependencies + id: scheme_dependencies if: inputs.suite == 'check-scheme' timeout-minutes: 12 env: @@ -82,26 +87,72 @@ jobs: command -v timeout gerbil deps --install - name: Verify declared suite + id: verify_suite if: inputs.suite != 'check-scheme' timeout-minutes: 30 run: go -C go run ./cmd/weaver-dev -clean-source "$WEAVER_VERIFY_SUITE" - name: Verify Scheme modules, Cedar FFI and streaming recovery + id: verify_scheme if: inputs.suite == 'check-scheme' timeout-minutes: 20 env: GERBIL_GXI: ${{ env.GERBIL_PREFIX }}/bin/gxi GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil run: go -C go run ./cmd/weaver-dev -clean-source check-scheme - - name: Publish latest structured result + - name: Require successful phase receipts + id: receipt_check + timeout-minutes: 1 + run: | + test -s .cache/verification/latest-bootstrap-build.json + test -s ".cache/verification/latest-$WEAVER_VERIFY_SUITE.json" + if [ "$WEAVER_VERIFY_SUITE" = check-policy ]; then + test -s .cache/verification/latest-bootstrap-proofs.json + fi + - name: Write verification job receipt + if: always() + timeout-minutes: 1 + env: + JOB_RECEIPT: >- + { + "schema": "weaver.ci-job.v1", + "suite": ${{ toJSON(inputs.suite) }}, + "runId": ${{ toJSON(github.run_id) }}, + "runAttempt": ${{ toJSON(github.run_attempt) }}, + "headRevision": ${{ toJSON(github.event.pull_request.head.sha || github.sha) }}, + "expectedCheckoutRevision": ${{ toJSON(github.sha) }}, + "checkoutRevision": ${{ toJSON(steps.source.outputs.revision || null) }}, + "os": ${{ toJSON(runner.os) }}, + "arch": ${{ toJSON(runner.arch) }}, + "status": ${{ toJSON(job.status) }}, + "phases": { + "checkout": ${{ toJSON(steps.checkout.outcome || 'skipped') }}, + "source": ${{ toJSON(steps.source.outcome || 'skipped') }}, + "toolchain": ${{ toJSON(steps.toolchain.outcome || 'skipped') }}, + "bootstrapBuild": ${{ toJSON(steps.bootstrap_build.outcome || 'skipped') }}, + "bootstrapProofs": ${{ toJSON(steps.bootstrap_proofs.outcome || 'skipped') }}, + "schemeSdk": ${{ toJSON(steps.scheme_sdk.outcome || 'skipped') }}, + "schemeWatchdog": ${{ toJSON(steps.scheme_watchdog.outcome || 'skipped') }}, + "schemeDependencies": ${{ toJSON(steps.scheme_dependencies.outcome || 'skipped') }}, + "verifySuite": ${{ toJSON(steps.verify_suite.outcome || 'skipped') }}, + "verifyScheme": ${{ toJSON(steps.verify_scheme.outcome || 'skipped') }}, + "receiptCheck": ${{ toJSON(steps.receipt_check.outcome || 'skipped') }} + } + } + run: | + mkdir -p .cache/verification + printf '%s\n' "$JOB_RECEIPT" > .cache/verification/ci-job.json + - name: Publish structured verification receipts if: always() timeout-minutes: 2 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: - name: ${{ inputs.suite }}-${{ runner.os }}-${{ runner.arch }}-${{ github.sha }} + name: ${{ inputs.suite }}-${{ runner.os }}-${{ runner.arch }}-${{ github.sha }}-attempt-${{ github.run_attempt }} path: | - .cache/verification/ci-source.txt - .cache/verification/latest-* - .cache/spec-qualification/**/spec-exact-delta-qualification.log + .cache/verification/ci-job.json + .cache/verification/latest-bootstrap-build.json + .cache/verification/latest-bootstrap-proofs.json + .cache/verification/latest-${{ inputs.suite }}.json + .cache/verification/spec/*/receipt.json include-hidden-files: true - if-no-files-found: warn + if-no-files-found: error retention-days: 7 diff --git a/Project.sysml b/Project.sysml index 88dd8ea1..a8d9d00b 100644 --- a/Project.sysml +++ b/Project.sysml @@ -140,6 +140,51 @@ package WeaverProject { part architecture : VerificationSuite { part 'check-architecture' : VerificationMode; } part policy : VerificationSuite { part 'check-policy' : VerificationMode; } part benchmarks : VerificationSuite { part bench : VerificationMode; } + + package Artifacts { + doc /* The repository owns reproducible inputs. Toolchains own build + products and caches. The verification owner publishes typed + receipts through one output directory. GitHub transports the + declared JSON paths as one artifact per job attempt. */ + part def CIReceipt; + part def LocalResult; + part def ToolOutput; + part def ReleaseEvidence; + + part '.cache/verification/ci-job.json' : CIReceipt { + doc /* The reusable workflow binds the run, attempt, PR head, + actual checkout, runner and phase outcomes. Publish after + failure as well as success. An absent checkout is explicit. */ + } + part '.cache/verification/latest-bootstrap-build.json' : CIReceipt; + part '.cache/verification/latest-bootstrap-proofs.json' : CIReceipt; + part '.cache/verification/latest-.json' : CIReceipt { + doc /* weaver-dev owns suite receipts. Preserve committed input + digests, stage status, exit, duration and output digest. + Bench measurements remain separate from correctness claims. */ + } + part '.cache/verification/spec/*/receipt.json' : CIReceipt { + doc /* The SPEC owner retains per-run verdicts and stage evidence + alongside its typed catalog. Only the receipt is exported to CI. */ + } + part '.cache/verification/spec/*/catalog.json' : LocalResult; + part '.cache/verification/latest-benchmark-summary.org' : LocalResult; + part transientProcessOutput : ToolOutput { + doc /* Native process owners use private temporary directories. + Retain bounded diagnostics inside the typed receipt and clean + the scratch directory when the producer finishes. */ + } + part toolchainProducts : ToolOutput { + doc /* Cargo and Scheme Build Packages own compiled outputs. + Their stores and caches are inputs to reproducibility checks + where required. Ordinary jobs export the declared receipts. */ + } + part approvedReleaseEvidence : ReleaseEvidence { + doc /* Site authority binds the deployable release and its + manifest to approval, activation and workload identity. + Production qualification follows the separate site protocol. */ + } + } } package AssuranceResponsibilities { diff --git a/docs/50-59-research-program/59-provider-rpc/59.22-parallel-ci.org b/docs/50-59-research-program/59-provider-rpc/59.22-parallel-ci.org index 90ea5ff6..5be5566c 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.22-parallel-ci.org +++ b/docs/50-59-research-program/59-provider-rpc/59.22-parallel-ci.org @@ -66,14 +66,48 @@ The published Scheme Gerbil toolchain setup action is reused at the same immutab as the authorized bridge dependency. Its release/host admission remains separate from application and formal proof results. -* Results and cleanup - -Each job produces source-bound compact latest results. Per-run stdout/stderr, -module links and compiler output use system temporary directories and are removed -on completion, including failures. Structured results retain exit status, source -identity, output hashes and at most 4096 bytes of a failed stage's diagnostics. -They overwrite fixed slots. CI uploads these compact files and the latest -benchmark table as expiring artifacts; raw run logs are not archived by the project. +* Artifact organization + +=WeaverProject::Verification::Artifacts= in =Project.sysml= owns the publication +inventory. The workflow test checks the declared CI receipt paths against the +actual upload allowlist. GitHub receives one artifact per suite, runner, tested +checkout and run attempt. + +#+begin_example +.cache/verification/ + ci-job.json GitHub job and phase outcomes + latest-bootstrap-build.json Rust and Go dependency preparation + latest-bootstrap-proofs.json Cedar and Lean dependency preparation + latest-.json Committed source and verification result + spec/run-*/receipt.json SPEC analyzer or kernel evidence + spec/run-*/catalog.json Local validated SPEC catalog + latest-benchmark-summary.org Local human-readable benchmark projection +#+end_example + +| Class | Producer and custody | Publication | +|-------+----------------------+-------------| +| Reproducible inputs | Repository source, SysML models, lockfiles and fixed test declarations | Git owns the definitions consumed by each job. | +| Native build products | Cargo and Gerbil Build Packages own executables, archives, package libraries and build caches | The ordinary verification artifact carries receipts. Release delivery identifies actual deployed bytes separately. | +| Verification receipts | GitHub owns job and phase outcomes. =weaver-dev= and the SPEC tests own typed suite and proof results. | CI exports the declared JSON receipts with seven-day retention. | +| Local result projections | SPEC emits a validated catalog. The benchmark runner derives the human-readable summary from measured results. | Both live under the verification root. CI retains benchmark observations in the suite JSON and SPEC status in the proof receipt. | +| Process scratch | The stage owner captures native compiler and test output in a private temporary directory. | Cleanup runs after success or failure. The receipt retains the exit status, output hash and a bounded failure diagnostic. | +| Production release evidence | The site authority owns deployment approval, catalog and activated release binding. | The site release protocol associates these records with the approved workload and exact image. | + +=ci-job.json= records the PR head and the actual checked-out revision separately. +GitHub can test a PR merge revision. Suite receipts bind that revision to source +digests and stage outcomes. A preparation failure can prevent a suite receipt +from existing; the job receipt records the failed phase and skipped phases. A +successful workflow requires its bootstrap and suite receipts before publishing +the job envelope. Diagnostic excerpts are bounded fields within receipts. + +Praxis separates benchmark execution and comparison and publishes a typed result +keyed by the tested SHA. Agent Gateway gives timing and failure artifacts their +own job-scoped paths. Weaver applies those ownership boundaries to its existing +verification owner and publishes the SysML-declared JSON inventory. +[[https://github.com/praxis-proxy/praxis/blob/c3d2ae3628cf3167780e58c5e8b38580d0241399/.github/workflows/benchmarks.yaml][Praxis benchmark workflow]] +[[https://github.com/agentgateway/agentgateway/blob/134897e1975fa26fa5c5b8ba45d720d05d3f7fb8/.github/workflows/pull_request.yml][Agent Gateway pull request workflow]] + +* Qualification boundaries Local passes, workflow syntax admission and remote execution are distinct results. A job that cannot install its SDK, finish cleanup, or complete a control fails. diff --git a/go/dev/ci_test.go b/go/dev/ci_test.go index a2e1e3d4..0f9f13a8 100644 --- a/go/dev/ci_test.go +++ b/go/dev/ci_test.go @@ -89,6 +89,15 @@ func TestCIWorkflowsMatchProjectSuites(t *testing.T) { } `yaml:"inputs"` } `yaml:"workflow_call"` } `yaml:"on"` + Jobs map[string]struct { + Steps []struct { + Uses string `yaml:"uses"` + If string `yaml:"if"` + With struct { + Path string `yaml:"path"` + } `yaml:"with"` + } `yaml:"steps"` + } `yaml:"jobs"` } if err := yaml.Unmarshal(data, &reusable); err != nil { t.Fatal(err) @@ -96,6 +105,33 @@ func TestCIWorkflowsMatchProjectSuites(t *testing.T) { if reusable.On.Call.Inputs["runner"].Default != "ubuntu-latest" { t.Fatal("default suite runner must follow ubuntu-latest") } + wantedReceipts := map[string]bool{} + for _, part := range parts { + if part.Properties["owner"] == projectNamespace+"Verification::Artifacts" && projectKind(part) == "Verification::Artifacts::CIReceipt" { + path := strings.ReplaceAll(part.Properties["name"], "", "${{ inputs.suite }}") + wantedReceipts[path] = true + } + } + if len(wantedReceipts) == 0 { + t.Fatal("missing SysML CI receipt allocation") + } + for _, step := range reusable.Jobs["verify"].Steps { + if !strings.HasPrefix(step.Uses, "actions/upload-artifact@") { + continue + } + if step.If != "always()" { + t.Fatal("verification receipt upload must cover failed stages") + } + for _, path := range strings.Split(strings.TrimSpace(step.With.Path), "\n") { + if !wantedReceipts[path] || !strings.HasPrefix(path, ".cache/verification/") || !strings.HasSuffix(path, ".json") { + t.Fatalf("unexpected verification artifact path %q", path) + } + delete(wantedReceipts, path) + } + } + if len(wantedReceipts) != 0 { + t.Fatalf("CI upload is missing declared receipts: %v", wantedReceipts) + } for _, path := range []string{".github/workflows/verify-suite.yml", ".github/actions/prepare-toolchain/action.yml"} { data, err := os.ReadFile(filepath.Join(root(t), path)) if err != nil { diff --git a/go/internal/devrunner/retention.go b/go/internal/devrunner/retention.go index 3850e0c2..a37f0df6 100644 --- a/go/internal/devrunner/retention.go +++ b/go/internal/devrunner/retention.go @@ -19,11 +19,15 @@ import ( const failureTailBytes int64 = 4096 +func verificationDirectory(root string) string { + return filepath.Join(root, ".cache", "verification") +} + func latestResultPath(root, mode string) string { if mode == "" { mode = "check" } - return filepath.Join(root, ".cache", "verification", "latest-"+mode+".json") + return filepath.Join(verificationDirectory(root), "latest-"+mode+".json") } // summarizeOutput hashes the complete output while retaining at most one bounded diff --git a/go/internal/devrunner/spec_proof_integration_test.go b/go/internal/devrunner/spec_proof_integration_test.go index 17cba05f..60e78300 100644 --- a/go/internal/devrunner/spec_proof_integration_test.go +++ b/go/internal/devrunner/spec_proof_integration_test.go @@ -18,19 +18,32 @@ import ( "time" ) -func TestSPECProofClosureComposition(t *testing.T) { - root, err := FindRoot(".") +func retainSPECProofReceipt(t *testing.T, root, scratch string, receipt Receipt) { + t.Helper() + if t.Failed() { + receipt.Status = "FAIL" + } + for i := range receipt.Stages { + if err := summarizeOutput(scratch, &receipt.Stages[i]); err != nil { + t.Fatal(err) + } + } + evidence, err := newSpecEvidenceDirectory(root) if err != nil { t.Fatal(err) } - base := filepath.Join(root, ".cache", "spec-qualification") - if err = os.MkdirAll(base, 0700); err != nil { + if err := writeReceipt(evidence, receipt); err != nil { t.Fatal(err) } - directory, err := os.MkdirTemp(base, "proof-closure-") + t.Logf("SPEC proof receipt %s", filepath.Join(evidence, "receipt.json")) +} + +func TestSPECProofClosureComposition(t *testing.T) { + root, err := FindRoot(".") if err != nil { t.Fatal(err) } + directory := t.TempDir() ctx, cancel := context.WithTimeout(t.Context(), 2*time.Minute) defer cancel() stage := Stage{Name: "spec-semantic-composition-audit", Binary: "elan", Args: []string{"run", proofToolchain, "lake", "-d", "dev/proofs/cedar", "env", "lean", "--json", "dev/proofs/cedar/QualifiedReview.lean"}} @@ -39,9 +52,9 @@ func TestSPECProofClosureComposition(t *testing.T) { if err != nil { t.Fatal(err) } - if err = writeReceipt(directory, Receipt{Root: root, Status: result.Status, Mode: "spec-semantic-composition-audit", Inputs: inputs, Stages: []Result{result}}); err != nil { - t.Fatal(err) - } + t.Cleanup(func() { + retainSPECProofReceipt(t, root, directory, Receipt{Root: root, Status: result.Status, Mode: "spec-semantic-composition-audit", Inputs: inputs, Stages: []Result{result}}) + }) if result.Status != "PASS" || result.ExitCode == nil || *result.ExitCode != 0 || result.Lean == nil { t.Fatalf("real SPEC composition must pass the unchanged strict axiom gate: %+v", result) } @@ -62,7 +75,7 @@ func TestSPECProofClosureComposition(t *testing.T) { if structural != 2 || semantic != 1 { t.Fatal("missing actual structural/semantic proof", structural, semantic) } - t.Logf("PASS real SPEC composition; structural=%d semantic=%d audit=%s", structural, semantic, directory) + t.Logf("PASS real SPEC composition; structural=%d semantic=%d", structural, semantic) } func TestSPECProofClosureRejectsFalseArithmetic(t *testing.T) { @@ -70,14 +83,7 @@ func TestSPECProofClosureRejectsFalseArithmetic(t *testing.T) { if err != nil { t.Fatal(err) } - base := filepath.Join(root, ".cache", "spec-qualification") - if err = os.MkdirAll(base, 0700); err != nil { - t.Fatal(err) - } - directory, err := os.MkdirTemp(base, "false-arithmetic-") - if err != nil { - t.Fatal(err) - } + directory := t.TempDir() source := "import SpecProofClosure\nopen Lean Elab Command Meta Term\nrun_cmd do\n logInfo \"CHECKING_FALSE_ARITHMETIC\"\n liftTermElabM do\n let type ← elabType (← `(decide ((1 : Nat) = 2) = true))\n let _ ← Weaver.SpecProofClosure.proveClosedArithmetic type\n pure ()\n" path := filepath.Join(directory, "FalseArithmetic.lean") if err = os.WriteFile(path, []byte(source), 0600); err != nil { @@ -100,26 +106,25 @@ func TestSPECProofClosureResearchModels(t *testing.T) { if err != nil { t.Fatal(err) } - base := filepath.Join(root, ".cache", "spec-qualification") - if err = os.MkdirAll(base, 0700); err != nil { - t.Fatal(err) - } - directory, err := os.MkdirTemp(base, "model-closure-") - if err != nil { - t.Fatal(err) - } + directory := t.TempDir() ctx, cancel := context.WithTimeout(t.Context(), 2*time.Minute) defer cancel() before, err := SourceInputs(root) if err != nil { t.Fatal(err) } + var stages []Result + t.Cleanup(func() { + retainSPECProofReceipt(t, root, directory, Receipt{Root: root, Status: "PASS", Mode: "model-closure-positive-audit", Inputs: before, Stages: stages}) + }) build := runStage(ctx, root, directory, os.Environ(), Stage{Name: "model-closure-source-build", Binary: "elan", Args: []string{"run", proofToolchain, "lake", "-d", "dev/proofs/cedar", "build", "ModelClosure"}}) + stages = append(stages, build) if build.Status != "PASS" { t.Fatalf("model source closure build failed: %+v", build) } stage := Stage{Name: "model-closure-positive-audit", Binary: "elan", Args: []string{"run", proofToolchain, "lake", "-d", "dev/proofs/cedar", "env", "lean", "--json", "dev/proofs/cedar/ModelClosure.lean"}} result := runStage(ctx, root, directory, os.Environ(), stage) + stages = append(stages, result) if result.Status != "PASS" || result.ExitCode == nil || *result.ExitCode != 0 || result.Lean == nil { t.Fatalf("complete model closure must pass the strict positive audit: %+v", result) } @@ -202,8 +207,5 @@ func TestSPECProofClosureResearchModels(t *testing.T) { if !maps.Equal(before, inputs) { t.Fatal("model sources changed during acceptance") } - if err = writeReceipt(directory, Receipt{Root: root, Status: result.Status, Mode: "model-closure-positive-audit", Inputs: inputs, Stages: []Result{build, result}}); err != nil { - t.Fatal(err) - } - t.Logf("PASS modules=%d theorems=%d evidence=%s", len(expected), reportedProofs, directory) + t.Logf("PASS modules=%d theorems=%d", len(expected), reportedProofs) } diff --git a/go/internal/devrunner/spec_qualification.go b/go/internal/devrunner/spec_qualification.go index a625897a..e485ee41 100644 --- a/go/internal/devrunner/spec_qualification.go +++ b/go/internal/devrunner/spec_qualification.go @@ -11,11 +11,13 @@ import ( "encoding/hex" "errors" "fmt" - v1 "github.com/HardenedLinux/weaver/go/api/v1" "io" "maps" "os" "path/filepath" + "time" + + v1 "github.com/HardenedLinux/weaver/go/api/v1" ) // SpecQualification is generated by the pinned analyzer, never caller verdicts. @@ -24,18 +26,39 @@ type SpecQualification struct { Digest, Path string } +func newSpecEvidenceDirectory(root string) (string, error) { + base := filepath.Join(verificationDirectory(root), "spec") + if err := os.MkdirAll(base, 0700); err != nil { + return "", err + } + return os.MkdirTemp(base, "run-") +} + // QualifySpec runs real SPEC analysis in the existing development process owner. // Production request/publication paths do not launch Lean or communicate by CLI. -func QualifySpec(ctx context.Context, root string) (SpecQualification, error) { +func QualifySpec(ctx context.Context, root string) (_ SpecQualification, runErr error) { before, err := SourceInputs(root) if err != nil { return SpecQualification{}, err } - base := filepath.Join(root, ".cache", "spec-qualification") - if err = os.MkdirAll(base, 0700); err != nil { + evidence, err := newSpecEvidenceDirectory(root) + if err != nil { return SpecQualification{}, err } - directory, err := os.MkdirTemp(base, "run-") + receipt := Receipt{Root: root, Mode: "qualify-policy", Status: "PASS", Inputs: before, Started: time.Now().UTC().Format(time.RFC3339Nano)} + directory, err := os.MkdirTemp("", "weaver-spec-") + defer func() { + if directory != "" { + runErr = errors.Join(runErr, os.RemoveAll(directory)) + } + if runErr != nil { + receipt.Status = "FAIL" + if len(receipt.Stages) == 0 || receipt.Stages[len(receipt.Stages)-1].Status == "PASS" { + receipt.Stages = append(receipt.Stages, Result{Name: "spec-qualification-result", Status: "FAIL", Error: runErr.Error()}) + } + } + runErr = errors.Join(runErr, writeReceipt(evidence, receipt)) + }() if err != nil { return SpecQualification{}, err } @@ -43,8 +66,14 @@ func QualifySpec(ctx context.Context, root string) (SpecQualification, error) { analysis := Stage{Name: "spec-exact-delta-qualification", Binary: "elan", Args: []string{"run", proofToolchain, "lake", "-d", "dev/proofs/cedar", "env", "lean", "--run", "dev/proofs/cedar/ReviewQualification.lean"}} for _, stage := range []Stage{imports, analysis} { result := runStage(ctx, root, directory, os.Environ(), stage) + if err := summarizeOutput(directory, &result); err != nil { + result.Status = "FAIL" + result.Error = fmt.Sprintf("capture stage evidence: %v (stage error: %q)", err, result.Error) + result.Log = "" + } + receipt.Stages = append(receipt.Stages, result) if result.Status != "PASS" { - return SpecQualification{}, fmt.Errorf("SPEC qualification refused: %s: %s", filepath.Join(directory, result.Log), result.Error) + return SpecQualification{}, fmt.Errorf("SPEC qualification refused at %s: %s (receipt %s)", stage.Name, result.Error, filepath.Join(evidence, "receipt.json")) } } file, err := os.Open(filepath.Join(directory, analysis.Name+".log")) @@ -74,7 +103,7 @@ func QualifySpec(ctx context.Context, root string) (SpecQualification, error) { if !maps.Equal(before, after) { return SpecQualification{}, errors.New("sources changed during SPEC qualification") } - path := filepath.Join(directory, "catalog.json") + path := filepath.Join(evidence, "catalog.json") if err = os.WriteFile(path, document, 0600); err != nil { return SpecQualification{}, err } From 384cd26433333fb3930e1ec2a66e773258a9cf0a Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 18:40:00 +0800 Subject: [PATCH 006/105] Keep metering and provider contracts within the ASP gate --- crates/contracts/src/metering.rs | 39 +++++++++++++------ crates/contracts/src/provider_catalog.rs | 30 +++++++++----- .../src/provider_profile/artifact.rs | 2 + crates/contracts/src/quotas.rs | 3 ++ 4 files changed, 52 insertions(+), 22 deletions(-) diff --git a/crates/contracts/src/metering.rs b/crates/contracts/src/metering.rs index bdf7ed45..02f62171 100644 --- a/crates/contracts/src/metering.rs +++ b/crates/contracts/src/metering.rs @@ -17,6 +17,7 @@ pub struct MeteringTenant { pub rates: [u64; 4], } +/// Deployment-wide tenant assignments and optional quota and procurement rules. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct MeteringDeployment { @@ -30,6 +31,7 @@ pub struct MeteringDeployment { pub provider_quotes: BTreeMap, } +/// Versioned procurement terms and token bounds bound to a tenant pricing formula. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct ProviderQuote { @@ -57,20 +59,11 @@ impl MeteringDeployment { let mut keys = BTreeSet::new(); for (tenant, rule) in &self.tenants { identifier(tenant)?; - identifier(&rule.issuer)?; - if !digest(&rule.public_key, 64) - || !keys.insert(&rule.public_key) - || rule.principals.is_empty() - || rule.rates.iter().any(|rate| *rate > MAX_CREDITS) - { + rule.validate()?; + if !keys.insert(&rule.public_key) { return Err(Error::Invalid("metering tenant configuration")); } - for principal in &rule.principals { - identifier(principal)?; - if !principals.insert(principal) { - return Err(Error::Invalid("ambiguous metering principal")); - } - } + rule.register_principals(&mut principals)?; } if let Some(quotas) = &self.quotas { quotas.validate(self)?; @@ -108,6 +101,27 @@ impl MeteringDeployment { } impl MeteringTenant { + fn validate(&self) -> Result<()> { + identifier(&self.issuer)?; + if !digest(&self.public_key, 64) + || self.principals.is_empty() + || self.rates.iter().any(|rate| *rate > MAX_CREDITS) + { + return Err(Error::Invalid("metering tenant configuration")); + } + Ok(()) + } + + fn register_principals<'a>(&'a self, principals: &mut BTreeSet<&'a String>) -> Result<()> { + for principal in &self.principals { + identifier(principal)?; + if !principals.insert(principal) { + return Err(Error::Invalid("ambiguous metering principal")); + } + } + Ok(()) + } + pub fn formula_digest(&self) -> Result { Ok(body_digest(&serde_json::to_string(&( "weaver.metering.linear-ceil-per-million.v1", @@ -204,6 +218,7 @@ impl MeteringReceipt { } } +/// Settlement records how a reservation was charged and how much was released. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct MeteringApplication { pub application: String, diff --git a/crates/contracts/src/provider_catalog.rs b/crates/contracts/src/provider_catalog.rs index 92927d95..3110ca95 100644 --- a/crates/contracts/src/provider_catalog.rs +++ b/crates/contracts/src/provider_catalog.rs @@ -2,12 +2,15 @@ // // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 +//! Versioned provider plans and the tenant tariffs required to admit them. + use crate::{ Error, MAX_CREDITS, MeteringDeployment, ProviderQuote, Result, body_digest, identifier, }; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; +/// An ordered provider plan snapshot linked to its parent catalog. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct ProviderCatalog { @@ -15,6 +18,7 @@ pub struct ProviderCatalog { pub entries: BTreeMap, } +/// One plan's module, capability, latency and pricing declarations. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct CatalogEntry { @@ -42,16 +46,7 @@ impl ProviderCatalog { } let mut tariffs = BTreeMap::new(); for (plan, entry) in &self.entries { - identifier(&entry.module)?; - if entry.capabilities.len() > 32 - || entry.latency_millis == 0 - || entry.latency_millis > MAX_CREDITS - { - return Err(Error::Invalid("provider catalog entry bounds")); - } - for capability in &entry.capabilities { - identifier(capability)?; - } + entry.validate_shape()?; let tenant = deployment .tenants .get(&entry.quote.tenant) @@ -70,3 +65,18 @@ impl ProviderCatalog { Ok(()) } } + +impl CatalogEntry { + fn validate_shape(&self) -> Result<()> { + identifier(&self.module)?; + if self.capabilities.len() > 32 + || self.latency_millis == 0 + || self.latency_millis > MAX_CREDITS + { + return Err(Error::Invalid("provider catalog entry bounds")); + } + self.capabilities + .iter() + .try_for_each(|capability| identifier(capability)) + } +} diff --git a/crates/contracts/src/provider_profile/artifact.rs b/crates/contracts/src/provider_profile/artifact.rs index df6b2f06..3e27b5a7 100644 --- a/crates/contracts/src/provider_profile/artifact.rs +++ b/crates/contracts/src/provider_profile/artifact.rs @@ -8,8 +8,10 @@ use serde::{Deserialize, Serialize}; /// Closed implementation protocol; other protocols require their own semantic owner. pub const CHAT_TEXT_SSE: &str = "openai.chat-text-sse.v1"; +/// Anthropic Messages text streaming with the validated SSE event sequence. pub const ANTHROPIC_MESSAGES_SSE: &str = "anthropic.messages-text-sse.v1"; +/// Supported request and stream adapters selected from a validated profile. #[derive(Clone, Copy)] pub enum ProviderProtocol { OpenAi, diff --git a/crates/contracts/src/quotas.rs b/crates/contracts/src/quotas.rs index 119217df..da321aa0 100644 --- a/crates/contracts/src/quotas.rs +++ b/crates/contracts/src/quotas.rs @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 +//! Deployment quota bindings across credential keys, principals and tenants. + use crate::{Error, MAX_CREDITS, MeteringDeployment, Result, identifier}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -16,6 +18,7 @@ pub struct QuotaDeployment { pub tenants: BTreeMap, } +/// The principal binding and credit limit for a stable credential identifier. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct QuotaKey { From d0a6cf611fbefe753cd148a7008e06d146b7d09f Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 18:44:17 +0800 Subject: [PATCH 007/105] Reserve CI time for structured native timeout receipts --- .github/workflows/verify-suite.yml | 8 +- Project.sysml | 78 ++++++++++++++++++- .../59-provider-rpc/59.22-parallel-ci.org | 58 ++++++++++++++ go/cmd/weaver-dev/main.go | 9 +++ go/dev/ci_test.go | 27 ++++++- go/internal/devrunner/retention.go | 2 +- go/internal/devrunner/runner.go | 42 +++++++--- go/internal/devrunner/stage_process_other.go | 16 ++++ go/internal/devrunner/stage_process_unix.go | 27 +++++++ .../devrunner/stage_process_unix_test.go | 46 +++++++++++ 10 files changed, 295 insertions(+), 18 deletions(-) create mode 100644 go/internal/devrunner/stage_process_other.go create mode 100644 go/internal/devrunner/stage_process_unix.go create mode 100644 go/internal/devrunner/stage_process_unix_test.go diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index c56a7f14..b78168cb 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -55,12 +55,12 @@ jobs: - name: Fetch locked Rust and Go dependencies id: bootstrap_build timeout-minutes: 4 - run: go -C go run ./cmd/weaver-dev -clean-source bootstrap-build + run: go -C go run ./cmd/weaver-dev -clean-source -timeout 3m bootstrap-build - name: Prepare Cedar and Lean proof dependencies id: bootstrap_proofs if: inputs.suite == 'check-policy' timeout-minutes: 8 - run: go -C go run ./cmd/weaver-dev -clean-source bootstrap-proofs + run: go -C go run ./cmd/weaver-dev -clean-source -timeout 7m bootstrap-proofs - name: Prepare published Scheme SDK id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-scheme", "bench"]'), inputs.suite) @@ -90,7 +90,7 @@ jobs: id: verify_suite if: inputs.suite != 'check-scheme' timeout-minutes: 30 - run: go -C go run ./cmd/weaver-dev -clean-source "$WEAVER_VERIFY_SUITE" + run: go -C go run ./cmd/weaver-dev -clean-source -timeout 28m "$WEAVER_VERIFY_SUITE" - name: Verify Scheme modules, Cedar FFI and streaming recovery id: verify_scheme if: inputs.suite == 'check-scheme' @@ -98,7 +98,7 @@ jobs: env: GERBIL_GXI: ${{ env.GERBIL_PREFIX }}/bin/gxi GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil - run: go -C go run ./cmd/weaver-dev -clean-source check-scheme + run: go -C go run ./cmd/weaver-dev -clean-source -timeout 18m check-scheme - name: Require successful phase receipts id: receipt_check timeout-minutes: 1 diff --git a/Project.sysml b/Project.sysml index a8d9d00b..ceec3cda 100644 --- a/Project.sysml +++ b/Project.sysml @@ -119,6 +119,78 @@ package WeaverProject { closure; a production import of one is rejected, never exempted. */ } + package ArtifactOrganization { + doc /* Project-wide custody and lifecycle. Verification::Artifacts owns + the implemented CI path inventory. Each other producer keeps its + native entry point and store. This model allocates responsibility + and records remaining implementation work. */ + part def ReproducibleInput; + part def NativeBuildProduct; + part def VerificationRun; + part def DerivedView; + part def LocalQualification; + part def ReleaseBundle; + part def SiteRuntimeState; + part def SiteQualification; + + part checkedInSources : ReproducibleInput { + doc /* Git owns source, schemas, locks, deterministic fixtures and + reproducible projections. A generated file in Git must have a + checked-in recipe and a reproducibility check. Site data, local + digests, and individual execution verdicts stay outside Git. */ + } + part nativeBuild : NativeBuildProduct { + doc /* Cargo and Gerbil Build Packages prepare and reuse their own + outputs. The release consumer selects exact executable, linked + image and package closure. Toolchain clean operates on owned + outputs and does not remove verification evidence or site data. */ + } + part verificationRuns : VerificationRun { + doc /* weaver-dev and the existing native suites emit typed outcomes. + Verification::Artifacts declares the implemented local and CI + paths. CI retains outcomes by job attempt for seven days. + The remaining local design retains an immutable run by identity + before updating any latest view. A failed or incomplete attempt + remains separately addressable and never qualifies the input. */ + } + part reportViews : DerivedView { + doc /* Org summaries and other views consume typed results. Views + inherit their evidence identity and can be regenerated. Scratch + is process-owned and cleaned on exit. Only structured diagnostics + and explicitly retained historical evidence survive cleanup. */ + } + part localSnakeOil : LocalQualification { + doc /* Native Go integration owns local developer qualification. + Use .cache/weaver-deployment-qualification/ as its dedicated + root for generated catalogs, config and isolated ledgers. The + design gives each new run a private subdirectory and binds the + fixture and build identities in its typed result. Existing runs + and original verdicts stay where they were recorded. */ + } + part deployableRelease : ReleaseBundle { + doc /* The release design freezes one digest-bound manifest for the + selected executable or image, Gerbil package library and + resolved closure, build inputs and toolchain revisions. The + deployment owner verifies the delivered bytes. Project CI + receipts alone cannot authorize release publication. */ + } + part runtimeCustody : SiteRuntimeState { + doc /* The site launcher supplies settings and a selected catalog. + The Rust authority owns the persistent ledger. Keep catalog + and ledger at separate paths on the site's persistent storage. + A mutable ledger is bound to qualification by its admitted cut + or verified snapshot, never by copying a live database into CI. */ + } + part formalQualification : SiteQualification { + doc /* Site approval, activation, catalog, replay and baseline cut + bind to the same immutable release before sampling. The + existing Governor preregistration governs A/A and retained A/B. + Site authority retains these records and formal verdicts + independently of CI expiry. Missing site records keep formal + qualification pending. */ + } + } + package Verification { doc /* The Go verification owner inventories maintained project sources, the complete Lean/Quint/Cedar proof source trees and Org/D2 design @@ -145,7 +217,8 @@ package WeaverProject { doc /* The repository owns reproducible inputs. Toolchains own build products and caches. The verification owner publishes typed receipts through one output directory. GitHub transports the - declared JSON paths as one artifact per job attempt. */ + declared JSON paths as one artifact per job attempt. + ArtifactOrganization defines custody beyond verification. */ part def CIReceipt; part def LocalResult; part def ToolOutput; @@ -161,6 +234,9 @@ package WeaverProject { part '.cache/verification/latest-.json' : CIReceipt { doc /* weaver-dev owns suite receipts. Preserve committed input digests, stage status, exit, duration and output digest. + The native deadline precedes the GitHub step deadline so + timeout evidence can finish publication. Native recovery + and natural-exit acceptance keep their separate fences. Bench measurements remain separate from correctness claims. */ } part '.cache/verification/spec/*/receipt.json' : CIReceipt { diff --git a/docs/50-59-research-program/59-provider-rpc/59.22-parallel-ci.org b/docs/50-59-research-program/59-provider-rpc/59.22-parallel-ci.org index 5be5566c..5d926184 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.22-parallel-ci.org +++ b/docs/50-59-research-program/59-provider-rpc/59.22-parallel-ci.org @@ -68,6 +68,55 @@ from application and formal proof results. * Artifact organization +=WeaverProject::ArtifactOrganization= in =Project.sysml= allocates the +project-wide lifecycle. The build owner produces bytes, verification records +what it exercised, and the deployment owner selects and activates a release. +The site binds formal measurements to that activation. + +| Class | Owner and storage | Identity and retention | State | +|-------+-------------------+------------------------+-------| +| Reproducible inputs and projections | Git holds source, model, locks, fixed Snake Oil fixtures and reproducible views. | A committed generated file needs a checked-in recipe and reproducibility check. Per-run output stays outside Git. | Existing policy and entry points. | +| Native outputs | Cargo owns =target/=. Gerbil Build Packages owns its package outputs. | Each tool reuses and cleans its own build products. A release selects the exact executable or image, Scheme library and resolved closure. | Native owners exist. The release handoff is specified below. | +| Verification | =weaver-dev= and native suite owners write under =.cache/verification/=. GitHub transports a JSON allowlist. | Job attempt and tested checkout identify remote evidence. The local design keeps a separate immutable result per run before advancing a latest view. | CI envelope and suite receipts implemented. Local suite files still use =latest-*.json=, while SPEC already has per-run paths. | +| Local deployment qualification | The native Go entry runs Snake Oil. Its dedicated data root is =.cache/weaver-deployment-qualification/=. | New run directories should isolate generated catalog, configuration and ledger and associate them with the tested build and fixture. Retain original failed attempts with their verdicts. | Native path and dedicated root documented. Uniform per-run custody is pending. | +| Deployable release | The release owner packages selected native outputs and the dependency closure. | A frozen manifest binds release digest, delivered bytes, application source and toolchain identities. The consumer verifies the manifest before activation. | Binding is specified in the Governor preregistration. No release publication job is allocated here. | +| Runtime and site qualification | The launcher selects the catalog. The Rust authority owns the ledger. The site owns approval, activation, replay and formal results. | Bind activation, catalog and replay to one release digest and an admitted ledger cut or verified snapshot. Site records have independent retention. | Catalog and ledger inputs exist. Site approval and approved replay are pending. | + +For the pending local storage work, use the existing owners and these +subdirectories of the existing roots. + +#+begin_example +.cache/verification/runs//.json +.cache/verification/latest-.json +.cache/weaver-deployment-qualification/runs// + weaver.toml + governance/catalog.json + ledger/ +#+end_example + +The first path is the proposed authoritative local suite receipt. The second +remains the existing convenience path, updated only after the run receipt is +committed. The native integration test owns the qualification directory and +selects the actual config and ledger paths for its roles. The runtime +continues to receive its settings through the existing launcher boundary. + +The deployment and experiment contract is in +[[file:59.64-governance-capture-ownership.org::*Governor release preregistration][Governor release preregistration]]. +The local run identity needs to distinguish retries of the same source and +record the tested checkout, resolved inputs and execution scope. A latest +view can point to a failed run, and an incomplete attempt must remain visible +as such. Native diagnostics are process scratch, with bounded structured +fields retained in the run record. Existing historical evidence remains in +its original custody. + +Accept the local storage change when concurrent runs and a failed retry keep +their distinct receipts, latest resolves to a complete receipt with the same +run identity, and cleaning a build leaves both verification evidence and +site data intact. These are bounded controls using the existing Go entry and +fixture, independent of formal release sampling. + +** Implemented CI receipt layout + =WeaverProject::Verification::Artifacts= in =Project.sysml= owns the publication inventory. The workflow test checks the declared CI receipt paths against the actual upload allowlist. GitHub receives one artifact per suite, runner, tested @@ -100,12 +149,21 @@ from existing; the job receipt records the failed phase and skipped phases. A successful workflow requires its bootstrap and suite receipts before publishing the job envelope. Diagnostic excerpts are bounded fields within receipts. +The verification owner stops dependency preparation at 3 minutes for Rust +and Go and 7 minutes for proof dependencies. It stops Scheme verification at +18 minutes and the other suites at 28 minutes. Each GitHub step allows another +one or two minutes for tool invocation, process cleanup and receipt writing. +A runner deadline records `TIMEOUT` in JSON. The separate 12-second recovery +and 15-second natural-exit fences remain inside native integration. + Praxis separates benchmark execution and comparison and publishes a typed result keyed by the tested SHA. Agent Gateway gives timing and failure artifacts their own job-scoped paths. Weaver applies those ownership boundaries to its existing verification owner and publishes the SysML-declared JSON inventory. +Agent Gateway also uses a dedicated release workflow for registry images. [[https://github.com/praxis-proxy/praxis/blob/c3d2ae3628cf3167780e58c5e8b38580d0241399/.github/workflows/benchmarks.yaml][Praxis benchmark workflow]] [[https://github.com/agentgateway/agentgateway/blob/134897e1975fa26fa5c5b8ba45d720d05d3f7fb8/.github/workflows/pull_request.yml][Agent Gateway pull request workflow]] +[[https://github.com/agentgateway/agentgateway/blob/134897e1975fa26fa5c5b8ba45d720d05d3f7fb8/.github/workflows/release.yml][Agent Gateway release workflow]] * Qualification boundaries diff --git a/go/cmd/weaver-dev/main.go b/go/cmd/weaver-dev/main.go index 7fd2e297..8aaf3b99 100644 --- a/go/cmd/weaver-dev/main.go +++ b/go/cmd/weaver-dev/main.go @@ -26,8 +26,12 @@ func main() { func run() error { goBinary := flag.String("go-bin", "", "Go executable; defaults to the compiling toolchain") clean := flag.Bool("clean-source", false, "Require every verification input to match the same committed revision") + timeout := flag.Duration("timeout", 0, "Verification deadline including all native stages (zero disables it)") view := flag.String("view", "", "Render one exact SysML-mapped D2 source; default renders the complete inventory") flag.Parse() + if *timeout < 0 { + return errors.New("-timeout must be nonnegative") + } if flag.NArg() != 1 { return errors.New("usage: weaver-dev [-go-bin PATH] [-clean-source] qualify-policy|bootstrap|bootstrap-build|bootstrap-proofs|check|check-rust|check-go|check-policy|check-architecture|check-scheme|check-storage|check-telemetry|bench|bench-runtime|bench-execution|render-diagrams|check-diagrams|generate-rpc|prepare-ci-host") } @@ -49,6 +53,11 @@ func run() error { } ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) defer stop() + if *timeout > 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, *timeout) + defer cancel() + } if flag.Arg(0) == "qualify-policy" { qualified, err := devrunner.QualifySpec(ctx, working) if err != nil { diff --git a/go/dev/ci_test.go b/go/dev/ci_test.go index 0f9f13a8..6c9a246e 100644 --- a/go/dev/ci_test.go +++ b/go/dev/ci_test.go @@ -9,6 +9,7 @@ import ( "path/filepath" "strings" "testing" + "time" "github.com/HardenedLinux/weaver/go/internal/devrunner" "gopkg.in/yaml.v3" @@ -91,9 +92,12 @@ func TestCIWorkflowsMatchProjectSuites(t *testing.T) { } `yaml:"on"` Jobs map[string]struct { Steps []struct { - Uses string `yaml:"uses"` - If string `yaml:"if"` - With struct { + ID string `yaml:"id"` + Uses string `yaml:"uses"` + If string `yaml:"if"` + Run string `yaml:"run"` + TimeoutMinutes int `yaml:"timeout-minutes"` + With struct { Path string `yaml:"path"` } `yaml:"with"` } `yaml:"steps"` @@ -115,7 +119,21 @@ func TestCIWorkflowsMatchProjectSuites(t *testing.T) { if len(wantedReceipts) == 0 { t.Fatal("missing SysML CI receipt allocation") } + deadlined := map[string]bool{ + "bootstrap_build": true, "bootstrap_proofs": true, + "verify_suite": true, "verify_scheme": true, + } for _, step := range reusable.Jobs["verify"].Steps { + if deadlined[step.ID] { + _, tail, hasDeadline := strings.Cut(step.Run, "-timeout ") + value, _, hasCommand := strings.Cut(tail, " ") + inner, err := time.ParseDuration(value) + outer := time.Duration(step.TimeoutMinutes) * time.Minute + if !hasDeadline || !hasCommand || err != nil || inner <= 0 || outer-inner < time.Minute { + t.Fatalf("%s must leave a minute between its runner deadline and GitHub cutoff", step.ID) + } + delete(deadlined, step.ID) + } if !strings.HasPrefix(step.Uses, "actions/upload-artifact@") { continue } @@ -132,6 +150,9 @@ func TestCIWorkflowsMatchProjectSuites(t *testing.T) { if len(wantedReceipts) != 0 { t.Fatalf("CI upload is missing declared receipts: %v", wantedReceipts) } + if len(deadlined) != 0 { + t.Fatalf("missing CI phases with native deadlines: %v", deadlined) + } for _, path := range []string{".github/workflows/verify-suite.yml", ".github/actions/prepare-toolchain/action.yml"} { data, err := os.ReadFile(filepath.Join(root(t), path)) if err != nil { diff --git a/go/internal/devrunner/retention.go b/go/internal/devrunner/retention.go index a37f0df6..385460a9 100644 --- a/go/internal/devrunner/retention.go +++ b/go/internal/devrunner/retention.go @@ -142,7 +142,7 @@ func publishLatestResult(root, directory, mode string, runErr error) (path strin if receipt.Status == "PASS" { receipt.Stages = append(receipt.Stages, Result{Name: "run-finalization", Status: "FAIL", Error: runErr.Error()}) } - if receipt.Status != "CANCELLED" { + if receipt.Status != "CANCELLED" && receipt.Status != "TIMEOUT" { receipt.Status = "FAIL" } } diff --git a/go/internal/devrunner/runner.go b/go/internal/devrunner/runner.go index fa8184a8..38f2812a 100644 --- a/go/internal/devrunner/runner.go +++ b/go/internal/devrunner/runner.go @@ -132,13 +132,20 @@ func Run(ctx context.Context, config Config, output io.Writer) (report string, r if config.RequireClean { admission, revision := committedSource(ctx, root, directory, "committed-source-before", "", inputs) receipt.Revision = revision + if interruption := ctx.Err(); interruption != nil { + admission.Status = interruptionStatus(interruption) + admission.Error = interruption.Error() + } receipt.Stages = append(receipt.Stages, admission) if admission.Status != "PASS" { - receipt.Status = "FAIL" + receipt.Status = admission.Status if err := writeReceipt(directory, receipt); err != nil { return directory, err } - fmt.Fprintf(output, "FAIL %s\n", admission.Name) + fmt.Fprintf(output, "%s %s\n", admission.Status, admission.Name) + if ctx.Err() != nil { + return directory, ctx.Err() + } return directory, errors.New("source does not match a committed revision") } fmt.Fprintf(output, "PASS %s\n", admission.Name) @@ -161,7 +168,6 @@ func Run(ctx context.Context, config Config, output io.Writer) (report string, r } for _, stage := range stages { if ctx.Err() != nil { - receipt.Status = "CANCELLED" failed = true break } @@ -175,7 +181,7 @@ func Run(ctx context.Context, config Config, output io.Writer) (report string, r } fmt.Fprintf(output, "%s %s\n", result.Status, result.Name) } - if mode != "generate-rpc" { + if mode != "generate-rpc" && ctx.Err() == nil { current := sourceCurrentness(root, directory, inputs) receipt.Stages = append(receipt.Stages, current) if current.Status != "PASS" { @@ -189,7 +195,7 @@ func Run(ctx context.Context, config Config, output io.Writer) (report string, r fmt.Fprintf(output, "FAIL benchmark artifacts: %v\n", err) } } - if config.RequireClean { + if config.RequireClean && ctx.Err() == nil { admission, _ := committedSource(ctx, root, directory, "committed-source-after", receipt.Revision, inputs) receipt.Stages = append(receipt.Stages, admission) if admission.Status != "PASS" { @@ -198,10 +204,10 @@ func Run(ctx context.Context, config Config, output io.Writer) (report string, r fmt.Fprintf(output, "%s %s\n", admission.Status, admission.Name) } if ctx.Err() != nil { - receipt.Status = "CANCELLED" + receipt.Status = interruptionStatus(ctx.Err()) failed = true } - if receipt.Status != "CANCELLED" { + if receipt.Status == "RUNNING" { if refs, err := proofReferences(root, receipt.Stages); err != nil { receipt.Stages = append(receipt.Stages, Result{Name: "proof-references", Status: "FAIL", Error: err.Error()}) failed = true @@ -218,10 +224,18 @@ func Run(ctx context.Context, config Config, output io.Writer) (report string, r } fmt.Fprintf(output, "Result: %s\n", latestResultPath(root, mode)) if failed { - return directory, errors.New("verification did not pass; see the latest structured result") + return directory, errors.Join(errors.New("verification did not pass; see the latest structured result"), ctx.Err()) } return directory, nil } + +func interruptionStatus(err error) string { + if errors.Is(err, context.DeadlineExceeded) { + return "TIMEOUT" + } + return "CANCELLED" +} + func runStage(ctx context.Context, root, directory string, environment []string, stage Stage) Result { return runStageCapture(ctx, root, directory, environment, stage, true) } @@ -257,6 +271,7 @@ func runStageObserved(ctx context.Context, root, directory string, environment [ return result } cmd := exec.CommandContext(ctx, stage.Binary, stage.Args...) + boundStageProcess(cmd) result.ResolvedBinary = cmd.Path if resolved, err := filepath.EvalSymlinks(cmd.Path); err == nil { result.ResolvedBinary = resolved @@ -278,6 +293,9 @@ func runStageObserved(ctx context.Context, root, directory string, environment [ } err = cmd.Wait() } + if err == nil { + err = ctx.Err() + } finished := time.Now() if observation != nil { result.SchemeTiming = observation.timing(finished) @@ -367,7 +385,13 @@ func runStageObserved(ctx context.Context, root, directory string, environment [ code := cmd.ProcessState.ExitCode() result.ExitCode = &code } - if err == nil && closeErr == nil { + if interruption := ctx.Err(); interruption != nil { + result.Status = interruptionStatus(interruption) + if !errors.Is(err, interruption) { + err = errors.Join(err, interruption) + } + result.Error = fmt.Sprint(errors.Join(err, closeErr)) + } else if err == nil && closeErr == nil { result.Status = "PASS" } else { result.Error = fmt.Sprint(errors.Join(err, closeErr)) diff --git a/go/internal/devrunner/stage_process_other.go b/go/internal/devrunner/stage_process_other.go new file mode 100644 index 00000000..09ce3f58 --- /dev/null +++ b/go/internal/devrunner/stage_process_other.go @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build !unix + +package devrunner + +import ( + "os/exec" + "time" +) + +func boundStageProcess(cmd *exec.Cmd) { + cmd.WaitDelay = 2 * time.Second +} diff --git a/go/internal/devrunner/stage_process_unix.go b/go/internal/devrunner/stage_process_unix.go new file mode 100644 index 00000000..ccd035de --- /dev/null +++ b/go/internal/devrunner/stage_process_unix.go @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build unix + +package devrunner + +import ( + "errors" + "os" + "os/exec" + "syscall" + "time" +) + +func boundStageProcess(cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + cmd.Cancel = func() error { + err := syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) + if errors.Is(err, syscall.ESRCH) { + return os.ErrProcessDone + } + return err + } + cmd.WaitDelay = 2 * time.Second +} diff --git a/go/internal/devrunner/stage_process_unix_test.go b/go/internal/devrunner/stage_process_unix_test.go new file mode 100644 index 00000000..358c0f27 --- /dev/null +++ b/go/internal/devrunner/stage_process_unix_test.go @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build unix + +package devrunner + +import ( + "context" + "errors" + "os" + "path/filepath" + "strings" + "testing" + "time" +) + +func TestStageDeadlineRetainsEvidenceAndStopsChild(t *testing.T) { + root, scratch := t.TempDir(), t.TempDir() + ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) + defer cancel() + result := runStage(ctx, root, scratch, os.Environ(), Stage{ + Name: "deadline-control", Binary: "sh", + Args: []string{"-c", "(sleep 1; touch survived) & echo child-started; wait"}, + }) + if result.Status != "TIMEOUT" || !strings.Contains(result.Error, context.DeadlineExceeded.Error()) { + t.Fatalf("expected a timeout result, got %+v", result) + } + receipt := Receipt{Status: "TIMEOUT", Root: root, Mode: "check", Stages: []Result{result}} + if err := writeReceipt(scratch, receipt); err != nil { + t.Fatal(err) + } + path, err := publishLatestResult(root, scratch, "check", context.DeadlineExceeded) + if err != nil { + t.Fatal(err) + } + content, err := os.ReadFile(path) + if err != nil || !strings.Contains(string(content), "child-started") || !strings.Contains(string(content), `"status": "TIMEOUT"`) { + t.Fatalf("timeout evidence was lost: %s (%v)", content, err) + } + time.Sleep(1100 * time.Millisecond) + if _, err := os.Stat(filepath.Join(root, "survived")); !errors.Is(err, os.ErrNotExist) { + t.Fatalf("descendant escaped stage cancellation: %v", err) + } +} From 368ce519362a93dd9f14dad186583485e519d723 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 18:47:19 +0800 Subject: [PATCH 008/105] Allocate artifact declarations to Scheme and materialization to Rust --- Project.sysml | 36 ++++++++++++++---- .../59-provider-rpc/59.22-parallel-ci.org | 37 +++++++++++++------ 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/Project.sysml b/Project.sysml index ceec3cda..fdbe4419 100644 --- a/Project.sysml +++ b/Project.sysml @@ -120,10 +120,13 @@ package WeaverProject { } package ArtifactOrganization { - doc /* Project-wide custody and lifecycle. Verification::Artifacts owns - the implemented CI path inventory. Each other producer keeps its - native entry point and store. This model allocates responsibility - and records remaining implementation work. */ + doc /* Project-wide custody and lifecycle. SysML allocates the + responsibilities. The intended executable declaration lives in + Gerbil Scheme through the Weaver Scheme/POO Module system. + Verification::Artifacts records the implemented CI paths until + the executable projection can be checked against the workflow. */ + part def SchemeArtifactDeclaration; + part def RustArtifactMaterializer; part def ReproducibleInput; part def NativeBuildProduct; part def VerificationRun; @@ -133,6 +136,24 @@ package WeaverProject { part def SiteRuntimeState; part def SiteQualification; + part artifactPlan : SchemeArtifactDeclaration { + doc /* Typed POO objects declare artifact kinds, relative layout, + producers, identity bindings, publication scope and retention. + The existing Module Interface exports the checked plan. + Gerbil Build Packages compiles that export. Derive Rust input + and the CI publication inventory from the same plan. A change + to an admitted declaration invalidates both projections. */ + } + part materialization : RustArtifactMaterializer { + doc /* Rust consumes the versioned Scheme plan over the existing + typed bridge or its build projection. Validate relative paths + and required identity before materializing a typed record. + Publish the immutable run record before advancing latest. + Go and native tools supply observations. GitHub can still + record early job failures before the native owner exists. + Neither observation path may override Scheme publication rules. + The Scheme declaration and Rust materializer are design work. */ + } part checkedInSources : ReproducibleInput { doc /* Git owns source, schemas, locks, deterministic fixtures and reproducible projections. A generated file in Git must have a @@ -146,9 +167,10 @@ package WeaverProject { outputs and does not remove verification evidence or site data. */ } part verificationRuns : VerificationRun { - doc /* weaver-dev and the existing native suites emit typed outcomes. - Verification::Artifacts declares the implemented local and CI - paths. CI retains outcomes by job attempt for seven days. + doc /* weaver-dev and native suites produce verification outcomes. + Rust materializes records from those observations under the + Scheme plan once implemented. Verification::Artifacts declares + the current local and CI paths. CI retains job attempts for seven days. The remaining local design retains an immutable run by identity before updating any latest view. A failed or incomplete attempt remains separately addressable and never qualifies the input. */ diff --git a/docs/50-59-research-program/59-provider-rpc/59.22-parallel-ci.org b/docs/50-59-research-program/59-provider-rpc/59.22-parallel-ci.org index 5d926184..f465a2db 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.22-parallel-ci.org +++ b/docs/50-59-research-program/59-provider-rpc/59.22-parallel-ci.org @@ -69,15 +69,28 @@ from application and formal proof results. * Artifact organization =WeaverProject::ArtifactOrganization= in =Project.sysml= allocates the -project-wide lifecycle. The build owner produces bytes, verification records -what it exercised, and the deployment owner selects and activates a release. -The site binds formal measurements to that activation. +project-wide lifecycle. Gerbil Scheme is the planned source of executable +artifact declarations. POO objects describe each artifact's kind, producer, +relative location, identity fields, publication scope and retention. +Use the existing Yuanxu Module Interface and Gerbil Build Packages. The +Rust owner consumes the compiled, versioned declaration through the existing +typed Scheme bridge or a build projection of the same export. Rust validates +paths and bindings, writes the typed record atomically and advances =latest= +only after the immutable result is available. Go runs the existing tests +and passes their observations to the materializer. + +Generate or check the CI allowlist against that same Scheme declaration. +GitHub keeps its own minimal job envelope for checkout or bootstrap failures +that occur before the native materializer is available. Cargo and Gerbil +continue to own their build products. Site authority owns approval and +activation. The Scheme declaration and Rust materializer remain to be +implemented. | Class | Owner and storage | Identity and retention | State | |-------+-------------------+------------------------+-------| | Reproducible inputs and projections | Git holds source, model, locks, fixed Snake Oil fixtures and reproducible views. | A committed generated file needs a checked-in recipe and reproducibility check. Per-run output stays outside Git. | Existing policy and entry points. | | Native outputs | Cargo owns =target/=. Gerbil Build Packages owns its package outputs. | Each tool reuses and cleans its own build products. A release selects the exact executable or image, Scheme library and resolved closure. | Native owners exist. The release handoff is specified below. | -| Verification | =weaver-dev= and native suite owners write under =.cache/verification/=. GitHub transports a JSON allowlist. | Job attempt and tested checkout identify remote evidence. The local design keeps a separate immutable result per run before advancing a latest view. | CI envelope and suite receipts implemented. Local suite files still use =latest-*.json=, while SPEC already has per-run paths. | +| Verification | Today =weaver-dev= and native suite owners write under =.cache/verification/=. The target gives Rust custody of materialization under the Scheme plan. | Job attempt and tested checkout identify remote evidence. The local design keeps a separate immutable result per run before advancing a latest view. | CI envelope and suite receipts implemented. Local suite files still use =latest-*.json=, while SPEC already has per-run paths. | | Local deployment qualification | The native Go entry runs Snake Oil. Its dedicated data root is =.cache/weaver-deployment-qualification/=. | New run directories should isolate generated catalog, configuration and ledger and associate them with the tested build and fixture. Retain original failed attempts with their verdicts. | Native path and dedicated root documented. Uniform per-run custody is pending. | | Deployable release | The release owner packages selected native outputs and the dependency closure. | A frozen manifest binds release digest, delivered bytes, application source and toolchain identities. The consumer verifies the manifest before activation. | Binding is specified in the Governor preregistration. No release publication job is allocated here. | | Runtime and site qualification | The launcher selects the catalog. The Rust authority owns the ledger. The site owns approval, activation, replay and formal results. | Bind activation, catalog and replay to one release digest and an admitted ledger cut or verified snapshot. Site records have independent retention. | Catalog and ledger inputs exist. Site approval and approved replay are pending. | @@ -109,16 +122,18 @@ as such. Native diagnostics are process scratch, with bounded structured fields retained in the run record. Existing historical evidence remains in its original custody. -Accept the local storage change when concurrent runs and a failed retry keep -their distinct receipts, latest resolves to a complete receipt with the same -run identity, and cleaning a build leaves both verification evidence and -site data intact. These are bounded controls using the existing Go entry and -fixture, independent of formal release sampling. +Start with verification receipts as the first vertical slice. Accept it +when a changed Scheme declaration updates both the Rust writer and the CI +inventory, an escaping path or mismatched declaration identity is refused, +and concurrent runs and a failed retry keep their distinct receipts. Verify +that latest resolves to a complete receipt with the same run identity and +that cleaning a build leaves both evidence and site data intact. Use bounded +controls at the existing Go entry, independent of formal release sampling. ** Implemented CI receipt layout -=WeaverProject::Verification::Artifacts= in =Project.sysml= owns the publication -inventory. The workflow test checks the declared CI receipt paths against the +=WeaverProject::Verification::Artifacts= in =Project.sysml= describes the current +publication inventory. The workflow test checks the declared CI receipt paths against the actual upload allowlist. GitHub receives one artifact per suite, runner, tested checkout and run attempt. From 3924da5c6ac7047f1281aafc73d489b9e3e9f695 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 18:58:47 +0800 Subject: [PATCH 009/105] Capture early stream failures in the saturation gate --- go/dev/provider_capacity_test.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/go/dev/provider_capacity_test.go b/go/dev/provider_capacity_test.go index f1886675..fa1dda07 100644 --- a/go/dev/provider_capacity_test.go +++ b/go/dev/provider_capacity_test.go @@ -79,6 +79,7 @@ func TestProviderSaturatedExecutionPreservesRevocationAndObservation(t *testing. } first := make(chan struct{}, streams) type outcome struct { + node string count int err error } @@ -93,14 +94,18 @@ func TestProviderSaturatedExecutionPreservesRevocationAndObservation(t *testing. } return nil }) - results <- outcome{count, err} + results <- outcome{node: plan.Node, count: count, err: err} }() } - for range streams { + for ready := range streams { select { case <-first: + case result := <-results: + t.Fatalf("stream %s ended before revocation after %d events (%d/%d first events observed, %d primary requests): %v", + result.node, result.count, ready, streams, f.primary.Load(), result.err) case <-ctx.Done(): - t.Fatal("execution capacity did not fill before deadline") + t.Fatalf("execution capacity did not fill before deadline (%d/%d first events observed, %d primary requests)", + ready, streams, f.primary.Load()) } } // Capacity rejection occurs before considering a duplicate root or its Policy. From f89d741260ee3eda61803eefcaf19f745e86f2a2 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 19:25:24 +0800 Subject: [PATCH 010/105] Drive provider SSE and delivery readiness on Tokio --- crates/broker/Cargo.toml | 2 +- crates/broker/src/provider/anthropic_sse.rs | 24 ++++---- crates/broker/src/provider/io_runtime.rs | 4 +- crates/broker/src/provider/openai_sse.rs | 22 +++---- crates/broker/src/provider/range_output.rs | 56 ++++++++++++++---- crates/broker/src/provider/response.rs | 58 ++++++++++--------- crates/broker/src/provider/runtime.rs | 54 +++++++++++------ crates/broker/tests/unit/provider_sse.rs | 45 ++++++++++---- crates/ledger/src/persistence/authority.rs | 20 +++++++ crates/ledger/src/persistence/scope.rs | 52 ++++++++++++----- crates/ledger/src/provider_delivery.rs | 17 ++++++ crates/ledger/tests/unit/provider_delivery.rs | 22 ++++++- crates/server/src/grpc_delivery_producer.rs | 29 +++++++--- crates/server/src/grpc_output.rs | 16 +++++ dev/sysml/ProviderRpc.sysml | 8 +++ 15 files changed, 317 insertions(+), 112 deletions(-) diff --git a/crates/broker/Cargo.toml b/crates/broker/Cargo.toml index 061fbb3f..63f63ccd 100644 --- a/crates/broker/Cargo.toml +++ b/crates/broker/Cargo.toml @@ -22,12 +22,12 @@ http-body-util.workspace = true tokio.workspace = true tokio-rustls.workspace = true rustls-platform-verifier.workspace = true -futures-executor.workspace = true rustls.workspace = true serde.workspace = true serde_json.workspace = true [dev-dependencies] asp-rust.workspace = true +futures-executor.workspace = true criterion.workspace = true tempfile.workspace = true rcgen.workspace = true diff --git a/crates/broker/src/provider/anthropic_sse.rs b/crates/broker/src/provider/anthropic_sse.rs index 9f8a2b23..b2430083 100644 --- a/crates/broker/src/provider/anthropic_sse.rs +++ b/crates/broker/src/provider/anthropic_sse.rs @@ -4,7 +4,7 @@ //! Bounded Anthropic Messages text stream. Only message_stop completes usage. use serde_json::Value; -use std::io::{BufRead, BufReader, Read}; +use tokio::io::{AsyncBufReadExt, AsyncRead, AsyncReadExt, BufReader}; use weaver_contracts::{Error, MAX_CREDITS, ProviderEvent, ProviderEventKind, Result}; pub(super) struct Decoder { @@ -28,7 +28,7 @@ enum State { Done, } -impl Decoder { +impl Decoder { pub(super) fn new(reader: R, model: &str) -> Self { Self { reader: BufReader::new(reader), @@ -47,17 +47,18 @@ impl Decoder { self.tokens } - pub(super) fn next(&mut self) -> Result { - self.next_event(false)? + pub(super) async fn next(&mut self) -> Result { + self.next_event(false) + .await? .ok_or(Error::Conflict("Anthropic stream missing terminal event")) } - pub(super) fn next_buffered(&mut self) -> Result> { - self.next_event(true) + pub(super) async fn next_buffered(&mut self) -> Result> { + self.next_event(true).await } - fn next_event(&mut self, buffered: bool) -> Result> { - while let Some(frame) = self.frame(buffered)? { + async fn next_event(&mut self, buffered: bool) -> Result> { + while let Some(frame) = self.frame(buffered).await? { if let Some(event) = self.accept(&frame)? { return Ok(Some(event)); } @@ -65,7 +66,7 @@ impl Decoder { Ok(None) } - fn frame(&mut self, buffered: bool) -> Result> { + async fn frame(&mut self, buffered: bool) -> Result> { if buffered && !super::sse_buffer::buffered_sse_record(self.reader.buffer()) { return Ok(None); } @@ -73,11 +74,10 @@ impl Decoder { let mut kind = None; loop { self.line.clear(); - let count = self - .reader - .by_ref() + let count = (&mut self.reader) .take(65537) .read_until(b'\n', &mut self.line) + .await .map_err(|_| Error::Conflict("Anthropic stream interrupted"))?; if count == 0 || self.line.last() != Some(&b'\n') { return Err(Error::Conflict("Anthropic stream missing terminal event")); diff --git a/crates/broker/src/provider/io_runtime.rs b/crates/broker/src/provider/io_runtime.rs index 7279447d..2f1c9ad6 100644 --- a/crates/broker/src/provider/io_runtime.rs +++ b/crates/broker/src/provider/io_runtime.rs @@ -18,8 +18,8 @@ impl IoRuntime { if Instant::now() >= deadline { return Err(Error::Conflict("provider outcome unknown")); } - let _entered = self.handle.enter(); - futures_executor::block_on(tokio::time::timeout_at(deadline, future)) + self.handle + .block_on(async { tokio::time::timeout_at(deadline, future).await }) .map_err(|_| Error::Conflict("provider outcome unknown"))? } } diff --git a/crates/broker/src/provider/openai_sse.rs b/crates/broker/src/provider/openai_sse.rs index 1ba624ca..f6c48aad 100644 --- a/crates/broker/src/provider/openai_sse.rs +++ b/crates/broker/src/provider/openai_sse.rs @@ -3,9 +3,9 @@ // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 //! Incremental, bounded data-only SSE decoder for single-choice text completions. -use std::io::{BufRead, BufReader, Read}; +use tokio::io::{AsyncBufReadExt, AsyncRead, BufReader}; use weaver_contracts::{Error, ProviderEvent, ProviderEventKind, Result}; -pub(super) struct Decoder { +pub(super) struct Decoder { input: BufReader, model: String, id: Option, @@ -19,7 +19,7 @@ pub(super) struct Decoder { #[cfg(test)] #[path = "../../tests/unit/provider_sse.rs"] mod tests; -impl Decoder { +impl Decoder { pub(super) fn new(input: R, model: &str) -> Self { Self { input: BufReader::new(input), @@ -32,22 +32,23 @@ impl Decoder { terminal_tokens: None, } } - pub(super) fn next(&mut self) -> Result { - self.next_event(false)? + pub(super) async fn next(&mut self) -> Result { + self.next_event(false) + .await? .ok_or(Error::Conflict("SSE ended without DONE")) } - pub(super) fn next_buffered(&mut self) -> Result> { - self.next_event(true) + pub(super) async fn next_buffered(&mut self) -> Result> { + self.next_event(true).await } - fn next_event(&mut self, buffered: bool) -> Result> { + async fn next_event(&mut self, buffered: bool) -> Result> { let mut data = Vec::new(); if buffered && !super::sse_buffer::buffered_sse_record(self.input.buffer()) { return Ok(None); } loop { - let line = self.line()?; + let line = self.line().await?; if line.is_empty() { if data.is_empty() { if buffered && !super::sse_buffer::buffered_sse_record(self.input.buffer()) { @@ -88,12 +89,13 @@ impl Decoder { } } } - fn line(&mut self) -> Result> { + async fn line(&mut self) -> Result> { let mut line = Vec::new(); loop { let buffer = self .input .fill_buf() + .await .map_err(|_| Error::Conflict("provider stream interrupted"))?; if buffer.is_empty() { return Err(Error::Conflict("SSE ended without DONE")); diff --git a/crates/broker/src/provider/range_output.rs b/crates/broker/src/provider/range_output.rs index 8c0e84a4..ea638cd8 100644 --- a/crates/broker/src/provider/range_output.rs +++ b/crates/broker/src/provider/range_output.rs @@ -4,39 +4,75 @@ //! Opportunistic storage coalescing with one guarded queue insertion per frame. use super::runtime::{ProviderOutput, StreamDecoder}; -use std::io::Read; +use std::future::poll_fn; +use tokio::io::AsyncRead; use weaver_contracts::{Error, ProviderEvent, ProviderEventKind, Result, body_digest}; use weaver_ledger::{ Ledger, MAX_PROVIDER_PREPARATION_RANGES, MAX_PROVIDER_PREPARATION_ROWS, ProviderDispatch, ProviderRelease, }; -pub(super) fn relay( +pub(super) fn relay( ledger: &mut Ledger, permit: &ProviderDispatch, output: &mut O, - reader: &mut StreamDecoder, + response: super::response::Response, format: &str, rows: usize, -) -> Result<()> { +) -> Result> { let mut pending = Vec::with_capacity(rows); let width = preparation_width(output, rows); + let (reactor, deadline) = response.reactor(); + let mut reader = StreamDecoder::new(response, permit); loop { if output.stopped() { return Err(Error::Conflict("provider response cancelled")); } - let mut terminal = push_event(&mut pending, reader.next()?); + // Keep the exact decoder future across wakeups, including partially + // consumed SSE records. The blocking owner services ledger work between + // reactor waits and never while holding a network poll. + let event = { + let mut next = std::pin::pin!(reader.next()); + loop { + let pending = output.service_delivery(ledger, permit, format)?; + let event = reactor.wait(deadline, async { + if let Some(delivery_deadline) = pending { + tokio::select! { + biased; + () = poll_fn(|cx| output.poll_delivery_ready(cx)) => Ok(None), + () = tokio::time::sleep_until(delivery_deadline) => Ok(None), + event = &mut next => event.map(Some), + } + } else { + next.as_mut().await.map(Some) + } + })?; + if let Some(event) = event { + break event; + } + } + }; + let mut terminal = push_event(&mut pending, event); if !terminal && pending.len() != rows { continue; } let mut ready = Vec::with_capacity(width); ready.push(std::mem::replace(&mut pending, Vec::with_capacity(rows))); - let buffered = - collect_buffered(reader, &mut pending, &mut ready, rows, width, &mut terminal); + let buffered = reactor.wait( + deadline, + collect_buffered( + &mut reader, + &mut pending, + &mut ready, + rows, + width, + &mut terminal, + ), + ); release_ranges(ledger, permit, output, format, &mut ready)?; buffered?; if terminal { - return Ok(()); + return Ok(reader.terminal_tokens()); } } } @@ -55,7 +91,7 @@ fn push_event(range: &mut Vec, event: ProviderEvent) -> bool { terminal } -fn collect_buffered( +async fn collect_buffered( reader: &mut StreamDecoder, pending: &mut Vec, ready: &mut Vec>, @@ -64,7 +100,7 @@ fn collect_buffered( terminal: &mut bool, ) -> Result<()> { while !*terminal && ready.len() < width { - let Some(event) = reader.next_buffered()? else { + let Some(event) = reader.next_buffered().await? else { break; }; *terminal = push_event(pending, event); diff --git a/crates/broker/src/provider/response.rs b/crates/broker/src/provider/response.rs index 704b5122..9d654417 100644 --- a/crates/broker/src/provider/response.rs +++ b/crates/broker/src/provider/response.rs @@ -17,7 +17,7 @@ use hyper::{ use hyper_util::rt::TokioIo; use std::{ future::{Future, poll_fn}, - io::{self, Read}, + io, pin::Pin, sync::{ Arc, @@ -25,7 +25,11 @@ use std::{ }, task::{Context, Poll}, }; -use tokio::{net::TcpStream, time::Instant}; +use tokio::{ + io::{AsyncRead, ReadBuf}, + net::TcpStream, + time::Instant, +}; use tokio_rustls::client::TlsStream; use weaver_contracts::{Error, Result}; pub(super) type Connection = @@ -146,34 +150,36 @@ pub(super) struct Response { runtime: Arc, deadline: Instant, } -impl Read for Response { - fn read(&mut self, bytes: &mut [u8]) -> io::Result { - if bytes.is_empty() { - return Ok(0); +impl Response { + pub(super) fn reactor(&self) -> (Arc, Instant) { + (self.runtime.clone(), self.deadline) + } +} +impl AsyncRead for Response { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bytes: &mut ReadBuf<'_>, + ) -> Poll> { + if bytes.remaining() == 0 { + return Poll::Ready(Ok(())); } - while self.pending.is_empty() { - let frame = self - .runtime - .wait( - self.deadline, - poll_fn(|cx| { - self.driver.pump(cx)?; - Pin::new(&mut self.body).poll_frame(cx).map(|r| { - r.transpose() - .map_err(|_| Error::Conflict("provider outcome unknown")) - }) - }), - ) - .map_err(|_| io::Error::from(io::ErrorKind::ConnectionAborted))?; - let Some(frame) = frame else { return Ok(0) }; + let this = self.get_mut(); + let aborted = |_| io::Error::from(io::ErrorKind::ConnectionAborted); + while this.pending.is_empty() { + this.driver.pump(cx).map_err(aborted)?; + let Some(frame) = std::task::ready!(Pin::new(&mut this.body).poll_frame(cx)) else { + return Poll::Ready(Ok(())); + }; + let frame = frame.map_err(|_| io::Error::from(io::ErrorKind::ConnectionAborted))?; // Hyper parses chunk framing. Trailer metadata cannot authorize use. if let Ok(data) = frame.into_data() { - self.pending = data; + this.pending = data; } } - let count = bytes.len().min(self.pending.len()); - bytes[..count].copy_from_slice(&self.pending[..count]); - self.pending = self.pending.slice(count..); - Ok(count) + let count = bytes.remaining().min(this.pending.len()); + bytes.put_slice(&this.pending[..count]); + this.pending = this.pending.slice(count..); + Poll::Ready(Ok(())) } } diff --git a/crates/broker/src/provider/runtime.rs b/crates/broker/src/provider/runtime.rs index 77452924..9142dfc0 100644 --- a/crates/broker/src/provider/runtime.rs +++ b/crates/broker/src/provider/runtime.rs @@ -218,6 +218,20 @@ pub trait ProviderOutput { type PreparedFrame; fn stopped(&self) -> bool; fn reserve(&mut self) -> Result; + /// Advance local handoffs while waiting for upstream data and return the + /// original deadline of the oldest pending handoff. + fn service_delivery( + &mut self, + _ledger: &mut Ledger, + _permit: &ProviderDispatch, + _format: &str, + ) -> Result> { + Ok(None) + } + /// Poll the oldest pending handoff's state changes on the same reactor. + fn poll_delivery_ready(&self, _cx: &mut std::task::Context<'_>) -> std::task::Poll<()> { + std::task::Poll::Pending + } /// Reconcile bounded inert deliveries before waiting for actual output credit. fn reserve_for_delivery( &mut self, @@ -347,40 +361,42 @@ pub fn execute_catalog_provider_with_oauth( oauth, )?; let response = open_guarded(ledger, &permit, transport, output)?; - let mut reader = match permit.protocol() { - ProviderProtocol::OpenAi => { - StreamDecoder::OpenAi(openai_sse::Decoder::new(response, &plan.model)) - } - ProviderProtocol::Anthropic => { - StreamDecoder::Anthropic(anthropic_sse::Decoder::new(response, &plan.model)) - } - }; - super::range_output::relay(ledger, &permit, output, &mut reader, format, batch_rows)?; + let tokens = super::range_output::relay(ledger, &permit, output, response, format, batch_rows)?; output.drain_delivery(ledger, &permit, format)?; - ledger.complete_provider_with_usage(&permit, format, reader.terminal_tokens()) + ledger.complete_provider_with_usage(&permit, format, tokens) } -pub(super) enum StreamDecoder { +pub(super) enum StreamDecoder { OpenAi(openai_sse::Decoder), Anthropic(anthropic_sse::Decoder), } -impl StreamDecoder { - pub(super) fn next(&mut self) -> Result { +impl StreamDecoder { + pub(super) fn new(input: R, permit: &ProviderDispatch) -> Self { + let model = &permit.plan().model; + match permit.protocol() { + ProviderProtocol::OpenAi => Self::OpenAi(openai_sse::Decoder::new(input, model)), + ProviderProtocol::Anthropic => { + Self::Anthropic(anthropic_sse::Decoder::new(input, model)) + } + } + } + + pub(super) async fn next(&mut self) -> Result { match self { - Self::OpenAi(reader) => reader.next(), - Self::Anthropic(reader) => reader.next(), + Self::OpenAi(reader) => reader.next().await, + Self::Anthropic(reader) => reader.next().await, } } - pub(super) fn next_buffered(&mut self) -> Result> { + pub(super) async fn next_buffered(&mut self) -> Result> { match self { - Self::OpenAi(reader) => reader.next_buffered(), - Self::Anthropic(reader) => reader.next_buffered(), + Self::OpenAi(reader) => reader.next_buffered().await, + Self::Anthropic(reader) => reader.next_buffered().await, } } - fn terminal_tokens(&self) -> Option<[u64; 4]> { + pub(super) fn terminal_tokens(&self) -> Option<[u64; 4]> { match self { Self::OpenAi(reader) => reader.terminal_tokens, Self::Anthropic(reader) => Some(reader.tokens()), diff --git a/crates/broker/tests/unit/provider_sse.rs b/crates/broker/tests/unit/provider_sse.rs index e09d7cb2..ca3ef067 100644 --- a/crates/broker/tests/unit/provider_sse.rs +++ b/crates/broker/tests/unit/provider_sse.rs @@ -3,18 +3,38 @@ // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 use super::Decoder; -use std::io::{Cursor, Read}; +use std::{ + io::Cursor, + pin::Pin, + sync::LazyLock, + task::{Context, Poll}, +}; +use tokio::io::{AsyncRead, ReadBuf}; use weaver_contracts::ProviderEventKind; struct Fragmented { input: Cursor>, chunk: usize, } -impl Read for Fragmented { - fn read(&mut self, output: &mut [u8]) -> std::io::Result { - let count = output.len().min(self.chunk); - self.input.read(&mut output[..count]) +impl AsyncRead for Fragmented { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + output: &mut ReadBuf<'_>, + ) -> Poll> { + let limit = self.chunk.min(output.remaining()); + let mut fragment = ReadBuf::new(output.initialize_unfilled_to(limit)); + std::task::ready!(Pin::new(&mut self.input).poll_read(cx, &mut fragment))?; + let count = fragment.filled().len(); + output.advance(count); + Poll::Ready(Ok(())) } } +static RUNTIME: LazyLock = LazyLock::new(|| { + tokio::runtime::Builder::new_multi_thread() + .worker_threads(4) + .build() + .expect("Tokio test runtime") +}); fn stream(text: &str) -> Vec { let chunk = serde_json::json!({"id":"s","object":"chat.completion.chunk","model":"model-a","choices":[{"index":0,"delta":{"content":text},"finish_reason":null}]}); let finish = serde_json::json!({"id":"s","object":"chat.completion.chunk","model":"model-a","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}); @@ -25,30 +45,33 @@ proptest::proptest! { #[test] fn arbitrary_network_fragmentation_preserves_sse_identity(chunk in 1usize..64,text in "[a-z界é]{0,32}") { let mut decoder=Decoder::new(Fragmented{input:Cursor::new(stream(&text)),chunk},"model-a"); - let event=decoder.next().expect("delta");proptest::prop_assert_eq!(event.text,text); - proptest::prop_assert_eq!(decoder.next().expect("finish").kind,ProviderEventKind::Finish); - proptest::prop_assert_eq!(decoder.next().expect("done").kind,ProviderEventKind::Done); + let event=RUNTIME.block_on(decoder.next()).expect("delta");proptest::prop_assert_eq!(event.text,text); + proptest::prop_assert_eq!(RUNTIME.block_on(decoder.next()).expect("finish").kind,ProviderEventKind::Finish); + proptest::prop_assert_eq!(RUNTIME.block_on(decoder.next()).expect("done").kind,ProviderEventKind::Done); } } -#[test] -fn truncated_oversized_and_wrong_model_streams_are_not_completed() { +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] +async fn truncated_oversized_and_wrong_model_streams_are_not_completed() { assert!( Decoder::new(Cursor::new(b"data: [DONE]\n\n"), "model-a") .next() + .await .is_err() ); assert!( Decoder::new(Cursor::new(vec![b'x'; 65537]), "model-a") .next() + .await .is_err() ); let mut wrong = Decoder::new(Cursor::new(stream("hello")), "different-model"); - assert!(wrong.next().is_err()); + assert!(wrong.next().await.is_err()); let bytes = stream("prefix"); let end = bytes.iter().position(|b| *b == b'\n').expect("newline"); assert!( Decoder::new(Cursor::new(bytes[..end].to_vec()), "model-a") .next() + .await .is_err() ); } diff --git a/crates/ledger/src/persistence/authority.rs b/crates/ledger/src/persistence/authority.rs index da79d46c..75b9a48c 100644 --- a/crates/ledger/src/persistence/authority.rs +++ b/crates/ledger/src/persistence/authority.rs @@ -83,6 +83,7 @@ pub(crate) struct Receipt { pub consumed: bool, pub rejected: bool, pub waker: Option, + pub producer_waker: Option, pub deadline: Option, #[cfg(any(test, feature = "commit-observer"))] pub acknowledged_at: Option, @@ -294,7 +295,13 @@ impl Authority { state.waiters.push(waker.clone()); } receipt.refresh = true; + let producer = receipt.producer_waker.take(); completion.changed.notify_all(); + drop(receipt); + drop(state); + if let Some(waker) = producer { + waker.wake(); + } return Ok(None); } drop(qualification); @@ -304,6 +311,16 @@ impl Authority { receipt.lock_wait_nanos = entered.duration_since(arrived).as_nanos(); receipt.turn_nanos = entered.elapsed().as_nanos(); } + let producer = if receipt.consumed { + receipt.producer_waker.take() + } else { + None + }; + drop(receipt); + drop(state); + if let Some(waker) = producer { + waker.wake(); + } accepted.map(Some) } } @@ -409,6 +426,9 @@ impl Close<'_> { } else { qualification.rejected = true; receipt.rejected = true; + if let Some(waker) = receipt.producer_waker.take() { + state.waiters.push(waker); + } } drop(qualification); completion.changed.notify_all(); diff --git a/crates/ledger/src/persistence/scope.rs b/crates/ledger/src/persistence/scope.rs index bcd5a4a4..076ba827 100644 --- a/crates/ledger/src/persistence/scope.rs +++ b/crates/ledger/src/persistence/scope.rs @@ -80,9 +80,10 @@ pub fn begin_family<'a>(session: &'a mut Session, family: &str) -> driver::Resul Change::Semantic, ) } -/// A queued execution request is not an accepted authority intent. Acquire its -/// exclusive turn and recheck root discovery before closing, then start SQL. -/// Source changes, OAuth intents and migration never use this entrypoint. +/// Queued execution waits for its deciding turn before closing. MVCC rechecks +/// scheduler roots before SQL. WAL acquires the native writer before closing +/// and performs admission inside that transaction. Source changes, OAuth +/// intents and migration never use this entrypoint. pub(crate) fn begin_provider_admission<'a>( session: &'a mut Session, family: &str, @@ -166,12 +167,15 @@ fn start<'a>( && crate::provider::shared_provider_reads(); #[cfg(any(test, feature = "commit-observer"))] let admission_request = matches!(&change, Change::Admission(_)); - let selected_admission = - concurrent && matches!(&change, Change::Admission(proof) if proof.wait_before_close()); + let queued_admission = matches!(&change, Change::Admission(proof) if proof.wait_before_close()); + let selected_admission = concurrent && queued_admission; + let wait_for_wal_writer = !concurrent + && (queued_admission || matches!(&change, Change::Lifecycle(proof) if proof.origin_only())); let authority_entered = Instant::now(); // Accepted source/Policy/OAuth intents close immediately, including while - // waiting. Only an unaccepted provider request may wait before closure. - let authority = if selected_admission { + // waiting. WAL provider admission and exact lifecycle work may wait for + // the native writer. Neither can use that transaction before closing. + let authority = if selected_admission || wait_for_wal_writer { None } else { Some(match change { @@ -256,12 +260,11 @@ fn start<'a>( } (false, _) => None, }; - let (authority, authority_entered) = match authority { - Some(authority) => (authority, authority_entered), - None => { - let entered = Instant::now(); - (session.owner.authority.close(close_scope)?, entered) - } + let authority = if selected_admission { + let entered = Instant::now(); + Some((session.owner.authority.close(close_scope.clone())?, entered)) + } else { + authority.map(|close| (close, authority_entered)) }; let parallel = concurrent && family.is_some(); // The mutable Session borrow provides exclusive custody for the whole scope. @@ -275,6 +278,29 @@ fn start<'a>( }, )) })?; + let (authority, authority_entered) = if let Some(authority) = authority { + authority + } else { + let entered = Instant::now(); + match session.owner.authority.close(close_scope) { + Ok(authority) => (authority, entered), + Err(error) => { + if let Err(rollback_error) = + super::timing::measure(&mut session.timings.rollback, || { + block_on(native.rollback()) + }) + { + session.poisoned.store(true, Ordering::Release); + let _ = release_failed_transaction(&session.connection); + return Err(driver::Error::BatchRollbackFailed { + error: Box::new(error), + rollback_error: Box::new(rollback_error), + }); + } + return Err(error); + } + } + }; Ok(WriteScope { connection: &session.connection, authority, diff --git a/crates/ledger/src/provider_delivery.rs b/crates/ledger/src/provider_delivery.rs index e43d25ba..5e9b51c0 100644 --- a/crates/ledger/src/provider_delivery.rs +++ b/crates/ledger/src/provider_delivery.rs @@ -117,6 +117,18 @@ impl ProviderDelivery { } } impl DeliveryProducer { + /// Register a reactor wake for receipt consumption, refresh or rejection. + /// The producer must still recheck the actual state with `progress`. + pub fn poll_progress_ready(&self, cx: &Context<'_>) -> Poll<()> { + let Ok(mut receipt) = self.0.completion.state.lock() else { + return Poll::Ready(()); + }; + if receipt.consumed || receipt.refresh || receipt.rejected { + return Poll::Ready(()); + } + receipt.producer_waker = Some(cx.waker().clone()); + Poll::Pending + } pub fn acknowledge(&self, deadline: Instant) -> Result<()> { let mut receipt = self .0 @@ -297,7 +309,12 @@ impl Drop for DeliveryFrame { if !receipt.consumed { receipt.rejected = true; } + let producer = receipt.producer_waker.take(); self.0.completion.changed.notify_all(); + drop(receipt); + if let Some(waker) = producer { + waker.wake(); + } } } } diff --git a/crates/ledger/tests/unit/provider_delivery.rs b/crates/ledger/tests/unit/provider_delivery.rs index 66eb7cf2..5e829357 100644 --- a/crates/ledger/tests/unit/provider_delivery.rs +++ b/crates/ledger/tests/unit/provider_delivery.rs @@ -6,11 +6,24 @@ use super::{SCHEMA, fixture}; use proptest::{prop_assert, prop_assert_eq, proptest, test_runner::Config}; use std::{ collections::BTreeSet, - task::{Context, Poll, Waker}, + sync::{ + Arc, + atomic::{AtomicBool, Ordering}, + }, + task::{Context, Poll, Wake, Waker}, time::{Duration, Instant}, }; use weaver_ledger::{DeliveryCursor, DeliveryWait, Ledger, persistence}; +#[derive(Default)] +struct DeliveryWake(AtomicBool); + +impl Wake for DeliveryWake { + fn wake(self: Arc) { + self.0.store(true, Ordering::Relaxed); + } +} + proptest! { #![proptest_config(Config::with_cases(24))] #[test] @@ -38,18 +51,25 @@ proptest! { let (producer, frame) = staged.expect("inert frame"); prop_assert!(cursor.poll(&frame, &cx, &mut Some(())).is_pending(), "commit is not producer acknowledgment"); producer.acknowledge(Instant::now()+Duration::from_secs(1)).expect("confirmed receipt"); + let signal = Arc::new(DeliveryWake::default()); + let waker = Waker::from(signal.clone()); + let producer_cx = Context::from_waker(&waker); + prop_assert!(producer.poll_progress_ready(&producer_cx).is_pending()); // A real different connection commits after validation and before the final owner turn. let tx = persistence::begin(&mut storage).expect("close real write"); prop_assert!(cursor.poll(&frame, &cx, &mut Some(())).is_pending(), "closed lane admitted bytes"); persistence::exec(&tx,"UPDATE tasks SET held=held WHERE family='f'",()).expect("same-view native write"); tx.commit().expect("native commit"); prop_assert!(cursor.poll(&frame, &cx, &mut Some(())).is_pending(), "old view skipped requalification"); + prop_assert!(signal.0.swap(false, Ordering::Relaxed), "refresh did not wake the producer"); prop_assert_eq!(producer.wait(|| false, Instant::now()+Duration::from_secs(1)).expect("refresh"), DeliveryWait::Refresh); if revoke { ledger.publish_typed(Some(0), "forbid(principal,action,resource);", SCHEMA, 2).expect("revoke"); } let refreshed = ledger.refresh_provider_delivery(&permit, &producer, "arrow"); prop_assert_eq!(refreshed.is_ok(), !revoke); if !revoke { + prop_assert!(producer.poll_progress_ready(&producer_cx).is_pending()); prop_assert!(matches!(cursor.poll(&frame, &cx, &mut Some(())), Poll::Ready(Ok(())))); + prop_assert!(signal.0.load(Ordering::Relaxed), "acceptance did not wake the producer"); prop_assert!(matches!(cursor.poll(&frame, &cx, &mut Some(())), Poll::Ready(Err(_))), "range duplicated"); } drop(producer); drop(frame); drop(cursor); drop(storage); diff --git a/crates/server/src/grpc_delivery_producer.rs b/crates/server/src/grpc_delivery_producer.rs index da5dad61..d2aa8f0a 100644 --- a/crates/server/src/grpc_delivery_producer.rs +++ b/crates/server/src/grpc_delivery_producer.rs @@ -14,8 +14,8 @@ use weaver_contracts::{Error, Result}; use weaver_ledger::{DeliveryProducer, DeliveryWait, Ledger, ProviderDispatch}; pub(crate) struct PendingDelivery { - receipt: DeliveryProducer, - deadline: Instant, + pub(crate) receipt: DeliveryProducer, + pub(crate) deadline: Instant, } impl PendingDelivery { pub(crate) fn new(receipt: DeliveryProducer, deadline: Instant) -> Self { @@ -52,7 +52,7 @@ impl Output { format: &str, ) -> Result<()> { while let Some(first) = self.deliveries.front() { - match first.receipt.wait(|| self.stopped(), first.deadline)? { + match self.wait_delivery(first, first.deadline)? { DeliveryWait::Refresh => { ledger.refresh_provider_delivery(permit, &first.receipt, format)? } @@ -61,6 +61,24 @@ impl Output { } Ok(()) } + fn wait_delivery(&self, entry: &PendingDelivery, deadline: Instant) -> Result { + loop { + if let Some(progress) = entry.receipt.progress()? { + return Ok(progress); + } + let stopped = || Error::Conflict("delivery cancelled or unavailable"); + self.runtime.block_on(async { + tokio::select! { + biased; + () = self.cancelled.cancelled() => Err(stopped()), + () = self.shutdown.cancelled() => Err(stopped()), + () = self.sender.closed() => Err(stopped()), + () = tokio::time::sleep_until(deadline.into()) => Err(stopped()), + () = poll_fn(|cx| entry.receipt.poll_progress_ready(cx)) => Ok(()), + } + })?; + } + } pub(crate) fn reserve_guarded( &mut self, ledger: &mut Ledger, @@ -120,10 +138,7 @@ impl Output { .deliveries .front() .ok_or(Error::Conflict("capacity without pending owner"))?; - match first - .receipt - .wait(|| self.stopped(), deadline.min(first.deadline))? - { + match self.wait_delivery(first, deadline.min(first.deadline))? { DeliveryWait::Accepted => self.completed_delivery(), DeliveryWait::Refresh => refresh = true, } diff --git a/crates/server/src/grpc_output.rs b/crates/server/src/grpc_output.rs index 01a9a631..d5f2b376 100644 --- a/crates/server/src/grpc_output.rs +++ b/crates/server/src/grpc_output.rs @@ -143,6 +143,22 @@ impl ProviderOutput for Output { ) -> Result<()> { self.drain_deliveries(ledger, permit, format) } + fn service_delivery( + &mut self, + ledger: &mut weaver_ledger::Ledger, + permit: &weaver_ledger::ProviderDispatch, + format: &str, + ) -> Result> { + self.progress_deliveries(ledger, permit, format)?; + Ok(self.deliveries.front().map(|entry| entry.deadline.into())) + } + fn poll_delivery_ready(&self, cx: &mut std::task::Context<'_>) -> std::task::Poll<()> { + self.deliveries + .front() + .map_or(std::task::Poll::Pending, |entry| { + entry.receipt.poll_progress_ready(cx) + }) + } fn prepare( route: &ProviderRoute, model: &str, diff --git a/dev/sysml/ProviderRpc.sysml b/dev/sysml/ProviderRpc.sysml index 629a5648..34455efd 100644 --- a/dev/sysml/ProviderRpc.sysml +++ b/dev/sysml/ProviderRpc.sysml @@ -97,6 +97,14 @@ package ProviderRpc { any mutation or callback. Cancelled or stale tickets are discarded. Disjoint tickets may advance independently. Overlapping tickets need an explicit order and maximum wait policy. */ + doc /* In WAL, queued provider admission and exact lifecycle work + close the delivery barrier after acquiring the native writer + and before any business read, mutation or callback. Accepted + source, Policy and OAuth mutations close before waiting. + The existing Tokio reactor polls upstream and delivery readiness. + Keep the same decoder future across handoff wakeups. The blocking + owner services ledger work outside reactor polling, without + draining the output queue or extending either deadline. */ } requirement def EncodingAuthorityEquivalence { doc /* Protobuf events and optional Arrow IPC batches use the same row-by-row current Cedar and fence guard before bounded queue admission. */ From b0d1e3f529d5fa43ba0dc7a2e035ef5b3cd4cb02 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 19:35:49 +0800 Subject: [PATCH 011/105] Qualify benchmarks by native Criterion identities --- Cargo.lock | 1 + crates/broker/Cargo.toml | 2 +- crates/broker/benches/gateway.rs | 23 +- go/internal/devrunner/benchmark.go | 299 +++++++++++++----------- go/internal/devrunner/benchmark_test.go | 53 ++++- go/internal/devrunner/runner.go | 9 +- 6 files changed, 238 insertions(+), 149 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e52d85e..e76d7121 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1162,6 +1162,7 @@ dependencies = [ "serde", "serde_json", "tinytemplate", + "tokio", "walkdir", ] diff --git a/crates/broker/Cargo.toml b/crates/broker/Cargo.toml index 63f63ccd..e2e0434f 100644 --- a/crates/broker/Cargo.toml +++ b/crates/broker/Cargo.toml @@ -28,7 +28,7 @@ serde_json.workspace = true [dev-dependencies] asp-rust.workspace = true futures-executor.workspace = true -criterion.workspace = true +criterion = { workspace = true, features = ["async_tokio"] } tempfile.workspace = true rcgen.workspace = true socket2.workspace = true diff --git a/crates/broker/benches/gateway.rs b/crates/broker/benches/gateway.rs index 7145cacb..75ad24cf 100644 --- a/crates/broker/benches/gateway.rs +++ b/crates/broker/benches/gateway.rs @@ -197,6 +197,10 @@ mod sse_buffer; fn anthropic_decode(c: &mut Criterion) { use weaver_contracts::ProviderEventKind; + let runtime = tokio::runtime::Builder::new_multi_thread() + .worker_threads(4) + .build() + .expect("Tokio SSE benchmark runtime"); let mut data = String::new(); for (event, fields) in [ ( @@ -217,10 +221,10 @@ fn anthropic_decode(c: &mut Criterion) { } data.push_str("event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}\n\nevent: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"},\"usage\":{\"output_tokens\":64}}\n\nevent: message_stop\ndata: {\"type\":\"message_stop\"}\n\n"); c.bench_function("broker/anthropic_sse_64_deltas", |b| { - b.iter(|| { + b.to_async(&runtime).iter(|| async { let mut decoder = anthropic_sse::Decoder::new(black_box(data.as_bytes()), "fixture"); loop { - let event = black_box(decoder.next().expect("bounded provider event")); + let event = black_box(decoder.next().await.expect("bounded provider event")); if event.kind == ProviderEventKind::Done { break; } @@ -229,13 +233,18 @@ fn anthropic_decode(c: &mut Criterion) { }) }); c.bench_function("broker/anthropic_buffered_sse_64_deltas", |b| { - b.iter(|| { + b.to_async(&runtime).iter(|| async { let mut decoder = anthropic_sse::Decoder::new(black_box(data.as_bytes()), "fixture"); loop { - let event = decoder.next_buffered().expect("bounded buffered event"); - let event = black_box( - event.unwrap_or_else(|| decoder.next().expect("bounded provider event")), - ); + let event = match decoder + .next_buffered() + .await + .expect("bounded buffered event") + { + Some(event) => event, + None => decoder.next().await.expect("bounded provider event"), + }; + let event = black_box(event); if event.kind == ProviderEventKind::Done { break; } diff --git a/go/internal/devrunner/benchmark.go b/go/internal/devrunner/benchmark.go index 3463355f..7fb57879 100644 --- a/go/internal/devrunner/benchmark.go +++ b/go/internal/devrunner/benchmark.go @@ -17,101 +17,108 @@ import ( ) // Every timed case must produce fresh evidence; one case cannot qualify its package. -var storageBenchmarkCases = []string{"ledger_final_family_pair/wal", "ledger_final_family_pair/mvcc-serial", "ledger_final_family_pair/mvcc-parallel", "ledger_final_family_pair/mvcc-shared-budget", "ledger_final_family_pair/mvcc-shared-history", "ledger_task_origin_registration/fresh", "ledger_task_origin_registration/receipt-replay", "ledger_task_origin_registration/rebind-rejected"} +var storageBenchmarkCases = []string{"ledger/final_family_pair/wal", "ledger/final_family_pair/mvcc-serial", "ledger/final_family_pair/mvcc-parallel", "ledger/final_family_pair/mvcc-shared-budget", "ledger/final_family_pair/mvcc-shared-history", "ledger/task_origin_registration/fresh", "ledger/task_origin_registration/receipt-replay", "ledger/task_origin_registration/rebind-rejected"} -var rustBenchmarkCases = []string{ - "telemetry_local/record", - "telemetry_local/snapshot", - "ledger_task_origin_registration/fresh", - "ledger_task_origin_registration/receipt-replay", - "ledger_task_origin_registration/rebind-rejected", - "governance_owned_source_validate", - "governance_original_source_capture_and_bind", - "governance_source_lane_roundtrip", - "governance_producer_catalog_roundtrip/1", - "governance_producer_catalog_roundtrip/64", - "governance-build_stage_request", - "contracts_provider_commitment/128", - "contracts_provider_commitment/16384", - "contracts_provider_commitment/524288", - "contracts_publication_commitment", - "contracts_publication_review_commitment", - "contracts_source_rotation_commitment", - "contracts_profile_commitment", - "contracts_profile_request_validation/128", - "contracts_profile_request_validation/16384", - "contracts_profile_request_validation/524288", - "policy_typed_schema_validation", - "policy_context_json_local", - "policy_context_literal_local", - "policy_context_json_shared", - "policy_context_literal_shared", - "policy_warm_compilation_current_decision", - "policy_compilation_cache_churn", - "policy_materialized_json_schema_validation", - "policy_spec_schema_bound_candidate_replay", - "policy_spec_parent_bound_revision_replay", - "policy-ffi_typed_preflight", - "ledger_provider_release/1", - "ledger_provider_release/8", - "ledger_provider_release/32", - "ledger_fresh_admission", - "ledger_concurrent_family_pair/wal", - "ledger_concurrent_family_pair/mvcc", - "ledger_final_family_pair/wal", - "ledger_final_family_pair/mvcc-serial", - "ledger_final_family_pair/mvcc-parallel", - "ledger_final_family_pair/mvcc-shared-budget", - "ledger_final_family_pair/mvcc-shared-history", - "ledger_consume_and_dispatch_burn", - "ledger_shared_exposure_dispatch/1", - "ledger_shared_exposure_dispatch/8", - "ledger_shared_exposure_dispatch/64", - "ledger_stream_manifest_guard/1", - "ledger_stream_manifest_guard/8", - "ledger_stream_manifest_guard/64", - "ledger_range_tail_guard/0", - "ledger_range_tail_guard/8", - "ledger_range_tail_guard/64", - "ledger_original_reservation_bytes/1/128", - "ledger_original_reservation_bytes/8/128", - "ledger_original_reservation_bytes/64/128", - "ledger_original_reservation_bytes/1/16384", - "ledger_original_reservation_bytes/8/16384", - "ledger_original_reservation_bytes/64/16384", - "ledger_original_reservation_bytes/1/524288", - "ledger_idempotent_admission", - "ledger_publication_atomic_commit", - "ledger_publication_stage_and_decide", - "ledger_reviewed_publication_register_and_commit", - "ledger_spec_replay_register_and_commit", - "ledger_spec_parent_bound_revision_registration", - "ledger_source_key_handoff", - "ledger_source_authenticated_publication", - "ledger_source_empty_store_enrollment/0", - "ledger_source_empty_store_enrollment/32", - "ledger_publication_exact_replay", - "ledger_publication_historical_lookup", - "ledger_profile_task_registration", - "ledger_profile_task_replay/1", - "ledger_profile_task_replay/256", - "broker_https_guarded_sse_three_events", - "broker_anthropic_sse_64_deltas", - "broker_anthropic_buffered_sse_64_deltas", - "broker_wif_cached_token", - "server_encoding_guard_hold/inside", - "server_encoding_guard_hold/outside", - "server_response_encoding/protobuf_frames/1", - "server_response_encoding/protobuf_frames/32", - "server_response_encoding/arrow_batch/1", - "server_response_encoding/arrow_batch/32", - "server_source_certificate_spki_identity", +var providerReleaseBenchmarkCases = []string{ + "ledger/provider_release/trusted-host/1", + "ledger/provider_release/trusted-host/8", + "ledger/provider_release/trusted-host/32", + "ledger/provider_release/reviewed/1", + "ledger/provider_release/reviewed/8", + "ledger/provider_release/reviewed/32", } -// Criterion sanitizes the package/group separator to an underscore on disk. +var rustBenchmarkCases = slices.Concat([]string{ + "telemetry/local/record", + "telemetry/local/snapshot", + "ledger/task_origin_registration/fresh", + "ledger/task_origin_registration/receipt-replay", + "ledger/task_origin_registration/rebind-rejected", + "governance/owned_source_validate", + "governance/original_source_capture_and_bind", + "governance/source_lane_roundtrip", + "governance/producer_catalog_roundtrip/1", + "governance/producer_catalog_roundtrip/64", + "governance-build/stage_request", + "contracts/provider_commitment/128", + "contracts/provider_commitment/16384", + "contracts/provider_commitment/524288", + "contracts/publication_commitment", + "contracts/publication_review_commitment", + "contracts/source_rotation_commitment", + "contracts/profile_commitment", + "contracts/profile_request_validation/128", + "contracts/profile_request_validation/16384", + "contracts/profile_request_validation/524288", + "policy/typed_schema_validation", + "policy/context_json_local", + "policy/context_literal_local", + "policy/context_json_shared", + "policy/context_literal_shared", + "policy/warm_compilation_current_decision", + "policy/compilation_cache_churn", + "policy/materialized_json_schema_validation", + "policy/spec_schema_bound_candidate_replay", + "policy/spec_parent_bound_revision_replay", + "policy-ffi/typed_preflight", + "policy-ffi/document_and_aggregate_preflight", + "ledger/fresh_admission", + "ledger/concurrent_family_pair/wal", + "ledger/concurrent_family_pair/mvcc", + "ledger/final_family_pair/wal", + "ledger/final_family_pair/mvcc-serial", + "ledger/final_family_pair/mvcc-parallel", + "ledger/final_family_pair/mvcc-shared-budget", + "ledger/final_family_pair/mvcc-shared-history", + "ledger/consume_and_dispatch_burn", + "ledger/shared_exposure_dispatch/1", + "ledger/shared_exposure_dispatch/8", + "ledger/shared_exposure_dispatch/64", + "ledger/stream_manifest_guard/1", + "ledger/stream_manifest_guard/8", + "ledger/stream_manifest_guard/64", + "ledger/range_tail_guard/0", + "ledger/range_tail_guard/8", + "ledger/range_tail_guard/64", + "ledger/original_reservation_bytes/1/128", + "ledger/original_reservation_bytes/8/128", + "ledger/original_reservation_bytes/64/128", + "ledger/original_reservation_bytes/1/16384", + "ledger/original_reservation_bytes/8/16384", + "ledger/original_reservation_bytes/64/16384", + "ledger/original_reservation_bytes/1/524288", + "ledger/idempotent_admission", + "ledger/publication_atomic_commit", + "ledger/publication_stage_and_decide", + "ledger/reviewed_publication_register_and_commit", + "ledger/spec_replay_register_and_commit", + "ledger/spec_parent_bound_revision_registration", + "ledger/source_key_handoff", + "ledger/source_authenticated_publication", + "ledger/source_empty_store_enrollment/0", + "ledger/source_empty_store_enrollment/32", + "ledger/publication_exact_replay", + "ledger/publication_historical_lookup", + "ledger/profile_task_registration", + "ledger/profile_task_replay/1", + "ledger/profile_task_replay/256", + "broker/https_guarded_sse_three_events", + "broker/anthropic_sse_64_deltas", + "broker/anthropic_buffered_sse_64_deltas", + "broker/wif_cached_token", + "server/encoding_guard_hold/inside", + "server/encoding_guard_hold/outside", + "server/response_encoding/protobuf_frames/1", + "server/response_encoding/protobuf_frames/32", + "server/response_encoding/arrow_batch/1", + "server/response_encoding/arrow_batch/32", + "server/source_certificate_spki_identity", +}, providerReleaseBenchmarkCases) + +// Each Criterion ID starts with the declared Cargo package owner. func benchmarkPackage(name string) (string, error) { for _, member := range []string{"contracts", "governance", "governance-build", "policy", "policy-ffi", "ledger", "broker", "server", "telemetry"} { - if strings.HasPrefix(name, member+"_") { + if strings.HasPrefix(name, member+"/") { return "weaver-" + member, nil } } @@ -187,7 +194,32 @@ func positiveFinite(value float64) bool { return value > 0 && !math.IsInf(value, 0) && !math.IsNaN(value) } -// Copy only structured Criterion data; raw stage logs retain Go/Rust environment receipts. +func criterionBenchmarkID(directory, relative string, begin time.Time) (string, error) { + path := filepath.Join(directory, "benchmark.json") + info, err := os.Lstat(path) + if err != nil { + return "", err + } + if !info.Mode().IsRegular() || info.ModTime().Before(begin) { + return "", fmt.Errorf("stale or nonregular benchmark identity: %s", path) + } + data, err := os.ReadFile(path) + if err != nil { + return "", err + } + var identity struct { + FullID string `json:"full_id"` + Directory string `json:"directory_name"` + } + if err := json.Unmarshal(data, &identity); err != nil { + return "", err + } + if identity.FullID == "" || identity.Directory != relative { + return "", fmt.Errorf("benchmark identity does not match Criterion directory: %s", relative) + } + return identity.FullID, nil +} + func collectBenchmarks(targetDirectory, directory, started string, selected ...string) error { expected := rustBenchmarkCases if len(selected) != 0 { @@ -211,72 +243,67 @@ func collectBenchmarks(targetDirectory, directory, started string, selected ...s if err != nil { return err } - if entry.IsDir() { - return nil - } - if filepath.Ext(path) != ".json" && filepath.Ext(path) != ".csv" { + if entry.Name() != "estimates.json" || filepath.Base(filepath.Dir(path)) != "new" { return nil } info, err := entry.Info() if err != nil { return err } - if info.ModTime().Before(begin) { + if !info.Mode().IsRegular() || info.ModTime().Before(begin) { return nil } - relative, err := filepath.Rel(source, path) + directory := filepath.Dir(path) + relative, err := filepath.Rel(source, filepath.Dir(directory)) + if err != nil { + return err + } + name, err := criterionBenchmarkID(directory, filepath.ToSlash(relative), begin) if err != nil { return err } - if len(selected) != 0 && !slices.ContainsFunc(expected, func(name string) bool { return strings.HasPrefix(filepath.ToSlash(relative), name+"/") }) { + if len(selected) != 0 && !slices.Contains(expected, name) { return nil } - bytes, err := os.ReadFile(path) + if measured[name] { + return fmt.Errorf("duplicate fresh Rust benchmark case: %s", name) + } + if !slices.Contains(rustBenchmarkCases, name) { + return fmt.Errorf("unmapped Rust benchmark case: %s", name) + } + data, err := os.ReadFile(path) if err != nil { return err } - target := filepath.Join(directory, "criterion", relative) - if err := os.MkdirAll(filepath.Dir(target), 0700); err != nil { + // Criterion names confidence bounds explicitly. + var value map[string]json.RawMessage + if err := json.Unmarshal(data, &value); err != nil { return err } - if err := os.WriteFile(target, bytes, 0600); err != nil { + var mean struct { + Point float64 `json:"point_estimate"` + Interval struct { + Lower float64 `json:"lower_bound"` + Upper float64 `json:"upper_bound"` + } `json:"confidence_interval"` + } + if err := json.Unmarshal(value["mean"], &mean); err != nil { return err } - if strings.HasSuffix(filepath.ToSlash(relative), "/new/estimates.json") { - // Criterion names confidence bounds explicitly. - var value map[string]json.RawMessage - if err := json.Unmarshal(bytes, &value); err != nil { - return err - } - var mean struct { - Point float64 `json:"point_estimate"` - Interval struct { - Lower float64 `json:"lower_bound"` - Upper float64 `json:"upper_bound"` - } `json:"confidence_interval"` - } - if err := json.Unmarshal(value["mean"], &mean); err != nil { - return err - } - name := strings.TrimSuffix(filepath.ToSlash(relative), "/new/estimates.json") - if !slices.Contains(rustBenchmarkCases, name) { - return fmt.Errorf("unmapped Rust benchmark case: %s", name) - } - if !positiveFinite(mean.Point) || !positiveFinite(mean.Interval.Lower) || - !positiveFinite(mean.Interval.Upper) || mean.Interval.Lower > mean.Point || mean.Point > mean.Interval.Upper { - return fmt.Errorf("invalid benchmark mean or confidence bounds: %s", name) - } - owner, err := benchmarkPackage(name) - if err != nil { - return err - } - samples, err := benchmarkSamples(filepath.Join(filepath.Dir(path), "sample.json"), begin) - if err != nil { - return fmt.Errorf("%s: %w", name, err) - } - measured[name] = true - rows = append(rows, fmt.Sprintf("| %s | %s | %d | %.3f | %.3f | %.3f |", owner, name, samples, mean.Point, mean.Interval.Lower, mean.Interval.Upper)) + if !positiveFinite(mean.Point) || !positiveFinite(mean.Interval.Lower) || + !positiveFinite(mean.Interval.Upper) || mean.Interval.Lower > mean.Point || mean.Interval.Upper < mean.Point { + return fmt.Errorf("invalid benchmark mean or confidence bounds: %s", name) + } + owner, err := benchmarkPackage(name) + if err != nil { + return err + } + samples, err := benchmarkSamples(filepath.Join(directory, "sample.json"), begin) + if err != nil { + return fmt.Errorf("%s: %w", name, err) } + measured[name] = true + rows = append(rows, fmt.Sprintf("| %s | %s | %d | %.3f | %.3f | %.3f |", owner, name, samples, mean.Point, mean.Interval.Lower, mean.Interval.Upper)) return nil }) if err != nil { diff --git a/go/internal/devrunner/benchmark_test.go b/go/internal/devrunner/benchmark_test.go index 281b144b..739fe4f4 100644 --- a/go/internal/devrunner/benchmark_test.go +++ b/go/internal/devrunner/benchmark_test.go @@ -59,10 +59,22 @@ func TestBenchmarkPlanChecksPackageContractBeforeMeasurement(t *testing.T) { func writeBenchmarkEstimate(t *testing.T, root, name string) { t.Helper() - path := filepath.Join(root, "target/criterion", name, "new/estimates.json") + writeCriterionEstimate(t, root, name, name) +} + +func writeCriterionEstimate(t *testing.T, root, name, directory string) { + t.Helper() + path := filepath.Join(root, "target/criterion", directory, "new/estimates.json") if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil { t.Fatal(err) } + identity, err := json.Marshal(map[string]string{"full_id": name, "directory_name": directory}) + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(filepath.Dir(path), "benchmark.json"), identity, 0600); err != nil { + t.Fatal(err) + } if err := os.WriteFile(path, []byte(`{"mean":{"point_estimate":1,"confidence_interval":{"lower_bound":1,"upper_bound":1}}}`), 0600); err != nil { t.Fatal(err) } @@ -196,3 +208,42 @@ func TestBenchmarkEvidenceRejectsUnmappedCase(t *testing.T) { t.Fatalf("unmapped case accepted: %v", err) } } + +func TestBenchmarkEvidenceUsesCriterionIdentity(t *testing.T) { + const name = "governance/producer_catalog_roundtrip/1" + const escaped = "governance_producer_catalog_roundtrip_1" + started := time.Unix(200, 0).UTC().Format(time.RFC3339Nano) + for _, fault := range []string{"", "duplicate", "stale", "wrong-directory"} { + t.Run(fault, func(t *testing.T) { + root, output := t.TempDir(), t.TempDir() + writeCriterionEstimate(t, root, name, escaped) + path := filepath.Join(root, "target/criterion", escaped, "new/benchmark.json") + switch fault { + case "duplicate": + writeCriterionEstimate(t, root, name, escaped+"_2") + case "stale": + if err := os.Chtimes(path, time.Unix(100, 0), time.Unix(100, 0)); err != nil { + t.Fatal(err) + } + case "wrong-directory": + if err := os.WriteFile(path, []byte(`{"full_id":"governance/producer_catalog_roundtrip/1","directory_name":"other"}`), 0600); err != nil { + t.Fatal(err) + } + } + err := collectBenchmarks(filepath.Join(root, "target"), output, started, name) + if fault != "" { + if err == nil { + t.Fatal("invalid Criterion identity accepted") + } + return + } + if err != nil { + t.Fatal(err) + } + summary, err := os.ReadFile(filepath.Join(output, "benchmark-summary.org")) + if err != nil || !strings.Contains(string(summary), "| "+name+" | 30 |") { + t.Fatalf("missing canonical Criterion evidence: %v, %s", err, summary) + } + }) + } +} diff --git a/go/internal/devrunner/runner.go b/go/internal/devrunner/runner.go index 38f2812a..fdb17db1 100644 --- a/go/internal/devrunner/runner.go +++ b/go/internal/devrunner/runner.go @@ -192,6 +192,7 @@ func Run(ctx context.Context, config Config, output io.Writer) (report string, r if mode == "bench" && !failed { if err := collectCargoBenchmarks(ctx, root, directory, receipt.Started, environment); err != nil { failed = true + receipt.Stages = append(receipt.Stages, Result{Name: "benchmark-evidence", Status: "FAIL", Error: err.Error()}) fmt.Fprintf(output, "FAIL benchmark artifacts: %v\n", err) } } @@ -346,16 +347,16 @@ func runStageObserved(ctx context.Context, root, directory string, environment [ if (stage.Name == "storage-final-benchmark" || stage.Name == "telemetry-benchmark" || stage.Name == "execution-policy-benchmark" || stage.Name == "execution-ledger-benchmark" || stage.Name == "execution-provider-benchmark" || stage.Name == "execution-encoding-benchmark") && err == nil && closeErr == nil { cases := storageBenchmarkCases if stage.Name == "execution-encoding-benchmark" { - cases = []string{"server_encoding_guard_hold/inside", "server_encoding_guard_hold/outside"} + cases = []string{"server/encoding_guard_hold/inside", "server/encoding_guard_hold/outside"} } if stage.Name == "execution-provider-benchmark" { - cases = []string{"broker_https_guarded_sse_three_events"} + cases = []string{"broker/https_guarded_sse_three_events"} } if stage.Name == "execution-ledger-benchmark" { - cases = []string{"ledger_provider_release/1", "ledger_provider_release/8", "ledger_provider_release/32"} + cases = providerReleaseBenchmarkCases } if stage.Name == "execution-policy-benchmark" { - cases = []string{"policy_context_json_local", "policy_context_literal_local", "policy_context_json_shared", "policy_context_literal_shared"} + cases = []string{"policy/context_json_local", "policy/context_literal_local", "policy/context_json_shared", "policy/context_literal_shared"} } if stage.Name == "telemetry-benchmark" { cases = nil From 059321cb26893cb09ef8c4da23e0c13a215d6739 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 19:37:08 +0800 Subject: [PATCH 012/105] Provision and bind the Cedar solver in Policy CI --- .github/actions/prepare-toolchain/action.yml | 11 +++++++++++ go/internal/devrunner/ci.go | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/actions/prepare-toolchain/action.yml b/.github/actions/prepare-toolchain/action.yml index 479e6553..6d0cae70 100644 --- a/.github/actions/prepare-toolchain/action.yml +++ b/.github/actions/prepare-toolchain/action.yml @@ -20,3 +20,14 @@ runs: - name: Install Ubuntu or Darwin packages shell: sh run: go -C go run ./cmd/weaver-dev prepare-ci-tools + - name: Bind the Cedar solver + if: env.WEAVER_VERIFY_SUITE == 'check-policy' + shell: sh + run: | + solver=$(command -v cvc5) + case "$solver" in + /*) test -x "$solver" ;; + *) exit 1 ;; + esac + "$solver" --version + printf 'CVC5=%s\n' "$solver" >> "$GITHUB_ENV" diff --git a/go/internal/devrunner/ci.go b/go/internal/devrunner/ci.go index 93039e1c..4fc73a23 100644 --- a/go/internal/devrunner/ci.go +++ b/go/internal/devrunner/ci.go @@ -50,7 +50,7 @@ func PrepareCITools(ctx context.Context, output io.Writer) error { } packages := []string{"apt-get", "install", "-y", "--no-install-recommends", "build-essential", "ca-certificates", "pkg-config", "libssl-dev", "zlib1g-dev", "protobuf-compiler"} if suite == "check-policy" { - packages = append(packages, "elan") + packages = append(packages, "elan", "cvc5") } if err := run("sudo", packages...); err != nil { return err @@ -58,7 +58,7 @@ func PrepareCITools(ctx context.Context, output io.Writer) error { case "darwin": packages := []string{"install", "pkg-config", "openssl@3", "zlib", "protobuf"} if suite == "check-policy" { - packages = append(packages, "elan") + packages = append(packages, "elan", "cvc5") } if err := run("brew", packages...); err != nil { return err From 81f24e4324d75742dd72ff1c78fe3eb6f1d032c4 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 19:43:17 +0800 Subject: [PATCH 013/105] Pin the native Scheme bridge to the current upstream PR revision --- .github/workflows/verify-suite.yml | 2 +- Cargo.lock | 10 +++++----- Cargo.toml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index b78168cb..bae885e0 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -65,7 +65,7 @@ jobs: id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 - uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@838af1ab4e6c0c8177fed176efba448c694012b5 + uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog diff --git a/Cargo.lock b/Cargo.lock index e76d7121..b258b958 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "gerbil-scheme" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=838af1ab4e6c0c8177fed176efba448c694012b5#838af1ab4e6c0c8177fed176efba448c694012b5" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e#380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e" dependencies = [ "gerbil-scheme-rust-project-harness-policy", "gerbil-scheme-sys", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-aot-build" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=838af1ab4e6c0c8177fed176efba448c694012b5#838af1ab4e6c0c8177fed176efba448c694012b5" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e#380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e" dependencies = [ "cbindgen", "cc", @@ -1822,7 +1822,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness" version = "0.1.2" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=838af1ab4e6c0c8177fed176efba448c694012b5#838af1ab4e6c0c8177fed176efba448c694012b5" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e#380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e" dependencies = [ "cargo-lock", "cargo_toml", @@ -1840,7 +1840,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness-policy" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=838af1ab4e6c0c8177fed176efba448c694012b5#838af1ab4e6c0c8177fed176efba448c694012b5" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e#380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e" dependencies = [ "gerbil-scheme-rust-project-harness", ] @@ -1848,7 +1848,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-sys" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=838af1ab4e6c0c8177fed176efba448c694012b5#838af1ab4e6c0c8177fed176efba448c694012b5" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e#380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e" dependencies = [ "gerbil-scheme-aot-build", "gerbil-scheme-rust-project-harness-policy", diff --git a/Cargo.toml b/Cargo.toml index dc137f1f..d31ddac5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,9 @@ arrow-array = "58.4.0" arrow-schema = "58.4.0" arrow-ipc = "58.4.0" criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } -gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "838af1ab4e6c0c8177fed176efba448c694012b5" } -gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "838af1ab4e6c0c8177fed176efba448c694012b5" } -gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "838af1ab4e6c0c8177fed176efba448c694012b5", features = ["external-program"] } +gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e" } +gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e" } +gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e", features = ["external-program"] } asp-rust = { git = "https://github.com/tao3k/asp-rust", rev = "1ca41124b846dec947f3d05119cafa07eaa57924", default-features = false } From 0775f2bfdc42791f7bfc46fe29774d16a425e96d Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 19:46:55 +0800 Subject: [PATCH 014/105] Keep Scheme layout authority in SysML --- Project.sysml | 8 +++- go/dev/ci_test.go | 2 +- go/dev/project_test.go | 7 ++- go/dev/scheme_layout_test.go | 86 ----------------------------------- go/internal/devrunner/plan.go | 6 +-- 5 files changed, 16 insertions(+), 93 deletions(-) delete mode 100644 go/dev/scheme_layout_test.go diff --git a/Project.sysml b/Project.sysml index fdbe4419..c2238565 100644 --- a/Project.sysml +++ b/Project.sysml @@ -49,6 +49,7 @@ package WeaverProject { } requirement architectureViews : ArchitectureViewGrammar; part def File; + part def ExecutableFile :> File; part def IgnoredDirectory; part def Absent; part def RuntimeDependency; @@ -72,11 +73,14 @@ package WeaverProject { part 'benches/README.org' : File; } part def SchemeModule { + doc /* The Scheme Module Interface and its native Contract own role + semantics. The native package build qualifies selected products. */ part 'types.ss' : File; part 'objects.ss' : File; part 'func.ss' : File; part 'config.ss' : File; part 'interface.ss' : File; + part 'gerbil.pkg' : Absent; } package SourcePolicy { @@ -483,7 +487,7 @@ package WeaverProject { part 'go/go.mod' : File; part 'go/go.sum' : File; part 'gerbil.pkg' : File; - part 'build.ss' : File; + part 'build.ss' : ExecutableFile; part 'init.ss' : File; part 'proto/gateway/v1/gateway.proto' : File; part '.github/workflows/ci.yml' : File; @@ -761,6 +765,8 @@ package WeaverProject { part 'scheme/modules' : Absent; part 'scheme/weaver' : Absent; part 'scheme/gerbil.pkg' : Absent; + part 'dev/build.ss' : Absent; + part 'dev/gerbil.pkg' : Absent; part 'packages/server' : Absent; part 'packages/control' : Absent; part 'dev/models' : Absent; diff --git a/go/dev/ci_test.go b/go/dev/ci_test.go index 6c9a246e..a9b9034e 100644 --- a/go/dev/ci_test.go +++ b/go/dev/ci_test.go @@ -141,7 +141,7 @@ func TestCIWorkflowsMatchProjectSuites(t *testing.T) { t.Fatal("verification receipt upload must cover failed stages") } for _, path := range strings.Split(strings.TrimSpace(step.With.Path), "\n") { - if !wantedReceipts[path] || !strings.HasPrefix(path, ".cache/verification/") || !strings.HasSuffix(path, ".json") { + if !wantedReceipts[path] { t.Fatalf("unexpected verification artifact path %q", path) } delete(wantedReceipts, path) diff --git a/go/dev/project_test.go b/go/dev/project_test.go index 621c929f..fb57d31c 100644 --- a/go/dev/project_test.go +++ b/go/dev/project_test.go @@ -104,10 +104,13 @@ func projectPath(root, path, kind string) error { if info.Mode()&os.ModeSymlink != 0 { return fmt.Errorf("project owner is a symlink: %s", path) } - if kind == "File" { + if kind == "File" || kind == "ExecutableFile" { if !info.Mode().IsRegular() { return fmt.Errorf("project source is not a regular file: %s", path) } + if kind == "ExecutableFile" && info.Mode().Perm()&0111 == 0 { + return fmt.Errorf("project entry is not executable: %s", path) + } } else if !info.IsDir() { return fmt.Errorf("project owner is not a directory: %s", path) } @@ -163,7 +166,7 @@ func TestProjectArchitecture(t *testing.T) { continue } switch kind { - case "Directory", "File", "RustPackage", "SchemeModule", "GoPackage", "Absent": + case "Directory", "File", "ExecutableFile", "RustPackage", "SchemeModule", "GoPackage", "Absent": default: t.Fatalf("unknown layout kind %s", kind) } diff --git a/go/dev/scheme_layout_test.go b/go/dev/scheme_layout_test.go deleted file mode 100644 index c8977d9f..00000000 --- a/go/dev/scheme_layout_test.go +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors -// -// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 - -package dev - -import ( - "os" - "path/filepath" - "regexp" - "strings" - "testing" -) - -func TestSchemeModuleOwnershipAndSpecificContracts(t *testing.T) { - repository := root(t) - manifest, err := os.ReadFile(filepath.Join(repository, "gerbil.pkg")) - if err != nil { - t.Fatal(err) - } - dependencies := regexp.MustCompile(`"github\.com/[^\"]+"`).FindAllString(string(manifest), -1) - if len(dependencies) != 1 || !strings.HasPrefix(dependencies[0], `"github.com/tao3k/agentic-ai-lab`) { - t.Fatal("Agentic AI Lab must remain the only direct Scheme dependency", dependencies) - } - for _, name := range []string{"gerbil.pkg", "build.ss", "init.ss"} { - info, err := os.Stat(filepath.Join(repository, name)) - if err != nil || !info.Mode().IsRegular() { - t.Fatalf("missing root Scheme package entry %s: %v", name, err) - } - } - expected := map[string]bool{} - for path := range projectLayout(projectParts(t), "SchemeModule") { - expected[filepath.Base(path)] = true - } - entries, err := os.ReadDir(filepath.Join(repository, "scheme")) - if err != nil { - t.Fatal(err) - } - generic := regexp.MustCompile(`\bAny\b`) - for _, entry := range entries { - if !entry.IsDir() || !expected[entry.Name()] { - t.Fatalf("Scheme directory is a module collection, unexpected owner: %s", entry.Name()) - } - directory := filepath.Join(repository, "scheme", entry.Name()) - if _, err := os.Stat(filepath.Join(directory, "gerbil.pkg")); !os.IsNotExist(err) { - t.Fatal("nested package root inside a Scheme module") - } - for _, role := range []string{"types", "objects", "func", "config", "interface"} { - data, err := os.ReadFile(filepath.Join(directory, role+".ss")) - if err != nil || len(data) == 0 { - t.Fatalf("module %s missing %s role: %v", entry.Name(), role, err) - } - if role == "types" && (generic.Match(data) || !strings.Contains(string(data), "(Record") || !strings.Contains(string(data), "(Function")) { - t.Fatalf("module %s lacks specific native Record/Function contracts", entry.Name()) - } - } - delete(expected, entry.Name()) - } - if len(expected) != 0 { - t.Fatalf("missing Scheme module owners: %v", expected) - } - build, err := os.ReadFile(filepath.Join(repository, "build.ss")) - if err != nil { - t.Fatal(err) - } - for _, required := range []string{"./init.ss", "std-make-spec", "defbuild-script", "scheme/policy/cedar-ffi", "pkg-config-cflags", "pkg-config-libs"} { - if !strings.Contains(string(build), required) { - t.Fatalf("root build does not use its declared owner: %s", required) - } - } - info, err := os.Stat(filepath.Join(repository, "build.ss")) - if err != nil || info.Mode()&0111 == 0 || !strings.HasPrefix(string(build), "#!/usr/bin/env gxi\n") { - t.Fatal("root must retain the standard Gerbil package script") - } - if strings.Contains(string(build), "target/debug") { - t.Fatal("Scheme build must obtain FFI paths from pkg-config") - } - if strings.Contains(string(build), "exe:") || strings.Contains(string(build), "bin:") { - t.Fatal("FFI-loaded governance libraries must not acquire executable build targets") - } - for _, retired := range []string{"dev/build.ss", "dev/gerbil.pkg"} { - if _, err := os.Stat(filepath.Join(repository, retired)); !os.IsNotExist(err) { - t.Fatalf("unneeded Scheme executable package remains: %s", retired) - } - } -} diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index 66a59b80..53889561 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -28,7 +28,7 @@ func Plan(goBinary string) []Stage { {"proof-environment", "elan", []string{"run", proofToolchain, "lean", "--version"}}, {"lean-json-integration", goBinary, []string{"-C", "go", "test", "-count=1", "-tags=proofintegration", "./internal/devrunner", "-run", "^TestLeanJSONCompilerAndRunner$", "-v"}}, {"spec-real-qualification", goBinary, []string{"-C", "go", "test", "-race", "-count=1", "-tags=proofintegration", "./internal/specreview"}}, - {"project-architecture", goBinary, []string{"-C", "go", "test", "-count=1", "./dev", "-run", "^Test(ProjectArchitecture|SysMLSDKAndRequirementTrace|CargoWorkspace|SchemeModuleOwnership|CIWorkflows)", "-v"}}, + {"project-architecture", goBinary, []string{"-C", "go", "test", "-count=1", "./dev", "-run", "^Test(ProjectArchitecture|SysMLSDKAndRequirementTrace|CargoWorkspace|CIWorkflows)", "-v"}}, {"workflow-contract", "actionlint", nil}, {"rust-format", "cargo", []string{"fmt", "--all", "--", "--check"}}, {"rust-default-profile", "cargo", []string{"check", "--workspace", "--all-targets", "--locked", "--offline"}}, @@ -209,7 +209,7 @@ func Stages(mode, goBinary string) ([]Stage, error) { }, nil case "check-scheme": return []Stage{ - {"project-architecture", goBinary, []string{"-C", "go", "test", "-count=1", "./dev", "-run", "^Test(ProjectArchitecture|SysMLSDKAndRequirementTrace|CargoWorkspace|SchemeModuleOwnership|CIWorkflows)", "-v"}}, + {"project-architecture", goBinary, []string{"-C", "go", "test", "-count=1", "./dev", "-run", "^Test(ProjectArchitecture|SysMLSDKAndRequirementTrace|CargoWorkspace|CIWorkflows)", "-v"}}, {"scheme-policy-library", "cargo", []string{"build", "-p", "weaver-policy-ffi", "--locked", "--offline"}}, {"scheme-policy-preflight", "cargo", []string{"test", "-p", "weaver-policy-ffi", "--lib", "--benches", "--locked", "--offline"}}, {"scheme-policy-pkg-config", "cargo", []string{"run", "-p", "weaver-policy-ffi", "--example", "policy_pkg_config", "--locked", "--offline"}}, @@ -257,7 +257,7 @@ func Stages(mode, goBinary string) ([]Stage, error) { }, nil case "bench": return []Stage{ - {"project-architecture", goBinary, []string{"-C", "go", "test", "-count=1", "./dev", "-run", "^Test(ProjectArchitecture|SysMLSDKAndRequirementTrace|CargoWorkspace|SchemeModuleOwnership|CIWorkflows)", "-v"}}, + {"project-architecture", goBinary, []string{"-C", "go", "test", "-count=1", "./dev", "-run", "^Test(ProjectArchitecture|SysMLSDKAndRequirementTrace|CargoWorkspace|CIWorkflows)", "-v"}}, {"rust-environment", "rustc", []string{"-vV"}}, {"go-environment", goBinary, []string{"-C", "go", "version"}}, {"benchmark-package-contract", goBinary, []string{"-C", "go", "test", "-count=1", "./dev", "./internal/devrunner", "-run", "^Test(CargoWorkspaceAndDevelopmentGates|Benchmark.*)$"}}, From 5612ed1f9afa8103727d6c4a79a0a3a39c921890 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 19:59:04 +0800 Subject: [PATCH 015/105] Keep control-plane action ownership in SysML --- dev/sysml/README.org | 3 ++ dev/sysml/WeaverExecution.sysml | 48 +++++++++++++++---------------- dev/sysml/runtime-trace.json | 1 - go/dev/model_test.go | 51 --------------------------------- 4 files changed, 27 insertions(+), 76 deletions(-) diff --git a/dev/sysml/README.org b/dev/sysml/README.org index 9c30f360..f88c13ab 100644 --- a/dev/sysml/README.org +++ b/dev/sysml/README.org @@ -11,6 +11,9 @@ The root =Project.sysml= and every =dev/sysml/*.sysml= document are parsed as on model through the Go OpenSysML SDK's =ParseFiles= API with strict conformance. Root components reference actual domain part definitions. SysML allocations bind those components to the modeled Scheme, Go and Rust code owners. +Semantic derivation, source publication, original admission and final-effect +guarding each have a private action definition within their owning part. +Strict conformance rejects references to those definitions from other parts. =runtime-trace.json= binds each domain requirement to named implementation, native-test, Quint or Lean witnesses. The gate queries the linked SDK model for diff --git a/dev/sysml/WeaverExecution.sysml b/dev/sysml/WeaverExecution.sysml index 0584c2a7..19241f2b 100644 --- a/dev/sysml/WeaverExecution.sysml +++ b/dev/sysml/WeaverExecution.sysml @@ -714,34 +714,16 @@ package WeaverExecution { port def WirePort { out item request : CanonicalWireRequest; } - action def DeriveSemanticCandidate { - in item original : PolicyEvidenceDesign::SemanticCommitment; - out item candidate : PolicyEvidenceDesign::SourceCommand; - doc /* Derivation preserves independently admitted original meaning. - This action grants no publication, consumption or transport right. */ - } - action def OrchestrateSourcePublication { - in item candidate : PolicyEvidenceDesign::SourceCommand; - out item command : PolicyEvidenceDesign::SourceCommand; - doc /* Preserve original commitment while submitting authenticated - current-source commands; reconcile uncertain outcomes by identity. */ - } - action def CommitOriginalAdmission { - in item command : PolicyEvidenceDesign::SourceCommand; - out item observation : PolicyEvidenceDesign::PublishedObservation; - doc /* Existing deciding transaction, current authority and immutable - original binding. Commit produces an observation, never external IO. */ - } - action def GuardFinalEffect { - in item permit : ConsumedPermit; - out item request : CanonicalWireRequest; - doc /* Rejoin actual current authority and retained consumption under - final custody. An inert candidate cannot invoke this action. */ - } part def SchemeSemanticPublisher { attribute overviewName : String = "Task contract"; attribute overviewSummary : String = "Original scope"; attribute overviewGlyph : String = "task-contract"; + private action def DeriveSemanticCandidate { + in item original : PolicyEvidenceDesign::SemanticCommitment; + out item candidate : PolicyEvidenceDesign::SourceCommand; + doc /* Derivation preserves independently admitted original meaning. + This action grants no publication, consumption or transport right. */ + } action deriveCandidate : DeriveSemanticCandidate; doc /* Normative semantic allocation: reuse Agentic AI Lab Governor to select admitted original scope and Governance to assess obligations, @@ -798,6 +780,12 @@ package WeaverExecution { attribute overviewName : String = "Route proposal"; attribute overviewSummary : String = "Suggest a provider"; attribute overviewGlyph : String = "route-choice"; + private action def OrchestrateSourcePublication { + in item candidate : PolicyEvidenceDesign::SourceCommand; + out item command : PolicyEvidenceDesign::SourceCommand; + doc /* Preserve original commitment while submitting authenticated + current-source commands; reconcile uncertain outcomes by identity. */ + } action publishCandidate : OrchestrateSourcePublication; doc /* Preserve the semantic original through configuration normalization, protocol aliasing and authenticated publication. JSON/YAML populates @@ -974,6 +962,12 @@ package WeaverExecution { attribute overviewName : String = "Claim + budget"; attribute overviewSummary : String = "Record before sending"; attribute overviewGlyph : String = "budget-ledger"; + private action def CommitOriginalAdmission { + in item command : PolicyEvidenceDesign::SourceCommand; + out item observation : PolicyEvidenceDesign::PublishedObservation; + doc /* Existing deciding transaction, current authority and immutable + original binding. Commit produces an observation, never external IO. */ + } action commitOriginal : CommitOriginalAdmission; doc /* Implement the semantic original binding in the existing source deciding transaction, with exact-outcome recovery and current fencing. @@ -1027,6 +1021,12 @@ package WeaverExecution { attribute overviewName : String = "Final-use gate"; attribute overviewSummary : String = "Recheck actual use"; attribute overviewGlyph : String = "permission-check"; + private action def GuardFinalEffect { + in item permit : ConsumedPermit; + out item request : CanonicalWireRequest; + doc /* Rejoin actual current authority and retained consumption under + final custody. An inert candidate cannot invoke this action. */ + } action guardEffect : GuardFinalEffect; attribute leanDeclaration : String = "CedarPooSpec.Gateway.ZeroTrust.FinalUse"; attribute leanFields : String = "sameView,authenticated,current,profileAuthority,committed,unknownRetained,notRevoked,mediated"; diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index 4386daaa..e7c43e5b 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -452,7 +452,6 @@ {"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"metadataAsInitializationCounterexampleTest"}, {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem graph_membership_cannot_replace_initialization"}]}, {"id":"GovernorSourceHandoff","witnesses":[ - {"file":"go/dev/model_test.go","pattern":"func TestSysMLSemanticResponsibilityAllocation"}, {"file":"scheme/gateway/types.ss","pattern":"def GatewayProgram"}, {"file":"scheme/gateway/program.ss","pattern":"def \\(make-gateway-program"}, {"file":"t/gateway-source-test.ss","pattern":"program installation and close follow an irreversible lifecycle"}, diff --git a/go/dev/model_test.go b/go/dev/model_test.go index 1e86b3df..a5ea2c47 100644 --- a/go/dev/model_test.go +++ b/go/dev/model_test.go @@ -31,15 +31,6 @@ func TestSysMLSDKAndRequirementTrace(t *testing.T) { defer client.Close() model := projectModel(t, ctx, client) declared := map[string]bool{} - diagnostics, err := client.Diagnostics(ctx, model) - if err != nil { - t.Fatal(err) - } - for _, d := range diagnostics { - if d.Severity == opensysml.SeverityError { - t.Fatal(d.String()) - } - } requirements, err := client.Query(ctx, model, opensysml.Query{ Select: []string{"name"}, Where: opensysml.Equals("@type", "RequirementDefinition"), }) @@ -106,45 +97,3 @@ func TestSysMLSDKRejectsSemanticErrors(t *testing.T) { t.Fatalf("missing expected unresolved-type evidence: %v", model.Errors()) } } - -// Check ownership through the linked SDK model, rather than a second manifest. -// This guards architecture allocation; it does not establish runtime refinement. -func TestSysMLSemanticResponsibilityAllocation(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - client, err := opensysml.New(opensysml.WithCacheSize(1)) - if err != nil { - t.Fatal(err) - } - defer client.Close() - model := projectModel(t, ctx, client) - actions, err := client.Query(ctx, model, opensysml.Query{ - Scope: []string{"WeaverExecution"}, Select: []string{"name", "owner", "type"}, - Where: opensysml.Equals("@type", "ActionUsage"), - }) - if err != nil { - t.Fatal(err) - } - want := map[string]string{ - "WeaverExecution::SchemeSemanticPublisher::deriveCandidate": "WeaverExecution::DeriveSemanticCandidate", - "WeaverExecution::GoControlAdapter::publishCandidate": "WeaverExecution::OrchestrateSourcePublication", - "WeaverExecution::RustLedger::commitOriginal": "WeaverExecution::CommitOriginalAdmission", - "WeaverExecution::RustFinalBroker::guardEffect": "WeaverExecution::GuardFinalEffect", - } - for _, action := range actions { - key := action.Properties["owner"] + "::" + action.Properties["name"] - if expected, ok := want[key]; ok { - if action.Properties["type"] != expected { - t.Fatalf("%s has type %q, want %s", key, action.Properties["type"], expected) - } - delete(want, key) - continue - } - if action.Properties["type"] == "WeaverExecution::GuardFinalEffect" { - t.Fatalf("final-effect action allocated outside the Rust broker: %s", key) - } - } - if len(want) != 0 { - t.Fatalf("missing semantic/publication/commit/final-effect allocations: %v; SDK actions: %v", want, actions) - } -} From 7428bc8ab0e0f96b67bb0cc85ff30f31a1701794 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 20:08:45 +0800 Subject: [PATCH 016/105] Preserve native Go timeout diagnostics in verification receipts --- go/internal/devrunner/retention.go | 8 +++++++- go/internal/devrunner/retention_test.go | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/go/internal/devrunner/retention.go b/go/internal/devrunner/retention.go index 385460a9..48129cc8 100644 --- a/go/internal/devrunner/retention.go +++ b/go/internal/devrunner/retention.go @@ -92,7 +92,13 @@ func firstFailureExcerpt(input io.Reader) ([]byte, error) { var excerpt, preceding []byte for { fragment, err := reader.ReadSlice('\n') - marker := bytes.Contains(fragment, []byte("--- FAIL:")) || bytes.Contains(fragment, []byte("*** ERROR")) || bytes.Contains(fragment, []byte("error:")) || bytes.Contains(fragment, []byte("control readiness:")) || bytes.Contains(fragment, []byte("negative control")) + marker := bytes.Contains(fragment, []byte("--- FAIL:")) || + bytes.Contains(fragment, []byte("*** ERROR")) || + bytes.Contains(fragment, []byte("error:")) || + bytes.Contains(fragment, []byte("control readiness:")) || + bytes.Contains(fragment, []byte("negative control")) || + bytes.HasPrefix(fragment, []byte("panic: test timed out after ")) || + bytes.HasPrefix(fragment, []byte("SIGQUIT: quit")) if len(excerpt) == 0 && marker { // Go prints t.Fatal diagnostics before the FAIL marker. Keep a // bounded preceding window rather than retaining only later passes. diff --git a/go/internal/devrunner/retention_test.go b/go/internal/devrunner/retention_test.go index f952f050..a24a1ce1 100644 --- a/go/internal/devrunner/retention_test.go +++ b/go/internal/devrunner/retention_test.go @@ -143,9 +143,15 @@ func TestFailureSummaryRetainsFirstCauseBeforePassingSuffix(t *testing.T) { func FuzzFailureExcerptRetainsPrecedingDiagnostic(f *testing.F) { f.Add(uint16(0), uint16(0)) f.Add(uint16(8191), uint16(8191)) + f.Add(uint16(8192), uint16(8191)) f.Fuzz(func(t *testing.T, prefix, suffix uint16) { const cause = " gateway_test.go:42: original capacity deadline exceeded\n" - const marker = "--- FAIL: TestGateway/PROTOBUF\n" + markers := [...]string{ + "--- FAIL: TestGateway/PROTOBUF\n", + "panic: test timed out after 10m0s\n", + "SIGQUIT: quit\n", + } + marker := markers[int(prefix)%len(markers)] output := strings.Repeat("passing progress\n", int(prefix%8192)) + cause + marker + strings.Repeat("later passing case\n", int(suffix%8192)) excerpt, err := firstFailureExcerpt(strings.NewReader(output)) if err != nil || len(excerpt) > 2048 || !strings.Contains(string(excerpt), cause) || !strings.Contains(string(excerpt), marker) { From 5b36ae4e64f9e8487b6d7b39a56121992e041ecc Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 20:10:56 +0800 Subject: [PATCH 017/105] Use four Tokio workers in provider runtime tests --- crates/server/src/grpc_config.rs | 2 +- crates/server/tests/unit/output_backpressure.rs | 6 +++--- crates/server/tests/unit/review_rpc.rs | 2 +- crates/server/tests/unit/runtime_lifecycle.rs | 2 +- crates/server/tests/unit/source_owner.rs | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/server/src/grpc_config.rs b/crates/server/src/grpc_config.rs index 827ba4c9..1e36abed 100644 --- a/crates/server/src/grpc_config.rs +++ b/crates/server/src/grpc_config.rs @@ -89,7 +89,7 @@ fn load_transport() -> Result { } #[cfg(test)] -#[tokio::test(flavor = "multi_thread")] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] #[ignore = "started as a child by the Go WIF fixture"] async fn serve_wif_gateway() { crate::entrypoint::run_on_runtime() diff --git a/crates/server/tests/unit/output_backpressure.rs b/crates/server/tests/unit/output_backpressure.rs index e53c45d9..8d4da031 100644 --- a/crates/server/tests/unit/output_backpressure.rs +++ b/crates/server/tests/unit/output_backpressure.rs @@ -167,7 +167,7 @@ fn prepared_ledger(path: &std::path::Path) -> (Ledger, weaver_ledger::ProviderDi (ledger, permit) } -#[tokio::test(flavor = "multi_thread")] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn waiting_capacity_does_not_hold_sql_or_authorize_after_publication() { let directory = tempfile::tempdir().expect("temp"); let path = directory.path().join("ledger.db"); @@ -196,7 +196,7 @@ async fn waiting_capacity_does_not_hold_sql_or_authorize_after_publication() { assert_eq!(ledger.held("f").expect("hold"), 4); } -#[tokio::test(flavor = "multi_thread")] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn pending_range_history_created_during_capacity_wait_cannot_be_replayed() { let directory = tempfile::tempdir().expect("temp"); let path = directory.path().join("ledger.db"); @@ -233,7 +233,7 @@ async fn pending_range_history_created_during_capacity_wait_cannot_be_replayed() assert_eq!(receipt.held, 4); } -#[tokio::test(flavor = "multi_thread")] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn cancellation_interrupts_actual_capacity_wait_without_refund() { let directory = tempfile::tempdir().expect("temp"); let (ledger, _permit) = prepared_ledger(&directory.path().join("ledger.db")); diff --git a/crates/server/tests/unit/review_rpc.rs b/crates/server/tests/unit/review_rpc.rs index 447eb578..03834566 100644 --- a/crates/server/tests/unit/review_rpc.rs +++ b/crates/server/tests/unit/review_rpc.rs @@ -11,7 +11,7 @@ use sha2::{Digest, Sha256}; use tonic::transport::{Certificate, Identity, ServerTlsConfig}; use weaver_contracts::{DeltaDisposition, DeltaReview, PublicationKey, PublicationReview}; -#[tokio::test(flavor = "multi_thread")] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn source_rpc_reads_owned_parent_and_registers_only_authenticated_evidence() { let directory = tempfile::tempdir().expect("dir"); let database = directory.path().join("rpc.db"); diff --git a/crates/server/tests/unit/runtime_lifecycle.rs b/crates/server/tests/unit/runtime_lifecycle.rs index 07503dff..eebf3e8d 100644 --- a/crates/server/tests/unit/runtime_lifecycle.rs +++ b/crates/server/tests/unit/runtime_lifecycle.rs @@ -7,7 +7,7 @@ use std::{future::Future, sync::Arc, task::Poll, time::Duration}; use tokio::sync::{Semaphore, oneshot}; use weaver_contracts::Error; -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn detached_executor_writer_keeps_slot_until_drain_acknowledges_completion() { let owner = RuntimeOwner::new(); let slots = Arc::new(Semaphore::new(1)); diff --git a/crates/server/tests/unit/source_owner.rs b/crates/server/tests/unit/source_owner.rs index 6e545f02..8040ddaa 100644 --- a/crates/server/tests/unit/source_owner.rs +++ b/crates/server/tests/unit/source_owner.rs @@ -36,7 +36,7 @@ fn slot() -> Arc { ) } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn reused_source_connection_observes_other_writer_and_preserves_historical_result() { let directory = tempfile::tempdir().expect("directory"); let path = directory.path().join("source.db"); @@ -142,7 +142,7 @@ async fn startup_failure_closes_runtime_and_drains_source_owner() { assert!(runtime.closing()); } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn disconnected_source_caller_keeps_capacity_until_original_sql_work_finishes() { use std::{collections::BTreeSet, future::Future, task::Poll}; let directory = tempfile::tempdir().expect("directory"); @@ -226,7 +226,7 @@ async fn disconnected_source_caller_keeps_capacity_until_original_sql_work_finis ); } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn review_context_uses_provisioned_metadata_and_does_not_publish() { let directory = tempfile::tempdir().expect("dir"); let path = directory.path().join("review.db"); From 887a1c6a492aabebed2e43aefbbe068ad5c5bb97 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 20:10:57 +0800 Subject: [PATCH 018/105] Preregister Governor release performance qualification --- .../59.64-governance-capture-ownership.org | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.org b/docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.org index 4f9fba42..8cb2015b 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.org +++ b/docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.org @@ -1781,6 +1781,84 @@ execution budget. The ordinary source RPC remains the explicitly trusted administrative profile; full semantic-adapter restrictions on that profile are not newly claimed by the startup mechanism. +** Governor release preregistration + +Protocol prepared. Site evidence, the execution selector and the statistical +design inputs remain pending. The local Snake Oil correctness qualification is +closed. Its four-arm wiring wave and previous failed attempts remain in their +original evidence scopes. + +*** Site records and release binding + +| Site record | Required binding | +|-------------+------------------| +| Approval and activation | Site and environment ID, approving principal or verifiable review receipt, approval scope and time, deployment ID, activation receipt and authoritative activation version. Bind the receipt to the running release digest, catalog digest and admitted source authority. | +| Approved application and build | Scheme module ID and source revision, Build Packages manifest, Gerbil SDK revision, executable SHA-256 and deployment image digest. Record the Scheme package library and all native dependencies resolved outside the linked image with effective loader origins and content digests. | +| Approved catalog and policy | Exact catalog bytes selected by =WEAVER_GOVERNANCE_CATALOG= and their SHA-256, authenticated source identity fingerprints and epoch, policy/schema digests, hard-fact starting cut and original ledger/claim state or verified snapshot. Use the site's credential configuration for access. | +| Approved workload and execution envelope | Replay identity and digest, capture and approval window, request and response streams, open-loop arrival schedule, response release gates, fault/restart schedule, concurrency and outstanding-work limits, expected operation identities and outcomes, and independent owner and exit opportunities. Record the permitted replay environment and the policy for upstream effects. | + +Freeze these records in one manifest before sampling. Resolve the approved +application through Build Packages and =scheme-program=, then verify that the +test-owned executable SHA-256 and the effective runtime dependency digests match +the approved release. Bind the running image to the site activation receipt. +Check the same manifest before and after each cohort. Run both arms from separate +ledger instances initialized from the same approved cut. Preserve original +operation identities and authoritative admission checks in each instance. Keep +catalog, policy, replay, host class and capacity settings fixed across arms. For +retained A/B, the runtime derivation mode is the sole treatment change in the +same executable. + +Use the site's approved runtime inputs and endpoint mapping to freeze the exact +command that drives replay through the native Control and Rust release entry +points. The developer qualification's nine-node loopback workload provides a +local correctness fixture. Formal registration stays pending +until the chosen entry consumes the approved site replay and emits the required +cut, release, reservation and shutdown evidence. Record the exact executable +selector and verify it during preflight, outside the formal sample. + +*** Sampling and decisions + +1. Freeze the primary site join and its correspondence between arms. Measure + durable complete release to the successful reservation commit using a + monotonic clock. Report other joins, first ASCENT open, warm derivation, queue, + FFI, ledger and natural stop separately. Match by scheduled operation and + compare both Governor cut and ready-node digests. Keep timeouts, refusals, + mismatches and incomplete blocks in the cohort record. +2. Use fresh versus fresh for A/A. Collect matched blocks using the same offered + work with a frozen, balanced arm order. Keep all observations from a reused owner and + its dependent windows in the same analysis cluster. Treat shutdown as one + observation per owner exit. Freeze the number of independent matched blocks, + eligible requests per window, exit opportunities, warmup, host admission, + total wall-clock budget and stopping rule before the first formal sample. + The original capacity controls, four workers, 12-second recovery and + 15-second natural-exit fences remain in force. Prelaunch host refusals are + recorded separately. Readiness failure after launch is a failed trial. +3. Use nearest-rank empirical p99 for each arm. Calculate the B-to-A ratio on + the matched primary endpoints, preserving all within-owner + observations. Estimate two-sided 95% ratio intervals by resampling whole + independent matched blocks, with 20,000 draws and seed =20261106=. Calculate + natural-stop p99 and its ratio interval separately from independent matched + exits. Before locking sample sizes, use approved planning windows outside the + formal cohorts to check interval coverage and precision under plausible tail + variability and clustering. Target at least 90% probability of passing A/A + when the true ratio is 1.00 and 90% power for the declared retained planning + effect across the adoption gates. Leave a margin between the planning ratios + and the adoption bounds. Record the assumptions, simulation results, chosen + sizes and budget together. Freeze both cohort designs before the first formal + A/A sample. If tail support or the budget is insufficient, leave the gate pending. +4. A/A passes when the primary p99 ratio interval lies within =[0.90, 1.10]= + and all semantic and capacity controls pass. Then run the separately frozen + A/B cohort, with fresh A and retained B. Adopt retained only when the upper + primary p99 ratio bound and median ratio are both at most =0.90=, the upper + natural-stop p99 ratio bound is at most =1.10=, admitted work matches and all + controls pass. A failed, missing or incomplete trial prevents qualification. + Retain failures at their deadlines and preserve the run's original verdict. + +Record production approval and workload replay as separate missing inputs until +the site provides both. Freeze the numeric sample plan once those inputs support +it. The default remains fresh derivation on one Scheme owner while qualification +is pending. + ** Evidence and retained gaps The first graph attempts failed during metadata import: importing a module From 9bd3511ca613b2c151eb81af71f576f7d37d1e1a Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 20:19:19 +0800 Subject: [PATCH 019/105] Keep native package sources visible to the Cargo build owner --- crates/governance-build/src/lib.rs | 4 + crates/governance-build/src/tooling.rs | 46 ++++++++++++ .../tests/unit/package_sources.rs | 74 +++++++++++++++++++ dev/sysml/ControlActivation.sysml | 5 ++ dev/sysml/runtime-trace.json | 4 +- 5 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 crates/governance-build/tests/unit/package_sources.rs diff --git a/crates/governance-build/src/lib.rs b/crates/governance-build/src/lib.rs index fc725ddb..73cbb890 100644 --- a/crates/governance-build/src/lib.rs +++ b/crates/governance-build/src/lib.rs @@ -17,3 +17,7 @@ asp_rust::asp_rust_cargo_test_gate!(mode = deny, config = asp_rust::default_asp_ mod path_tests; pub use tooling::{PackageTooling, stage_program}; + +#[cfg(all(test, unix))] +#[path = "../tests/unit/package_sources.rs"] +mod package_source_tests; diff --git a/crates/governance-build/src/tooling.rs b/crates/governance-build/src/tooling.rs index 9e362dc9..121383ac 100644 --- a/crates/governance-build/src/tooling.rs +++ b/crates/governance-build/src/tooling.rs @@ -4,6 +4,7 @@ //! Typed SDK bindings supplied by Cargo's build-host dependency context. use crate::ProgramStageRequest; +use std::{fs, io, path::Path}; /// Only linkage is injected; this crate owns package preparation and staging. /// No erased values, expression parser or runtime authority are introduced. @@ -20,6 +21,8 @@ impl PackageTooling { let prefix = std::path::Path::new(request.output).join("package"); let library = prefix.join("lib"); std::fs::create_dir_all(&library).expect("native build output prefix"); + bind_package_sources(Path::new(request.library), &prefix) + .expect("native package source inputs"); let libraries = std::env::join_paths([library.as_path(), std::path::Path::new(request.library)]) .expect("build library path list"); @@ -76,6 +79,49 @@ impl PackageTooling { } } +/// Borrow Gerbil's existing package source directory into the fresh Cargo owner. +/// Only `lib` is an output. No dependency discovery, installation or source copy +/// is performed here; native `pkg-root-dir` retains the selected input store. +/// Bind before creating the tooling VM, while this Cargo output has no live owner. +pub(crate) fn bind_package_sources(library: &Path, prefix: &Path) -> io::Result<()> { + let source = library + .parent() + .ok_or_else(|| io::Error::other("input library prefix required"))? + .join("pkg") + .canonicalize()?; + if !source.is_dir() || source.starts_with(prefix.canonicalize()?) { + return Err(io::Error::other( + "independent package source directory required", + )); + } + let destination = prefix.join("pkg"); + match fs::symlink_metadata(&destination) { + Ok(metadata) if metadata.file_type().is_symlink() => { + match destination.canonicalize() { + Ok(current) if current == source => return Ok(()), + Ok(_) => {} + Err(error) if error.kind() == io::ErrorKind::NotFound => {} + Err(error) => return Err(error), + } + // The old store may have been replaced or removed. Replace only + // the link in this build's output. + fs::remove_file(&destination)?; + } + Ok(metadata) if metadata.is_dir() => fs::remove_dir(&destination)?, + Ok(_) => return Err(io::Error::other("package input mount is occupied")), + Err(error) if error.kind() == io::ErrorKind::NotFound => {} + Err(error) => return Err(error), + } + #[cfg(unix)] + { + std::os::unix::fs::symlink(source, destination) + } + #[cfg(windows)] + { + std::os::windows::fs::symlink_dir(source, destination) + } +} + /// Stage with one affine SDK owner and Cargo-owned outputs; source trees are inputs. pub fn stage_program( request: ProgramStageRequest<'_>, diff --git a/crates/governance-build/tests/unit/package_sources.rs b/crates/governance-build/tests/unit/package_sources.rs new file mode 100644 index 00000000..cc9674f7 --- /dev/null +++ b/crates/governance-build/tests/unit/package_sources.rs @@ -0,0 +1,74 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +use crate::tooling::bind_package_sources; +use std::{ + fs, + time::{SystemTime, UNIX_EPOCH}, +}; + +#[test] +fn native_package_inputs_follow_the_selected_store_without_overwriting_sources() { + let root = std::env::temp_dir().join(format!( + "weaver-package-sources-{}-{}", + std::process::id(), + SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("clock") + .as_nanos() + )); + let input = root.join("input"); + let next = root.join("next"); + let output = root.join("output"); + for path in [ + input.join("lib"), + input.join("pkg/github.com/lab/modules"), + next.join("lib"), + next.join("pkg/github.com/lab/modules"), + output.clone(), + ] { + fs::create_dir_all(path).expect("fixture directories"); + } + let leaf = "github.com/lab/modules/governance"; + fs::write(input.join("pkg").join(leaf), "original source").expect("input"); + fs::write(next.join("pkg").join(leaf), "next source").expect("next"); + // Native gxpkg may already have created an empty package directory. + fs::create_dir(output.join("pkg")).expect("empty native store"); + bind_package_sources(&input.join("lib"), &output).expect("borrow input"); + bind_package_sources(&input.join("lib"), &output).expect("same input"); + assert_eq!( + fs::read_to_string(output.join("pkg").join(leaf)).expect("native path"), + "original source" + ); + bind_package_sources(&next.join("lib"), &output).expect("new build owner"); + assert_eq!( + fs::read_to_string(output.join("pkg").join(leaf)).expect("new path"), + "next source" + ); + assert_eq!( + fs::read_to_string(input.join("pkg").join(leaf)).expect("old input retained"), + "original source" + ); + fs::rename(next.join("pkg"), next.join("retired-pkg")).expect("retire input store"); + bind_package_sources(&input.join("lib"), &output).expect("replace dangling output link"); + assert_eq!( + fs::read_to_string(output.join("pkg").join(leaf)).expect("rebound path"), + "original source" + ); + assert_eq!( + fs::read_to_string(next.join("retired-pkg").join(leaf)).expect("retired store retained"), + "next source" + ); + fs::remove_file(output.join("pkg")).expect("remove owned link"); + fs::create_dir(output.join("pkg")).expect("occupied directory"); + fs::write(output.join("pkg/keep"), "keep").expect("sentinel"); + assert!(bind_package_sources(&input.join("lib"), &output).is_err()); + assert_eq!( + fs::read_to_string(output.join("pkg/keep")).expect("sentinel survives"), + "keep" + ); + assert!(bind_package_sources(&root.join("missing/lib"), &output).is_err()); + assert!(bind_package_sources(&output.join("lib"), &output).is_err()); + fs::remove_dir_all(root).expect("fixture cleanup"); +} diff --git a/dev/sysml/ControlActivation.sysml b/dev/sysml/ControlActivation.sysml index 254b24d8..2cf641ea 100644 --- a/dev/sysml/ControlActivation.sysml +++ b/dev/sysml/ControlActivation.sysml @@ -49,6 +49,11 @@ package ControlActivation { archive/source correspondence and package lifecycle operations. Weaver's Go runner records actual command outcomes and root source currentness; it is not a second package manager. */ + doc /* Cargo-owned native library outputs retain the selected SDK's + existing package source directory as an explicit input. Bind that + native pkg root before creating the tooling owner; do not resolve + versions, install dependencies, copy packages or alter source trees. + An occupied nonempty output directory must refuse replacement. */ doc /* A package result or release label grants no Policy, publication or send authority. Changed-source and preparation-cut laws retain their explicit host premises; an upstream SDK API alone does not prove diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index e7c43e5b..8fd209a5 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -531,7 +531,9 @@ {"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"}, {"file":"go/internal/controlplane/deployment.go","pattern":"trace\\(\"authority-reconciled\"\\)"}, {"file":"t/fixtures/governed-control.ss","pattern":"fixture-module-ready"}, - {"file":"go/dev/provider_control_test.go","pattern":"These unauthenticated diagnostics never replace readiness or exit checks"}]}, + {"file":"go/dev/provider_control_test.go","pattern":"These unauthenticated diagnostics never replace readiness or exit checks"}, + {"file":"crates/governance-build/src/tooling.rs","pattern":"fn bind_package_sources"}, + {"file":"crates/governance-build/tests/unit/package_sources.rs","pattern":"fn native_package_inputs_follow_the_selected_store_without_overwriting_sources"}]}, {"id":"PolicyCAbiIsInert","witnesses":[ {"file":"scheme/policy/func.ss","pattern":"def \\(validate-policy-projection!"}, {"file":"scheme/gateway/func.ss","pattern":"validate-policy-projection! projection"}, From fd52d6d20712b0743c4082e05b508aa92999c3e4 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 20:23:05 +0800 Subject: [PATCH 020/105] Bound native provider fixture startup failure cleanup --- go/dev/provider_fixture_test.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/go/dev/provider_fixture_test.go b/go/dev/provider_fixture_test.go index 3b52e0ad..cb99173b 100644 --- a/go/dev/provider_fixture_test.go +++ b/go/dev/provider_fixture_test.go @@ -51,6 +51,9 @@ var controlBinary string func TestMain(m *testing.M) { flag.Parse() + if flag.Lookup("test.list").Value.String() != "" { + os.Exit(m.Run()) + } if os.Getenv(pressureChild) == "1" && flag.Lookup("test.run").Value.String() == "^TestProviderCPUPressureWorker$" { os.Exit(m.Run()) } @@ -397,8 +400,7 @@ func (f *fixture) start(t testing.TB) { f.client, err = gatewayclient.Dial(ctx, f.address, ownerToken, security) t.Logf("Rust owner startup operation-channel started=%s elapsed=%s error=%v", started.UTC().Format(time.RFC3339Nano), time.Since(started), err) if err != nil { - f.child.Process.Signal(syscall.SIGTERM) - <-f.exited + f.stop(t) data, _ := os.ReadFile(filepath.Join(f.directory, "server.log")) t.Fatalf("gRPC startup: %v: %s", err, data) } @@ -420,7 +422,9 @@ func (f *fixture) stop(t testing.TB) { if f.child == nil { return } - f.client.Connection.Close() + if f.client != nil { + f.client.Connection.Close() + } if f.admin != nil { f.admin.Connection.Close() } From ca9c1c7ce444d0054d2f293e198b868401c71c05 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 20:29:25 +0800 Subject: [PATCH 021/105] Budget provider image builds separately from Go integration --- Project.sysml | 9 ++++++++- go/internal/devrunner/plan.go | 9 ++++++--- go/internal/devrunner/runner.go | 26 ++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/Project.sysml b/Project.sysml index c2238565..9cbc34ad 100644 --- a/Project.sysml +++ b/Project.sysml @@ -233,7 +233,14 @@ package WeaverProject { not completion evidence. Go testing.F exercises protocol corruption; transcript checks do not prove SDK execution or final-send safety. */ part rust : VerificationSuite { part 'check-rust' : VerificationMode; } - part go : VerificationSuite { part 'check-go' : VerificationMode; } + part go : VerificationSuite { + part 'check-go' : VerificationMode; + doc /* Prepare the ordinary provider and commit-observer images with + Cargo in separate five-minute stages before the Go Provider + integration suite. The same Cargo targets remain the fixture's + image authority. The integration package keeps its ten-minute + timeout and all existing recovery and natural-exit gates. */ + } part scheme : VerificationSuite { part 'check-scheme' : VerificationMode; } part architecture : VerificationSuite { part 'check-architecture' : VerificationMode; } part policy : VerificationSuite { part 'check-policy' : VerificationMode; } diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index 53889561..11fd561c 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -138,7 +138,9 @@ func Plan(goBinary string) []Stage { {"publication-lean", "elan", []string{"run", proofToolchain, "lean", "--json", "dev/proofs/lean/PublicationRecovery.lean"}}, {"source-owner-quint-tests", "quint", []string{"test", "dev/proofs/quint/SourceOwner.qnt", "--main", "SourceOwner", "--seed", "293"}}, {"source-owner-quint-safety", "quint", []string{"run", "dev/proofs/quint/SourceOwner.qnt", "--main", "SourceOwner", "--invariant", "safe", "--max-samples", "1000", "--max-steps", "60", "--seed", "293"}}, - {"go-provider-grpc-integration", goBinary, []string{"-C", "go", "test", "-count=1", "-race", "-tags=integration", "./dev", "-run", "TestProvider", "-v"}}, + {"go-provider-server-build", "cargo", []string{"build", "-p", "weaver-server", "--bin", "weaver-server", "--features", "arrow", "--locked", "--offline", "-j", "4"}}, + {"go-provider-observer-build", "cargo", []string{"test", "-p", "weaver-server", "--lib", "--features", "arrow", "--locked", "--offline", "-j", "4", "--no-run"}}, + {"go-provider-grpc-integration", goBinary, []string{"-C", "go", "test", "-count=1", "-race", "-tags=integration", "-timeout=10m", "./dev", "-run", "TestProvider", "-v"}}, {"control-bundle-pbt", goBinary, []string{"-C", "go", "test", "./internal/config", "-run", "^$", "-fuzz", "FuzzSourceBundleCannotExpandOriginalSelection", "-fuzztime=3s"}}, {"authority-publication-quint-tests", "quint", []string{"test", "dev/proofs/quint/AuthorityPublication.qnt", "--main", "AuthorityPublication", "--seed", "293", "--match", "^authority[A-Z]"}}, {"authority-publication-quint-safety", "quint", []string{"run", "dev/proofs/quint/AuthorityPublication.qnt", "--main", "AuthorityPublication", "--invariant", "safe", "--max-samples", "1000", "--max-steps", "60", "--seed", "293"}}, @@ -187,8 +189,9 @@ func Stages(mode, goBinary string) ([]Stage, error) { var selected []Stage for _, stage := range Plan(goBinary) { common := stage.Name == "project-architecture" || stage.Name == "workflow-contract" - language := mode == "check-rust" && (stage.Binary == "cargo" || stage.Binary == "rustc") || - mode == "check-go" && stage.Binary == goBinary && stage.Name != "lean-json-integration" && stage.Name != "spec-real-qualification" && stage.Name != "spec-proof-closure-integration" || + providerBuild := stage.providerBuild() + language := mode == "check-rust" && !providerBuild && (stage.Binary == "cargo" || stage.Binary == "rustc") || + mode == "check-go" && (providerBuild || stage.Binary == goBinary && stage.Name != "lean-json-integration" && stage.Name != "spec-real-qualification" && stage.Name != "spec-proof-closure-integration") || mode == "check-policy" && (stage.Binary == "quint" || stage.Binary == "elan" || stage.Name == "lean-json-integration" || stage.Name == "spec-real-qualification" || stage.Name == "spec-proof-closure-integration") if common || language { selected = append(selected, stage) diff --git a/go/internal/devrunner/runner.go b/go/internal/devrunner/runner.go index fdb17db1..aee470a7 100644 --- a/go/internal/devrunner/runner.go +++ b/go/internal/devrunner/runner.go @@ -28,6 +28,11 @@ type Stage struct { Name, Binary string Args []string } + +func (stage Stage) providerBuild() bool { + return stage.Name == "go-provider-server-build" || stage.Name == "go-provider-observer-build" +} + type Result struct { HeaderSeal *HeaderSealEvidence `json:"headerSeal,omitempty"` Contention *ContentionEvidence `json:"contention,omitempty"` @@ -166,15 +171,25 @@ func Run(ctx context.Context, config Config, output io.Writer) (report string, r settings["GERBIL_BUILD_CORES"] = strconv.Itoa(runtime.NumCPU()) environment = Environment(settings) } + var providerBuildFailure string for _, stage := range stages { if ctx.Err() != nil { failed = true break } - result := runStage(ctx, root, directory, environment, stage) + var result Result + if stage.Name == "go-provider-grpc-integration" && providerBuildFailure != "" { + result = Result{Name: stage.Name, Status: "SKIP", Binary: stage.Binary, Args: stage.Args, + Error: "required native build did not pass: " + providerBuildFailure} + } else { + result = runStage(ctx, root, directory, environment, stage) + } receipt.Stages = append(receipt.Stages, result) if result.Status != "PASS" { failed = true + if stage.providerBuild() { + providerBuildFailure = stage.Name + } } if err := writeReceipt(directory, receipt); err != nil { return directory, err @@ -258,9 +273,16 @@ func runStageObserved(ctx context.Context, root, directory string, environment [ case "scheme-source-integration-tests": tests = "t/integration" } + deadline := time.Duration(0) if tests != "" { + deadline = schemePackageTestTimeout + } + if stage.providerBuild() { + deadline = 5 * time.Minute + } + if deadline != 0 { var cancel context.CancelFunc - ctx, cancel = context.WithTimeout(ctx, schemePackageTestTimeout) + ctx, cancel = context.WithTimeout(ctx, deadline) defer cancel() } From f391288ae62e93d36dd106dcdfaee4cc8f265a47 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 20:39:02 +0800 Subject: [PATCH 022/105] Bind fact barriers and Session progression to ledger admission --- crates/contracts/src/hard_fact.rs | 341 +++++++++++++ crates/contracts/src/lib.rs | 7 + crates/ledger/src/hard_fact.rs | 477 ++++++++++++++++++ crates/ledger/src/lib.rs | 8 + crates/ledger/src/provider.rs | 121 ++--- crates/ledger/src/provider_admission.rs | 82 +++ crates/ledger/src/provider_workflow.rs | 323 ++++++++++++ crates/ledger/src/provider_workflow_choice.rs | 287 +++++++++++ crates/ledger/src/provider_workflow_nested.rs | 240 +++++++++ crates/ledger/src/schema.rs | 15 + crates/ledger/src/source_authority.rs | 4 + crates/ledger/src/store.rs | 5 + crates/ledger/src/stream_state.rs | 7 + crates/ledger/tests/unit/provider.rs | 2 + crates/ledger/tests/unit/provider/workflow.rs | 382 ++++++++++++++ dev/sysml/PolicyEvidenceDesign.sysml | 77 ++- dev/sysml/WeaverExecution.sysml | 21 + dev/sysml/runtime-trace.json | 9 +- 18 files changed, 2336 insertions(+), 72 deletions(-) create mode 100644 crates/contracts/src/hard_fact.rs create mode 100644 crates/ledger/src/hard_fact.rs create mode 100644 crates/ledger/src/provider_admission.rs create mode 100644 crates/ledger/src/provider_workflow.rs create mode 100644 crates/ledger/src/provider_workflow_choice.rs create mode 100644 crates/ledger/src/provider_workflow_nested.rs create mode 100644 crates/ledger/tests/unit/provider/workflow.rs diff --git a/crates/contracts/src/hard_fact.rs b/crates/contracts/src/hard_fact.rs new file mode 100644 index 00000000..e407f5cb --- /dev/null +++ b/crates/contracts/src/hard_fact.rs @@ -0,0 +1,341 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Durable fact-feed inputs and the sealed topology of a governed Session. + +use crate::{Error, MAX_CREDITS, Result, SourceAuthority, body_digest, identifier}; +use serde::{Deserialize, Serialize}; +use std::collections::{BTreeMap, BTreeSet}; + +/// Wire schema for an ordered Session path. +pub const SESSION_WORKFLOW_SCHEMA: &str = "weaver.session-workflow.v1"; + +/// Wire schema for a Session with concurrent branches and joins. +pub const SESSION_DAG_SCHEMA: &str = "weaver.session-dag.v1"; +/// Wire schema for a Session with nested conditional gates. +pub const SESSION_NESTED_SCHEMA: &str = "weaver.session-nested.v1"; +/// Wire schema for a Session with one two-arm selector. +pub const SESSION_CHOICE_SCHEMA: &str = "weaver.session-choice.v1"; +/// Maximum size of a selector's completely released structured result. +pub const MAX_WORKFLOW_RESULT_BYTES: usize = 512; + +/// A selector's typed route to one of its admitted arms. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum WorkflowRoute { + Left, + Right, +} + +impl WorkflowRoute { + pub fn as_str(self) -> &'static str { + match self { + Self::Left => "left", + Self::Right => "right", + } + } + + pub fn arm(self, nodes: &[String; 4]) -> &str { + match self { + Self::Left => &nodes[1], + Self::Right => &nodes[2], + } + } +} + +/// Trusted deployment admission for one ledger-local, ordered availability feed. +/// Each edge is (dependent, dependency) within the independently admitted task. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct FactFeed { + pub domain: String, + pub authority: SourceAuthority, + pub family: String, + pub root: String, + pub dependencies: Vec<(String, String)>, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub workflow: Option, + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub workflow_path: Vec, + #[serde(default, skip_serializing_if = "std::ops::Not::not")] + pub workflow_dag: bool, + #[serde(default, skip_serializing_if = "std::ops::Not::not")] + pub workflow_choice: bool, + /// Each selector names the entry of its left and right arms. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub workflow_selectors: Vec<[String; 3]>, +} + +/// One explicitly admitted outgoing edge of a compiled Governor task. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct ProviderWorkflow { + pub predecessor: String, + pub successor: String, +} + +impl FactFeed { + pub fn session_schema(&self) -> &'static str { + if !self.workflow_selectors.is_empty() { + SESSION_NESTED_SCHEMA + } else if self.workflow_choice { + SESSION_CHOICE_SCHEMA + } else if self.workflow_dag { + SESSION_DAG_SCHEMA + } else { + SESSION_WORKFLOW_SCHEMA + } + } + + pub fn choice_nodes(&self) -> Option<&[String; 4]> { + if self.workflow_choice { + self.workflow_path.as_slice().try_into().ok() + } else { + None + } + } + + pub fn workflow_predecessors(&self, node: &str) -> Vec<&str> { + if self.workflow_dag { + return self + .dependencies + .iter() + .filter(|(child, _)| child == node) + .map(|(_, parent)| parent.as_str()) + .collect(); + } + if let Some(edge) = &self.workflow { + return (edge.successor == node) + .then_some(edge.predecessor.as_str()) + .into_iter() + .collect(); + } + self.workflow_path + .windows(2) + .find(|pair| pair[1] == node) + .map(|pair| pair[0].as_str()) + .into_iter() + .collect() + } + + pub fn validate(&self) -> Result<()> { + identifier(&self.domain)?; + identifier(&self.family)?; + identifier(&self.root)?; + self.authority.identity.validate()?; + if self.authority.epoch > MAX_CREDITS || self.dependencies.len() > 64 { + return Err(Error::Invalid("fact feed bounds")); + } + for (dependent, dependency) in &self.dependencies { + identifier(dependent)?; + identifier(dependency)?; + } + self.validate_workflow() + } + + fn validate_workflow(&self) -> Result<()> { + if let Some(workflow) = &self.workflow { + identifier(&workflow.predecessor)?; + identifier(&workflow.successor)?; + if workflow.predecessor == workflow.successor { + return Err(Error::Invalid("provider workflow edge")); + } + } + if !self.workflow_path.is_empty() { + if self.workflow.is_some() + || !(2..=64).contains(&self.workflow_path.len()) + || self.workflow_path[0] != self.root + { + return Err(Error::Invalid("provider workflow path")); + } + let mut seen = BTreeSet::new(); + for node in &self.workflow_path { + identifier(node)?; + if !seen.insert(node) { + return Err(Error::Invalid("provider workflow repeated node")); + } + } + if self.workflow_dag { + validate_session_dag(&self.workflow_path, &self.dependencies)?; + } else if self.workflow_path.windows(2).any(|pair| { + !self + .dependencies + .iter() + .any(|(dependent, dependency)| dependent == &pair[1] && dependency == &pair[0]) + }) { + return Err(Error::Invalid("provider workflow availability dependency")); + } + } + if !self.workflow_selectors.is_empty() { + if !self.workflow_dag || self.workflow_choice { + return Err(Error::Invalid("nested Session profile")); + } + validate_session_selectors( + &self.workflow_path, + &self.dependencies, + &self.workflow_selectors, + )?; + } + if self.workflow_choice { + if !self.workflow_dag { + return Err(Error::Invalid("conditional Session requires DAG")); + } + validate_session_choice(&self.workflow_path, &self.dependencies)?; + } + if self.workflow_dag && self.workflow_path.is_empty() { + return Err(Error::Invalid("Session DAG path missing")); + } + Ok(()) + } +} + +/// Each gate is independently bound to an actual single-parent entry. +pub fn validate_session_selectors( + nodes: &[String], + edges: &[(String, String)], + selectors: &[[String; 3]], +) -> Result<()> { + validate_session_dag(nodes, edges)?; + if selectors.is_empty() || selectors.len() > 31 { + return Err(Error::Invalid("nested Session selector bound")); + } + if selectors.windows(2).any(|pair| pair[0][0] >= pair[1][0]) { + return Err(Error::Invalid("nested Session selector order")); + } + let mut parents = BTreeMap::new(); + for (child, parent) in edges { + parents + .entry(child) + .and_modify(|previous| *previous = None) + .or_insert(Some(parent)); + } + let mut entries = BTreeSet::new(); + for (entry, selector) in selectors + .iter() + .flat_map(|[selector, left, right]| [(left, selector), (right, selector)]) + { + if !entries.insert(entry) || parents.get(entry) != Some(&Some(selector)) { + return Err(Error::Invalid("nested Session gated entry")); + } + } + Ok(()) +} + +/// A sealed choice has one selector, two ordered arms, and one join. +pub fn validate_session_choice(nodes: &[String], edges: &[(String, String)]) -> Result<()> { + validate_session_dag(nodes, edges)?; + let [root, left, right, join] = nodes else { + return Err(Error::Invalid("conditional Session nodes")); + }; + if edges.len() != 4 + || [(left, root), (right, root), (join, left), (join, right)] + .iter() + .any(|(child, parent)| !edges.iter().any(|(c, p)| c == *child && p == *parent)) + { + return Err(Error::Invalid("conditional Session edges")); + } + Ok(()) +} + +/// Nodes are in topological order. Every node after the root has an incoming +/// edge, so the sealed graph has one root and every node is reachable from it. +pub fn validate_session_dag(nodes: &[String], edges: &[(String, String)]) -> Result<()> { + if !(2..=64).contains(&nodes.len()) || edges.len() > 64 { + return Err(Error::Invalid("Session DAG bounds")); + } + let order: BTreeMap<_, _> = nodes + .iter() + .enumerate() + .map(|(index, node)| (node, index)) + .collect(); + if order.len() != nodes.len() { + return Err(Error::Invalid("Session DAG repeated node")); + } + let mut seen = BTreeSet::new(); + let mut previous = None; + for edge @ (child, parent) in edges { + let child_index = order.get(child); + let parent_index = order.get(parent); + if !matches!((child_index, parent_index), (Some(c), Some(p)) if p < c) + || previous.is_some_and(|last| last >= edge) + { + return Err(Error::Invalid("Session DAG edges")); + } + previous = Some(edge); + seen.insert(child); + } + if nodes.iter().skip(1).any(|node| !seen.contains(node)) { + return Err(Error::Invalid("Session DAG disconnected node")); + } + Ok(()) +} + +/// One authenticated proposal to change availability at a specific source cut. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct FactIntent { + pub operation_id: String, + pub domain: String, + pub source_epoch: u64, + pub revision: u64, + pub previous_snapshot: String, + pub expected_floor: u64, + pub available: bool, +} + +impl FactIntent { + pub fn snapshot(&self) -> Result { + identifier(&self.operation_id)?; + identifier(&self.domain)?; + if self.source_epoch > MAX_CREDITS + || self.revision == 0 + || self.revision > MAX_CREDITS + || self.expected_floor >= MAX_CREDITS + || self.previous_snapshot.len() != 64 + || !self + .previous_snapshot + .bytes() + .all(|b| b.is_ascii_hexdigit() && !b.is_ascii_uppercase()) + { + return Err(Error::Invalid("hard fact intent bounds")); + } + Ok(body_digest(&serde_json::to_string(&( + "weaver.hard-fact.v1", + self, + ))?)) + } +} + +/// The durable intent identity and ordered prefix that fence final use. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct FactBarrier { + pub operation_id: String, + pub source_epoch: u64, + pub revision: u64, + pub snapshot: String, + pub floor: u64, + pub pending_prefix: String, +} + +/// The committed availability projection and the remaining pending prefix. +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct FactResolution { + pub barrier: FactBarrier, + pub affected: Vec, + pub floor: u64, + pub previous_pending_prefix: String, + pub remaining_pending_prefix: Option, +} + +/// Detached from the persisted barrier; no caller-supplied graph or projection. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct FactWork { + pub barrier: FactBarrier, + pub expected_floor: u64, + pub pending_prefix: String, + pub root: String, + pub dependencies: Vec<(String, String)>, + pub available: bool, +} diff --git a/crates/contracts/src/lib.rs b/crates/contracts/src/lib.rs index 90cc0ca3..cc1ae8b5 100644 --- a/crates/contracts/src/lib.rs +++ b/crates/contracts/src/lib.rs @@ -6,7 +6,14 @@ mod delta_review; pub use delta_review::{DeltaDisposition, DeltaReview, PublicationReviewContext, ReviewAuthority}; mod domains; +mod hard_fact; pub use domains::{TaskAdmission, TaskAdmissionReceipt}; +pub use hard_fact::{ + FactBarrier, FactFeed, FactIntent, FactResolution, FactWork, MAX_WORKFLOW_RESULT_BYTES, + ProviderWorkflow, SESSION_CHOICE_SCHEMA, SESSION_DAG_SCHEMA, SESSION_NESTED_SCHEMA, + SESSION_WORKFLOW_SCHEMA, WorkflowRoute, validate_session_choice, validate_session_dag, + validate_session_selectors, +}; mod json; pub use domains::{ DomainBinding, DomainMigration, DomainMigrationReceipt, DomainStamp, DomainView, diff --git a/crates/ledger/src/hard_fact.rs b/crates/ledger/src/hard_fact.rs new file mode 100644 index 00000000..4ff363ef --- /dev/null +++ b/crates/ledger/src/hard_fact.rs @@ -0,0 +1,477 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! One local ordered fact feed. Staging and installation are separate authority transactions. +use crate::{ + Ledger, + persistence::{begin, driver::Connection, exec, maybe_current, params}, + source_authority, + store::{db, integer}, +}; +use weaver_contracts::{ + Error, FactBarrier, FactFeed, FactIntent, FactResolution, FactWork, Result, SourceIdentity, + body_digest, decode, +}; + +const GENESIS: &str = "0000000000000000000000000000000000000000000000000000000000000000"; +const MAX_PENDING: u64 = 64; + +/// Either a detached derivation request or the original committed resolution. +pub enum FactPreparation { + Pending(FactWork), + Resolved(FactResolution), +} + +struct Head { + feed: FactFeed, + floor: u64, + revision: u64, + snapshot: String, + pending: Option, +} + +fn head(c: &Connection) -> Result> { + let row = maybe_current( + c, + "SELECT record,floor,revision,snapshot,pending FROM main.hard_fact_feed WHERE singleton=1", + (), + |row| { + Ok(( + row.get::(0)?, + integer(row, 1)?, + integer(row, 2)?, + row.get(3)?, + row.get(4)?, + )) + }, + ) + .map_err(db)?; + row.map(|(record, floor, revision, snapshot, pending)| { + Ok(Head { + feed: decode(record.as_bytes())?, + floor, + revision, + snapshot, + pending, + }) + }) + .transpose() +} + +fn authorize(c: &Connection, caller: Option<&SourceIdentity>, feed: &FactFeed) -> Result<()> { + if caller != Some(&feed.authority.identity) + || source_authority::current(c)?.as_ref() != Some(&feed.authority) + { + return Err(Error::Denied); + } + Ok(()) +} + +pub(crate) fn require_enrollment(c: &Connection, caller: &SourceIdentity) -> Result<()> { + if let Some(head) = head(c)? + && (head.feed.authority.epoch != 0 || head.feed.authority.identity != *caller) + { + return Err(Error::Denied); + } + Ok(()) +} + +pub(crate) fn has_fact_state(c: &Connection) -> Result { + Ok( + head(c)? + .is_some_and(|head| head.floor != 0 || head.revision != 0 || head.pending.is_some()), + ) +} + +#[derive(PartialEq, Eq)] +pub(crate) struct UseCut { + pub(crate) expects_workflow_result: bool, + floor: u64, + revision: u64, + snapshot: String, +} + +pub(crate) fn require_available( + c: &Connection, + family: &str, + node: &str, +) -> Result> { + let scoped = maybe_current( + c, + "SELECT feed.record,feed.revision,feed.pending IS NOT NULL, + feed.floor,feed.snapshot, + EXISTS(SELECT 1 FROM json_each(feed.unavailable) WHERE value=?2) + FROM main.hard_fact_feed feed + WHERE feed.family=?1 OR EXISTS( + SELECT 1 FROM main.family_origins own JOIN main.family_origins alias ON own.origin=alias.origin + WHERE own.family=feed.family AND alias.family=?1)", + params![family.to_owned(), node.to_owned()], + |row| { + Ok(( + row.get::(0)?, + integer(row, 1)?, + row.get::(2)?, + integer(row, 3)?, + row.get::(4)?, + row.get::(5)?, + )) + }, + ) + .map_err(db)?; + if let Some((record, revision, pending, floor, snapshot, unavailable)) = scoped { + let feed: FactFeed = decode(record.as_bytes())?; + if !feed.workflow_path.is_empty() && feed.family != family { + return Err(Error::Conflict("workflow requires the original family")); + } + if revision == 0 + || pending + || unavailable + || source_authority::current(c)?.as_ref() != Some(&feed.authority) + { + return Err(Error::Conflict("hard fact unavailable")); + } + return Ok(Some(UseCut { + expects_workflow_result: selects(&feed, node), + floor, + revision, + snapshot, + })); + } + Ok(None) +} + +fn selects(feed: &FactFeed, node: &str) -> bool { + (feed.workflow_choice && node == feed.root) + || feed.workflow_selectors.iter().any(|row| row[0] == node) +} + +pub(crate) fn is_workflow_selector(c: &Connection, family: &str, node: &str) -> Result { + Ok(head(c)?.is_some_and(|head| head.feed.family == family && selects(&head.feed, node))) +} + +pub(crate) fn nested_feed(c: &Connection, family: &str) -> Result> { + Ok(head(c)? + .map(|head| head.feed) + .filter(|feed| feed.family == family && !feed.workflow_selectors.is_empty())) +} + +pub(crate) fn choice_nodes(c: &Connection, family: &str) -> Result> { + Ok(head(c)? + .filter(|head| head.feed.family == family) + .and_then(|head| head.feed.choice_nodes().cloned())) +} + +/// The edge is independently deployed. A fact observation cannot add one. +pub(crate) fn workflow_cut( + c: &Connection, + family: &str, + node: &str, +) -> Result, u64, String)>> { + let Some(head) = head(c)? else { + return Ok(None); + }; + let predecessors = head.feed.workflow_predecessors(node); + if predecessors.is_empty() { + return Ok(None); + } + let matching = head.feed.family == family || crate::persistence::one_current( + c, + "SELECT EXISTS(SELECT 1 FROM main.family_origins own JOIN main.family_origins alias ON own.origin=alias.origin WHERE own.family=?1 AND alias.family=?2)", + params![head.feed.family.clone(), family.to_owned()], + |row| row.get(0), + ).map_err(db)?; + if !matching { + return Ok(None); + } + if head.feed.family != family { + return Err(Error::Conflict("workflow requires the original family")); + } + Ok(Some(( + predecessors.into_iter().map(str::to_owned).collect(), + head.floor, + head.snapshot, + ))) +} + +fn bound_intent( + c: &Connection, + operation_id: &str, +) -> Result)>> { + let row = maybe_current( + c, + "SELECT original,barrier,resolution FROM main.hard_fact_intents WHERE operation_id=?1", + params![operation_id.to_owned()], + |row| { + Ok(( + row.get::(0)?, + row.get::(1)?, + row.get::>(2)?, + )) + }, + ) + .map_err(db)?; + row.map(|(original, barrier, resolution)| { + Ok(( + decode(original.as_bytes())?, + decode(barrier.as_bytes())?, + resolution + .map(|encoded| decode(encoded.as_bytes())) + .transpose()?, + )) + }) + .transpose() +} + +fn tail(c: &Connection, head: &Head) -> Result> { + head.pending + .as_deref() + .map(|operation_id| { + let (_, barrier, resolution) = bound_intent(c, operation_id)? + .ok_or(Error::Conflict("hard fact pending tail missing"))?; + if resolution.is_some() + || barrier.floor != head.floor + || barrier.revision <= head.revision + { + return Err(Error::Conflict("hard fact pending tail changed")); + } + Ok(barrier) + }) + .transpose() +} + +fn pending_prefix(installed: &str, tail: &FactBarrier) -> Result { + Ok(body_digest(&serde_json::to_string(&( + "weaver.hard-fact-membership.v1", + installed, + &tail.pending_prefix, + ))?)) +} + +fn preparation( + c: &Connection, + caller: Option<&SourceIdentity>, + barrier: &FactBarrier, +) -> Result { + let head = head(c)?.ok_or(Error::Denied)?; + authorize(c, caller, &head.feed)?; + let (intent, original, resolution) = bound_intent(c, &barrier.operation_id)? + .ok_or(Error::Conflict("hard fact intent missing"))?; + if original != *barrier { + return Err(Error::Conflict("hard fact barrier binding")); + } + if let Some(resolution) = resolution { + return Ok(FactPreparation::Resolved(resolution)); + } + let tail = tail(c, &head)?.ok_or(Error::Conflict("hard fact pending prefix missing"))?; + if head.revision.checked_add(1) != Some(barrier.revision) + || head.snapshot != intent.previous_snapshot + || intent.snapshot()? != barrier.snapshot + || intent.source_epoch != head.feed.authority.epoch + || barrier.floor > tail.floor + { + return Err(Error::Conflict("hard fact source cut changed")); + } + Ok(FactPreparation::Pending(FactWork { + barrier: original, + expected_floor: tail.floor, + pending_prefix: pending_prefix(&head.snapshot, &tail)?, + root: head.feed.root, + dependencies: head.feed.dependencies, + available: intent.available, + })) +} + +fn next_barrier( + connection: &Connection, + head: &Head, + intent: &FactIntent, + snapshot: String, +) -> Result { + let tail = tail(connection, head)?; + let (previous_revision, previous_snapshot, previous_prefix) = match &tail { + Some(tail) => (tail.revision, &tail.snapshot, tail.pending_prefix.as_str()), + None => (head.revision, &head.snapshot, GENESIS), + }; + if intent.domain != head.feed.domain + || intent.source_epoch != head.feed.authority.epoch + || intent.expected_floor != head.floor + || previous_revision.checked_add(1) != Some(intent.revision) + || &intent.previous_snapshot != previous_snapshot + || previous_revision.saturating_sub(head.revision) >= MAX_PENDING + { + return Err(Error::Conflict("hard fact predecessor changed")); + } + let task = crate::stream_state::task(connection, &head.feed.family)?; + if !task.nodes.contains(&head.feed.root) + || head + .feed + .dependencies + .iter() + .any(|(a, b)| !task.nodes.contains(a) || !task.nodes.contains(b)) + || head.feed.workflow.as_ref().is_some_and(|edge| { + !task.nodes.contains(&edge.predecessor) || !task.nodes.contains(&edge.successor) + }) + || head + .feed + .workflow_path + .iter() + .any(|node| !task.nodes.contains(node)) + { + return Err(Error::Invalid("hard fact graph outside original task")); + } + let floor = head.floor + 1; + let pending_prefix = body_digest(&serde_json::to_string(&( + "weaver.hard-fact-prefix.v1", + &head.feed, + floor, + previous_prefix, + &snapshot, + ))?); + Ok(FactBarrier { + operation_id: intent.operation_id.clone(), + source_epoch: intent.source_epoch, + revision: intent.revision, + snapshot, + floor, + pending_prefix, + }) +} + +impl Ledger { + /// Trusted startup configuration. A previously installed feed may not be removed or retargeted. + pub fn configure_fact_feed(&mut self, requested: Option<&FactFeed>) -> Result<()> { + if let Some(feed) = requested { + feed.validate()?; + } + let tx = begin(&mut self.connection).map_err(db)?; + match (head(&tx)?, requested) { + (None, None) => {} + (Some(head), Some(feed)) if head.feed == *feed => {} + (None, Some(feed)) => { + if let Some(authority) = source_authority::current(&tx)? + && authority != feed.authority + { + return Err(Error::Denied); + } + exec( + &tx, + "INSERT INTO main.hard_fact_feed VALUES(1,?1,?2,0,0,?3,NULL,'[]')", + params![ + feed.family.clone(), + serde_json::to_string(feed)?, + GENESIS.to_owned() + ], + ) + .map_err(db)?; + } + _ => return Err(Error::Conflict("hard fact feed deployment changed")), + } + tx.commit().map_err(db) + } + + /// Stage the exact original and install the pending barrier before a worker sees the intent. + pub fn stage_fact_intent(&mut self, intent: &FactIntent) -> Result { + let snapshot = intent.snapshot()?; + let tx = begin(&mut self.connection).map_err(db)?; + let head = head(&tx)?.ok_or(Error::Denied)?; + authorize(&tx, self.source.as_ref(), &head.feed)?; + if let Some((original, barrier, _)) = bound_intent(&tx, &intent.operation_id)? { + if original != *intent { + return Err(Error::Conflict("hard fact intent identity reused")); + } + return Ok(barrier); + } + let barrier = next_barrier(&tx, &head, intent, snapshot)?; + exec( + &tx, + "INSERT INTO main.hard_fact_intents VALUES(?1,?2,?3,NULL)", + params![ + intent.operation_id.clone(), + serde_json::to_string(intent)?, + serde_json::to_string(&barrier)? + ], + ) + .map_err(db)?; + exec( + &tx, + "UPDATE main.hard_fact_feed SET floor=?1,pending=?2 WHERE singleton=1", + params![barrier.floor as i64, intent.operation_id.clone()], + ) + .map_err(db)?; + tx.commit().map_err(db)?; + Ok(barrier) + } + + pub fn prepare_fact_projection(&mut self, barrier: &FactBarrier) -> Result { + let tx = begin(&mut self.connection).map_err(db)?; + let result = preparation(&tx, self.source.as_ref(), barrier)?; + tx.commit().map_err(db)?; + Ok(result) + } + + /// Only the trusted native derivation owner calls this. The RPC accepts no projection rows. + pub fn resolve_fact_projection( + &mut self, + work: &FactWork, + affected: Vec, + ) -> Result { + let tx = begin(&mut self.connection).map_err(db)?; + match preparation(&tx, self.source.as_ref(), &work.barrier)? { + FactPreparation::Pending(exact) if exact == *work => {} + FactPreparation::Resolved(original) if original.affected == affected => { + return Ok(original); + } + _ => return Err(Error::Conflict("hard fact projection input changed")), + } + if affected.is_empty() + || affected.len() > 65 + || !affected.contains(&work.root) + || affected.windows(2).any(|pair| pair[0] >= pair[1]) + || affected.iter().any(|node| { + node != &work.root + && !work + .dependencies + .iter() + .any(|(dependent, _)| dependent == node) + }) + || work.dependencies.iter().any(|(dependent, dependency)| { + affected.binary_search(dependency).is_ok() + && affected.binary_search(dependent).is_err() + }) + { + return Err(Error::Invalid("invalid hard fact impact")); + } + let barrier = &work.barrier; + let head = head(&tx)?.ok_or(Error::Conflict("hard fact feed missing"))?; + let remaining = tail(&tx, &head)?.filter(|tail| tail.operation_id != barrier.operation_id); + let remaining_pending_prefix = remaining + .as_ref() + .map(|tail| pending_prefix(&barrier.snapshot, tail)) + .transpose()?; + let unavailable = if work.available { + "[]".to_owned() + } else { + serde_json::to_string(&affected)? + }; + let resolution = FactResolution { + barrier: barrier.clone(), + affected, + floor: work.expected_floor, + previous_pending_prefix: work.pending_prefix.clone(), + remaining_pending_prefix, + }; + exec(&tx, "UPDATE main.hard_fact_feed SET revision=?1,snapshot=?2,pending=?3,unavailable=?4 WHERE singleton=1", + params![barrier.revision as i64, barrier.snapshot.clone(), remaining.map(|tail| tail.operation_id), unavailable]).map_err(db)?; + exec( + &tx, + "UPDATE main.hard_fact_intents SET resolution=?1 WHERE operation_id=?2", + params![ + serde_json::to_string(&resolution)?, + barrier.operation_id.clone() + ], + ) + .map_err(db)?; + tx.commit().map_err(db)?; + Ok(resolution) + } +} diff --git a/crates/ledger/src/lib.rs b/crates/ledger/src/lib.rs index 0745be66..6bf7fd86 100644 --- a/crates/ledger/src/lib.rs +++ b/crates/ledger/src/lib.rs @@ -16,6 +16,8 @@ extern crate self as weaver_ledger; mod delta_registration; mod domains; mod execution_exposure; +mod hard_fact; +pub use hard_fact::FactPreparation; mod exposure_manifest; mod metering; mod metering_credentials; @@ -35,6 +37,12 @@ mod provider_publication; #[cfg(feature = "commit-observer")] pub use provider_publication::use_locked_publication_review; mod provider_quota; +mod provider_workflow; +mod provider_workflow_choice; +mod provider_workflow_nested; +pub use provider_workflow::{ProviderProgression, WorkflowObservation}; +pub use provider_workflow_choice::WorkflowChoiceObservation; +pub use provider_workflow_nested::NestedObservation; mod publication; mod publication_barrier; mod publication_review; diff --git a/crates/ledger/src/provider.rs b/crates/ledger/src/provider.rs index 5a94af9d..c77aa552 100644 --- a/crates/ledger/src/provider.rs +++ b/crates/ledger/src/provider.rs @@ -3,12 +3,15 @@ // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 //! One canonical provider invocation and affine response releases; no retry reset exists. +#[path = "provider_admission.rs"] +mod admission; #[path = "provider_release_group.rs"] mod release_group; pub use release_group::{MAX_PROVIDER_PREPARATION_RANGES, MAX_PROVIDER_PREPARATION_ROWS}; use crate::persistence::{ProviderScopePhase, WriteScope}; use crate::{Ledger, db, integer}; +use admission::{admissible_receipt, store_authorized_provider_plan}; use std::collections::BTreeSet; use weaver_contracts::{ DomainView, Error, ProviderOAuthUse, ProviderPlan, ProviderReceipt, ProviderRoute, @@ -124,11 +127,17 @@ pub struct ProviderDispatch { pub(super) original: Option, pub(super) oauth: Option, pub(super) oauth_expires: Option, + fact_cut: Option, } impl ProviderDispatch { pub fn plan(&self) -> &ProviderPlan { &self.plan } + pub fn expects_workflow_result(&self) -> bool { + self.fact_cut + .as_ref() + .is_some_and(|cut| cut.expects_workflow_result) + } pub fn protocol(&self) -> weaver_contracts::ProviderProtocol { self.binding.protocol() } @@ -203,6 +212,17 @@ impl Ledger { plan: &ProviderPlan, catalog: &str, oauth: Option<&ProviderOAuthUse>, + ) -> Result { + self.enqueue_provider_progression(plan, catalog, oauth, None) + } + + /// Commit the prepared successor frontier with the existing claim and hold. + pub fn enqueue_provider_progression( + &mut self, + plan: &ProviderPlan, + catalog: &str, + oauth: Option<&ProviderOAuthUse>, + progression: Option<&crate::ProviderProgression>, ) -> Result { let digest = plan.digest()?; let encoded = serde_json::to_string(plan)?; @@ -218,15 +238,12 @@ impl Ledger { &AdmissionRequest { _sealed: () }, ) .map_err(db)?; - tx.check_provider_oauth(prepared.as_ref())?; - let new_claim = match receipt(&tx, &plan.family, &plan.node)? { - Some(old) if old.digest != digest => { - return Err(Error::Conflict("provider logical key already bound")); - } - Some(old) if old.state != ProviderState::Queued => return Ok(old), - Some(_) => false, - None => true, - }; + let new_claim = + match admissible_receipt(&tx, plan, &digest, prepared.as_ref(), progression)? { + Some(old) if old.state != ProviderState::Queued => return Ok(old), + Some(_) => false, + None => true, + }; store_authorized_provider_plan( &tx, plan, @@ -236,6 +253,7 @@ impl Ledger { &publication?, original.as_ref(), )?; + crate::provider_workflow::record_admission(&tx, plan, &digest, progression, new_claim)?; tx.commit_provider_admission().map_err(db)?; self.provider_receipt(&plan.family, &plan.node)? .ok_or(Error::Conflict("provider receipt missing")) @@ -297,6 +315,7 @@ impl Ledger { original, oauth: prepared, oauth_expires, + fact_cut: selected.fact_cut, }) } /// The exact consumed route and current authority serialize with the sole HTTPS request. @@ -361,6 +380,16 @@ impl Ledger { permit: &ProviderDispatch, format: &str, tokens: Option<[u64; 4]>, + ) -> Result<()> { + self.complete_provider_with_result(permit, format, tokens, None) + } + + pub fn complete_provider_with_result( + &mut self, + permit: &ProviderDispatch, + format: &str, + tokens: Option<[u64; 4]>, + response: Option<&str>, ) -> Result<()> { self.check_provider_session(permit)?; let (tx, domains) = @@ -376,6 +405,14 @@ impl Ledger { crate::persistence::params![permit.plan.family.to_owned(), permit.plan.node.to_owned()], ) .map_err(db)?; + if let Some(response) = response { + crate::provider_workflow_choice::record_result( + &tx, + &permit.plan, + progress.next, + response, + )?; + } if let Some(tokens) = tokens { crate::persistence::exec( &tx, @@ -436,64 +473,6 @@ fn record_dispatch_callback(tx: &WriteScope<'_>, permit: &ProviderDispatch) -> R } Ok(()) } -fn store_authorized_provider_plan( - tx: &WriteScope<'_>, - plan: &ProviderPlan, - (digest, encoded): (&str, String), - catalog: &str, - new_claim: bool, - publication: &crate::provider_publication::Prepared, - original: Option<&crate::task_origins::PreparedOriginal>, -) -> Result<()> { - let selected = any_authorized(tx, plan, "admitProvider", None, publication)?; - tx.provider_claim(|| crate::domains::require_view(tx, &selected.domains, original))?; - if new_claim { - reserve_provider_claim(tx, plan, digest, encoded, catalog, &selected.domains)?; - } else { - crate::persistence::exec( - tx, - "UPDATE provider_runs SET plan=?1 WHERE family=?2 AND node=?3", - crate::persistence::params![encoded, (plan.family).to_owned(), (plan.node).to_owned()], - ) - .map_err(db)?; - } - Ok(()) -} - -fn reserve_provider_claim( - tx: &WriteScope<'_>, - plan: &ProviderPlan, - digest: &str, - encoded: String, - catalog: &str, - domains: &DomainView, -) -> Result<()> { - crate::execution_exposure::retain_in_view( - tx, - crate::execution_exposure::ReservationClaim { - family: &plan.family, - node: &plan.node, - kind: crate::execution_exposure::ClaimKind::Provider, - member: "", - digest, - ceiling: plan.ceiling, - }, - domains, - )?; - let held = crate::persistence::exec( - tx, - "UPDATE tasks SET held=held+?1 WHERE family=?2 AND ?1<=budget-held", - crate::persistence::params![(plan.ceiling as i64).to_owned(), (plan.family).to_owned()], - ) - .map_err(db)?; - if held != 1 { - return Err(Error::Conflict("shared provider budget exhausted")); - } - crate::persistence::exec(tx, "INSERT INTO provider_runs(family,node,digest,plan,reserved,state) VALUES(?1,?2,?3,?4,?5,'queued')", crate::persistence::params![(plan.family).to_owned(),(plan.node).to_owned(),digest.to_owned(),encoded,(plan.ceiling as i64).to_owned()]).map_err(db)?; - crate::metering::bind(tx, plan, digest, catalog)?; - Ok(()) -} - fn authorize_provider_consumption( tx: &WriteScope<'_>, family: &str, @@ -514,6 +493,7 @@ fn authorize_provider_consumption( )?; let selected = any_authorized(tx, &plan, "invokeProvider", Some(eligible), publication)?; let digest = plan.digest()?; + crate::provider_workflow::require_winner(tx, &plan, &digest)?; tx.provider_claim(|| { crate::execution_exposure::provider(tx, &plan, &digest, &selected.domains, original, None) })?; @@ -601,6 +581,7 @@ fn require_provider_effect<'a>( "execution domain migrated; old permit fenced", )); } + crate::provider_workflow::require_winner(&tx, &p.plan, &p.digest)?; tx.provider_claim(|| { crate::execution_exposure::provider( &tx, @@ -771,6 +752,7 @@ struct AuthorizedRoute { binding: weaver_policy::BoundProviderPolicy, profile: crate::provider_profiles::CheckedProfile, domains: DomainView, + fact_cut: Option, } fn any_authorized( @@ -784,6 +766,7 @@ fn any_authorized( if domains.canonical_family != p.family { return Err(Error::Conflict("family alias is not an executable origin")); } + let fact_cut = crate::hard_fact::require_available(tx, &p.family, &p.node)?; for route in &p.routes { if eligible.is_none_or(|set| set.contains(&route.target)) && let Ok((binding, profile)) = guard(tx, p, route, action, &domains, publication) @@ -793,6 +776,7 @@ fn any_authorized( binding, profile, domains, + fact_cut, }); } } @@ -857,6 +841,9 @@ pub(super) fn guard_live_range( format: &str, ) -> Result<()> { tx.provider_pending(|| crate::publication_barrier::require_clear(tx))?; + if crate::hard_fact::require_available(tx, &p.plan.family, &p.plan.node)? != p.fact_cut { + return Err(Error::Conflict("provider permit has a stale hard fact cut")); + } tx.check_provider_oauth(p.oauth.as_ref())?; let source = p .publication diff --git a/crates/ledger/src/provider_admission.rs b/crates/ledger/src/provider_admission.rs new file mode 100644 index 00000000..8ec50cea --- /dev/null +++ b/crates/ledger/src/provider_admission.rs @@ -0,0 +1,82 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Bind an admissible provider plan and its reservation to the existing writer. +use super::{any_authorized, receipt}; +use crate::{db, persistence::WriteScope}; +use weaver_contracts::{DomainView, Error, ProviderPlan, ProviderReceipt, Result}; + +pub(super) fn admissible_receipt( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + digest: &str, + oauth: Option<&crate::provider_oauth::PreparedUse>, + progression: Option<&crate::ProviderProgression>, +) -> Result> { + tx.check_provider_oauth(oauth)?; + crate::provider_workflow::require_admission(tx, plan, progression)?; + let previous = receipt(tx, &plan.family, &plan.node)?; + if previous.as_ref().is_some_and(|row| row.digest != digest) { + return Err(Error::Conflict("provider logical key already bound")); + } + Ok(previous) +} + +pub(super) fn store_authorized_provider_plan( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + (digest, encoded): (&str, String), + catalog: &str, + new_claim: bool, + publication: &crate::provider_publication::Prepared, + original: Option<&crate::task_origins::PreparedOriginal>, +) -> Result<()> { + let selected = any_authorized(tx, plan, "admitProvider", None, publication)?; + tx.provider_claim(|| crate::domains::require_view(tx, &selected.domains, original))?; + if new_claim { + reserve_provider_claim(tx, plan, digest, encoded, catalog, &selected.domains)?; + } else { + crate::persistence::exec( + tx, + "UPDATE provider_runs SET plan=?1 WHERE family=?2 AND node=?3", + crate::persistence::params![encoded, (plan.family).to_owned(), (plan.node).to_owned()], + ) + .map_err(db)?; + } + Ok(()) +} + +fn reserve_provider_claim( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + digest: &str, + encoded: String, + catalog: &str, + domains: &DomainView, +) -> Result<()> { + crate::execution_exposure::retain_in_view( + tx, + crate::execution_exposure::ReservationClaim { + family: &plan.family, + node: &plan.node, + kind: crate::execution_exposure::ClaimKind::Provider, + member: "", + digest, + ceiling: plan.ceiling, + }, + domains, + )?; + let held = crate::persistence::exec( + tx, + "UPDATE tasks SET held=held+?1 WHERE family=?2 AND ?1<=budget-held", + crate::persistence::params![(plan.ceiling as i64).to_owned(), (plan.family).to_owned()], + ) + .map_err(db)?; + if held != 1 { + return Err(Error::Conflict("shared provider budget exhausted")); + } + crate::persistence::exec(tx, "INSERT INTO provider_runs(family,node,digest,plan,reserved,state) VALUES(?1,?2,?3,?4,?5,'queued')", crate::persistence::params![(plan.family).to_owned(),(plan.node).to_owned(),digest.to_owned(),encoded,(plan.ceiling as i64).to_owned()]).map_err(db)?; + crate::metering::bind(tx, plan, digest, catalog)?; + Ok(()) +} diff --git a/crates/ledger/src/provider_workflow.rs b/crates/ledger/src/provider_workflow.rs new file mode 100644 index 00000000..dadd2a76 --- /dev/null +++ b/crates/ledger/src/provider_workflow.rs @@ -0,0 +1,323 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Compiled workflow edges using the existing provider claim and response outcome. +use crate::{ + Ledger, + persistence::{WriteScope, begin_family, exec, one_current, params}, + provider_workflow_choice::{self as choice, ChoiceBasis, WorkflowChoiceObservation}, + provider_workflow_nested::{self as nested, NestedDraft, NestedObservation}, + store::{db, integer}, +}; +use serde::Serialize; +use weaver_contracts::{DomainStamp, Error, ProviderPlan, ProviderState, Result}; + +/// A prepared successor bound to the observed fact cut and complete releases. +#[derive(PartialEq, Eq)] +pub struct ProviderProgression { + predecessors: Vec, + successor_digest: String, + origin: DomainStamp, + fact_floor: u64, + fact_snapshot: String, + observations: Vec, + observed_winner: Option, + choice: Option, + nested: Option, +} + +#[derive(PartialEq, Eq, Serialize)] +struct ReleasedResponse { + digest: String, + reserved: u64, + released_events: u64, +} + +/// The Governor sees detached, coherent observations of the sealed plan set. +/// The cut is compared again before admitting its derived candidates. +pub struct WorkflowObservation { + pub complete: Vec, + pub available: Vec, + pub pending: Vec, + pub choice: Option, + pub nested: Option, + floor: u64, + snapshot: String, +} + +fn released_response( + tx: &WriteScope<'_>, + predecessor: &ProviderPlan, + domains: &weaver_contracts::DomainView, +) -> Result { + let digest = predecessor.digest()?; + require_winner(tx, predecessor, &digest)?; + // The provider owner records 2 only after the actual dispatch callback. + // The earlier burn (1) does not establish that a response was observed. + let released_events = one_current( + tx, + "SELECT run.next_event FROM main.provider_runs run + WHERE family=?1 AND node=?2 AND digest=?3 AND reserved=?4 + AND state='complete' AND dispatched=2 AND next_event>0 + AND NOT EXISTS(SELECT 1 FROM main.provider_releases release + WHERE release.family=run.family AND release.node=run.node + AND release.state!='released')", + params![ + predecessor.family.clone(), + predecessor.node.clone(), + digest.clone(), + predecessor.ceiling as i64 + ], + |row| integer(row, 0), + ) + .map_err(|error| match error { + crate::persistence::Error::QueryReturnedNoRows => { + Error::Conflict("provider response release incomplete") + } + other => db(other), + })?; + crate::execution_exposure::provider(tx, predecessor, &digest, domains, None, None)?; + Ok(ReleasedResponse { + digest, + reserved: predecessor.ceiling, + released_events, + }) +} + +fn prepare( + tx: &WriteScope<'_>, + predecessors: &[ProviderPlan], + successor: &ProviderPlan, +) -> Result { + let (mut expected, fact_floor, fact_snapshot) = + crate::hard_fact::workflow_cut(tx, &successor.family, &successor.node)? + .ok_or(Error::Conflict("provider workflow not admitted"))?; + let domains = crate::domains::provider_view(tx, &successor.family)?; + let choice = choice::prepare( + tx, + successor, + &domains.stamp.origin, + &mut expected, + fact_floor, + &fact_snapshot, + )?; + let nested = nested::prepare( + tx, + successor, + &domains.stamp.origin, + &mut expected, + fact_floor, + &fact_snapshot, + )?; + if !expected + .iter() + .map(String::as_str) + .eq(predecessors.iter().map(|plan| plan.node.as_str())) + || predecessors.iter().any(|plan| { + plan.family != successor.family + || plan.revision != successor.revision + || plan.fence != successor.fence + }) + { + return Err(Error::Conflict("provider workflow predecessors changed")); + } + crate::hard_fact::require_available(tx, &successor.family, &successor.node)?; + if let Some(basis) = &choice { + basis.verify_join(predecessors)?; + } + let observations = predecessors + .iter() + .map(|plan| { + crate::hard_fact::require_available(tx, &plan.family, &plan.node)?; + released_response(tx, plan, &domains) + }) + .collect::>>()?; + let successor_digest = successor.digest()?; + let observed_winner = crate::persistence::maybe_current( + tx, + "SELECT successor_digest FROM main.provider_workflow_transitions WHERE origin=?1 AND successor=?2", + params![domains.stamp.origin.clone(), successor.node.clone()], + |row| row.get::(0), + ).map_err(db)?; + if observed_winner + .as_ref() + .is_some_and(|winner| winner != &successor_digest) + { + return Err(Error::Conflict("provider workflow winner changed")); + } + Ok(ProviderProgression { + predecessors: predecessors.to_vec(), + successor_digest, + origin: domains.stamp, + fact_floor, + fact_snapshot, + observations, + observed_winner, + choice, + nested, + }) +} + +impl Ledger { + /// The trusted host supplies two plans from the sealed compiled original. + /// The ledger supplies the authentic complete response observation and frontier. + pub fn prepare_provider_progression( + &mut self, + predecessor: &ProviderPlan, + successor: &ProviderPlan, + ) -> Result { + self.prepare_workflow_candidate(std::slice::from_ref(predecessor), successor, None) + } + + pub fn prepare_workflow_candidate( + &mut self, + predecessors: &[ProviderPlan], + successor: &ProviderPlan, + observed: Option<&WorkflowObservation>, + ) -> Result { + let tx = begin_family(&mut self.connection, &successor.family).map_err(db)?; + let proposal = prepare(&tx, predecessors, successor)?; + if observed.is_some_and(|cut| { + cut.floor != proposal.fact_floor || cut.snapshot != proposal.fact_snapshot + }) { + return Err(Error::Conflict("Governor observation changed")); + } + tx.commit().map_err(db)?; + Ok(proposal) + } + + pub fn observe_workflow(&mut self, plans: &[ProviderPlan]) -> Result { + let [root, successor, ..] = plans else { + return Err(Error::Invalid("Session plan set")); + }; + let tx = begin_family(&mut self.connection, &root.family).map_err(db)?; + let (_, floor, snapshot) = + crate::hard_fact::workflow_cut(&tx, &root.family, &successor.node)? + .ok_or(Error::Conflict("Session fact cut unavailable"))?; + let domains = crate::domains::provider_view(&tx, &root.family)?; + let mut cut = WorkflowObservation { + complete: vec![], + available: vec![], + pending: vec![], + choice: choice::observe(&tx, &root.family, &domains.stamp.origin)?, + nested: nested::observe(&tx, &root.family, &domains.stamp.origin)?, + floor, + snapshot, + }; + for plan in plans { + match crate::hard_fact::require_available(&tx, &plan.family, &plan.node) { + Ok(Some(_)) => cut.available.push(plan.node.clone()), + Err(Error::Conflict(_)) => {} + Ok(None) => return Err(Error::Conflict("Session fact scope changed")), + Err(error) => return Err(error), + } + match crate::provider::receipt(&tx, &plan.family, &plan.node)? { + Some(receipt) if receipt.digest != plan.digest()? => { + return Err(Error::Conflict("Session plan changed")); + } + Some(receipt) if receipt.state == ProviderState::Complete => { + released_response(&tx, plan, &domains)?; + cut.complete.push(plan.node.clone()); + } + Some(receipt) if receipt.state == ProviderState::Unknown => {} + _ => cut.pending.push(plan.node.clone()), + } + } + tx.commit().map_err(db)?; + Ok(cut) + } +} + +pub(crate) fn require_admission( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + proposal: Option<&ProviderProgression>, +) -> Result<()> { + let governed = crate::hard_fact::workflow_cut(tx, &plan.family, &plan.node)?.is_some(); + match (governed, proposal) { + (false, None) => Ok(()), + (true, Some(proposal)) if prepare(tx, &proposal.predecessors, plan)? == *proposal => Ok(()), + _ => Err(Error::Conflict("provider workflow frontier changed")), + } +} + +pub(crate) fn record_admission( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + digest: &str, + proposal: Option<&ProviderProgression>, + new_claim: bool, +) -> Result<()> { + match (proposal, new_claim) { + (Some(proposal), true) => bind_winner(tx, plan, proposal), + (Some(_), false) => require_winner(tx, plan, digest), + (None, _) => Ok(()), + } +} + +fn bind_winner( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + proposal: &ProviderProgression, +) -> Result<()> { + if proposal.observed_winner.is_some() { + return Err(Error::Conflict( + "provider workflow frontier already advanced", + )); + } + if let Some(ChoiceBasis::Admit(decision)) = &proposal.choice { + let selector = proposal + .predecessors + .first() + .ok_or(Error::Conflict("workflow selector missing"))?; + choice::bind(tx, &proposal.origin.origin, &selector.node, decision)?; + } + if let Some(draft) = &proposal.nested { + nested::bind(tx, &proposal.origin.origin, draft)?; + } + let basis: Vec<_> = proposal + .predecessors + .iter() + .zip(&proposal.observations) + .map(|(plan, release)| (&plan.node, release)) + .collect(); + let record = serde_json::to_string(&( + "response-release-complete", + basis, + &proposal.origin, + proposal.fact_floor, + &proposal.fact_snapshot, + "admitted", + ))?; + exec( + tx, + "INSERT INTO main.provider_workflow_transitions VALUES(?1,?2,?3,?4)", + params![ + proposal.origin.origin.clone(), + plan.node.clone(), + proposal.successor_digest.clone(), + record + ], + ) + .map_err(db)?; + Ok(()) +} + +pub(crate) fn require_winner(tx: &WriteScope<'_>, plan: &ProviderPlan, digest: &str) -> Result<()> { + if crate::hard_fact::workflow_cut(tx, &plan.family, &plan.node)?.is_some() { + let origin = crate::domains::provider_view(tx, &plan.family)? + .stamp + .origin; + let valid: bool = one_current(tx, + "SELECT EXISTS(SELECT 1 FROM main.provider_workflow_transitions WHERE origin=?1 AND successor=?2 AND successor_digest=?3)", + params![origin.clone(), plan.node.clone(), digest.to_owned()], |row| row.get(0)).map_err(db)?; + if !valid { + return Err(Error::Conflict( + "provider successor has no committed transition", + )); + } + choice::require(tx, plan, &origin, digest)?; + nested::require_entry(tx, plan, &origin, digest)?; + } + Ok(()) +} diff --git a/crates/ledger/src/provider_workflow_choice.rs b/crates/ledger/src/provider_workflow_choice.rs new file mode 100644 index 00000000..dc2f6719 --- /dev/null +++ b/crates/ledger/src/provider_workflow_choice.rs @@ -0,0 +1,287 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Conditional branch evidence, bound to the existing release and winner transactions. +use crate::{ + persistence::{WriteScope, exec, maybe_current, params}, + store::{db, integer}, +}; +use serde::{Deserialize, Serialize}; +use weaver_contracts::{ + Error, MAX_WORKFLOW_RESULT_BYTES, ProviderPlan, Result, WorkflowRoute, body_digest, decode, +}; + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct ResultDocument { + route: WorkflowRoute, +} + +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub(crate) struct ReleasedChoice { + pub(crate) route: WorkflowRoute, + pub(crate) response_digest: String, + pub(crate) plan_digest: String, + pub(crate) released_events: u64, +} + +#[derive(PartialEq, Eq, Serialize, Deserialize)] +pub(crate) struct ChoiceDecision { + pub(crate) result: ReleasedChoice, + pub(crate) arm: String, + pub(crate) arm_digest: String, + pub(crate) floor: u64, + pub(crate) snapshot: String, +} + +#[derive(PartialEq, Eq)] +pub(crate) enum ChoiceBasis { + Admit(ChoiceDecision), + Retain(ChoiceDecision), +} + +/// The selector's complete result and any durable decision at the observed cut. +pub struct WorkflowChoiceObservation { + pub arms: [String; 2], + pub join: String, + pub route: Option, + pub decided: Option, +} + +pub(crate) fn record_result( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + released_events: u64, + response: &str, +) -> Result<()> { + if response.len() > MAX_WORKFLOW_RESULT_BYTES || released_events == 0 { + return Ok(()); + } + let Ok(ResultDocument { route }) = serde_json::from_str(response) else { + return Ok(()); + }; + if !crate::hard_fact::is_workflow_selector(tx, &plan.family, &plan.node)? { + return Err(Error::Conflict("workflow result from another node")); + } + let result = ReleasedChoice { + route, + response_digest: body_digest(response), + plan_digest: plan.digest()?, + released_events, + }; + exec( + tx, + "INSERT INTO main.provider_terminal_results VALUES(?1,?2,?3)", + params![ + plan.family.clone(), + plan.node.clone(), + serde_json::to_string(&result)? + ], + ) + .map_err(db)?; + Ok(()) +} + +pub(crate) fn read_result( + tx: &WriteScope<'_>, + family: &str, + selector: &str, +) -> Result> { + let terminal = maybe_current( + tx, + "SELECT result.record, run.digest, run.next_event FROM main.provider_terminal_results result + JOIN main.provider_runs run ON run.family=result.family AND run.node=result.node + WHERE run.family=?1 AND run.node=?2 AND run.state='complete' AND run.dispatched=2 + AND NOT EXISTS(SELECT 1 FROM main.provider_releases release + WHERE release.family=run.family AND release.node=run.node + AND release.state!='released')", + params![family.to_owned(), selector.to_owned()], + |row| Ok((row.get::(0)?, row.get::(1)?, integer(row, 2)?)), + ).map_err(db)?; + terminal + .map(|(record, digest, events)| { + let result: ReleasedChoice = decode(record.as_bytes())?; + if result.plan_digest != digest || result.released_events != events || events == 0 { + return Err(Error::Conflict( + "workflow result no longer binds the complete release", + )); + } + Ok(result) + }) + .transpose() +} + +pub(crate) fn read_decision( + tx: &WriteScope<'_>, + origin: &str, + selector: &str, + arms: [&str; 2], + result: Option<&ReleasedChoice>, + nested: bool, +) -> Result> { + let query = if nested { + "SELECT arm_digest, record FROM main.provider_workflow_decisions WHERE origin=?1 AND selector=?2" + } else { + "SELECT successor_digest, record FROM main.provider_workflow_transitions WHERE origin=?1 AND successor=?2" + }; + maybe_current( + tx, + query, + params![origin.to_owned(), selector.to_owned()], + |row| Ok((row.get::(0)?, row.get::(1)?)), + ) + .map_err(db)? + .map(|(digest, record)| { + let decision: ChoiceDecision = decode(record.as_bytes())?; + let expected = match decision.result.route { + WorkflowRoute::Left => arms[0], + WorkflowRoute::Right => arms[1], + }; + if result != Some(&decision.result) + || decision.arm != expected + || decision.arm_digest != digest + { + return Err(Error::Conflict("persisted workflow choice changed")); + } + Ok(decision) + }) + .transpose() +} + +fn read_basis( + tx: &WriteScope<'_>, + family: &str, + origin: &str, + nodes: &[String; 4], +) -> Result<(Option, Option)> { + let result = read_result(tx, family, &nodes[0])?; + let decision = read_decision( + tx, + origin, + &nodes[0], + [&nodes[1], &nodes[2]], + result.as_ref(), + false, + )?; + Ok((result, decision)) +} + +pub(crate) fn observe( + tx: &WriteScope<'_>, + family: &str, + origin: &str, +) -> Result> { + let Some(nodes) = crate::hard_fact::choice_nodes(tx, family)? else { + return Ok(None); + }; + let (result, decision) = read_basis(tx, family, origin, &nodes)?; + let [_, left, right, join] = nodes; + Ok(Some(WorkflowChoiceObservation { + arms: [left, right], + join, + route: result.map(|r| r.route), + decided: decision.map(|d| d.arm), + })) +} + +pub(crate) fn prepare( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + origin: &str, + expected: &mut Vec, + floor: u64, + snapshot: &str, +) -> Result> { + let Some(nodes) = crate::hard_fact::choice_nodes(tx, &plan.family)? else { + return Ok(None); + }; + let (result, decision) = read_basis(tx, &plan.family, origin, &nodes)?; + if plan.node == nodes[3] { + let decision = decision.ok_or(Error::Conflict("workflow choice is uncommitted"))?; + expected.retain(|parent| parent == &decision.arm); + return Ok(Some(ChoiceBasis::Retain(decision))); + } + let result = result.ok_or(Error::Conflict( + "workflow selector has no complete structured result", + ))?; + if plan.node != result.route.arm(&nodes) { + return Err(Error::Conflict("workflow arm was not selected")); + } + let arm_digest = plan.digest()?; + let basis = match decision { + Some(decision) if decision.arm_digest == arm_digest => ChoiceBasis::Retain(decision), + Some(_) => return Err(Error::Conflict("workflow arm identity changed")), + None => ChoiceBasis::Admit(ChoiceDecision { + result, + arm: plan.node.clone(), + arm_digest, + floor, + snapshot: snapshot.to_owned(), + }), + }; + Ok(Some(basis)) +} + +pub(crate) fn bind( + tx: &WriteScope<'_>, + origin: &str, + selector: &str, + decision: &ChoiceDecision, +) -> Result<()> { + exec( + tx, + "INSERT INTO main.provider_workflow_transitions VALUES(?1,?2,?3,?4)", + params![ + origin.to_owned(), + selector.to_owned(), + decision.arm_digest.clone(), + serde_json::to_string(decision)? + ], + ) + .map_err(db)?; + Ok(()) +} + +pub(crate) fn require( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + origin: &str, + digest: &str, +) -> Result<()> { + let Some(nodes) = crate::hard_fact::choice_nodes(tx, &plan.family)? else { + return Ok(()); + }; + let (_, decision) = read_basis(tx, &plan.family, origin, &nodes)?; + let decision = decision.ok_or(Error::Conflict("workflow choice is uncommitted"))?; + if plan.node == nodes[3] { + let valid: bool = crate::persistence::one_current( + tx, + "SELECT EXISTS(SELECT 1 FROM main.provider_workflow_transitions WHERE origin=?1 AND successor=?2 AND successor_digest=?3)", + params![origin.to_owned(), decision.arm, decision.arm_digest], + |row| row.get(0), + ).map_err(db)?; + if !valid { + return Err(Error::Conflict("selected workflow arm claim missing")); + } + } else if plan.node != decision.arm || digest != decision.arm_digest { + return Err(Error::Conflict( + "workflow arm differs from committed decision", + )); + } + Ok(()) +} + +impl ChoiceBasis { + pub(crate) fn verify_join(&self, predecessors: &[ProviderPlan]) -> Result<()> { + if let (Self::Retain(decision), [predecessor]) = (self, predecessors) + && predecessor.node == decision.arm + && predecessor.digest()? != decision.arm_digest + { + return Err(Error::Conflict( + "join predecessor differs from selected claim", + )); + } + Ok(()) + } +} diff --git a/crates/ledger/src/provider_workflow_nested.rs b/crates/ledger/src/provider_workflow_nested.rs new file mode 100644 index 00000000..26d70a82 --- /dev/null +++ b/crates/ledger/src/provider_workflow_nested.rs @@ -0,0 +1,240 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Reconstruct active incoming edges from the deployed graph and durable selector decisions. +use crate::{ + persistence::{WriteScope, exec, params}, + provider_workflow_choice::{ChoiceDecision, ReleasedChoice, read_decision, read_result}, + store::db, +}; +use std::collections::BTreeMap; +use weaver_contracts::{Error, ProviderPlan, Result, WorkflowRoute}; + +/// Complete selector observations and the active predecessors of eligible nodes. +pub struct NestedObservation { + pub selectors: Vec<[String; 3]>, + pub results: Vec<(String, String)>, + pub decisions: Vec<(String, String)>, + pub predecessors: BTreeMap>, +} + +#[derive(PartialEq, Eq)] +pub(crate) struct NestedDraft { + selector: String, + decision: ChoiceDecision, +} + +struct Selector<'a> { + nodes: &'a [String; 3], + result: Option, + decision: Option, +} +impl Selector<'_> { + fn matches(&self, node: &str) -> bool { + self.result.as_ref().is_some_and(|result| { + node == match result.route { + WorkflowRoute::Left => &self.nodes[1], + WorkflowRoute::Right => &self.nodes[2], + } + }) + } +} + +#[derive(Default, Clone, Copy)] +struct Reach { + active: bool, + unresolved: bool, +} + +type SelectorDrafts = BTreeMap; + +fn load( + tx: &WriteScope<'_>, + family: &str, + origin: &str, + graph: &weaver_contracts::FactFeed, +) -> Result<(NestedObservation, SelectorDrafts)> { + let mut selectors = Vec::new(); + let mut gates = BTreeMap::new(); + let mut results = Vec::new(); + let mut decisions = Vec::new(); + for nodes @ [selector, left, right] in &graph.workflow_selectors { + let result = read_result(tx, family, selector)?; + let decision = read_decision(tx, origin, selector, [left, right], result.as_ref(), true)?; + if let Some(result) = &result { + results.push((selector.clone(), result.route.as_str().to_owned())); + } + if let Some(decision) = &decision { + if crate::provider::receipt(tx, family, &decision.arm)? + .is_none_or(|receipt| receipt.digest != decision.arm_digest) + { + return Err(Error::Conflict( + "nested selector decision has no selected claim", + )); + } + decisions.push((selector.clone(), decision.result.route.as_str().to_owned())); + } + gates.insert(left.as_str(), selectors.len()); + gates.insert(right.as_str(), selectors.len()); + selectors.push(Selector { + nodes, + result, + decision, + }); + } + let mut states = BTreeMap::from([( + graph.root.as_str(), + Reach { + active: true, + unresolved: false, + }, + )]); + let mut predecessors = BTreeMap::new(); + let mut drafts = BTreeMap::new(); + for node in graph.workflow_path.iter().skip(1) { + let selector = gates.get(node.as_str()).map(|&index| &selectors[index]); + let (reach, parents) = + active_parents(node, &graph.dependencies, &states, selector, &mut drafts)?; + if (!reach.unresolved || drafts.contains_key(node)) && !parents.is_empty() { + predecessors.insert(node.clone(), parents); + } + states.insert(node.as_str(), reach); + } + Ok(( + NestedObservation { + selectors: graph.workflow_selectors.clone(), + results, + decisions, + predecessors, + }, + drafts, + )) +} + +fn active_parents( + node: &str, + dependencies: &[(String, String)], + states: &BTreeMap<&str, Reach>, + selector: Option<&Selector<'_>>, + drafts: &mut SelectorDrafts, +) -> Result<(Reach, Vec)> { + let mut reach = Reach::default(); + let mut parents = Vec::new(); + for (_, parent) in dependencies.iter().filter(|(child, _)| child == node) { + let state = states + .get(parent.as_str()) + .ok_or(Error::Conflict("nested topology changed"))?; + reach.unresolved |= state.unresolved; + if !state.active { + continue; + } + if let Some(selector) = selector { + match &selector.decision { + Some(decision) if decision.arm != node => continue, + Some(_) => {} + None => { + reach.unresolved = true; + if !state.unresolved + && selector.matches(node) + && let Some(result) = &selector.result + { + drafts.insert(node.to_owned(), (parent.clone(), result.clone())); + parents.push(parent.clone()); + } + continue; + } + } + } + parents.push(parent.clone()); + reach.active = true; + } + Ok((reach, parents)) +} + +pub(crate) fn observe( + tx: &WriteScope<'_>, + family: &str, + origin: &str, +) -> Result> { + crate::hard_fact::nested_feed(tx, family)? + .map(|graph| load(tx, family, origin, &graph).map(|(observed, _)| observed)) + .transpose() +} + +pub(crate) fn prepare( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + origin: &str, + expected: &mut Vec, + floor: u64, + snapshot: &str, +) -> Result> { + let Some(graph) = crate::hard_fact::nested_feed(tx, &plan.family)? else { + return Ok(None); + }; + let (mut observation, mut drafts) = load(tx, &plan.family, origin, &graph)?; + *expected = observation + .predecessors + .remove(&plan.node) + .ok_or(Error::Conflict( + "nested workflow predecessors unresolved or inactive", + ))?; + drafts + .remove(&plan.node) + .map(|(selector, result)| { + Ok(NestedDraft { + selector, + decision: ChoiceDecision { + result, + arm: plan.node.clone(), + arm_digest: plan.digest()?, + floor, + snapshot: snapshot.to_owned(), + }, + }) + }) + .transpose() +} + +pub(crate) fn bind(tx: &WriteScope<'_>, origin: &str, draft: &NestedDraft) -> Result<()> { + exec( + tx, + "INSERT INTO main.provider_workflow_decisions VALUES(?1,?2,?3,?4)", + params![ + origin.to_owned(), + draft.selector.clone(), + draft.decision.arm_digest.clone(), + serde_json::to_string(&draft.decision)? + ], + ) + .map_err(db)?; + Ok(()) +} + +pub(crate) fn require_entry( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + origin: &str, + digest: &str, +) -> Result<()> { + let Some(graph) = crate::hard_fact::nested_feed(tx, &plan.family)? else { + return Ok(()); + }; + let Some([selector, left, right]) = graph + .workflow_selectors + .iter() + .find(|[_, left, right]| left == &plan.node || right == &plan.node) + else { + return Ok(()); + }; + let result = read_result(tx, &plan.family, selector)?; + if !read_decision(tx, origin, selector, [left, right], result.as_ref(), true)? + .is_some_and(|decision| decision.arm == plan.node && decision.arm_digest == digest) + { + return Err(Error::Conflict( + "nested workflow entry lacks its selector decision", + )); + } + Ok(()) +} diff --git a/crates/ledger/src/schema.rs b/crates/ledger/src/schema.rs index 78e1157d..a1ab2249 100644 --- a/crates/ledger/src/schema.rs +++ b/crates/ledger/src/schema.rs @@ -37,6 +37,12 @@ CREATE TABLE IF NOT EXISTS review_authority ( singleton INTEGER PRIMARY KEY CHECK(singleton=1), epoch INTEGER NOT NULL CHECK(epoch>=0), record TEXT NOT NULL); CREATE TABLE IF NOT EXISTS authority_pending ( operation_id TEXT PRIMARY KEY, digest TEXT NOT NULL, proposal TEXT NOT NULL); +CREATE TABLE IF NOT EXISTS hard_fact_feed ( + singleton INTEGER PRIMARY KEY CHECK(singleton=1), family TEXT NOT NULL, record TEXT NOT NULL, + floor INTEGER NOT NULL, revision INTEGER NOT NULL, snapshot TEXT NOT NULL, + pending TEXT REFERENCES hard_fact_intents(operation_id), unavailable TEXT NOT NULL); +CREATE TABLE IF NOT EXISTS hard_fact_intents ( + operation_id TEXT PRIMARY KEY, original TEXT NOT NULL, barrier TEXT NOT NULL, resolution TEXT); CREATE TABLE IF NOT EXISTS authority_review_requirements ( operation_id TEXT PRIMARY KEY, digest TEXT NOT NULL, parent TEXT NOT NULL); CREATE TABLE IF NOT EXISTS authority_reviews ( @@ -101,6 +107,12 @@ CREATE TABLE IF NOT EXISTS provider_runs ( reserved INTEGER NOT NULL CHECK(reserved>0), state TEXT NOT NULL CHECK(state IN ('queued','unknown','complete')), target TEXT, dispatched INTEGER NOT NULL DEFAULT 0, next_event INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(family,node)); +CREATE TABLE IF NOT EXISTS provider_workflow_decisions ( + origin TEXT NOT NULL, selector TEXT NOT NULL, arm_digest TEXT NOT NULL, + record TEXT NOT NULL, PRIMARY KEY(origin,selector)); +CREATE TABLE IF NOT EXISTS provider_workflow_transitions ( + origin TEXT NOT NULL, successor TEXT NOT NULL, successor_digest TEXT NOT NULL, + record TEXT NOT NULL, PRIMARY KEY(origin,successor)); CREATE TABLE IF NOT EXISTS provider_releases ( family TEXT NOT NULL, node TEXT NOT NULL, sequence INTEGER NOT NULL, length INTEGER NOT NULL, digest TEXT NOT NULL, state TEXT NOT NULL CHECK(state IN ('unknown','released')), PRIMARY KEY(family,node,sequence), @@ -130,6 +142,9 @@ CREATE TABLE IF NOT EXISTS provider_rate_bindings ( CREATE TABLE IF NOT EXISTS metering_credentials ( tenant TEXT NOT NULL, epoch INTEGER NOT NULL, certificate TEXT NOT NULL UNIQUE, public_key TEXT NOT NULL UNIQUE, credential TEXT NOT NULL UNIQUE, record TEXT NOT NULL, PRIMARY KEY(tenant,epoch)); +CREATE TABLE IF NOT EXISTS provider_terminal_results ( + family TEXT NOT NULL, node TEXT NOT NULL, record TEXT NOT NULL, + PRIMARY KEY(family,node), FOREIGN KEY(family,node) REFERENCES provider_runs(family,node)); CREATE TABLE IF NOT EXISTS provider_terminal_usage ( family TEXT NOT NULL, node TEXT NOT NULL, tokens TEXT NOT NULL, PRIMARY KEY(family,node), FOREIGN KEY(family,node) REFERENCES provider_runs(family,node)); diff --git a/crates/ledger/src/source_authority.rs b/crates/ledger/src/source_authority.rs index 668a6a27..7d4a3a10 100644 --- a/crates/ledger/src/source_authority.rs +++ b/crates/ledger/src/source_authority.rs @@ -68,6 +68,9 @@ pub(crate) fn write( fn has_application_rows(connection: &crate::persistence::driver::Connection) -> Result { let tables = crate::persistence::read_all(connection,"SELECT name FROM main.sqlite_schema WHERE type='table' AND name NOT GLOB 'sqlite_*' ORDER BY name",(),|r|r.get::(0)).map_err(db)?; for table in tables { + if table == "hard_fact_feed" && !crate::hard_fact::has_fact_state(connection)? { + continue; + } // An independently provisioned verifier is deployment metadata, not // application ownership. Invalid metadata still refuses enrollment. if matches!( @@ -118,6 +121,7 @@ fn ensure(ledger: &mut Ledger, caller: &SourceIdentity) -> Result<()> { } let tx = crate::persistence::begin(&mut ledger.connection).map_err(db)?; if current(&tx)?.is_none() { + crate::hard_fact::require_enrollment(&tx, caller)?; if has_application_rows(&tx)? { return Err(Error::Conflict( "source enrollment requires an empty unowned store", diff --git a/crates/ledger/src/store.rs b/crates/ledger/src/store.rs index 81604181..119fa09b 100644 --- a/crates/ledger/src/store.rs +++ b/crates/ledger/src/store.rs @@ -323,6 +323,11 @@ fn receipt( fn guard(tx: &WriteScope<'_>, p: &Proposal) -> Result<()> { crate::publication_barrier::require_resolved(tx)?; + if crate::hard_fact::require_available(tx, &p.family, &p.node)?.is_some() { + return Err(Error::Conflict( + "hard fact feed requires provider admission", + )); + } crate::task_publication::require(tx, &p.family)?; let (revision, fence, policy): (u64, u64, String) = crate::persistence::one( tx, diff --git a/crates/ledger/src/stream_state.rs b/crates/ledger/src/stream_state.rs index 9766b582..55184dc9 100644 --- a/crates/ledger/src/stream_state.rs +++ b/crates/ledger/src/stream_state.rs @@ -73,6 +73,13 @@ pub(crate) fn authority(tx: &WriteScope<'_>) -> Result<(u64, u64, String)> { .map_err(db) } pub(crate) fn authorize(tx: &WriteScope<'_>, check: StreamCheck<'_>) -> Result<()> { + if crate::hard_fact::require_available(tx, &check.contract.family, &check.contract.node)? + .is_some() + { + return Err(Error::Conflict( + "hard fact feed requires provider admission", + )); + } crate::task_publication::require(tx, &check.contract.family)?; let (revision, fence, policy) = authority(tx)?; if revision != check.revision || fence != check.fence { diff --git a/crates/ledger/tests/unit/provider.rs b/crates/ledger/tests/unit/provider.rs index 1ea1530e..e389d5b8 100644 --- a/crates/ledger/tests/unit/provider.rs +++ b/crates/ledger/tests/unit/provider.rs @@ -16,6 +16,8 @@ mod observation; mod properties; #[path = "provider_range_group.rs"] mod range_group; +#[path = "provider/workflow.rs"] +mod workflow; const POLICY: &str = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/../../prod/policies/provider/provider.cedar" diff --git a/crates/ledger/tests/unit/provider/workflow.rs b/crates/ledger/tests/unit/provider/workflow.rs new file mode 100644 index 00000000..e16492c5 --- /dev/null +++ b/crates/ledger/tests/unit/provider/workflow.rs @@ -0,0 +1,382 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +use super::fixture_nodes; +use std::collections::BTreeSet; +use weaver_contracts::{ProviderPlan, body_digest}; +use weaver_ledger::Ledger; + +#[test] +fn hard_fact_prefix_change_fences_stale_work_and_unsent_provider_output() { + use weaver_contracts::{FactFeed, FactIntent, SourceAuthority, SourceIdentity}; + use weaver_ledger::FactPreparation; + + let temp = tempfile::tempdir().expect("directory"); + let path = temp.path().join("facts.db"); + let caller = SourceIdentity { + certificate_sha256: body_digest("certificate"), + public_key_sha256: body_digest("key"), + credential_sha256: body_digest("credential"), + }; + let feed = FactFeed { + domain: "availability".into(), + authority: SourceAuthority { + epoch: 0, + identity: caller.clone(), + }, + family: "f".into(), + root: "infer".into(), + dependencies: vec![("second".into(), "infer".into())], + workflow: None, + workflow_path: vec![], + workflow_dag: false, + workflow_choice: false, + workflow_selectors: vec![], + }; + let mut initial = Ledger::open(&path).expect("ledger"); + initial.configure_fact_feed(Some(&feed)).expect("feed"); + initial + .with_authenticated_source(&caller, |_| Ok(())) + .expect("source enrollment"); + initial.close().expect("close"); + let (mut ledger, plan) = fixture_nodes(&path, &["infer", "second"]); + let stage = |ledger: &mut Ledger, intent: &FactIntent| { + ledger + .with_authenticated_source(&caller, |ledger| ledger.stage_fact_intent(intent)) + .expect("staged") + }; + let prepare = |ledger: &mut Ledger, barrier: &_| { + let FactPreparation::Pending(work) = ledger + .with_authenticated_source(&caller, |ledger| ledger.prepare_fact_projection(barrier)) + .expect("prepared") + else { + panic!("expected pending intent"); + }; + work + }; + let affected = vec!["infer".into(), "second".into()]; + let resolve = |ledger: &mut Ledger, work: &_| { + ledger.with_authenticated_source(&caller, |ledger| { + ledger.resolve_fact_projection(work, affected.clone()) + }) + }; + let mut intent = FactIntent { + operation_id: "a".into(), + domain: feed.domain.clone(), + source_epoch: 0, + revision: 1, + previous_snapshot: "0".repeat(64), + expected_floor: 0, + available: true, + }; + let a = stage(&mut ledger, &intent); + let work = prepare(&mut ledger, &a); + resolve(&mut ledger, &work).expect("A installed"); + ledger.enqueue_provider(&plan).expect("original hold"); + let permit = ledger + .consume_provider("f", "infer", &BTreeSet::from(["primary".into()])) + .expect("consume"); + ledger + .dispatch_provider(&permit, || Ok(())) + .expect("dispatch"); + let unsent = ledger + .prepare_provider_release(&permit, "tail", "protobuf", 1) + .expect("prepared output"); + intent = FactIntent { + operation_id: "b".into(), + revision: 2, + previous_snapshot: a.snapshot, + expected_floor: a.floor, + available: false, + ..intent + }; + let b = stage(&mut ledger, &intent); + let stale = prepare(&mut ledger, &b); + let mut released = false; + assert!( + ledger + .release_provider(&permit, unsent, "protobuf", |_| { + released = true; + Ok(()) + }) + .is_err() + ); + assert!(!released); + assert_eq!(ledger.held("f").expect("hold retained"), 4); + intent = FactIntent { + operation_id: "a-again".into(), + revision: 3, + previous_snapshot: b.snapshot.clone(), + expected_floor: b.floor, + available: true, + ..intent + }; + let restored = stage(&mut ledger, &intent); + assert!(resolve(&mut ledger, &stale).is_err()); + let fresh = prepare(&mut ledger, &b); + assert_ne!(stale.pending_prefix, fresh.pending_prefix); + assert!( + ledger + .with_authenticated_source(&caller, |ledger| { + ledger.resolve_fact_projection(&fresh, vec!["infer".into()]) + }) + .is_err() + ); + let withdrawn = resolve(&mut ledger, &fresh).expect("B installed"); + assert!(withdrawn.remaining_pending_prefix.is_some()); + let mut dependent = plan.clone(); + dependent.node = "second".into(); + assert!(ledger.enqueue_provider(&dependent).is_err()); + let work = prepare(&mut ledger, &restored); + assert_eq!( + work.pending_prefix, + withdrawn + .remaining_pending_prefix + .expect("remaining prefix") + ); + resolve(&mut ledger, &work).expect("new A installed"); + assert!(matches!( + ledger.prepare_provider_release(&permit, "tail", "protobuf", 1), + Err(weaver_contracts::Error::Conflict( + "provider permit has a stale hard fact cut" + )) + )); + ledger + .enqueue_provider(&dependent) + .expect("restored dependent"); + ledger + .rotate_source_authority( + &caller, + &weaver_contracts::SourceRotation { + operation_id: "retire-feed-key".into(), + expected_epoch: 0, + next: SourceIdentity { + certificate_sha256: body_digest("new certificate"), + public_key_sha256: body_digest("new key"), + credential_sha256: body_digest("new credential"), + }, + }, + ) + .expect("retire source authority"); + assert!( + ledger + .consume_provider("f", "second", &BTreeSet::from(["primary".into()])) + .is_err() + ); + assert_eq!(ledger.held("f").expect("retired feed cannot refund"), 8); +} + +#[test] +fn provider_workflow_rechecks_prepared_floor_and_frontier_before_one_reservation() { + check_workflow_rechecks_prepared_floor(false); +} + +#[test] +fn nested_workflow_rejects_stale_decision_and_keeps_winner_after_reopen() { + check_workflow_rechecks_prepared_floor(true); +} + +fn check_workflow_rechecks_prepared_floor(nested: bool) { + use weaver_contracts::{ + FactFeed, FactIntent, ProviderWorkflow, SourceAuthority, SourceIdentity, + }; + use weaver_ledger::FactPreparation; + + let temp = tempfile::tempdir().expect("directory"); + let path = temp.path().join("workflow.db"); + let caller = SourceIdentity { + certificate_sha256: body_digest("certificate"), + public_key_sha256: body_digest("key"), + credential_sha256: body_digest("credential"), + }; + let mut ledger = Ledger::open(&path).expect("ledger"); + ledger + .with_authenticated_source(&caller, |_| Ok(())) + .expect("source"); + ledger.close().expect("close"); + let nodes: &[&str] = if nested { + &["infer", "second", "left", "right", "skip", "join"] + } else { + &["infer", "second"] + }; + let (mut ledger, predecessor) = fixture_nodes(&path, nodes); + let mut successor = predecessor.clone(); + successor.node = "second".into(); + let mut feed = FactFeed { + domain: "availability".into(), + authority: SourceAuthority { + epoch: 0, + identity: caller.clone(), + }, + family: predecessor.family.clone(), + root: predecessor.node.clone(), + dependencies: vec![(successor.node.clone(), predecessor.node.clone())], + workflow: Some(ProviderWorkflow { + predecessor: predecessor.node.clone(), + successor: successor.node.clone(), + }), + workflow_path: vec![], + workflow_dag: false, + workflow_choice: false, + workflow_selectors: vec![], + }; + if nested { + feed.workflow = None; + feed.workflow_dag = true; + feed.workflow_path = nodes.iter().map(|node| (*node).into()).collect(); + feed.dependencies = [ + ("join", "left"), + ("join", "right"), + ("join", "skip"), + ("left", "second"), + ("right", "second"), + ("second", "infer"), + ("skip", "infer"), + ] + .into_iter() + .map(|(child, parent)| (child.into(), parent.into())) + .collect(); + feed.workflow_selectors = [["infer", "second", "skip"], ["second", "left", "right"]] + .map(|row| row.map(String::from)) + .to_vec(); + } + ledger + .configure_fact_feed(Some(&feed)) + .expect("installed workflow"); + let mut affected: Vec = nodes.iter().map(|node| (*node).into()).collect(); + affected.sort(); + let project = |ledger: &mut Ledger, intent: &FactIntent| { + ledger + .with_authenticated_source(&caller, |ledger| { + let barrier = ledger.stage_fact_intent(intent)?; + let FactPreparation::Pending(work) = ledger.prepare_fact_projection(&barrier)? + else { + panic!("expected pending intent"); + }; + ledger.resolve_fact_projection(&work, affected.clone())?; + Ok(barrier) + }) + .expect("projected fact") + }; + let intent = FactIntent { + operation_id: "first-fact".into(), + domain: feed.domain.clone(), + source_epoch: 0, + revision: 1, + previous_snapshot: "0".repeat(64), + expected_floor: 0, + available: true, + }; + let a = project(&mut ledger, &intent); + assert!( + ledger + .prepare_provider_progression(&predecessor, &successor) + .is_err() + ); + assert!(ledger.enqueue_provider(&successor).is_err()); + ledger + .enqueue_provider(&predecessor) + .expect("predecessor queued"); + let permit = ledger + .consume_provider("f", "infer", &BTreeSet::from(["primary".into()])) + .expect("consume"); + ledger + .dispatch_provider(&permit, || Ok(())) + .expect("dispatch"); + let release = ledger + .prepare_provider_release(&permit, "response", "protobuf", 1) + .expect("prepared"); + ledger + .release_provider(&permit, release, "protobuf", |_| Ok(())) + .expect("released"); + assert!( + ledger + .prepare_provider_progression(&predecessor, &successor) + .is_err(), + "released prefix is not terminal completion" + ); + ledger + .complete_provider_with_result( + &permit, + "protobuf", + None, + nested.then_some(r#"{"route":"left"}"#), + ) + .expect("complete response"); + + let stale = ledger + .prepare_provider_progression(&predecessor, &successor) + .expect("first frontier"); + project( + &mut ledger, + &FactIntent { + operation_id: "second-fact".into(), + revision: 2, + previous_snapshot: a.snapshot, + expected_floor: a.floor, + ..intent + }, + ); + assert!( + ledger + .enqueue_provider_progression(&successor, "", None, Some(&stale)) + .is_err() + ); + assert_eq!( + ledger.held("f").expect("stale proposal reserved nothing"), + 4 + ); + let plans: Vec<_> = nodes + .iter() + .map(|node| ProviderPlan { + node: (*node).into(), + ..predecessor.clone() + }) + .collect(); + if nested { + let cut = ledger + .observe_workflow(&plans) + .expect("frontier") + .nested + .expect("nested graph"); + assert!(cut.decisions.is_empty()); + assert!(!cut.predecessors.contains_key("join")); + } + let current = ledger + .prepare_provider_progression(&predecessor, &successor) + .expect("refreshed frontier"); + ledger + .enqueue_provider_progression(&successor, "", None, Some(¤t)) + .expect("one successor claim"); + assert!( + ledger + .enqueue_provider_progression(&successor, "", None, Some(¤t)) + .is_err() + ); + let replay = ledger + .prepare_provider_progression(&predecessor, &successor) + .expect("winning frontier"); + ledger + .enqueue_provider_progression(&successor, "", None, Some(&replay)) + .expect("exact replay"); + assert_eq!(ledger.held("f").expect("one successor hold"), 8); + if nested { + ledger.close().expect("close"); + let mut ledger = Ledger::open(&path).expect("reopen"); + let cut = ledger + .observe_workflow(&plans) + .expect("frontier") + .nested + .expect("nested graph"); + assert_eq!(cut.decisions, [("infer".into(), "left".into())]); + assert!( + ledger + .provider_receipt("f", "skip") + .expect("skipped arm") + .is_none() + ); + assert!(!cut.predecessors.contains_key("join")); + assert_eq!(ledger.held("f").expect("preserved winner hold"), 8); + } +} diff --git a/dev/sysml/PolicyEvidenceDesign.sysml b/dev/sysml/PolicyEvidenceDesign.sysml index 7c02c941..96776570 100644 --- a/dev/sysml/PolicyEvidenceDesign.sysml +++ b/dev/sysml/PolicyEvidenceDesign.sysml @@ -393,7 +393,11 @@ package PolicyEvidenceDesign { publisher credential is insufficient to assert arbitrary hard facts. Persist original intent and affected-domain barrier before trusting a replacement projection. Source revisions need their own admitted - ordering; do not sort timestamps or use Ascent/MRR generation as a fence. */ + ordering; do not sort timestamps or use Ascent/MRR generation as a fence. + The local availability feed binds one original task and dependency + graph to a deployment-admitted source identity and epoch. It orders + durable commands within the ledger and carries no remote freshness + promise. The first projection is required before use. */ } item def HardFactBarrier { item intent : HardFactIntent; @@ -438,7 +442,10 @@ package PolicyEvidenceDesign { another pending intent keeps the domain blocked. Fact replacement is not covered by a fixed-fact Policy delta. Lost replies recover the original outcome. Continuations reuse the existing canonical-family - contract and cannot erase pending intent or reset original domains. */ + contract and cannot erase pending intent or reset original domains. + The local availability profile runs a bounded native ASCENT closure + on the retained graph. Only the oldest intent can install, and an + appended intent invalidates the earlier computation's prefix. */ } item def PublicationCommand { doc /* At the existing publication CAS, compare operation/digest and the @@ -666,9 +673,53 @@ package PolicyEvidenceDesign { complete evidence for its named scope, not merely a complete invocation. This target does not claim an external provider billing guarantee. */ } + item def SessionWorkflowEdge { + attribute predecessorStep : String; + attribute successorStep : String; + } + item def PreparedSessionWorkflow { + attribute originalFamily : String; + attribute orderedProviderSteps : String[2..64] ordered; + item edges : SessionWorkflowEdge[0..64]; + item selectors : PreparedSessionSelector[0..31]; + doc /* The Session places a typed Yuanxu Funflow routine in its original + family. The Governor selection and original plans must contain exactly + those steps. The fixed source capture preserves their order. The + independently admitted hard-fact deployment must bind the same + nodes and graph dependencies. The projection carries + neither an effect observation nor permission to execute a step. */ + } + item def PreparedSessionSelector { + attribute selectorStep : String; + attribute leftEntry : String; + attribute rightEntry : String; + doc /* Each conditional fork binds its own complete result to one of + two entries in the compiled topology. Parallel forks propagate all + active entries, including when nested inside a conditional arm. */ + } + item def ReleasedWorkflowResult { + item release : EffectObservation; + attribute route : String; + attribute responseDigest : String; + doc /* The conditional Session accepts one bounded JSON route from the + completely released selector response. Its typed result and digest + commit with release completion. A partial or ambiguous result leaves + the branch undecided. */ + } + item def SessionBranchDecision { + item selector : ReleasedWorkflowResult; + attribute selectedStep : String; + attribute selectedPlanDigest : String; + attribute factFloor : Integer; + attribute factSnapshot : String; + doc /* The original selector owns one decision slot. Its winner commits + with the selected arm's claim and reservation. The join requires + the committed selected predecessor and its complete release. */ + } item def SessionProgressionProposal { item original : SemanticCommitment; - item predecessor : EffectObservation; + item predecessor : EffectObservation[1..64]; + item branch : SessionBranchDecision[0..31]; attribute successorStep : String; attribute transitionSlot : String; attribute expectedRoutineFrontier : String; @@ -684,7 +735,25 @@ package PolicyEvidenceDesign { authoritative frontier. Atomically bind the frontier comparison, transition winner, successor claim/reservation and immutable outcome in existing admission; no local-advance then separate claim gap. - Use existing claims/outcomes, not a second Session ledger. */ + Use existing claims/outcomes, not a second Session ledger. + The single-provider implementation specializes the linear Session + Workflow during Scheme preparation. After activation and retirement, + Rust instantiates the fixed complete-response predicate for each + adjacent edge with the actual release observation, predecessor winner + when applicable, current fact cut and original domain stamp. The + provider transaction compares the winner frontier and commits the + existing queued claim and reservation with the transition admission + outcome. The Session receives successor output through the existing + guarded local receiver. Durable completion wakes reconciliation. + On restart after reactivation, existing operation receipts identify + the first missing or queued successor. A wake carries no authority + and an unknown operation stops progression. The legacy Governor + deployment can still bind one edge. For a fork/join Workflow the + prepared source binds the ordered nodes and every graph edge. The + live Scheme Governor uses ASCENT to select candidates from detached + ledger observations. Each proposal joins the complete release of + all immediate predecessors and one current fact version. A join + retains one winner, claim and reservation across recovery. */ } item def SourceCommand { item policyPublication : PublicationCommand[0..1]; diff --git a/dev/sysml/WeaverExecution.sysml b/dev/sysml/WeaverExecution.sysml index 19241f2b..11170fb0 100644 --- a/dev/sysml/WeaverExecution.sysml +++ b/dev/sysml/WeaverExecution.sysml @@ -679,6 +679,27 @@ package WeaverExecution { requirement def NoImplicitRetry { doc /* One logical node has one consumed send opportunity; redirects and SDK retries are disabled. */ } + requirement def SessionWorkflowFrontier { + doc /* Match the compiled Session Workflow topology and the deployed + availability dependencies. Scheme Governor uses ASCENT over a + coherent observation of complete releases and current hard facts. + Independent ready branches can dispatch concurrently. A join needs + every active predecessor's complete response release. A conditional + fork uses the selector's complete structured result and current facts. + Commit one branch decision with the selected arm claim and reserve. + Its persisted arm defines the active frontier across nested selectors. + An unresolved active arm + holds its dependent join. Descendants of an unselected arm are + inactive, including any selector they contain. Parallel parents + inside the active arm each need a complete release. Admission rechecks + every release and the observed fact version. The Session wakes on + durable release completion, activation and fact resolution. Only the + root needs an operation request. Repeated wakes share one durable + winner, claim and reservation. Restart reconstructs the frontier from + existing receipts. A queued claim may resume and an unknown outcome + stops progression. Pending and resolved withdrawals block affected + successors until a new available revision is admitted. */ + } requirement def DevelopmentPolicy { doc /* ASP Rust is a deny-mode Cargo test dependency and is absent from the runtime graph. */ } diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index 8fd209a5..96c897d8 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -566,5 +566,12 @@ {"file":"crates/broker/benches/gateway.rs","pattern":"fn guarded_provider"}, {"file":"go/dev/provider_bench_test.go","pattern":"func BenchmarkGatewayInspect"}]}, {"id":"DurableRangeProgressJoin","witnesses":[{"file":"crates/ledger/src/stream_progress.rs","pattern":"fn message"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_message_cursor_cannot_hide_consumed_range"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_progress_cannot_release_old_writer_or_connection"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run restoredUnknownProjectionBlocksAdmissionTest"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run unknownResetDuplicatesRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unresolved_tail_blocks_admission","declaration":"Weaver.StreamingExecution.RangeProgress.unresolved_tail_blocks_admission"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem changed_progress_cannot_execute","declaration":"Weaver.StreamingExecution.RangeProgress.changed_progress_cannot_execute"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem joined_execution_preserves_safety","declaration":"Weaver.StreamingExecution.RangeProgress.joined_execution_preserves_safety"}]}, - {"id":"TursoAdmissionAtomicity","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"pub fn begin"},{"file":"crates/ledger/src/exposure_manifest.rs","pattern":"fn verified_members"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn failed_commit_releases_writer_and_poisoned_session_cannot_reenter"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn duplicate_claim_members_cannot_be_normalized_out_of_recovery"},{"file":"go/dev/workspace_test.go","pattern":"func TestProjectArchitectureStorageUsesMRRDataTursoOnly"},{"file":"dev/proofs/quint/TursoAdmission.qnt","pattern":"run tornCommitRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem storage_step_retains_admission_safety","declaration":"Weaver.RuntimeAdmission.Persistence.storage_step_retains_admission_safety"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem committed_consume_survives_reply_loss_and_restart","declaration":"Weaver.RuntimeAdmission.Persistence.committed_consume_survives_reply_loss_and_restart"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem commit_itself_does_not_send","declaration":"Weaver.RuntimeAdmission.Persistence.commit_itself_does_not_send"}]} + {"id":"TursoAdmissionAtomicity","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"pub fn begin"},{"file":"crates/ledger/src/exposure_manifest.rs","pattern":"fn verified_members"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn failed_commit_releases_writer_and_poisoned_session_cannot_reenter"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn duplicate_claim_members_cannot_be_normalized_out_of_recovery"},{"file":"go/dev/workspace_test.go","pattern":"func TestProjectArchitectureStorageUsesMRRDataTursoOnly"},{"file":"dev/proofs/quint/TursoAdmission.qnt","pattern":"run tornCommitRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem storage_step_retains_admission_safety","declaration":"Weaver.RuntimeAdmission.Persistence.storage_step_retains_admission_safety"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem committed_consume_survives_reply_loss_and_restart","declaration":"Weaver.RuntimeAdmission.Persistence.committed_consume_survives_reply_loss_and_restart"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem commit_itself_does_not_send","declaration":"Weaver.RuntimeAdmission.Persistence.commit_itself_does_not_send"}]}, + {"id":"SessionWorkflowFrontier","witnesses":[ + {"file":"crates/ledger/src/provider_workflow.rs","pattern":"fn bind_winner"}, + {"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn provider_workflow_rechecks_prepared_floor_and_frontier_before_one_reservation"}, + {"file":"crates/ledger/src/provider_workflow.rs","pattern":"pub fn observe_workflow"}, + {"file":"crates/ledger/src/provider_workflow_choice.rs","pattern":"fn record_result"}, + {"file":"crates/ledger/src/provider_workflow_nested.rs","pattern":"fn load"}, + {"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn nested_workflow_rejects_stale_decision_and_keeps_winner_after_reopen"}]} ] From 9c676e70086a15759d876d5bfafce16e317980d6 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 20:44:48 +0800 Subject: [PATCH 023/105] Run the real SPEC provider case in Policy CI --- .github/workflows/verify-suite.yml | 2 +- Project.sysml | 7 ++++++- go/internal/devrunner/ci_test.go | 2 +- go/internal/devrunner/plan.go | 10 +++++++--- go/internal/devrunner/runner.go | 3 ++- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index bae885e0..ae43617c 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -63,7 +63,7 @@ jobs: run: go -C go run ./cmd/weaver-dev -clean-source -timeout 7m bootstrap-proofs - name: Prepare published Scheme SDK id: scheme_sdk - if: contains(fromJSON('["check-rust", "check-go", "check-scheme", "bench"]'), inputs.suite) + if: contains(fromJSON('["check-rust", "check-go", "check-policy", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e with: diff --git a/Project.sysml b/Project.sysml index 9cbc34ad..f25d6d86 100644 --- a/Project.sysml +++ b/Project.sysml @@ -243,7 +243,12 @@ package WeaverProject { } part scheme : VerificationSuite { part 'check-scheme' : VerificationMode; } part architecture : VerificationSuite { part 'check-architecture' : VerificationMode; } - part policy : VerificationSuite { part 'check-policy' : VerificationMode; } + part policy : VerificationSuite { + part 'check-policy' : VerificationMode; + doc /* Own the real SPEC provider integration because it consumes + Lean and CVC5. Run its stream-release, before-commit and + after-commit cases after the same native image build stages. */ + } part benchmarks : VerificationSuite { part bench : VerificationMode; } package Artifacts { diff --git a/go/internal/devrunner/ci_test.go b/go/internal/devrunner/ci_test.go index 960fcfe5..6628f104 100644 --- a/go/internal/devrunner/ci_test.go +++ b/go/internal/devrunner/ci_test.go @@ -31,7 +31,7 @@ func TestModularCISuitesPreserveUnifiedGateCoverage(t *testing.T) { t.Fatal(err) } for _, stage := range stages { - if covered[stage.Name] && stage.Name != "project-architecture" && stage.Name != "workflow-contract" { + if covered[stage.Name] && stage.Name != "project-architecture" && stage.Name != "workflow-contract" && !stage.providerBuild() { t.Fatalf("unintended duplicated check %s", stage.Name) } covered[stage.Name] = true diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index 11fd561c..7d6f0f00 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -10,6 +10,7 @@ import ( ) const rustRuntimeFeatures = "weaver-server/arrow,weaver-governance/scheme-vm" +const providerSpecReviewCase = "^TestProviderRealSPECReviewRevocationLostRepliesAndRestart$" const proofToolchain = "leanprover/lean4:v4.35.0" @@ -140,7 +141,8 @@ func Plan(goBinary string) []Stage { {"source-owner-quint-safety", "quint", []string{"run", "dev/proofs/quint/SourceOwner.qnt", "--main", "SourceOwner", "--invariant", "safe", "--max-samples", "1000", "--max-steps", "60", "--seed", "293"}}, {"go-provider-server-build", "cargo", []string{"build", "-p", "weaver-server", "--bin", "weaver-server", "--features", "arrow", "--locked", "--offline", "-j", "4"}}, {"go-provider-observer-build", "cargo", []string{"test", "-p", "weaver-server", "--lib", "--features", "arrow", "--locked", "--offline", "-j", "4", "--no-run"}}, - {"go-provider-grpc-integration", goBinary, []string{"-C", "go", "test", "-count=1", "-race", "-tags=integration", "-timeout=10m", "./dev", "-run", "TestProvider", "-v"}}, + {"go-provider-grpc-integration", goBinary, []string{"-C", "go", "test", "-count=1", "-race", "-tags=integration", "-timeout=10m", "./dev", "-run", "TestProvider", "-skip", providerSpecReviewCase, "-v"}}, + {"policy-provider-spec-integration", goBinary, []string{"-C", "go", "test", "-count=1", "-race", "-tags=integration", "-timeout=4m", "./dev", "-run", providerSpecReviewCase, "-v"}}, {"control-bundle-pbt", goBinary, []string{"-C", "go", "test", "./internal/config", "-run", "^$", "-fuzz", "FuzzSourceBundleCannotExpandOriginalSelection", "-fuzztime=3s"}}, {"authority-publication-quint-tests", "quint", []string{"test", "dev/proofs/quint/AuthorityPublication.qnt", "--main", "AuthorityPublication", "--seed", "293", "--match", "^authority[A-Z]"}}, {"authority-publication-quint-safety", "quint", []string{"run", "dev/proofs/quint/AuthorityPublication.qnt", "--main", "AuthorityPublication", "--invariant", "safe", "--max-samples", "1000", "--max-steps", "60", "--seed", "293"}}, @@ -190,9 +192,11 @@ func Stages(mode, goBinary string) ([]Stage, error) { for _, stage := range Plan(goBinary) { common := stage.Name == "project-architecture" || stage.Name == "workflow-contract" providerBuild := stage.providerBuild() + proofGo := stage.Name == "lean-json-integration" || stage.Name == "spec-real-qualification" || + stage.Name == "spec-proof-closure-integration" || stage.Name == "policy-provider-spec-integration" language := mode == "check-rust" && !providerBuild && (stage.Binary == "cargo" || stage.Binary == "rustc") || - mode == "check-go" && (providerBuild || stage.Binary == goBinary && stage.Name != "lean-json-integration" && stage.Name != "spec-real-qualification" && stage.Name != "spec-proof-closure-integration") || - mode == "check-policy" && (stage.Binary == "quint" || stage.Binary == "elan" || stage.Name == "lean-json-integration" || stage.Name == "spec-real-qualification" || stage.Name == "spec-proof-closure-integration") + mode == "check-go" && (providerBuild || stage.Binary == goBinary && !proofGo) || + mode == "check-policy" && (providerBuild || stage.Binary == "quint" || stage.Binary == "elan" || proofGo) if common || language { selected = append(selected, stage) } diff --git a/go/internal/devrunner/runner.go b/go/internal/devrunner/runner.go index aee470a7..5813a0ed 100644 --- a/go/internal/devrunner/runner.go +++ b/go/internal/devrunner/runner.go @@ -178,7 +178,8 @@ func Run(ctx context.Context, config Config, output io.Writer) (report string, r break } var result Result - if stage.Name == "go-provider-grpc-integration" && providerBuildFailure != "" { + if (stage.Name == "go-provider-grpc-integration" || stage.Name == "policy-provider-spec-integration") && + providerBuildFailure != "" { result = Result{Name: stage.Name, Status: "SKIP", Binary: stage.Binary, Args: stage.Args, Error: "required native build did not pass: " + providerBuildFailure} } else { From 7a2169fe1fd1afcbd9583da77feaf53494de2400 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 20:48:11 +0800 Subject: [PATCH 024/105] Bind workflow selector results to fully delivered provider output --- crates/broker/benches/gateway.rs | 2 +- crates/broker/src/lib.rs | 7 ++-- crates/broker/src/provider/mod.rs | 5 ++- crates/broker/src/provider/range_output.rs | 26 ++++++++++-- crates/broker/src/provider/runtime.rs | 41 +++++++++++++++++-- crates/broker/tests/unit/provider_dispatch.rs | 2 +- crates/broker/tests/unit/provider_request.rs | 4 +- crates/broker/tests/unit/provider_wif.rs | 2 +- crates/broker/tests/unit/runtime.rs | 11 ++--- 9 files changed, 78 insertions(+), 22 deletions(-) diff --git a/crates/broker/benches/gateway.rs b/crates/broker/benches/gateway.rs index 75ad24cf..e0ec75da 100644 --- a/crates/broker/benches/gateway.rs +++ b/crates/broker/benches/gateway.rs @@ -116,7 +116,7 @@ impl Provider { } }); Self { - runtime: fixture_runtime::fixture_runtime(), + runtime: fixture_runtime::fixture_runtime(None), address, endpoint: format!("https://localhost:{}/v1/chat/completions", address.port()), pem, diff --git a/crates/broker/src/lib.rs b/crates/broker/src/lib.rs index 6246393f..a612596d 100644 --- a/crates/broker/src/lib.rs +++ b/crates/broker/src/lib.rs @@ -9,9 +9,10 @@ mod transport; pub use broker::execute::execute; pub use broker::stream_session::StreamSession; pub use provider::{ - AnthropicWifConfig, ProviderExecution, ProviderExecutionAuthority, ProviderOutput, - ProviderTransport, ProviderTransportPhases, TransportStage, execute_catalog_provider, - execute_catalog_provider_with_oauth, execute_provider, + AnthropicWifConfig, ProviderExecution, ProviderExecutionAdmission, ProviderExecutionAuthority, + ProviderOutput, ProviderTransport, ProviderTransportPhases, TransportStage, + execute_catalog_provider, execute_catalog_provider_with_oauth, execute_provider, + execute_provider_progression, }; pub use transport::https::{HttpsTransport, SendObservation}; pub use transport::stream_sink::StreamTlsConfig; diff --git a/crates/broker/src/provider/mod.rs b/crates/broker/src/provider/mod.rs index d4b0302a..9bd6e8c4 100644 --- a/crates/broker/src/provider/mod.rs +++ b/crates/broker/src/provider/mod.rs @@ -17,8 +17,9 @@ mod wif; mod wif_cache; mod write_seal; pub use runtime::{ - ProviderExecution, ProviderExecutionAuthority, ProviderOutput, ProviderTransport, - execute_catalog_provider, execute_catalog_provider_with_oauth, execute_provider, + ProviderExecution, ProviderExecutionAdmission, ProviderExecutionAuthority, ProviderOutput, + ProviderTransport, execute_catalog_provider, execute_catalog_provider_with_oauth, + execute_provider, execute_provider_progression, }; pub use wif::AnthropicWifConfig; diff --git a/crates/broker/src/provider/range_output.rs b/crates/broker/src/provider/range_output.rs index ea638cd8..a639dc5f 100644 --- a/crates/broker/src/provider/range_output.rs +++ b/crates/broker/src/provider/range_output.rs @@ -6,7 +6,9 @@ use super::runtime::{ProviderOutput, StreamDecoder}; use std::future::poll_fn; use tokio::io::AsyncRead; -use weaver_contracts::{Error, ProviderEvent, ProviderEventKind, Result, body_digest}; +use weaver_contracts::{ + Error, MAX_WORKFLOW_RESULT_BYTES, ProviderEvent, ProviderEventKind, Result, body_digest, +}; use weaver_ledger::{ Ledger, MAX_PROVIDER_PREPARATION_RANGES, MAX_PROVIDER_PREPARATION_ROWS, ProviderDispatch, ProviderRelease, @@ -19,7 +21,8 @@ pub(super) fn relay( response: super::response::Response, format: &str, rows: usize, -) -> Result> { + mut result: Option, +) -> Result<(Option<[u64; 4]>, Option)> { let mut pending = Vec::with_capacity(rows); let width = preparation_width(output, rows); let (reactor, deadline) = response.reactor(); @@ -71,10 +74,27 @@ pub(super) fn relay( ); release_ranges(ledger, permit, output, format, &mut ready)?; buffered?; + result = result.and_then(|capture| capture_workflow_result(capture, &ready)); if terminal { - return Ok(reader.terminal_tokens()); + return Ok((reader.terminal_tokens(), result)); + } + } +} + +fn capture_workflow_result(mut capture: String, ranges: &[Vec]) -> Option { + let deltas = ranges.iter().flatten().filter(|event| { + matches!( + event.kind, + ProviderEventKind::Delta | ProviderEventKind::Finish + ) + }); + for delta in deltas { + if delta.text.len() > MAX_WORKFLOW_RESULT_BYTES - capture.len() { + return None; } + capture.push_str(&delta.text); } + Some(capture) } fn preparation_width(_output: &O, rows: usize) -> usize { diff --git a/crates/broker/src/provider/runtime.rs b/crates/broker/src/provider/runtime.rs index 9142dfc0..db8859d0 100644 --- a/crates/broker/src/provider/runtime.rs +++ b/crates/broker/src/provider/runtime.rs @@ -324,12 +324,36 @@ pub struct ProviderExecutionAuthority<'a> { pub oauth: Option<&'a weaver_contracts::ProviderOAuthUse>, } +/// The host's current authority inputs and optional prepared Session successor. +pub struct ProviderExecutionAdmission<'a> { + pub authority: ProviderExecutionAuthority<'a>, + pub progression: Option<&'a weaver_ledger::ProviderProgression>, +} + /// Run the provider pipeline with the caller observation from authenticated RPC. pub fn execute_catalog_provider_with_oauth( ledger: &mut Ledger, request: ProviderExecution<'_>, output: &mut O, authority: ProviderExecutionAuthority<'_>, +) -> Result<()> { + execute_provider_progression( + ledger, + request, + output, + ProviderExecutionAdmission { + authority, + progression: None, + }, + ) +} + +/// Use the existing provider pipeline with an optional sealed successor proposal. +pub fn execute_provider_progression( + ledger: &mut Ledger, + request: ProviderExecution<'_>, + output: &mut O, + admission: ProviderExecutionAdmission<'_>, ) -> Result<()> { if !cfg!(feature = "llm-provider") { return Err(Error::Invalid("LLM provider feature disabled")); @@ -340,7 +364,7 @@ pub fn execute_catalog_provider_with_oauth( format, batch_rows, } = request; - let ProviderExecutionAuthority { catalog, oauth } = authority; + let ProviderExecutionAuthority { catalog, oauth } = admission.authority; if !(1..=32).contains(&batch_rows) || !matches!(format, "protobuf" | "arrow") || output.stopped() @@ -350,7 +374,7 @@ pub fn execute_catalog_provider_with_oauth( for route in &plan.routes { crate::HttpsTransport::validate_endpoint(&route.endpoint)?; } - ledger.enqueue_provider_with_oauth(plan, catalog, oauth)?; + ledger.enqueue_provider_progression(plan, catalog, oauth, admission.progression)?; if output.stopped() { return Err(Error::Conflict("cancelled before provider consumption")); } @@ -360,10 +384,19 @@ pub fn execute_catalog_provider_with_oauth( &transport.eligible(), oauth, )?; + let result_capture = permit.expects_workflow_result().then(String::new); let response = open_guarded(ledger, &permit, transport, output)?; - let tokens = super::range_output::relay(ledger, &permit, output, response, format, batch_rows)?; + let (tokens, response) = super::range_output::relay( + ledger, + &permit, + output, + response, + format, + batch_rows, + result_capture, + )?; output.drain_delivery(ledger, &permit, format)?; - ledger.complete_provider_with_usage(&permit, format, tokens) + ledger.complete_provider_with_result(&permit, format, tokens, response.as_deref()) } pub(super) enum StreamDecoder { diff --git a/crates/broker/tests/unit/provider_dispatch.rs b/crates/broker/tests/unit/provider_dispatch.rs index d28b5c34..1fef73da 100644 --- a/crates/broker/tests/unit/provider_dispatch.rs +++ b/crates/broker/tests/unit/provider_dispatch.rs @@ -122,7 +122,7 @@ impl Endpoint { } }); Self { - runtime: fixture_runtime::fixture_runtime(), + runtime: fixture_runtime::fixture_runtime(Some(4)), peer_closed, address, root, diff --git a/crates/broker/tests/unit/provider_request.rs b/crates/broker/tests/unit/provider_request.rs index 931d2767..bab5ab01 100644 --- a/crates/broker/tests/unit/provider_request.rs +++ b/crates/broker/tests/unit/provider_request.rs @@ -7,7 +7,7 @@ use crate::provider::test_runtime as fixture_runtime; use std::sync::Arc; #[test] fn prepared_bearer_retains_sensitive_debug_redaction_without_io() { - let runtime = fixture_runtime::fixture_runtime(); + let runtime = fixture_runtime::fixture_runtime(Some(4)); let config = rustls::ClientConfig::builder_with_provider(Arc::new( rustls::crypto::ring::default_provider(), )) @@ -39,7 +39,7 @@ fn prepared_bearer_retains_sensitive_debug_redaction_without_io() { #[test] fn expired_anthropic_bearer_is_rejected_before_io() { - let runtime = fixture_runtime::fixture_runtime(); + let runtime = fixture_runtime::fixture_runtime(Some(4)); let tls = rustls::ClientConfig::builder_with_provider(Arc::new( rustls::crypto::ring::default_provider(), )) diff --git a/crates/broker/tests/unit/provider_wif.rs b/crates/broker/tests/unit/provider_wif.rs index d289da7d..11bca587 100644 --- a/crates/broker/tests/unit/provider_wif.rs +++ b/crates/broker/tests/unit/provider_wif.rs @@ -131,7 +131,7 @@ fn synthetic_tls_exchange_coalesces_concurrent_refresh() { workspace_id: "wrkspc_fixture".into(), }) .expect("fixture federation"); - let runtime = crate::provider::test_runtime::fixture_runtime(); + let runtime = crate::provider::test_runtime::fixture_runtime(Some(4)); let io = IoRuntime { handle: runtime.handle().clone(), }; diff --git a/crates/broker/tests/unit/runtime.rs b/crates/broker/tests/unit/runtime.rs index 674aa5f2..97c89af9 100644 --- a/crates/broker/tests/unit/runtime.rs +++ b/crates/broker/tests/unit/runtime.rs @@ -5,9 +5,10 @@ //! Explicit standalone fixture owner. Production always borrows the server reactor. //! The endpoint/benchmark owns this value until its drivers and server thread //! have naturally drained; no detached provider tasks are spawned on this pool. -pub fn fixture_runtime() -> tokio::runtime::Runtime { - tokio::runtime::Builder::new_multi_thread() - .enable_all() - .build() - .expect("fixture reactor") +pub fn fixture_runtime(worker_threads: Option) -> tokio::runtime::Runtime { + let mut builder = tokio::runtime::Builder::new_multi_thread(); + if let Some(worker_threads) = worker_threads { + builder.worker_threads(worker_threads); + } + builder.enable_all().build().expect("fixture reactor") } From 95d48806073264543d49cb2ec65904c834f80b84 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 20:52:45 +0800 Subject: [PATCH 025/105] Derive admitted hard-fact impact with native ASCENT --- Cargo.lock | 84 +++++++++++++++++++++++++++++- Cargo.toml | 1 + crates/governance/Cargo.toml | 1 + crates/governance/src/hard_fact.rs | 61 ++++++++++++++++++++++ crates/governance/src/lib.rs | 2 + 5 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 crates/governance/src/hard_fact.rs diff --git a/Cargo.lock b/Cargo.lock index b258b958..b2291862 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,6 +79,12 @@ dependencies = [ "cc", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "allocator-api2" version = "0.4.0" @@ -299,6 +305,47 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ascent" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b69c5a0326edc45aea8469a51f84be0ff28ea1e3a4d087665468793be061682" +dependencies = [ + "ascent_base", + "ascent_macro", + "boxcar", + "cfg-if", + "hashbrown 0.14.5", + "pastey", + "rustc-hash 2.1.3", + "web-time", +] + +[[package]] +name = "ascent_base" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "792af0babe403e49368d8717763605fe978b3a1eb7d51b52e3d0a5cb97e6eb74" +dependencies = [ + "pastey", +] + +[[package]] +name = "ascent_macro" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ac2662b20bf37fd66d21687c0ef91f1c64320a7ca985a34d1c3e60cc9ba940a" +dependencies = [ + "ascent_base", + "derive-syn-parse", + "duplicate", + "itertools 0.15.0", + "petgraph 0.8.3", + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "ascii-canvas" version = "4.0.0" @@ -662,6 +709,12 @@ dependencies = [ "cfg_aliases", ] +[[package]] +name = "boxcar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c99613cb3cd7429889a08dfcf651721ca971c86afa30798461f8eee994de47" + [[package]] name = "branches" version = "0.4.6" @@ -1398,6 +1451,17 @@ dependencies = [ "serde_core", ] +[[package]] +name = "derive-syn-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "digest" version = "0.10.7" @@ -1438,6 +1502,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +[[package]] +name = "duplicate" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e92f10a49176cbffacaedabfaa11d51db1ea0f80a83c26e1873b43cd1742c24" + [[package]] name = "dyn-clone" version = "1.0.20" @@ -1972,6 +2042,16 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2 0.2.21", +] + [[package]] name = "hashbrown" version = "0.15.5" @@ -3365,6 +3445,7 @@ dependencies = [ "fixedbitset", "hashbrown 0.15.5", "indexmap 2.14.2", + "serde", ] [[package]] @@ -5189,7 +5270,7 @@ dependencies = [ "aegis", "aes", "aes-gcm", - "allocator-api2", + "allocator-api2 0.4.0", "antithesis_sdk", "arc-swap", "aristo", @@ -5678,6 +5759,7 @@ dependencies = [ name = "weaver-governance" version = "0.1.0" dependencies = [ + "ascent", "asp-rust", "criterion", "gerbil-scheme", diff --git a/Cargo.toml b/Cargo.toml index d31ddac5..4e470031 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ edition = "2024" license = "LGPL-2.1-or-later AND Apache-2.0" [workspace.dependencies] +ascent = { version = "=0.8.1", default-features = false } weaver-contracts = { path = "crates/contracts" } weaver-governance = { path = "crates/governance" } weaver-policy = { path = "crates/policy" } diff --git a/crates/governance/Cargo.toml b/crates/governance/Cargo.toml index 9c7c402b..7a508c34 100644 --- a/crates/governance/Cargo.toml +++ b/crates/governance/Cargo.toml @@ -14,6 +14,7 @@ scheme-program = ["scheme-vm", "dep:gerbil-scheme-sys", "dep:weaver-policy-ffi"] scheme-qualification = ["scheme-program"] [dependencies] +ascent.workspace = true weaver-contracts.workspace = true serde.workspace = true thiserror.workspace = true diff --git a/crates/governance/src/hard_fact.rs b/crates/governance/src/hard_fact.rs new file mode 100644 index 00000000..516a3c9b --- /dev/null +++ b/crates/governance/src/hard_fact.rs @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Closed impact rules over a deployment-admitted original task. +use ascent::ascent; +use weaver_contracts::{Error, FactWork, Result}; + +ascent! { + struct FactImpact; + relation depends(String, String); + relation changed(String); + relation affected(String); + affected(node) <-- changed(node); + affected(dependent) <-- depends(dependent, node), affected(node); +} + +/// Native evaluation is bounded by the admitted finite input graph. No source +/// mutation, authority observation or permission grant occurs in this function. +pub fn derive_fact_impact(work: &FactWork) -> Result> { + if work.dependencies.len() > 64 { + return Err(Error::Invalid("fact impact graph bound")); + } + let mut program = FactImpact { + depends: work.dependencies.clone(), + changed: vec![(work.root.clone(),)], + ..Default::default() + }; + program.run(); + let mut affected: Vec<_> = program.affected.into_iter().map(|(node,)| node).collect(); + affected.sort_unstable(); + Ok(affected) +} + +#[cfg(test)] +#[test] +fn hard_fact_impact_is_transitive_and_handles_cycles() { + let work = FactWork { + barrier: weaver_contracts::FactBarrier { + operation_id: "test".into(), + source_epoch: 0, + revision: 1, + snapshot: String::new(), + floor: 1, + pending_prefix: String::new(), + }, + expected_floor: 1, + pending_prefix: String::new(), + root: "root".into(), + dependencies: vec![ + ("direct".into(), "root".into()), + ("transitive".into(), "direct".into()), + ("root".into(), "transitive".into()), + ("unrelated".into(), "other".into()), + ], + available: false, + }; + assert_eq!( + derive_fact_impact(&work).expect("fixed point"), + ["direct", "root", "transitive"] + ); +} diff --git a/crates/governance/src/lib.rs b/crates/governance/src/lib.rs index 57137fde..48229b93 100644 --- a/crates/governance/src/lib.rs +++ b/crates/governance/src/lib.rs @@ -7,10 +7,12 @@ extern crate self as weaver_governance; mod binding; mod catalog; +mod hard_fact; mod host; mod source; pub use binding::{BoundSource, SourceExpectation}; pub use catalog::{ApprovedProducer, CatalogError, ProducerCatalog, ProducerClient}; +pub use hard_fact::derive_fact_impact; pub use host::{SourceClient, SourceInbox, SourceJob, SourceJobError, source_lane}; pub use source::{MAX_SOURCE_BYTES, OwnedSource, SourceData, SourceError, SourceSelection}; From 8f7bdbd7f2a77ed22b40e96056efc4a5c102cd4a Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 20:58:27 +0800 Subject: [PATCH 026/105] Serve authenticated hard-fact intents on the existing source lane --- crates/server/src/grpc.rs | 82 +++ crates/server/src/grpc_config.rs | 13 +- crates/server/src/runtime.rs | 13 +- crates/server/src/source_owner.rs | 101 ++- dev/sysml/runtime-trace.json | 2 + go/api/gateway/v1/gateway.pb.go | 876 ++++++++++++++++++--------- go/api/gateway/v1/gateway_grpc.pb.go | 78 +++ go/dev/provider_hard_fact_test.go | 145 +++++ proto/gateway/v1/gateway.proto | 27 + 9 files changed, 1038 insertions(+), 299 deletions(-) create mode 100644 go/dev/provider_hard_fact_test.go diff --git a/crates/server/src/grpc.rs b/crates/server/src/grpc.rs index 16bd9b95..a3248133 100644 --- a/crates/server/src/grpc.rs +++ b/crates/server/src/grpc.rs @@ -41,6 +41,18 @@ enum Ingress { Operation, Source(SourceOwner), } +impl Gateway { + fn fact_barrier(barrier: weaver_contracts::FactBarrier) -> pb::HardFactBarrier { + pb::HardFactBarrier { + operation_id: barrier.operation_id, + source_epoch: barrier.source_epoch, + revision: barrier.revision, + snapshot: barrier.snapshot, + floor: barrier.floor, + pending_prefix: barrier.pending_prefix, + } + } +} impl Ingress { fn role(&self) -> RpcRole { match self { @@ -293,6 +305,76 @@ impl Gateway { } #[tonic::async_trait] impl pb::gateway_server::Gateway for Gateway { + async fn stage_hard_fact( + &self, + request: Request, + ) -> Result, Status> { + let caller = self.source_identity(&request)?; + let change = request.into_inner(); + let intent = weaver_contracts::FactIntent { + operation_id: change.operation_id, + domain: change.domain, + source_epoch: change.source_epoch, + revision: change.revision, + previous_snapshot: change.previous_snapshot, + expected_floor: change.expected_floor, + available: change.available.ok_or(Status::invalid_argument( + "explicit hard fact value required", + ))?, + }; + intent + .snapshot() + .map_err(|_| Status::invalid_argument("invalid hard fact intent"))?; + let barrier = self.ingress.source()?.stage_fact(caller, intent).await?; + Ok(Response::new(Self::fact_barrier(barrier))) + } + + async fn resolve_hard_fact( + &self, + request: Request, + ) -> Result, Status> { + let caller = self.source_identity(&request)?; + let key = request.into_inner(); + weaver_contracts::identifier(&key.operation_id) + .map_err(|_| Status::invalid_argument("invalid hard fact identity"))?; + if key.snapshot.len() != 64 || key.pending_prefix.len() != 64 { + return Err(Status::invalid_argument("invalid hard fact barrier")); + } + let barrier = weaver_contracts::FactBarrier { + operation_id: key.operation_id, + source_epoch: key.source_epoch, + revision: key.revision, + snapshot: key.snapshot, + floor: key.floor, + pending_prefix: key.pending_prefix, + }; + let source = self.ingress.source()?; + let result = match source.prepare_fact(caller.clone(), barrier).await? { + weaver_ledger::FactPreparation::Resolved(resolution) => resolution, + weaver_ledger::FactPreparation::Pending(work) => { + let slot = self.admission.observation()?; + let job = self + .runtime + .spawn_blocking(slot, move |_| { + let affected = weaver_governance::derive_fact_impact(&work)?; + Ok((work, affected)) + }) + .map_err(status)?; + let (work, affected) = job + .await + .map_err(|_| Status::unavailable("hard fact derivation interrupted"))? + .map_err(status)?; + source.resolve_fact(caller, work, affected).await? + } + }; + Ok(Response::new(pb::FactBarrierResolution { + barrier: Some(Self::fact_barrier(result.barrier)), + affected: result.affected, + floor: result.floor, + previous_pending_prefix: result.previous_pending_prefix, + remaining_pending_prefix: result.remaining_pending_prefix, + })) + } async fn inspect_telemetry( &self, request: Request, diff --git a/crates/server/src/grpc_config.rs b/crates/server/src/grpc_config.rs index 1e36abed..856fde7a 100644 --- a/crates/server/src/grpc_config.rs +++ b/crates/server/src/grpc_config.rs @@ -159,15 +159,26 @@ async fn run_owned(runtime: crate::ServiceRuntime) -> Result<()> { std::time::SystemTime::now() ); let shutdown = crate::shutdown::signal()?; - let (settings, addresses, catalog) = crate::runtime::RuntimeOwner::initialize(|| { + let (settings, addresses, catalog, feed) = crate::runtime::RuntimeOwner::initialize(|| { let (settings, addresses) = load()?; + let feed = match std::env::var("WEAVER_HARD_FACT_FEED") { + Ok(value) => Some(weaver_contracts::decode::( + value.as_bytes(), + )?), + Err(std::env::VarError::NotPresent) => None, + Err(_) => return Err(Error::Invalid("hard fact feed deployment encoding")), + }; Ok(( settings, addresses, crate::governance_deployment::load_catalog()?, + feed, )) }) .await?; + if let Some(feed) = feed { + runtime.install_fact_feed(feed)?; + } let worker = crate::governance_deployment::start(&runtime, catalog).await?; eprintln!( "weaver startup stage=configured elapsed={:?}", diff --git a/crates/server/src/runtime.rs b/crates/server/src/runtime.rs index 79b99fd0..db0869a1 100644 --- a/crates/server/src/runtime.rs +++ b/crates/server/src/runtime.rs @@ -4,7 +4,7 @@ //! Typed runtime owner: bounded task admission, cancellation, tracking and drain acknowledgment. use std::sync::{ - Arc, Mutex, + Arc, Mutex, OnceLock, atomic::{AtomicBool, Ordering}, }; use tokio::sync::OwnedSemaphorePermit; @@ -23,6 +23,7 @@ struct Inner { closed: AtomicBool, cancel: CancellationToken, tasks: TaskTracker, + fact_feed: OnceLock, } struct AdmissionState { governance: Option, @@ -80,9 +81,19 @@ impl RuntimeOwner { closed: AtomicBool::new(false), cancel: CancellationToken::new(), tasks: TaskTracker::new(), + fact_feed: OnceLock::new(), }), } } + pub(crate) fn install_fact_feed(&self, feed: weaver_contracts::FactFeed) -> Result<()> { + self.inner + .fact_feed + .set(feed) + .map_err(|_| Error::Conflict("fact feed already installed")) + } + pub(crate) fn fact_feed(&self) -> Option<&weaver_contracts::FactFeed> { + self.inner.fact_feed.get() + } /// Bounded local observations only; callers acquire no authority capability. pub fn telemetry(&self) -> &Arc { &self.inner.telemetry diff --git a/crates/server/src/source_owner.rs b/crates/server/src/source_owner.rs index 048b43f8..edb58a64 100644 --- a/crates/server/src/source_owner.rs +++ b/crates/server/src/source_owner.rs @@ -12,10 +12,11 @@ use tokio::{ use tokio_util::sync::CancellationToken; use tonic::Status; use weaver_contracts::{ - Error, Publication, PublicationKey, PublicationReceipt, Result, SourceAuthority, - SourceIdentity, SourceRotation, SourceRotationReceipt, Task, + Error, FactBarrier, FactFeed, FactIntent, FactResolution, FactWork, Publication, + PublicationKey, PublicationReceipt, Result, SourceAuthority, SourceIdentity, SourceRotation, + SourceRotationReceipt, Task, }; -use weaver_ledger::Ledger; +use weaver_ledger::{FactPreparation, Ledger}; #[derive(Clone)] pub(crate) struct SourceOwner { @@ -30,9 +31,26 @@ struct SourceDeployment { review: Option, metering: Option, oauth: Option, + fact_feed: Option, } enum Command { + StageFact { + intent: FactIntent, + reply: oneshot::Sender>, + slot: OwnedSemaphorePermit, + }, + PrepareFact { + barrier: FactBarrier, + reply: oneshot::Sender>, + slot: OwnedSemaphorePermit, + }, + ResolveFact { + work: FactWork, + affected: Vec, + reply: oneshot::Sender>, + slot: OwnedSemaphorePermit, + }, ChangeProviderOAuth { action: Box, reply: oneshot::Sender>, @@ -157,6 +175,44 @@ impl SourceWorker { } } impl SourceOwner { + pub(crate) async fn stage_fact( + &self, + caller: SourceIdentity, + intent: FactIntent, + ) -> std::result::Result { + self.submit(caller, |reply, slot| Command::StageFact { + intent, + reply, + slot, + }) + .await + } + pub(crate) async fn prepare_fact( + &self, + caller: SourceIdentity, + barrier: FactBarrier, + ) -> std::result::Result { + self.submit(caller, |reply, slot| Command::PrepareFact { + barrier, + reply, + slot, + }) + .await + } + pub(crate) async fn resolve_fact( + &self, + caller: SourceIdentity, + work: FactWork, + affected: Vec, + ) -> std::result::Result { + self.submit(caller, |reply, slot| Command::ResolveFact { + work, + affected, + reply, + slot, + }) + .await + } pub(crate) async fn original( &self, caller: SourceIdentity, @@ -294,6 +350,7 @@ impl SourceOwner { oauth: Option, ) -> Result { authority.validate()?; + let fact_feed = runtime.fact_feed().cloned(); Self::start_inner( runtime, slot, @@ -302,6 +359,7 @@ impl SourceOwner { review: Some(authority), metering, oauth, + fact_feed, }, ) .await @@ -320,6 +378,7 @@ impl SourceOwner { review: None, metering: None, oauth: None, + fact_feed: None, }, ) .await @@ -541,6 +600,12 @@ fn run( .close() .and(Err(Error::Conflict("provider OAuth startup refused"))); } + if let Err(error) = ledger.configure_fact_feed(deployment.fact_feed.as_ref()) { + let _ = ready.send(Err(error)); + return ledger + .close() + .and(Err(Error::Conflict("hard fact feed startup refused"))); + } let result = if ready.send(Ok(())).is_err() { Err(Error::Conflict("source startup abandoned")) } else { @@ -568,6 +633,36 @@ fn process( ledger.require_quiescent()?; let Envelope { caller, command } = command; match command { + Command::StageFact { + intent, + reply, + slot, + } => { + let result = ledger + .with_authenticated_source(&caller, |ledger| ledger.stage_fact_intent(&intent)); + answer(ledger, reply, result, slot)?; + } + Command::PrepareFact { + barrier, + reply, + slot, + } => { + let result = ledger.with_authenticated_source(&caller, |ledger| { + ledger.prepare_fact_projection(&barrier) + }); + answer(ledger, reply, result, slot)?; + } + Command::ResolveFact { + work, + affected, + reply, + slot, + } => { + let result = ledger.with_authenticated_source(&caller, |ledger| { + ledger.resolve_fact_projection(&work, affected) + }); + answer(ledger, reply, result, slot)?; + } Command::ChangeProviderOAuth { action, reply, diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index 96c897d8..4077bcdc 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -568,6 +568,8 @@ {"id":"DurableRangeProgressJoin","witnesses":[{"file":"crates/ledger/src/stream_progress.rs","pattern":"fn message"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_message_cursor_cannot_hide_consumed_range"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_progress_cannot_release_old_writer_or_connection"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run restoredUnknownProjectionBlocksAdmissionTest"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run unknownResetDuplicatesRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unresolved_tail_blocks_admission","declaration":"Weaver.StreamingExecution.RangeProgress.unresolved_tail_blocks_admission"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem changed_progress_cannot_execute","declaration":"Weaver.StreamingExecution.RangeProgress.changed_progress_cannot_execute"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem joined_execution_preserves_safety","declaration":"Weaver.StreamingExecution.RangeProgress.joined_execution_preserves_safety"}]}, {"id":"TursoAdmissionAtomicity","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"pub fn begin"},{"file":"crates/ledger/src/exposure_manifest.rs","pattern":"fn verified_members"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn failed_commit_releases_writer_and_poisoned_session_cannot_reenter"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn duplicate_claim_members_cannot_be_normalized_out_of_recovery"},{"file":"go/dev/workspace_test.go","pattern":"func TestProjectArchitectureStorageUsesMRRDataTursoOnly"},{"file":"dev/proofs/quint/TursoAdmission.qnt","pattern":"run tornCommitRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem storage_step_retains_admission_safety","declaration":"Weaver.RuntimeAdmission.Persistence.storage_step_retains_admission_safety"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem committed_consume_survives_reply_loss_and_restart","declaration":"Weaver.RuntimeAdmission.Persistence.committed_consume_survives_reply_loss_and_restart"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem commit_itself_does_not_send","declaration":"Weaver.RuntimeAdmission.Persistence.commit_itself_does_not_send"}]}, {"id":"SessionWorkflowFrontier","witnesses":[ + {"file":"crates/governance/src/hard_fact.rs","pattern":"fn derive_fact_impact"}, + {"file":"go/dev/provider_hard_fact_test.go","pattern":"func TestProviderControlHardFactWithdrawalRestartAndABA"}, {"file":"crates/ledger/src/provider_workflow.rs","pattern":"fn bind_winner"}, {"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn provider_workflow_rechecks_prepared_floor_and_frontier_before_one_reservation"}, {"file":"crates/ledger/src/provider_workflow.rs","pattern":"pub fn observe_workflow"}, diff --git a/go/api/gateway/v1/gateway.pb.go b/go/api/gateway/v1/gateway.pb.go index 4f4b9c0c..dd748065 100644 --- a/go/api/gateway/v1/gateway.pb.go +++ b/go/api/gateway/v1/gateway.pb.go @@ -409,6 +409,258 @@ func (x *ProducerRequest) GetProducer() string { return "" } +type HardFactIntent struct { + state protoimpl.MessageState `protogen:"open.v1"` + OperationId string `protobuf:"bytes,1,opt,name=operation_id,json=operationId,proto3" json:"operation_id,omitempty"` + Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"` + SourceEpoch uint64 `protobuf:"varint,3,opt,name=source_epoch,json=sourceEpoch,proto3" json:"source_epoch,omitempty"` + Revision uint64 `protobuf:"varint,4,opt,name=revision,proto3" json:"revision,omitempty"` + PreviousSnapshot string `protobuf:"bytes,5,opt,name=previous_snapshot,json=previousSnapshot,proto3" json:"previous_snapshot,omitempty"` + ExpectedFloor uint64 `protobuf:"varint,6,opt,name=expected_floor,json=expectedFloor,proto3" json:"expected_floor,omitempty"` + Available *bool `protobuf:"varint,7,opt,name=available,proto3,oneof" json:"available,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HardFactIntent) Reset() { + *x = HardFactIntent{} + mi := &file_gateway_v1_gateway_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HardFactIntent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HardFactIntent) ProtoMessage() {} + +func (x *HardFactIntent) ProtoReflect() protoreflect.Message { + mi := &file_gateway_v1_gateway_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HardFactIntent.ProtoReflect.Descriptor instead. +func (*HardFactIntent) Descriptor() ([]byte, []int) { + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{3} +} + +func (x *HardFactIntent) GetOperationId() string { + if x != nil { + return x.OperationId + } + return "" +} + +func (x *HardFactIntent) GetDomain() string { + if x != nil { + return x.Domain + } + return "" +} + +func (x *HardFactIntent) GetSourceEpoch() uint64 { + if x != nil { + return x.SourceEpoch + } + return 0 +} + +func (x *HardFactIntent) GetRevision() uint64 { + if x != nil { + return x.Revision + } + return 0 +} + +func (x *HardFactIntent) GetPreviousSnapshot() string { + if x != nil { + return x.PreviousSnapshot + } + return "" +} + +func (x *HardFactIntent) GetExpectedFloor() uint64 { + if x != nil { + return x.ExpectedFloor + } + return 0 +} + +func (x *HardFactIntent) GetAvailable() bool { + if x != nil && x.Available != nil { + return *x.Available + } + return false +} + +type HardFactBarrier struct { + state protoimpl.MessageState `protogen:"open.v1"` + OperationId string `protobuf:"bytes,1,opt,name=operation_id,json=operationId,proto3" json:"operation_id,omitempty"` + SourceEpoch uint64 `protobuf:"varint,2,opt,name=source_epoch,json=sourceEpoch,proto3" json:"source_epoch,omitempty"` + Revision uint64 `protobuf:"varint,3,opt,name=revision,proto3" json:"revision,omitempty"` + Snapshot string `protobuf:"bytes,4,opt,name=snapshot,proto3" json:"snapshot,omitempty"` + Floor uint64 `protobuf:"varint,5,opt,name=floor,proto3" json:"floor,omitempty"` + PendingPrefix string `protobuf:"bytes,6,opt,name=pending_prefix,json=pendingPrefix,proto3" json:"pending_prefix,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HardFactBarrier) Reset() { + *x = HardFactBarrier{} + mi := &file_gateway_v1_gateway_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HardFactBarrier) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HardFactBarrier) ProtoMessage() {} + +func (x *HardFactBarrier) ProtoReflect() protoreflect.Message { + mi := &file_gateway_v1_gateway_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HardFactBarrier.ProtoReflect.Descriptor instead. +func (*HardFactBarrier) Descriptor() ([]byte, []int) { + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{4} +} + +func (x *HardFactBarrier) GetOperationId() string { + if x != nil { + return x.OperationId + } + return "" +} + +func (x *HardFactBarrier) GetSourceEpoch() uint64 { + if x != nil { + return x.SourceEpoch + } + return 0 +} + +func (x *HardFactBarrier) GetRevision() uint64 { + if x != nil { + return x.Revision + } + return 0 +} + +func (x *HardFactBarrier) GetSnapshot() string { + if x != nil { + return x.Snapshot + } + return "" +} + +func (x *HardFactBarrier) GetFloor() uint64 { + if x != nil { + return x.Floor + } + return 0 +} + +func (x *HardFactBarrier) GetPendingPrefix() string { + if x != nil { + return x.PendingPrefix + } + return "" +} + +type FactBarrierResolution struct { + state protoimpl.MessageState `protogen:"open.v1"` + Barrier *HardFactBarrier `protobuf:"bytes,1,opt,name=barrier,proto3" json:"barrier,omitempty"` + Affected []string `protobuf:"bytes,2,rep,name=affected,proto3" json:"affected,omitempty"` + Floor uint64 `protobuf:"varint,3,opt,name=floor,proto3" json:"floor,omitempty"` + PreviousPendingPrefix string `protobuf:"bytes,4,opt,name=previous_pending_prefix,json=previousPendingPrefix,proto3" json:"previous_pending_prefix,omitempty"` + RemainingPendingPrefix *string `protobuf:"bytes,5,opt,name=remaining_pending_prefix,json=remainingPendingPrefix,proto3,oneof" json:"remaining_pending_prefix,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FactBarrierResolution) Reset() { + *x = FactBarrierResolution{} + mi := &file_gateway_v1_gateway_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FactBarrierResolution) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FactBarrierResolution) ProtoMessage() {} + +func (x *FactBarrierResolution) ProtoReflect() protoreflect.Message { + mi := &file_gateway_v1_gateway_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FactBarrierResolution.ProtoReflect.Descriptor instead. +func (*FactBarrierResolution) Descriptor() ([]byte, []int) { + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{5} +} + +func (x *FactBarrierResolution) GetBarrier() *HardFactBarrier { + if x != nil { + return x.Barrier + } + return nil +} + +func (x *FactBarrierResolution) GetAffected() []string { + if x != nil { + return x.Affected + } + return nil +} + +func (x *FactBarrierResolution) GetFloor() uint64 { + if x != nil { + return x.Floor + } + return 0 +} + +func (x *FactBarrierResolution) GetPreviousPendingPrefix() string { + if x != nil { + return x.PreviousPendingPrefix + } + return "" +} + +func (x *FactBarrierResolution) GetRemainingPendingPrefix() string { + if x != nil && x.RemainingPendingPrefix != nil { + return *x.RemainingPendingPrefix + } + return "" +} + type GovernanceSelection struct { state protoimpl.MessageState `protogen:"open.v1"` Schema string `protobuf:"bytes,1,opt,name=schema,proto3" json:"schema,omitempty"` @@ -420,7 +672,7 @@ type GovernanceSelection struct { func (x *GovernanceSelection) Reset() { *x = GovernanceSelection{} - mi := &file_gateway_v1_gateway_proto_msgTypes[3] + mi := &file_gateway_v1_gateway_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -432,7 +684,7 @@ func (x *GovernanceSelection) String() string { func (*GovernanceSelection) ProtoMessage() {} func (x *GovernanceSelection) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[3] + mi := &file_gateway_v1_gateway_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -445,7 +697,7 @@ func (x *GovernanceSelection) ProtoReflect() protoreflect.Message { // Deprecated: Use GovernanceSelection.ProtoReflect.Descriptor instead. func (*GovernanceSelection) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{3} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{6} } func (x *GovernanceSelection) GetSchema() string { @@ -481,7 +733,7 @@ type SourceArtifact struct { func (x *SourceArtifact) Reset() { *x = SourceArtifact{} - mi := &file_gateway_v1_gateway_proto_msgTypes[4] + mi := &file_gateway_v1_gateway_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -493,7 +745,7 @@ func (x *SourceArtifact) String() string { func (*SourceArtifact) ProtoMessage() {} func (x *SourceArtifact) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[4] + mi := &file_gateway_v1_gateway_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -506,7 +758,7 @@ func (x *SourceArtifact) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceArtifact.ProtoReflect.Descriptor instead. func (*SourceArtifact) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{4} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{7} } func (x *SourceArtifact) GetGovernance() *GovernanceSelection { @@ -549,7 +801,7 @@ type CompiledSource struct { func (x *CompiledSource) Reset() { *x = CompiledSource{} - mi := &file_gateway_v1_gateway_proto_msgTypes[5] + mi := &file_gateway_v1_gateway_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -561,7 +813,7 @@ func (x *CompiledSource) String() string { func (*CompiledSource) ProtoMessage() {} func (x *CompiledSource) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[5] + mi := &file_gateway_v1_gateway_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -574,7 +826,7 @@ func (x *CompiledSource) ProtoReflect() protoreflect.Message { // Deprecated: Use CompiledSource.ProtoReflect.Descriptor instead. func (*CompiledSource) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{5} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{8} } func (x *CompiledSource) GetProducer() string { @@ -608,7 +860,7 @@ type OperationKey struct { func (x *OperationKey) Reset() { *x = OperationKey{} - mi := &file_gateway_v1_gateway_proto_msgTypes[6] + mi := &file_gateway_v1_gateway_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -620,7 +872,7 @@ func (x *OperationKey) String() string { func (*OperationKey) ProtoMessage() {} func (x *OperationKey) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[6] + mi := &file_gateway_v1_gateway_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -633,7 +885,7 @@ func (x *OperationKey) ProtoReflect() protoreflect.Message { // Deprecated: Use OperationKey.ProtoReflect.Descriptor instead. func (*OperationKey) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{6} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{9} } func (x *OperationKey) GetFamily() string { @@ -660,7 +912,7 @@ type Route struct { func (x *Route) Reset() { *x = Route{} - mi := &file_gateway_v1_gateway_proto_msgTypes[7] + mi := &file_gateway_v1_gateway_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -672,7 +924,7 @@ func (x *Route) String() string { func (*Route) ProtoMessage() {} func (x *Route) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[7] + mi := &file_gateway_v1_gateway_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -685,7 +937,7 @@ func (x *Route) ProtoReflect() protoreflect.Message { // Deprecated: Use Route.ProtoReflect.Descriptor instead. func (*Route) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{7} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{10} } func (x *Route) GetTarget() string { @@ -720,7 +972,7 @@ type ProviderPlan struct { func (x *ProviderPlan) Reset() { *x = ProviderPlan{} - mi := &file_gateway_v1_gateway_proto_msgTypes[8] + mi := &file_gateway_v1_gateway_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -732,7 +984,7 @@ func (x *ProviderPlan) String() string { func (*ProviderPlan) ProtoMessage() {} func (x *ProviderPlan) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[8] + mi := &file_gateway_v1_gateway_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -745,7 +997,7 @@ func (x *ProviderPlan) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderPlan.ProtoReflect.Descriptor instead. func (*ProviderPlan) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{8} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{11} } func (x *ProviderPlan) GetFamily() string { @@ -830,7 +1082,7 @@ type ProviderRequest struct { func (x *ProviderRequest) Reset() { *x = ProviderRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[9] + mi := &file_gateway_v1_gateway_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -842,7 +1094,7 @@ func (x *ProviderRequest) String() string { func (*ProviderRequest) ProtoMessage() {} func (x *ProviderRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[9] + mi := &file_gateway_v1_gateway_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -855,7 +1107,7 @@ func (x *ProviderRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderRequest.ProtoReflect.Descriptor instead. func (*ProviderRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{9} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{12} } func (x *ProviderRequest) GetPlan() *ProviderPlan { @@ -896,7 +1148,7 @@ type ProviderCatalogSnapshot struct { func (x *ProviderCatalogSnapshot) Reset() { *x = ProviderCatalogSnapshot{} - mi := &file_gateway_v1_gateway_proto_msgTypes[10] + mi := &file_gateway_v1_gateway_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -908,7 +1160,7 @@ func (x *ProviderCatalogSnapshot) String() string { func (*ProviderCatalogSnapshot) ProtoMessage() {} func (x *ProviderCatalogSnapshot) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[10] + mi := &file_gateway_v1_gateway_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -921,7 +1173,7 @@ func (x *ProviderCatalogSnapshot) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderCatalogSnapshot.ProtoReflect.Descriptor instead. func (*ProviderCatalogSnapshot) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{10} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{13} } func (x *ProviderCatalogSnapshot) GetVersion() string { @@ -947,7 +1199,7 @@ type ProviderCatalogChange struct { func (x *ProviderCatalogChange) Reset() { *x = ProviderCatalogChange{} - mi := &file_gateway_v1_gateway_proto_msgTypes[11] + mi := &file_gateway_v1_gateway_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -959,7 +1211,7 @@ func (x *ProviderCatalogChange) String() string { func (*ProviderCatalogChange) ProtoMessage() {} func (x *ProviderCatalogChange) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[11] + mi := &file_gateway_v1_gateway_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -972,7 +1224,7 @@ func (x *ProviderCatalogChange) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderCatalogChange.ProtoReflect.Descriptor instead. func (*ProviderCatalogChange) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{11} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{14} } func (x *ProviderCatalogChange) GetRecord() []byte { @@ -994,7 +1246,7 @@ type Event struct { func (x *Event) Reset() { *x = Event{} - mi := &file_gateway_v1_gateway_proto_msgTypes[12] + mi := &file_gateway_v1_gateway_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1006,7 +1258,7 @@ func (x *Event) String() string { func (*Event) ProtoMessage() {} func (x *Event) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[12] + mi := &file_gateway_v1_gateway_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1019,7 +1271,7 @@ func (x *Event) ProtoReflect() protoreflect.Message { // Deprecated: Use Event.ProtoReflect.Descriptor instead. func (*Event) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{12} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{15} } func (x *Event) GetSequence() uint64 { @@ -1061,7 +1313,7 @@ type ArrowBatch struct { func (x *ArrowBatch) Reset() { *x = ArrowBatch{} - mi := &file_gateway_v1_gateway_proto_msgTypes[13] + mi := &file_gateway_v1_gateway_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1073,7 +1325,7 @@ func (x *ArrowBatch) String() string { func (*ArrowBatch) ProtoMessage() {} func (x *ArrowBatch) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[13] + mi := &file_gateway_v1_gateway_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1086,7 +1338,7 @@ func (x *ArrowBatch) ProtoReflect() protoreflect.Message { // Deprecated: Use ArrowBatch.ProtoReflect.Descriptor instead. func (*ArrowBatch) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{13} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{16} } func (x *ArrowBatch) GetIpc() []byte { @@ -1125,7 +1377,7 @@ type ProviderFrame struct { func (x *ProviderFrame) Reset() { *x = ProviderFrame{} - mi := &file_gateway_v1_gateway_proto_msgTypes[14] + mi := &file_gateway_v1_gateway_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1137,7 +1389,7 @@ func (x *ProviderFrame) String() string { func (*ProviderFrame) ProtoMessage() {} func (x *ProviderFrame) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[14] + mi := &file_gateway_v1_gateway_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1150,7 +1402,7 @@ func (x *ProviderFrame) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderFrame.ProtoReflect.Descriptor instead. func (*ProviderFrame) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{14} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{17} } func (x *ProviderFrame) GetTarget() string { @@ -1224,7 +1476,7 @@ type ProviderReceipt struct { func (x *ProviderReceipt) Reset() { *x = ProviderReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[15] + mi := &file_gateway_v1_gateway_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1236,7 +1488,7 @@ func (x *ProviderReceipt) String() string { func (*ProviderReceipt) ProtoMessage() {} func (x *ProviderReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[15] + mi := &file_gateway_v1_gateway_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1249,7 +1501,7 @@ func (x *ProviderReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderReceipt.ProtoReflect.Descriptor instead. func (*ProviderReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{15} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{18} } func (x *ProviderReceipt) GetFamily() string { @@ -1328,7 +1580,7 @@ type Task struct { func (x *Task) Reset() { *x = Task{} - mi := &file_gateway_v1_gateway_proto_msgTypes[16] + mi := &file_gateway_v1_gateway_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1340,7 +1592,7 @@ func (x *Task) String() string { func (*Task) ProtoMessage() {} func (x *Task) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[16] + mi := &file_gateway_v1_gateway_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1353,7 +1605,7 @@ func (x *Task) ProtoReflect() protoreflect.Message { // Deprecated: Use Task.ProtoReflect.Descriptor instead. func (*Task) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{16} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{19} } func (x *Task) GetFamily() string { @@ -1453,7 +1705,7 @@ type ProviderProfile struct { func (x *ProviderProfile) Reset() { *x = ProviderProfile{} - mi := &file_gateway_v1_gateway_proto_msgTypes[17] + mi := &file_gateway_v1_gateway_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1465,7 +1717,7 @@ func (x *ProviderProfile) String() string { func (*ProviderProfile) ProtoMessage() {} func (x *ProviderProfile) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[17] + mi := &file_gateway_v1_gateway_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1478,7 +1730,7 @@ func (x *ProviderProfile) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderProfile.ProtoReflect.Descriptor instead. func (*ProviderProfile) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{17} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{20} } func (x *ProviderProfile) GetId() string { @@ -1525,7 +1777,7 @@ type RegisterTaskRequest struct { func (x *RegisterTaskRequest) Reset() { *x = RegisterTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[18] + mi := &file_gateway_v1_gateway_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1537,7 +1789,7 @@ func (x *RegisterTaskRequest) String() string { func (*RegisterTaskRequest) ProtoMessage() {} func (x *RegisterTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[18] + mi := &file_gateway_v1_gateway_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1550,7 +1802,7 @@ func (x *RegisterTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{18} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{21} } func (x *RegisterTaskRequest) GetTask() *Task { @@ -1572,7 +1824,7 @@ type DomainBinding struct { func (x *DomainBinding) Reset() { *x = DomainBinding{} - mi := &file_gateway_v1_gateway_proto_msgTypes[19] + mi := &file_gateway_v1_gateway_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1584,7 +1836,7 @@ func (x *DomainBinding) String() string { func (*DomainBinding) ProtoMessage() {} func (x *DomainBinding) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[19] + mi := &file_gateway_v1_gateway_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1597,7 +1849,7 @@ func (x *DomainBinding) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainBinding.ProtoReflect.Descriptor instead. func (*DomainBinding) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{19} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{22} } func (x *DomainBinding) GetOrigin() string { @@ -1642,7 +1894,7 @@ type DomainStamp struct { func (x *DomainStamp) Reset() { *x = DomainStamp{} - mi := &file_gateway_v1_gateway_proto_msgTypes[20] + mi := &file_gateway_v1_gateway_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1654,7 +1906,7 @@ func (x *DomainStamp) String() string { func (*DomainStamp) ProtoMessage() {} func (x *DomainStamp) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[20] + mi := &file_gateway_v1_gateway_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1667,7 +1919,7 @@ func (x *DomainStamp) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainStamp.ProtoReflect.Descriptor instead. func (*DomainStamp) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{20} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{23} } func (x *DomainStamp) GetOrigin() string { @@ -1726,7 +1978,7 @@ type DomainView struct { func (x *DomainView) Reset() { *x = DomainView{} - mi := &file_gateway_v1_gateway_proto_msgTypes[21] + mi := &file_gateway_v1_gateway_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1738,7 +1990,7 @@ func (x *DomainView) String() string { func (*DomainView) ProtoMessage() {} func (x *DomainView) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[21] + mi := &file_gateway_v1_gateway_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1751,7 +2003,7 @@ func (x *DomainView) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainView.ProtoReflect.Descriptor instead. func (*DomainView) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{21} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{24} } func (x *DomainView) GetFamily() string { @@ -1807,7 +2059,7 @@ type RegisterDomainTaskRequest struct { func (x *RegisterDomainTaskRequest) Reset() { *x = RegisterDomainTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[22] + mi := &file_gateway_v1_gateway_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1819,7 +2071,7 @@ func (x *RegisterDomainTaskRequest) String() string { func (*RegisterDomainTaskRequest) ProtoMessage() {} func (x *RegisterDomainTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[22] + mi := &file_gateway_v1_gateway_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1832,7 +2084,7 @@ func (x *RegisterDomainTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterDomainTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterDomainTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{22} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{25} } func (x *RegisterDomainTaskRequest) GetTask() *Task { @@ -1867,7 +2119,7 @@ type TaskAdmission struct { func (x *TaskAdmission) Reset() { *x = TaskAdmission{} - mi := &file_gateway_v1_gateway_proto_msgTypes[23] + mi := &file_gateway_v1_gateway_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1879,7 +2131,7 @@ func (x *TaskAdmission) String() string { func (*TaskAdmission) ProtoMessage() {} func (x *TaskAdmission) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[23] + mi := &file_gateway_v1_gateway_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1892,7 +2144,7 @@ func (x *TaskAdmission) ProtoReflect() protoreflect.Message { // Deprecated: Use TaskAdmission.ProtoReflect.Descriptor instead. func (*TaskAdmission) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{23} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{26} } func (x *TaskAdmission) GetTaskKey() string { @@ -1928,7 +2180,7 @@ type RegisterOriginalTaskRequest struct { func (x *RegisterOriginalTaskRequest) Reset() { *x = RegisterOriginalTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[24] + mi := &file_gateway_v1_gateway_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1940,7 +2192,7 @@ func (x *RegisterOriginalTaskRequest) String() string { func (*RegisterOriginalTaskRequest) ProtoMessage() {} func (x *RegisterOriginalTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[24] + mi := &file_gateway_v1_gateway_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1953,7 +2205,7 @@ func (x *RegisterOriginalTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterOriginalTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterOriginalTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{24} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{27} } func (x *RegisterOriginalTaskRequest) GetTask() *Task { @@ -1998,7 +2250,7 @@ type TaskAdmissionReceipt struct { func (x *TaskAdmissionReceipt) Reset() { *x = TaskAdmissionReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[25] + mi := &file_gateway_v1_gateway_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2010,7 +2262,7 @@ func (x *TaskAdmissionReceipt) String() string { func (*TaskAdmissionReceipt) ProtoMessage() {} func (x *TaskAdmissionReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[25] + mi := &file_gateway_v1_gateway_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2023,7 +2275,7 @@ func (x *TaskAdmissionReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use TaskAdmissionReceipt.ProtoReflect.Descriptor instead. func (*TaskAdmissionReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{25} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{28} } func (x *TaskAdmissionReceipt) GetOperationId() string { @@ -2078,7 +2330,7 @@ type FamilyAliasRequest struct { func (x *FamilyAliasRequest) Reset() { *x = FamilyAliasRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[26] + mi := &file_gateway_v1_gateway_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2090,7 +2342,7 @@ func (x *FamilyAliasRequest) String() string { func (*FamilyAliasRequest) ProtoMessage() {} func (x *FamilyAliasRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[26] + mi := &file_gateway_v1_gateway_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2103,7 +2355,7 @@ func (x *FamilyAliasRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FamilyAliasRequest.ProtoReflect.Descriptor instead. func (*FamilyAliasRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{26} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{29} } func (x *FamilyAliasRequest) GetFamily() string { @@ -2137,7 +2389,7 @@ type DomainMigration struct { func (x *DomainMigration) Reset() { *x = DomainMigration{} - mi := &file_gateway_v1_gateway_proto_msgTypes[27] + mi := &file_gateway_v1_gateway_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2149,7 +2401,7 @@ func (x *DomainMigration) String() string { func (*DomainMigration) ProtoMessage() {} func (x *DomainMigration) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[27] + mi := &file_gateway_v1_gateway_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2162,7 +2414,7 @@ func (x *DomainMigration) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainMigration.ProtoReflect.Descriptor instead. func (*DomainMigration) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{27} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{30} } func (x *DomainMigration) GetOperationId() string { @@ -2243,7 +2495,7 @@ type DomainMigrationReceipt struct { func (x *DomainMigrationReceipt) Reset() { *x = DomainMigrationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[28] + mi := &file_gateway_v1_gateway_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2255,7 +2507,7 @@ func (x *DomainMigrationReceipt) String() string { func (*DomainMigrationReceipt) ProtoMessage() {} func (x *DomainMigrationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[28] + mi := &file_gateway_v1_gateway_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2268,7 +2520,7 @@ func (x *DomainMigrationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainMigrationReceipt.ProtoReflect.Descriptor instead. func (*DomainMigrationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{28} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{31} } func (x *DomainMigrationReceipt) GetOperationId() string { @@ -2331,7 +2583,7 @@ type RegisterPublishedTaskRequest struct { func (x *RegisterPublishedTaskRequest) Reset() { *x = RegisterPublishedTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[29] + mi := &file_gateway_v1_gateway_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2343,7 +2595,7 @@ func (x *RegisterPublishedTaskRequest) String() string { func (*RegisterPublishedTaskRequest) ProtoMessage() {} func (x *RegisterPublishedTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[29] + mi := &file_gateway_v1_gateway_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2356,7 +2608,7 @@ func (x *RegisterPublishedTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterPublishedTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterPublishedTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{29} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{32} } func (x *RegisterPublishedTaskRequest) GetTask() *Task { @@ -2386,7 +2638,7 @@ type PublishRequest struct { func (x *PublishRequest) Reset() { *x = PublishRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[30] + mi := &file_gateway_v1_gateway_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2398,7 +2650,7 @@ func (x *PublishRequest) String() string { func (*PublishRequest) ProtoMessage() {} func (x *PublishRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[30] + mi := &file_gateway_v1_gateway_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2411,7 +2663,7 @@ func (x *PublishRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PublishRequest.ProtoReflect.Descriptor instead. func (*PublishRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{30} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{33} } func (x *PublishRequest) GetExpectedRevision() uint64 { @@ -2462,7 +2714,7 @@ type PublicationReceipt struct { func (x *PublicationReceipt) Reset() { *x = PublicationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[31] + mi := &file_gateway_v1_gateway_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2474,7 +2726,7 @@ func (x *PublicationReceipt) String() string { func (*PublicationReceipt) ProtoMessage() {} func (x *PublicationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[31] + mi := &file_gateway_v1_gateway_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2487,7 +2739,7 @@ func (x *PublicationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationReceipt.ProtoReflect.Descriptor instead. func (*PublicationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{31} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{34} } func (x *PublicationReceipt) GetOperationId() string { @@ -2535,7 +2787,7 @@ type PublicationKey struct { func (x *PublicationKey) Reset() { *x = PublicationKey{} - mi := &file_gateway_v1_gateway_proto_msgTypes[32] + mi := &file_gateway_v1_gateway_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2547,7 +2799,7 @@ func (x *PublicationKey) String() string { func (*PublicationKey) ProtoMessage() {} func (x *PublicationKey) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[32] + mi := &file_gateway_v1_gateway_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2560,7 +2812,7 @@ func (x *PublicationKey) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationKey.ProtoReflect.Descriptor instead. func (*PublicationKey) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{32} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{35} } func (x *PublicationKey) GetOperationId() string { @@ -2587,7 +2839,7 @@ type SourceAuthorityView struct { func (x *SourceAuthorityView) Reset() { *x = SourceAuthorityView{} - mi := &file_gateway_v1_gateway_proto_msgTypes[33] + mi := &file_gateway_v1_gateway_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2599,7 +2851,7 @@ func (x *SourceAuthorityView) String() string { func (*SourceAuthorityView) ProtoMessage() {} func (x *SourceAuthorityView) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[33] + mi := &file_gateway_v1_gateway_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2612,7 +2864,7 @@ func (x *SourceAuthorityView) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceAuthorityView.ProtoReflect.Descriptor instead. func (*SourceAuthorityView) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{33} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{36} } func (x *SourceAuthorityView) GetEpoch() uint64 { @@ -2642,7 +2894,7 @@ type SourceRotationRequest struct { func (x *SourceRotationRequest) Reset() { *x = SourceRotationRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[34] + mi := &file_gateway_v1_gateway_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2654,7 +2906,7 @@ func (x *SourceRotationRequest) String() string { func (*SourceRotationRequest) ProtoMessage() {} func (x *SourceRotationRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[34] + mi := &file_gateway_v1_gateway_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2667,7 +2919,7 @@ func (x *SourceRotationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceRotationRequest.ProtoReflect.Descriptor instead. func (*SourceRotationRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{34} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{37} } func (x *SourceRotationRequest) GetOperationId() string { @@ -2710,7 +2962,7 @@ type SourceRotationReceipt struct { func (x *SourceRotationReceipt) Reset() { *x = SourceRotationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[35] + mi := &file_gateway_v1_gateway_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2722,7 +2974,7 @@ func (x *SourceRotationReceipt) String() string { func (*SourceRotationReceipt) ProtoMessage() {} func (x *SourceRotationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[35] + mi := &file_gateway_v1_gateway_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2735,7 +2987,7 @@ func (x *SourceRotationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceRotationReceipt.ProtoReflect.Descriptor instead. func (*SourceRotationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{35} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{38} } func (x *SourceRotationReceipt) GetOperationId() string { @@ -2779,7 +3031,7 @@ type AuthorityParent struct { func (x *AuthorityParent) Reset() { *x = AuthorityParent{} - mi := &file_gateway_v1_gateway_proto_msgTypes[36] + mi := &file_gateway_v1_gateway_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2791,7 +3043,7 @@ func (x *AuthorityParent) String() string { func (*AuthorityParent) ProtoMessage() {} func (x *AuthorityParent) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[36] + mi := &file_gateway_v1_gateway_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2804,7 +3056,7 @@ func (x *AuthorityParent) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthorityParent.ProtoReflect.Descriptor instead. func (*AuthorityParent) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{36} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{39} } func (x *AuthorityParent) GetRevision() uint64 { @@ -2848,7 +3100,7 @@ type ReviewAuthority struct { func (x *ReviewAuthority) Reset() { *x = ReviewAuthority{} - mi := &file_gateway_v1_gateway_proto_msgTypes[37] + mi := &file_gateway_v1_gateway_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2860,7 +3112,7 @@ func (x *ReviewAuthority) String() string { func (*ReviewAuthority) ProtoMessage() {} func (x *ReviewAuthority) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[37] + mi := &file_gateway_v1_gateway_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2873,7 +3125,7 @@ func (x *ReviewAuthority) ProtoReflect() protoreflect.Message { // Deprecated: Use ReviewAuthority.ProtoReflect.Descriptor instead. func (*ReviewAuthority) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{37} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{40} } func (x *ReviewAuthority) GetAudience() string { @@ -2922,7 +3174,7 @@ type PublicationReview struct { func (x *PublicationReview) Reset() { *x = PublicationReview{} - mi := &file_gateway_v1_gateway_proto_msgTypes[38] + mi := &file_gateway_v1_gateway_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2934,7 +3186,7 @@ func (x *PublicationReview) String() string { func (*PublicationReview) ProtoMessage() {} func (x *PublicationReview) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[38] + mi := &file_gateway_v1_gateway_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2947,7 +3199,7 @@ func (x *PublicationReview) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationReview.ProtoReflect.Descriptor instead. func (*PublicationReview) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{38} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{41} } func (x *PublicationReview) GetPublication() *PublicationKey { @@ -2987,7 +3239,7 @@ type DeltaReview struct { func (x *DeltaReview) Reset() { *x = DeltaReview{} - mi := &file_gateway_v1_gateway_proto_msgTypes[39] + mi := &file_gateway_v1_gateway_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2999,7 +3251,7 @@ func (x *DeltaReview) String() string { func (*DeltaReview) ProtoMessage() {} func (x *DeltaReview) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[39] + mi := &file_gateway_v1_gateway_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3012,7 +3264,7 @@ func (x *DeltaReview) ProtoReflect() protoreflect.Message { // Deprecated: Use DeltaReview.ProtoReflect.Descriptor instead. func (*DeltaReview) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{39} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{42} } func (x *DeltaReview) GetReview() *PublicationReview { @@ -3083,7 +3335,7 @@ type PublicationReviewContext struct { func (x *PublicationReviewContext) Reset() { *x = PublicationReviewContext{} - mi := &file_gateway_v1_gateway_proto_msgTypes[40] + mi := &file_gateway_v1_gateway_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3095,7 +3347,7 @@ func (x *PublicationReviewContext) String() string { func (*PublicationReviewContext) ProtoMessage() {} func (x *PublicationReviewContext) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[40] + mi := &file_gateway_v1_gateway_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3108,7 +3360,7 @@ func (x *PublicationReviewContext) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationReviewContext.ProtoReflect.Descriptor instead. func (*PublicationReviewContext) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{40} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{43} } func (x *PublicationReviewContext) GetPublication() *PublicationKey { @@ -3149,7 +3401,7 @@ type ReviewRegistrationReceipt struct { func (x *ReviewRegistrationReceipt) Reset() { *x = ReviewRegistrationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[41] + mi := &file_gateway_v1_gateway_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3161,7 +3413,7 @@ func (x *ReviewRegistrationReceipt) String() string { func (*ReviewRegistrationReceipt) ProtoMessage() {} func (x *ReviewRegistrationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[41] + mi := &file_gateway_v1_gateway_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3174,7 +3426,7 @@ func (x *ReviewRegistrationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use ReviewRegistrationReceipt.ProtoReflect.Descriptor instead. func (*ReviewRegistrationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{41} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{44} } func (x *ReviewRegistrationReceipt) GetPublication() *PublicationKey { @@ -3204,7 +3456,7 @@ type MeterCredentialRotation struct { func (x *MeterCredentialRotation) Reset() { *x = MeterCredentialRotation{} - mi := &file_gateway_v1_gateway_proto_msgTypes[42] + mi := &file_gateway_v1_gateway_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3216,7 +3468,7 @@ func (x *MeterCredentialRotation) String() string { func (*MeterCredentialRotation) ProtoMessage() {} func (x *MeterCredentialRotation) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[42] + mi := &file_gateway_v1_gateway_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3229,7 +3481,7 @@ func (x *MeterCredentialRotation) ProtoReflect() protoreflect.Message { // Deprecated: Use MeterCredentialRotation.ProtoReflect.Descriptor instead. func (*MeterCredentialRotation) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{42} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{45} } func (x *MeterCredentialRotation) GetTenant() string { @@ -3276,7 +3528,7 @@ type MeterCredentialEpoch struct { func (x *MeterCredentialEpoch) Reset() { *x = MeterCredentialEpoch{} - mi := &file_gateway_v1_gateway_proto_msgTypes[43] + mi := &file_gateway_v1_gateway_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3288,7 +3540,7 @@ func (x *MeterCredentialEpoch) String() string { func (*MeterCredentialEpoch) ProtoMessage() {} func (x *MeterCredentialEpoch) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[43] + mi := &file_gateway_v1_gateway_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3301,7 +3553,7 @@ func (x *MeterCredentialEpoch) ProtoReflect() protoreflect.Message { // Deprecated: Use MeterCredentialEpoch.ProtoReflect.Descriptor instead. func (*MeterCredentialEpoch) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{43} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{46} } func (x *MeterCredentialEpoch) GetEpoch() uint64 { @@ -3332,7 +3584,7 @@ type MeteringReceipt struct { func (x *MeteringReceipt) Reset() { *x = MeteringReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[44] + mi := &file_gateway_v1_gateway_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3344,7 +3596,7 @@ func (x *MeteringReceipt) String() string { func (*MeteringReceipt) ProtoMessage() {} func (x *MeteringReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[44] + mi := &file_gateway_v1_gateway_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3357,7 +3609,7 @@ func (x *MeteringReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use MeteringReceipt.ProtoReflect.Descriptor instead. func (*MeteringReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{44} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{47} } func (x *MeteringReceipt) GetAudience() string { @@ -3462,7 +3714,7 @@ type MeteringApplication struct { func (x *MeteringApplication) Reset() { *x = MeteringApplication{} - mi := &file_gateway_v1_gateway_proto_msgTypes[45] + mi := &file_gateway_v1_gateway_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3474,7 +3726,7 @@ func (x *MeteringApplication) String() string { func (*MeteringApplication) ProtoMessage() {} func (x *MeteringApplication) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[45] + mi := &file_gateway_v1_gateway_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3487,7 +3739,7 @@ func (x *MeteringApplication) ProtoReflect() protoreflect.Message { // Deprecated: Use MeteringApplication.ProtoReflect.Descriptor instead. func (*MeteringApplication) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{45} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{48} } func (x *MeteringApplication) GetApplication() string { @@ -3525,7 +3777,7 @@ type ProviderOAuthChange struct { func (x *ProviderOAuthChange) Reset() { *x = ProviderOAuthChange{} - mi := &file_gateway_v1_gateway_proto_msgTypes[46] + mi := &file_gateway_v1_gateway_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3537,7 +3789,7 @@ func (x *ProviderOAuthChange) String() string { func (*ProviderOAuthChange) ProtoMessage() {} func (x *ProviderOAuthChange) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[46] + mi := &file_gateway_v1_gateway_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3550,7 +3802,7 @@ func (x *ProviderOAuthChange) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderOAuthChange.ProtoReflect.Descriptor instead. func (*ProviderOAuthChange) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{46} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{49} } func (x *ProviderOAuthChange) GetAction() isProviderOAuthChange_Action { @@ -3629,7 +3881,7 @@ type ProviderOAuthGrant struct { func (x *ProviderOAuthGrant) Reset() { *x = ProviderOAuthGrant{} - mi := &file_gateway_v1_gateway_proto_msgTypes[47] + mi := &file_gateway_v1_gateway_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3641,7 +3893,7 @@ func (x *ProviderOAuthGrant) String() string { func (*ProviderOAuthGrant) ProtoMessage() {} func (x *ProviderOAuthGrant) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[47] + mi := &file_gateway_v1_gateway_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3654,7 +3906,7 @@ func (x *ProviderOAuthGrant) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderOAuthGrant.ProtoReflect.Descriptor instead. func (*ProviderOAuthGrant) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{47} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{50} } func (x *ProviderOAuthGrant) GetIssuer() string { @@ -3752,7 +4004,7 @@ type ProviderOAuthIssuerRotation struct { func (x *ProviderOAuthIssuerRotation) Reset() { *x = ProviderOAuthIssuerRotation{} - mi := &file_gateway_v1_gateway_proto_msgTypes[48] + mi := &file_gateway_v1_gateway_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3764,7 +4016,7 @@ func (x *ProviderOAuthIssuerRotation) String() string { func (*ProviderOAuthIssuerRotation) ProtoMessage() {} func (x *ProviderOAuthIssuerRotation) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[48] + mi := &file_gateway_v1_gateway_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3777,7 +4029,7 @@ func (x *ProviderOAuthIssuerRotation) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderOAuthIssuerRotation.ProtoReflect.Descriptor instead. func (*ProviderOAuthIssuerRotation) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{48} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{51} } func (x *ProviderOAuthIssuerRotation) GetExpectedEpoch() uint64 { @@ -3818,7 +4070,31 @@ const file_gateway_v1_gateway_proto_rawDesc = "" + "\x0esnapshot_reads\x18\t \x01(\x04R\rsnapshotReads\"\a\n" + "\x05Empty\"-\n" + "\x0fProducerRequest\x12\x1a\n" + - "\bproducer\x18\x01 \x01(\tR\bproducer\"d\n" + + "\bproducer\x18\x01 \x01(\tR\bproducer\"\x8f\x02\n" + + "\x0eHardFactIntent\x12!\n" + + "\foperation_id\x18\x01 \x01(\tR\voperationId\x12\x16\n" + + "\x06domain\x18\x02 \x01(\tR\x06domain\x12!\n" + + "\fsource_epoch\x18\x03 \x01(\x04R\vsourceEpoch\x12\x1a\n" + + "\brevision\x18\x04 \x01(\x04R\brevision\x12+\n" + + "\x11previous_snapshot\x18\x05 \x01(\tR\x10previousSnapshot\x12%\n" + + "\x0eexpected_floor\x18\x06 \x01(\x04R\rexpectedFloor\x12!\n" + + "\tavailable\x18\a \x01(\bH\x00R\tavailable\x88\x01\x01B\f\n" + + "\n" + + "_available\"\xcc\x01\n" + + "\x0fHardFactBarrier\x12!\n" + + "\foperation_id\x18\x01 \x01(\tR\voperationId\x12!\n" + + "\fsource_epoch\x18\x02 \x01(\x04R\vsourceEpoch\x12\x1a\n" + + "\brevision\x18\x03 \x01(\x04R\brevision\x12\x1a\n" + + "\bsnapshot\x18\x04 \x01(\tR\bsnapshot\x12\x14\n" + + "\x05floor\x18\x05 \x01(\x04R\x05floor\x12%\n" + + "\x0epending_prefix\x18\x06 \x01(\tR\rpendingPrefix\"\x9b\x02\n" + + "\x15FactBarrierResolution\x12<\n" + + "\abarrier\x18\x01 \x01(\v2\".weaver.gateway.v1.HardFactBarrierR\abarrier\x12\x1a\n" + + "\baffected\x18\x02 \x03(\tR\baffected\x12\x14\n" + + "\x05floor\x18\x03 \x01(\x04R\x05floor\x126\n" + + "\x17previous_pending_prefix\x18\x04 \x01(\tR\x15previousPendingPrefix\x12=\n" + + "\x18remaining_pending_prefix\x18\x05 \x01(\tH\x00R\x16remainingPendingPrefix\x88\x01\x01B\x1b\n" + + "\x19_remaining_pending_prefix\"d\n" + "\x13GovernanceSelection\x12\x16\n" + "\x06schema\x18\x01 \x01(\tR\x06schema\x12\x16\n" + "\x06family\x18\x02 \x01(\tR\x06family\x12\x1d\n" + @@ -4127,7 +4403,7 @@ const file_gateway_v1_gateway_proto_rawDesc = "" + "\x1dDELTA_DISPOSITION_UNSPECIFIED\x10\x00\x12\r\n" + "\tBOOTSTRAP\x10\x01\x12\x15\n" + "\x11NO_EXECUTION_GAIN\x10\x02\x12\x15\n" + - "\x11EXPLICIT_APPROVAL\x10\x032\xee\x12\n" + + "\x11EXPLICIT_APPROVAL\x10\x032\xa7\x14\n" + "\aGateway\x12Y\n" + "\x0fExecuteProvider\x12\".weaver.gateway.v1.ProviderRequest\x1a .weaver.gateway.v1.ProviderFrame0\x01\x12N\n" + "\aInspect\x12\x1f.weaver.gateway.v1.OperationKey\x1a\".weaver.gateway.v1.ProviderReceipt\x12l\n" + @@ -4149,6 +4425,8 @@ const file_gateway_v1_gateway_proto_rawDesc = "" + "\x19RegisterPublicationReview\x12\x1e.weaver.gateway.v1.DeltaReview\x1a,.weaver.gateway.v1.ReviewRegistrationReceipt\x12Z\n" + "\x16InspectSourceAuthority\x12\x18.weaver.gateway.v1.Empty\x1a&.weaver.gateway.v1.SourceAuthorityView\x12k\n" + "\x15RotateSourceAuthority\x12(.weaver.gateway.v1.SourceRotationRequest\x1a(.weaver.gateway.v1.SourceRotationReceipt\x12V\n" + + "\rStageHardFact\x12!.weaver.gateway.v1.HardFactIntent\x1a\".weaver.gateway.v1.HardFactBarrier\x12_\n" + + "\x0fResolveHardFact\x12\".weaver.gateway.v1.HardFactBarrier\x1a(.weaver.gateway.v1.FactBarrierResolution\x12V\n" + "\rCompileSource\x12\".weaver.gateway.v1.ProducerRequest\x1a!.weaver.gateway.v1.CompiledSource\x12^\n" + "\x16InspectProviderCatalog\x12\x18.weaver.gateway.v1.Empty\x1a*.weaver.gateway.v1.ProviderCatalogSnapshot\x12n\n" + "\x16PublishProviderCatalog\x12(.weaver.gateway.v1.ProviderCatalogChange\x1a*.weaver.gateway.v1.ProviderCatalogSnapshot\x12R\n" + @@ -4168,7 +4446,7 @@ func file_gateway_v1_gateway_proto_rawDescGZIP() []byte { } var file_gateway_v1_gateway_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_gateway_v1_gateway_proto_msgTypes = make([]protoimpl.MessageInfo, 53) +var file_gateway_v1_gateway_proto_msgTypes = make([]protoimpl.MessageInfo, 56) var file_gateway_v1_gateway_proto_goTypes = []any{ (Encoding)(0), // 0: weaver.gateway.v1.Encoding (PublicationOutcome)(0), // 1: weaver.gateway.v1.PublicationOutcome @@ -4177,154 +4455,162 @@ var file_gateway_v1_gateway_proto_goTypes = []any{ (*TelemetrySnapshot)(nil), // 4: weaver.gateway.v1.TelemetrySnapshot (*Empty)(nil), // 5: weaver.gateway.v1.Empty (*ProducerRequest)(nil), // 6: weaver.gateway.v1.ProducerRequest - (*GovernanceSelection)(nil), // 7: weaver.gateway.v1.GovernanceSelection - (*SourceArtifact)(nil), // 8: weaver.gateway.v1.SourceArtifact - (*CompiledSource)(nil), // 9: weaver.gateway.v1.CompiledSource - (*OperationKey)(nil), // 10: weaver.gateway.v1.OperationKey - (*Route)(nil), // 11: weaver.gateway.v1.Route - (*ProviderPlan)(nil), // 12: weaver.gateway.v1.ProviderPlan - (*ProviderRequest)(nil), // 13: weaver.gateway.v1.ProviderRequest - (*ProviderCatalogSnapshot)(nil), // 14: weaver.gateway.v1.ProviderCatalogSnapshot - (*ProviderCatalogChange)(nil), // 15: weaver.gateway.v1.ProviderCatalogChange - (*Event)(nil), // 16: weaver.gateway.v1.Event - (*ArrowBatch)(nil), // 17: weaver.gateway.v1.ArrowBatch - (*ProviderFrame)(nil), // 18: weaver.gateway.v1.ProviderFrame - (*ProviderReceipt)(nil), // 19: weaver.gateway.v1.ProviderReceipt - (*Task)(nil), // 20: weaver.gateway.v1.Task - (*ProviderProfile)(nil), // 21: weaver.gateway.v1.ProviderProfile - (*RegisterTaskRequest)(nil), // 22: weaver.gateway.v1.RegisterTaskRequest - (*DomainBinding)(nil), // 23: weaver.gateway.v1.DomainBinding - (*DomainStamp)(nil), // 24: weaver.gateway.v1.DomainStamp - (*DomainView)(nil), // 25: weaver.gateway.v1.DomainView - (*RegisterDomainTaskRequest)(nil), // 26: weaver.gateway.v1.RegisterDomainTaskRequest - (*TaskAdmission)(nil), // 27: weaver.gateway.v1.TaskAdmission - (*RegisterOriginalTaskRequest)(nil), // 28: weaver.gateway.v1.RegisterOriginalTaskRequest - (*TaskAdmissionReceipt)(nil), // 29: weaver.gateway.v1.TaskAdmissionReceipt - (*FamilyAliasRequest)(nil), // 30: weaver.gateway.v1.FamilyAliasRequest - (*DomainMigration)(nil), // 31: weaver.gateway.v1.DomainMigration - (*DomainMigrationReceipt)(nil), // 32: weaver.gateway.v1.DomainMigrationReceipt - (*RegisterPublishedTaskRequest)(nil), // 33: weaver.gateway.v1.RegisterPublishedTaskRequest - (*PublishRequest)(nil), // 34: weaver.gateway.v1.PublishRequest - (*PublicationReceipt)(nil), // 35: weaver.gateway.v1.PublicationReceipt - (*PublicationKey)(nil), // 36: weaver.gateway.v1.PublicationKey - (*SourceAuthorityView)(nil), // 37: weaver.gateway.v1.SourceAuthorityView - (*SourceRotationRequest)(nil), // 38: weaver.gateway.v1.SourceRotationRequest - (*SourceRotationReceipt)(nil), // 39: weaver.gateway.v1.SourceRotationReceipt - (*AuthorityParent)(nil), // 40: weaver.gateway.v1.AuthorityParent - (*ReviewAuthority)(nil), // 41: weaver.gateway.v1.ReviewAuthority - (*PublicationReview)(nil), // 42: weaver.gateway.v1.PublicationReview - (*DeltaReview)(nil), // 43: weaver.gateway.v1.DeltaReview - (*PublicationReviewContext)(nil), // 44: weaver.gateway.v1.PublicationReviewContext - (*ReviewRegistrationReceipt)(nil), // 45: weaver.gateway.v1.ReviewRegistrationReceipt - (*MeterCredentialRotation)(nil), // 46: weaver.gateway.v1.MeterCredentialRotation - (*MeterCredentialEpoch)(nil), // 47: weaver.gateway.v1.MeterCredentialEpoch - (*MeteringReceipt)(nil), // 48: weaver.gateway.v1.MeteringReceipt - (*MeteringApplication)(nil), // 49: weaver.gateway.v1.MeteringApplication - (*ProviderOAuthChange)(nil), // 50: weaver.gateway.v1.ProviderOAuthChange - (*ProviderOAuthGrant)(nil), // 51: weaver.gateway.v1.ProviderOAuthGrant - (*ProviderOAuthIssuerRotation)(nil), // 52: weaver.gateway.v1.ProviderOAuthIssuerRotation - nil, // 53: weaver.gateway.v1.Task.EndpointsEntry - nil, // 54: weaver.gateway.v1.Task.BodyDigestsEntry - nil, // 55: weaver.gateway.v1.Task.NodeCostBoundsEntry - nil, // 56: weaver.gateway.v1.Task.StreamContractsEntry + (*HardFactIntent)(nil), // 7: weaver.gateway.v1.HardFactIntent + (*HardFactBarrier)(nil), // 8: weaver.gateway.v1.HardFactBarrier + (*FactBarrierResolution)(nil), // 9: weaver.gateway.v1.FactBarrierResolution + (*GovernanceSelection)(nil), // 10: weaver.gateway.v1.GovernanceSelection + (*SourceArtifact)(nil), // 11: weaver.gateway.v1.SourceArtifact + (*CompiledSource)(nil), // 12: weaver.gateway.v1.CompiledSource + (*OperationKey)(nil), // 13: weaver.gateway.v1.OperationKey + (*Route)(nil), // 14: weaver.gateway.v1.Route + (*ProviderPlan)(nil), // 15: weaver.gateway.v1.ProviderPlan + (*ProviderRequest)(nil), // 16: weaver.gateway.v1.ProviderRequest + (*ProviderCatalogSnapshot)(nil), // 17: weaver.gateway.v1.ProviderCatalogSnapshot + (*ProviderCatalogChange)(nil), // 18: weaver.gateway.v1.ProviderCatalogChange + (*Event)(nil), // 19: weaver.gateway.v1.Event + (*ArrowBatch)(nil), // 20: weaver.gateway.v1.ArrowBatch + (*ProviderFrame)(nil), // 21: weaver.gateway.v1.ProviderFrame + (*ProviderReceipt)(nil), // 22: weaver.gateway.v1.ProviderReceipt + (*Task)(nil), // 23: weaver.gateway.v1.Task + (*ProviderProfile)(nil), // 24: weaver.gateway.v1.ProviderProfile + (*RegisterTaskRequest)(nil), // 25: weaver.gateway.v1.RegisterTaskRequest + (*DomainBinding)(nil), // 26: weaver.gateway.v1.DomainBinding + (*DomainStamp)(nil), // 27: weaver.gateway.v1.DomainStamp + (*DomainView)(nil), // 28: weaver.gateway.v1.DomainView + (*RegisterDomainTaskRequest)(nil), // 29: weaver.gateway.v1.RegisterDomainTaskRequest + (*TaskAdmission)(nil), // 30: weaver.gateway.v1.TaskAdmission + (*RegisterOriginalTaskRequest)(nil), // 31: weaver.gateway.v1.RegisterOriginalTaskRequest + (*TaskAdmissionReceipt)(nil), // 32: weaver.gateway.v1.TaskAdmissionReceipt + (*FamilyAliasRequest)(nil), // 33: weaver.gateway.v1.FamilyAliasRequest + (*DomainMigration)(nil), // 34: weaver.gateway.v1.DomainMigration + (*DomainMigrationReceipt)(nil), // 35: weaver.gateway.v1.DomainMigrationReceipt + (*RegisterPublishedTaskRequest)(nil), // 36: weaver.gateway.v1.RegisterPublishedTaskRequest + (*PublishRequest)(nil), // 37: weaver.gateway.v1.PublishRequest + (*PublicationReceipt)(nil), // 38: weaver.gateway.v1.PublicationReceipt + (*PublicationKey)(nil), // 39: weaver.gateway.v1.PublicationKey + (*SourceAuthorityView)(nil), // 40: weaver.gateway.v1.SourceAuthorityView + (*SourceRotationRequest)(nil), // 41: weaver.gateway.v1.SourceRotationRequest + (*SourceRotationReceipt)(nil), // 42: weaver.gateway.v1.SourceRotationReceipt + (*AuthorityParent)(nil), // 43: weaver.gateway.v1.AuthorityParent + (*ReviewAuthority)(nil), // 44: weaver.gateway.v1.ReviewAuthority + (*PublicationReview)(nil), // 45: weaver.gateway.v1.PublicationReview + (*DeltaReview)(nil), // 46: weaver.gateway.v1.DeltaReview + (*PublicationReviewContext)(nil), // 47: weaver.gateway.v1.PublicationReviewContext + (*ReviewRegistrationReceipt)(nil), // 48: weaver.gateway.v1.ReviewRegistrationReceipt + (*MeterCredentialRotation)(nil), // 49: weaver.gateway.v1.MeterCredentialRotation + (*MeterCredentialEpoch)(nil), // 50: weaver.gateway.v1.MeterCredentialEpoch + (*MeteringReceipt)(nil), // 51: weaver.gateway.v1.MeteringReceipt + (*MeteringApplication)(nil), // 52: weaver.gateway.v1.MeteringApplication + (*ProviderOAuthChange)(nil), // 53: weaver.gateway.v1.ProviderOAuthChange + (*ProviderOAuthGrant)(nil), // 54: weaver.gateway.v1.ProviderOAuthGrant + (*ProviderOAuthIssuerRotation)(nil), // 55: weaver.gateway.v1.ProviderOAuthIssuerRotation + nil, // 56: weaver.gateway.v1.Task.EndpointsEntry + nil, // 57: weaver.gateway.v1.Task.BodyDigestsEntry + nil, // 58: weaver.gateway.v1.Task.NodeCostBoundsEntry + nil, // 59: weaver.gateway.v1.Task.StreamContractsEntry } var file_gateway_v1_gateway_proto_depIdxs = []int32{ - 7, // 0: weaver.gateway.v1.SourceArtifact.governance:type_name -> weaver.gateway.v1.GovernanceSelection - 20, // 1: weaver.gateway.v1.SourceArtifact.tasks:type_name -> weaver.gateway.v1.Task - 12, // 2: weaver.gateway.v1.SourceArtifact.plans:type_name -> weaver.gateway.v1.ProviderPlan - 34, // 3: weaver.gateway.v1.SourceArtifact.publication:type_name -> weaver.gateway.v1.PublishRequest - 37, // 4: weaver.gateway.v1.CompiledSource.authority:type_name -> weaver.gateway.v1.SourceAuthorityView - 8, // 5: weaver.gateway.v1.CompiledSource.artifact:type_name -> weaver.gateway.v1.SourceArtifact - 11, // 6: weaver.gateway.v1.ProviderPlan.routes:type_name -> weaver.gateway.v1.Route - 12, // 7: weaver.gateway.v1.ProviderRequest.plan:type_name -> weaver.gateway.v1.ProviderPlan - 0, // 8: weaver.gateway.v1.ProviderRequest.encoding:type_name -> weaver.gateway.v1.Encoding - 16, // 9: weaver.gateway.v1.ProviderFrame.event:type_name -> weaver.gateway.v1.Event - 17, // 10: weaver.gateway.v1.ProviderFrame.arrow:type_name -> weaver.gateway.v1.ArrowBatch - 53, // 11: weaver.gateway.v1.Task.endpoints:type_name -> weaver.gateway.v1.Task.EndpointsEntry - 54, // 12: weaver.gateway.v1.Task.body_digests:type_name -> weaver.gateway.v1.Task.BodyDigestsEntry - 55, // 13: weaver.gateway.v1.Task.node_cost_bounds:type_name -> weaver.gateway.v1.Task.NodeCostBoundsEntry - 56, // 14: weaver.gateway.v1.Task.stream_contracts:type_name -> weaver.gateway.v1.Task.StreamContractsEntry - 21, // 15: weaver.gateway.v1.Task.provider_profile:type_name -> weaver.gateway.v1.ProviderProfile - 20, // 16: weaver.gateway.v1.RegisterTaskRequest.task:type_name -> weaver.gateway.v1.Task - 24, // 17: weaver.gateway.v1.DomainView.stamp:type_name -> weaver.gateway.v1.DomainStamp - 20, // 18: weaver.gateway.v1.RegisterDomainTaskRequest.task:type_name -> weaver.gateway.v1.Task - 23, // 19: weaver.gateway.v1.RegisterDomainTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding - 36, // 20: weaver.gateway.v1.RegisterDomainTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey - 20, // 21: weaver.gateway.v1.RegisterOriginalTaskRequest.task:type_name -> weaver.gateway.v1.Task - 23, // 22: weaver.gateway.v1.RegisterOriginalTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding - 27, // 23: weaver.gateway.v1.RegisterOriginalTaskRequest.admission:type_name -> weaver.gateway.v1.TaskAdmission - 36, // 24: weaver.gateway.v1.RegisterOriginalTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey - 20, // 25: weaver.gateway.v1.RegisterPublishedTaskRequest.task:type_name -> weaver.gateway.v1.Task - 36, // 26: weaver.gateway.v1.RegisterPublishedTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey - 1, // 27: weaver.gateway.v1.PublicationReceipt.outcome:type_name -> weaver.gateway.v1.PublicationOutcome - 2, // 28: weaver.gateway.v1.SourceRotationReceipt.outcome:type_name -> weaver.gateway.v1.SourceRotationOutcome - 37, // 29: weaver.gateway.v1.SourceRotationReceipt.authority:type_name -> weaver.gateway.v1.SourceAuthorityView - 36, // 30: weaver.gateway.v1.PublicationReview.publication:type_name -> weaver.gateway.v1.PublicationKey - 40, // 31: weaver.gateway.v1.PublicationReview.parent:type_name -> weaver.gateway.v1.AuthorityParent - 42, // 32: weaver.gateway.v1.DeltaReview.review:type_name -> weaver.gateway.v1.PublicationReview - 3, // 33: weaver.gateway.v1.DeltaReview.disposition:type_name -> weaver.gateway.v1.DeltaDisposition - 36, // 34: weaver.gateway.v1.PublicationReviewContext.publication:type_name -> weaver.gateway.v1.PublicationKey - 40, // 35: weaver.gateway.v1.PublicationReviewContext.parent:type_name -> weaver.gateway.v1.AuthorityParent - 41, // 36: weaver.gateway.v1.PublicationReviewContext.reviewer:type_name -> weaver.gateway.v1.ReviewAuthority - 37, // 37: weaver.gateway.v1.PublicationReviewContext.source:type_name -> weaver.gateway.v1.SourceAuthorityView - 36, // 38: weaver.gateway.v1.ReviewRegistrationReceipt.publication:type_name -> weaver.gateway.v1.PublicationKey - 51, // 39: weaver.gateway.v1.ProviderOAuthChange.grant:type_name -> weaver.gateway.v1.ProviderOAuthGrant - 52, // 40: weaver.gateway.v1.ProviderOAuthChange.rotate_issuer:type_name -> weaver.gateway.v1.ProviderOAuthIssuerRotation - 13, // 41: weaver.gateway.v1.Gateway.ExecuteProvider:input_type -> weaver.gateway.v1.ProviderRequest - 10, // 42: weaver.gateway.v1.Gateway.Inspect:input_type -> weaver.gateway.v1.OperationKey - 46, // 43: weaver.gateway.v1.Gateway.RotateMeterCredential:input_type -> weaver.gateway.v1.MeterCredentialRotation - 10, // 44: weaver.gateway.v1.Gateway.InspectTerminalUsage:input_type -> weaver.gateway.v1.OperationKey - 48, // 45: weaver.gateway.v1.Gateway.ApplyMetering:input_type -> weaver.gateway.v1.MeteringReceipt - 22, // 46: weaver.gateway.v1.Gateway.RegisterTask:input_type -> weaver.gateway.v1.RegisterTaskRequest - 33, // 47: weaver.gateway.v1.Gateway.RegisterPublishedTask:input_type -> weaver.gateway.v1.RegisterPublishedTaskRequest - 26, // 48: weaver.gateway.v1.Gateway.RegisterDomainTask:input_type -> weaver.gateway.v1.RegisterDomainTaskRequest - 28, // 49: weaver.gateway.v1.Gateway.RegisterOriginalTask:input_type -> weaver.gateway.v1.RegisterOriginalTaskRequest - 30, // 50: weaver.gateway.v1.Gateway.RegisterFamilyAlias:input_type -> weaver.gateway.v1.FamilyAliasRequest - 31, // 51: weaver.gateway.v1.Gateway.MigrateExecutionDomains:input_type -> weaver.gateway.v1.DomainMigration - 10, // 52: weaver.gateway.v1.Gateway.InspectExecutionDomains:input_type -> weaver.gateway.v1.OperationKey - 34, // 53: weaver.gateway.v1.Gateway.PublishAuthority:input_type -> weaver.gateway.v1.PublishRequest - 34, // 54: weaver.gateway.v1.Gateway.StageAuthority:input_type -> weaver.gateway.v1.PublishRequest - 36, // 55: weaver.gateway.v1.Gateway.InspectPublication:input_type -> weaver.gateway.v1.PublicationKey - 34, // 56: weaver.gateway.v1.Gateway.StageReviewedAuthority:input_type -> weaver.gateway.v1.PublishRequest - 36, // 57: weaver.gateway.v1.Gateway.InspectPublicationReview:input_type -> weaver.gateway.v1.PublicationKey - 43, // 58: weaver.gateway.v1.Gateway.RegisterPublicationReview:input_type -> weaver.gateway.v1.DeltaReview - 5, // 59: weaver.gateway.v1.Gateway.InspectSourceAuthority:input_type -> weaver.gateway.v1.Empty - 38, // 60: weaver.gateway.v1.Gateway.RotateSourceAuthority:input_type -> weaver.gateway.v1.SourceRotationRequest - 6, // 61: weaver.gateway.v1.Gateway.CompileSource:input_type -> weaver.gateway.v1.ProducerRequest - 5, // 62: weaver.gateway.v1.Gateway.InspectProviderCatalog:input_type -> weaver.gateway.v1.Empty - 15, // 63: weaver.gateway.v1.Gateway.PublishProviderCatalog:input_type -> weaver.gateway.v1.ProviderCatalogChange - 5, // 64: weaver.gateway.v1.Gateway.InspectTelemetry:input_type -> weaver.gateway.v1.Empty - 50, // 65: weaver.gateway.v1.Gateway.ChangeProviderOAuth:input_type -> weaver.gateway.v1.ProviderOAuthChange - 18, // 66: weaver.gateway.v1.Gateway.ExecuteProvider:output_type -> weaver.gateway.v1.ProviderFrame - 19, // 67: weaver.gateway.v1.Gateway.Inspect:output_type -> weaver.gateway.v1.ProviderReceipt - 47, // 68: weaver.gateway.v1.Gateway.RotateMeterCredential:output_type -> weaver.gateway.v1.MeterCredentialEpoch - 48, // 69: weaver.gateway.v1.Gateway.InspectTerminalUsage:output_type -> weaver.gateway.v1.MeteringReceipt - 49, // 70: weaver.gateway.v1.Gateway.ApplyMetering:output_type -> weaver.gateway.v1.MeteringApplication - 5, // 71: weaver.gateway.v1.Gateway.RegisterTask:output_type -> weaver.gateway.v1.Empty - 5, // 72: weaver.gateway.v1.Gateway.RegisterPublishedTask:output_type -> weaver.gateway.v1.Empty - 5, // 73: weaver.gateway.v1.Gateway.RegisterDomainTask:output_type -> weaver.gateway.v1.Empty - 29, // 74: weaver.gateway.v1.Gateway.RegisterOriginalTask:output_type -> weaver.gateway.v1.TaskAdmissionReceipt - 25, // 75: weaver.gateway.v1.Gateway.RegisterFamilyAlias:output_type -> weaver.gateway.v1.DomainView - 32, // 76: weaver.gateway.v1.Gateway.MigrateExecutionDomains:output_type -> weaver.gateway.v1.DomainMigrationReceipt - 25, // 77: weaver.gateway.v1.Gateway.InspectExecutionDomains:output_type -> weaver.gateway.v1.DomainView - 35, // 78: weaver.gateway.v1.Gateway.PublishAuthority:output_type -> weaver.gateway.v1.PublicationReceipt - 36, // 79: weaver.gateway.v1.Gateway.StageAuthority:output_type -> weaver.gateway.v1.PublicationKey - 35, // 80: weaver.gateway.v1.Gateway.InspectPublication:output_type -> weaver.gateway.v1.PublicationReceipt - 36, // 81: weaver.gateway.v1.Gateway.StageReviewedAuthority:output_type -> weaver.gateway.v1.PublicationKey - 44, // 82: weaver.gateway.v1.Gateway.InspectPublicationReview:output_type -> weaver.gateway.v1.PublicationReviewContext - 45, // 83: weaver.gateway.v1.Gateway.RegisterPublicationReview:output_type -> weaver.gateway.v1.ReviewRegistrationReceipt - 37, // 84: weaver.gateway.v1.Gateway.InspectSourceAuthority:output_type -> weaver.gateway.v1.SourceAuthorityView - 39, // 85: weaver.gateway.v1.Gateway.RotateSourceAuthority:output_type -> weaver.gateway.v1.SourceRotationReceipt - 9, // 86: weaver.gateway.v1.Gateway.CompileSource:output_type -> weaver.gateway.v1.CompiledSource - 14, // 87: weaver.gateway.v1.Gateway.InspectProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot - 14, // 88: weaver.gateway.v1.Gateway.PublishProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot - 4, // 89: weaver.gateway.v1.Gateway.InspectTelemetry:output_type -> weaver.gateway.v1.TelemetrySnapshot - 5, // 90: weaver.gateway.v1.Gateway.ChangeProviderOAuth:output_type -> weaver.gateway.v1.Empty - 66, // [66:91] is the sub-list for method output_type - 41, // [41:66] is the sub-list for method input_type - 41, // [41:41] is the sub-list for extension type_name - 41, // [41:41] is the sub-list for extension extendee - 0, // [0:41] is the sub-list for field type_name + 8, // 0: weaver.gateway.v1.FactBarrierResolution.barrier:type_name -> weaver.gateway.v1.HardFactBarrier + 10, // 1: weaver.gateway.v1.SourceArtifact.governance:type_name -> weaver.gateway.v1.GovernanceSelection + 23, // 2: weaver.gateway.v1.SourceArtifact.tasks:type_name -> weaver.gateway.v1.Task + 15, // 3: weaver.gateway.v1.SourceArtifact.plans:type_name -> weaver.gateway.v1.ProviderPlan + 37, // 4: weaver.gateway.v1.SourceArtifact.publication:type_name -> weaver.gateway.v1.PublishRequest + 40, // 5: weaver.gateway.v1.CompiledSource.authority:type_name -> weaver.gateway.v1.SourceAuthorityView + 11, // 6: weaver.gateway.v1.CompiledSource.artifact:type_name -> weaver.gateway.v1.SourceArtifact + 14, // 7: weaver.gateway.v1.ProviderPlan.routes:type_name -> weaver.gateway.v1.Route + 15, // 8: weaver.gateway.v1.ProviderRequest.plan:type_name -> weaver.gateway.v1.ProviderPlan + 0, // 9: weaver.gateway.v1.ProviderRequest.encoding:type_name -> weaver.gateway.v1.Encoding + 19, // 10: weaver.gateway.v1.ProviderFrame.event:type_name -> weaver.gateway.v1.Event + 20, // 11: weaver.gateway.v1.ProviderFrame.arrow:type_name -> weaver.gateway.v1.ArrowBatch + 56, // 12: weaver.gateway.v1.Task.endpoints:type_name -> weaver.gateway.v1.Task.EndpointsEntry + 57, // 13: weaver.gateway.v1.Task.body_digests:type_name -> weaver.gateway.v1.Task.BodyDigestsEntry + 58, // 14: weaver.gateway.v1.Task.node_cost_bounds:type_name -> weaver.gateway.v1.Task.NodeCostBoundsEntry + 59, // 15: weaver.gateway.v1.Task.stream_contracts:type_name -> weaver.gateway.v1.Task.StreamContractsEntry + 24, // 16: weaver.gateway.v1.Task.provider_profile:type_name -> weaver.gateway.v1.ProviderProfile + 23, // 17: weaver.gateway.v1.RegisterTaskRequest.task:type_name -> weaver.gateway.v1.Task + 27, // 18: weaver.gateway.v1.DomainView.stamp:type_name -> weaver.gateway.v1.DomainStamp + 23, // 19: weaver.gateway.v1.RegisterDomainTaskRequest.task:type_name -> weaver.gateway.v1.Task + 26, // 20: weaver.gateway.v1.RegisterDomainTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding + 39, // 21: weaver.gateway.v1.RegisterDomainTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey + 23, // 22: weaver.gateway.v1.RegisterOriginalTaskRequest.task:type_name -> weaver.gateway.v1.Task + 26, // 23: weaver.gateway.v1.RegisterOriginalTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding + 30, // 24: weaver.gateway.v1.RegisterOriginalTaskRequest.admission:type_name -> weaver.gateway.v1.TaskAdmission + 39, // 25: weaver.gateway.v1.RegisterOriginalTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey + 23, // 26: weaver.gateway.v1.RegisterPublishedTaskRequest.task:type_name -> weaver.gateway.v1.Task + 39, // 27: weaver.gateway.v1.RegisterPublishedTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey + 1, // 28: weaver.gateway.v1.PublicationReceipt.outcome:type_name -> weaver.gateway.v1.PublicationOutcome + 2, // 29: weaver.gateway.v1.SourceRotationReceipt.outcome:type_name -> weaver.gateway.v1.SourceRotationOutcome + 40, // 30: weaver.gateway.v1.SourceRotationReceipt.authority:type_name -> weaver.gateway.v1.SourceAuthorityView + 39, // 31: weaver.gateway.v1.PublicationReview.publication:type_name -> weaver.gateway.v1.PublicationKey + 43, // 32: weaver.gateway.v1.PublicationReview.parent:type_name -> weaver.gateway.v1.AuthorityParent + 45, // 33: weaver.gateway.v1.DeltaReview.review:type_name -> weaver.gateway.v1.PublicationReview + 3, // 34: weaver.gateway.v1.DeltaReview.disposition:type_name -> weaver.gateway.v1.DeltaDisposition + 39, // 35: weaver.gateway.v1.PublicationReviewContext.publication:type_name -> weaver.gateway.v1.PublicationKey + 43, // 36: weaver.gateway.v1.PublicationReviewContext.parent:type_name -> weaver.gateway.v1.AuthorityParent + 44, // 37: weaver.gateway.v1.PublicationReviewContext.reviewer:type_name -> weaver.gateway.v1.ReviewAuthority + 40, // 38: weaver.gateway.v1.PublicationReviewContext.source:type_name -> weaver.gateway.v1.SourceAuthorityView + 39, // 39: weaver.gateway.v1.ReviewRegistrationReceipt.publication:type_name -> weaver.gateway.v1.PublicationKey + 54, // 40: weaver.gateway.v1.ProviderOAuthChange.grant:type_name -> weaver.gateway.v1.ProviderOAuthGrant + 55, // 41: weaver.gateway.v1.ProviderOAuthChange.rotate_issuer:type_name -> weaver.gateway.v1.ProviderOAuthIssuerRotation + 16, // 42: weaver.gateway.v1.Gateway.ExecuteProvider:input_type -> weaver.gateway.v1.ProviderRequest + 13, // 43: weaver.gateway.v1.Gateway.Inspect:input_type -> weaver.gateway.v1.OperationKey + 49, // 44: weaver.gateway.v1.Gateway.RotateMeterCredential:input_type -> weaver.gateway.v1.MeterCredentialRotation + 13, // 45: weaver.gateway.v1.Gateway.InspectTerminalUsage:input_type -> weaver.gateway.v1.OperationKey + 51, // 46: weaver.gateway.v1.Gateway.ApplyMetering:input_type -> weaver.gateway.v1.MeteringReceipt + 25, // 47: weaver.gateway.v1.Gateway.RegisterTask:input_type -> weaver.gateway.v1.RegisterTaskRequest + 36, // 48: weaver.gateway.v1.Gateway.RegisterPublishedTask:input_type -> weaver.gateway.v1.RegisterPublishedTaskRequest + 29, // 49: weaver.gateway.v1.Gateway.RegisterDomainTask:input_type -> weaver.gateway.v1.RegisterDomainTaskRequest + 31, // 50: weaver.gateway.v1.Gateway.RegisterOriginalTask:input_type -> weaver.gateway.v1.RegisterOriginalTaskRequest + 33, // 51: weaver.gateway.v1.Gateway.RegisterFamilyAlias:input_type -> weaver.gateway.v1.FamilyAliasRequest + 34, // 52: weaver.gateway.v1.Gateway.MigrateExecutionDomains:input_type -> weaver.gateway.v1.DomainMigration + 13, // 53: weaver.gateway.v1.Gateway.InspectExecutionDomains:input_type -> weaver.gateway.v1.OperationKey + 37, // 54: weaver.gateway.v1.Gateway.PublishAuthority:input_type -> weaver.gateway.v1.PublishRequest + 37, // 55: weaver.gateway.v1.Gateway.StageAuthority:input_type -> weaver.gateway.v1.PublishRequest + 39, // 56: weaver.gateway.v1.Gateway.InspectPublication:input_type -> weaver.gateway.v1.PublicationKey + 37, // 57: weaver.gateway.v1.Gateway.StageReviewedAuthority:input_type -> weaver.gateway.v1.PublishRequest + 39, // 58: weaver.gateway.v1.Gateway.InspectPublicationReview:input_type -> weaver.gateway.v1.PublicationKey + 46, // 59: weaver.gateway.v1.Gateway.RegisterPublicationReview:input_type -> weaver.gateway.v1.DeltaReview + 5, // 60: weaver.gateway.v1.Gateway.InspectSourceAuthority:input_type -> weaver.gateway.v1.Empty + 41, // 61: weaver.gateway.v1.Gateway.RotateSourceAuthority:input_type -> weaver.gateway.v1.SourceRotationRequest + 7, // 62: weaver.gateway.v1.Gateway.StageHardFact:input_type -> weaver.gateway.v1.HardFactIntent + 8, // 63: weaver.gateway.v1.Gateway.ResolveHardFact:input_type -> weaver.gateway.v1.HardFactBarrier + 6, // 64: weaver.gateway.v1.Gateway.CompileSource:input_type -> weaver.gateway.v1.ProducerRequest + 5, // 65: weaver.gateway.v1.Gateway.InspectProviderCatalog:input_type -> weaver.gateway.v1.Empty + 18, // 66: weaver.gateway.v1.Gateway.PublishProviderCatalog:input_type -> weaver.gateway.v1.ProviderCatalogChange + 5, // 67: weaver.gateway.v1.Gateway.InspectTelemetry:input_type -> weaver.gateway.v1.Empty + 53, // 68: weaver.gateway.v1.Gateway.ChangeProviderOAuth:input_type -> weaver.gateway.v1.ProviderOAuthChange + 21, // 69: weaver.gateway.v1.Gateway.ExecuteProvider:output_type -> weaver.gateway.v1.ProviderFrame + 22, // 70: weaver.gateway.v1.Gateway.Inspect:output_type -> weaver.gateway.v1.ProviderReceipt + 50, // 71: weaver.gateway.v1.Gateway.RotateMeterCredential:output_type -> weaver.gateway.v1.MeterCredentialEpoch + 51, // 72: weaver.gateway.v1.Gateway.InspectTerminalUsage:output_type -> weaver.gateway.v1.MeteringReceipt + 52, // 73: weaver.gateway.v1.Gateway.ApplyMetering:output_type -> weaver.gateway.v1.MeteringApplication + 5, // 74: weaver.gateway.v1.Gateway.RegisterTask:output_type -> weaver.gateway.v1.Empty + 5, // 75: weaver.gateway.v1.Gateway.RegisterPublishedTask:output_type -> weaver.gateway.v1.Empty + 5, // 76: weaver.gateway.v1.Gateway.RegisterDomainTask:output_type -> weaver.gateway.v1.Empty + 32, // 77: weaver.gateway.v1.Gateway.RegisterOriginalTask:output_type -> weaver.gateway.v1.TaskAdmissionReceipt + 28, // 78: weaver.gateway.v1.Gateway.RegisterFamilyAlias:output_type -> weaver.gateway.v1.DomainView + 35, // 79: weaver.gateway.v1.Gateway.MigrateExecutionDomains:output_type -> weaver.gateway.v1.DomainMigrationReceipt + 28, // 80: weaver.gateway.v1.Gateway.InspectExecutionDomains:output_type -> weaver.gateway.v1.DomainView + 38, // 81: weaver.gateway.v1.Gateway.PublishAuthority:output_type -> weaver.gateway.v1.PublicationReceipt + 39, // 82: weaver.gateway.v1.Gateway.StageAuthority:output_type -> weaver.gateway.v1.PublicationKey + 38, // 83: weaver.gateway.v1.Gateway.InspectPublication:output_type -> weaver.gateway.v1.PublicationReceipt + 39, // 84: weaver.gateway.v1.Gateway.StageReviewedAuthority:output_type -> weaver.gateway.v1.PublicationKey + 47, // 85: weaver.gateway.v1.Gateway.InspectPublicationReview:output_type -> weaver.gateway.v1.PublicationReviewContext + 48, // 86: weaver.gateway.v1.Gateway.RegisterPublicationReview:output_type -> weaver.gateway.v1.ReviewRegistrationReceipt + 40, // 87: weaver.gateway.v1.Gateway.InspectSourceAuthority:output_type -> weaver.gateway.v1.SourceAuthorityView + 42, // 88: weaver.gateway.v1.Gateway.RotateSourceAuthority:output_type -> weaver.gateway.v1.SourceRotationReceipt + 8, // 89: weaver.gateway.v1.Gateway.StageHardFact:output_type -> weaver.gateway.v1.HardFactBarrier + 9, // 90: weaver.gateway.v1.Gateway.ResolveHardFact:output_type -> weaver.gateway.v1.FactBarrierResolution + 12, // 91: weaver.gateway.v1.Gateway.CompileSource:output_type -> weaver.gateway.v1.CompiledSource + 17, // 92: weaver.gateway.v1.Gateway.InspectProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot + 17, // 93: weaver.gateway.v1.Gateway.PublishProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot + 4, // 94: weaver.gateway.v1.Gateway.InspectTelemetry:output_type -> weaver.gateway.v1.TelemetrySnapshot + 5, // 95: weaver.gateway.v1.Gateway.ChangeProviderOAuth:output_type -> weaver.gateway.v1.Empty + 69, // [69:96] is the sub-list for method output_type + 42, // [42:69] is the sub-list for method input_type + 42, // [42:42] is the sub-list for extension type_name + 42, // [42:42] is the sub-list for extension extendee + 0, // [0:42] is the sub-list for field type_name } func init() { file_gateway_v1_gateway_proto_init() } @@ -4332,15 +4618,17 @@ func file_gateway_v1_gateway_proto_init() { if File_gateway_v1_gateway_proto != nil { return } - file_gateway_v1_gateway_proto_msgTypes[14].OneofWrappers = []any{ + file_gateway_v1_gateway_proto_msgTypes[3].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[5].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[17].OneofWrappers = []any{ (*ProviderFrame_Event)(nil), (*ProviderFrame_Arrow)(nil), } - file_gateway_v1_gateway_proto_msgTypes[30].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[31].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[36].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[37].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[46].OneofWrappers = []any{ + file_gateway_v1_gateway_proto_msgTypes[33].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[34].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[39].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[40].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[49].OneofWrappers = []any{ (*ProviderOAuthChange_Grant)(nil), (*ProviderOAuthChange_RevokeTokenHash)(nil), (*ProviderOAuthChange_RotateIssuer)(nil), @@ -4351,7 +4639,7 @@ func file_gateway_v1_gateway_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_gateway_v1_gateway_proto_rawDesc), len(file_gateway_v1_gateway_proto_rawDesc)), NumEnums: 4, - NumMessages: 53, + NumMessages: 56, NumExtensions: 0, NumServices: 1, }, diff --git a/go/api/gateway/v1/gateway_grpc.pb.go b/go/api/gateway/v1/gateway_grpc.pb.go index bfd21834..da788127 100644 --- a/go/api/gateway/v1/gateway_grpc.pb.go +++ b/go/api/gateway/v1/gateway_grpc.pb.go @@ -43,6 +43,8 @@ const ( Gateway_RegisterPublicationReview_FullMethodName = "/weaver.gateway.v1.Gateway/RegisterPublicationReview" Gateway_InspectSourceAuthority_FullMethodName = "/weaver.gateway.v1.Gateway/InspectSourceAuthority" Gateway_RotateSourceAuthority_FullMethodName = "/weaver.gateway.v1.Gateway/RotateSourceAuthority" + Gateway_StageHardFact_FullMethodName = "/weaver.gateway.v1.Gateway/StageHardFact" + Gateway_ResolveHardFact_FullMethodName = "/weaver.gateway.v1.Gateway/ResolveHardFact" Gateway_CompileSource_FullMethodName = "/weaver.gateway.v1.Gateway/CompileSource" Gateway_InspectProviderCatalog_FullMethodName = "/weaver.gateway.v1.Gateway/InspectProviderCatalog" Gateway_PublishProviderCatalog_FullMethodName = "/weaver.gateway.v1.Gateway/PublishProviderCatalog" @@ -77,6 +79,9 @@ type GatewayClient interface { RegisterPublicationReview(ctx context.Context, in *DeltaReview, opts ...grpc.CallOption) (*ReviewRegistrationReceipt, error) InspectSourceAuthority(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*SourceAuthorityView, error) RotateSourceAuthority(ctx context.Context, in *SourceRotationRequest, opts ...grpc.CallOption) (*SourceRotationReceipt, error) + // Dedicated deployment-admitted feed. Resolve accepts only the exact durable barrier. + StageHardFact(ctx context.Context, in *HardFactIntent, opts ...grpc.CallOption) (*HardFactBarrier, error) + ResolveHardFact(ctx context.Context, in *HardFactBarrier, opts ...grpc.CallOption) (*FactBarrierResolution, error) // Preparation only. Actual ingress/source state selects an installed original; // request labels cannot supply authority, replacement source or module paths. CompileSource(ctx context.Context, in *ProducerRequest, opts ...grpc.CallOption) (*CompiledSource, error) @@ -319,6 +324,26 @@ func (c *gatewayClient) RotateSourceAuthority(ctx context.Context, in *SourceRot return out, nil } +func (c *gatewayClient) StageHardFact(ctx context.Context, in *HardFactIntent, opts ...grpc.CallOption) (*HardFactBarrier, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(HardFactBarrier) + err := c.cc.Invoke(ctx, Gateway_StageHardFact_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gatewayClient) ResolveHardFact(ctx context.Context, in *HardFactBarrier, opts ...grpc.CallOption) (*FactBarrierResolution, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(FactBarrierResolution) + err := c.cc.Invoke(ctx, Gateway_ResolveHardFact_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *gatewayClient) CompileSource(ctx context.Context, in *ProducerRequest, opts ...grpc.CallOption) (*CompiledSource, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(CompiledSource) @@ -396,6 +421,9 @@ type GatewayServer interface { RegisterPublicationReview(context.Context, *DeltaReview) (*ReviewRegistrationReceipt, error) InspectSourceAuthority(context.Context, *Empty) (*SourceAuthorityView, error) RotateSourceAuthority(context.Context, *SourceRotationRequest) (*SourceRotationReceipt, error) + // Dedicated deployment-admitted feed. Resolve accepts only the exact durable barrier. + StageHardFact(context.Context, *HardFactIntent) (*HardFactBarrier, error) + ResolveHardFact(context.Context, *HardFactBarrier) (*FactBarrierResolution, error) // Preparation only. Actual ingress/source state selects an installed original; // request labels cannot supply authority, replacement source or module paths. CompileSource(context.Context, *ProducerRequest) (*CompiledSource, error) @@ -472,6 +500,12 @@ func (UnimplementedGatewayServer) InspectSourceAuthority(context.Context, *Empty func (UnimplementedGatewayServer) RotateSourceAuthority(context.Context, *SourceRotationRequest) (*SourceRotationReceipt, error) { return nil, status.Errorf(codes.Unimplemented, "method RotateSourceAuthority not implemented") } +func (UnimplementedGatewayServer) StageHardFact(context.Context, *HardFactIntent) (*HardFactBarrier, error) { + return nil, status.Errorf(codes.Unimplemented, "method StageHardFact not implemented") +} +func (UnimplementedGatewayServer) ResolveHardFact(context.Context, *HardFactBarrier) (*FactBarrierResolution, error) { + return nil, status.Errorf(codes.Unimplemented, "method ResolveHardFact not implemented") +} func (UnimplementedGatewayServer) CompileSource(context.Context, *ProducerRequest) (*CompiledSource, error) { return nil, status.Errorf(codes.Unimplemented, "method CompileSource not implemented") } @@ -863,6 +897,42 @@ func _Gateway_RotateSourceAuthority_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } +func _Gateway_StageHardFact_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HardFactIntent) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GatewayServer).StageHardFact(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Gateway_StageHardFact_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GatewayServer).StageHardFact(ctx, req.(*HardFactIntent)) + } + return interceptor(ctx, in, info, handler) +} + +func _Gateway_ResolveHardFact_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HardFactBarrier) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GatewayServer).ResolveHardFact(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Gateway_ResolveHardFact_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GatewayServer).ResolveHardFact(ctx, req.(*HardFactBarrier)) + } + return interceptor(ctx, in, info, handler) +} + func _Gateway_CompileSource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ProducerRequest) if err := dec(in); err != nil { @@ -1036,6 +1106,14 @@ var Gateway_ServiceDesc = grpc.ServiceDesc{ MethodName: "RotateSourceAuthority", Handler: _Gateway_RotateSourceAuthority_Handler, }, + { + MethodName: "StageHardFact", + Handler: _Gateway_StageHardFact_Handler, + }, + { + MethodName: "ResolveHardFact", + Handler: _Gateway_ResolveHardFact_Handler, + }, { MethodName: "CompileSource", Handler: _Gateway_CompileSource_Handler, diff --git a/go/dev/provider_hard_fact_test.go b/go/dev/provider_hard_fact_test.go new file mode 100644 index 00000000..ae159482 --- /dev/null +++ b/go/dev/provider_hard_fact_test.go @@ -0,0 +1,145 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build integration && !windows + +package dev + +import ( + "context" + "crypto/sha256" + "crypto/x509" + "encoding/hex" + "encoding/json" + "strings" + "testing" + "time" + + pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +func hardFactFeedSetting(t *testing.T, f *fixture, family, root string, dependencies [][2]string, workflow map[string]string, workflowSchema string, selectors [][3]string, path ...string) string { + t.Helper() + certificate, err := x509.ParseCertificate(f.pki.source.Certificate[0]) + if err != nil { + t.Fatal(err) + } + leaf := sha256.Sum256(certificate.Raw) + key := sha256.Sum256(certificate.RawSubjectPublicKeyInfo) + token := sha256.Sum256([]byte(adminToken)) + config := map[string]any{ + "domain": "availability", + "authority": map[string]any{"epoch": 0, "identity": map[string]string{ + "certificate_sha256": hex.EncodeToString(leaf[:]), + "public_key_sha256": hex.EncodeToString(key[:]), + "credential_sha256": hex.EncodeToString(token[:]), + }}, + "family": family, "root": root, "dependencies": dependencies, + } + if workflow != nil { + config["workflow"] = workflow + } + if workflowSchema == "weaver.session-dag.v1" || workflowSchema == "weaver.session-choice.v1" || workflowSchema == "weaver.session-nested.v1" { + config["workflow_dag"] = true + } + if workflowSchema == "weaver.session-choice.v1" { + config["workflow_choice"] = true + } + if len(selectors) != 0 { + config["workflow_selectors"] = selectors + } + if len(path) != 0 { + config["workflow_path"] = path + } + feed, err := json.Marshal(config) + if err != nil { + t.Fatal(err) + } + return "WEAVER_HARD_FACT_FEED=" + string(feed) +} + +func TestProviderControlHardFactWithdrawalRestartAndABA(t *testing.T) { + f := newFixture(t, completeSSE, false) + f.stop(t) + f.env = append(f.env, hardFactFeedSetting(t, f, f.plan.Family, f.plan.Node, [][2]string{}, nil, "", nil)) + f.start(t) + + ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second) + defer cancel() + blocked := func(label string) { + t.Helper() + _, err := f.client.Execute(ctx, f.plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { + t.Errorf("%s emitted a provider event", label) + return nil + }) + if status.Code(err) != codes.FailedPrecondition || f.primary.Load() != 0 || f.backup.Load() != 0 { + t.Fatalf("%s: expected hard fact barrier, got %v", label, err) + } + } + stage := func(intent *pb.HardFactIntent) *pb.HardFactBarrier { + t.Helper() + barrier, err := f.admin.RPC.StageHardFact(f.admin.Context(ctx), intent) + if err != nil || barrier.GetFloor() != intent.ExpectedFloor+1 || barrier.GetRevision() != intent.Revision { + t.Fatalf("stage hard fact: %v %v", barrier, err) + } + return barrier + } + resolve := func(barrier *pb.HardFactBarrier) *pb.FactBarrierResolution { + t.Helper() + result, err := f.admin.RPC.ResolveHardFact(f.admin.Context(ctx), barrier) + if err != nil || !proto.Equal(barrier, result.GetBarrier()) || + len(result.GetAffected()) != 1 || result.GetAffected()[0] != f.plan.Node { + t.Fatalf("resolve hard fact: %v %v", result, err) + } + return result + } + + blocked("before first admitted fact") + intent := &pb.HardFactIntent{OperationId: "fact-a", Domain: "availability", Revision: 1, + PreviousSnapshot: strings.Repeat("0", 64), Available: proto.Bool(true)} + if _, err := f.client.RPC.StageHardFact(f.client.Context(ctx), intent); err == nil { + t.Fatal("operation credential staged a hard fact") + } + foreignDomain := proto.CloneOf(intent) + foreignDomain.Domain = "unadmitted" + if _, err := f.admin.RPC.StageHardFact(f.admin.Context(ctx), foreignDomain); err == nil { + t.Fatal("generic source credential staged a fact outside its feed") + } + a := stage(intent) + forged := proto.CloneOf(a) + forged.PendingPrefix = strings.Repeat("0", 64) + if _, err := f.admin.RPC.ResolveHardFact(f.admin.Context(ctx), forged); err == nil { + t.Fatal("forged pending prefix was accepted") + } + resolve(a) + withdrawal := &pb.HardFactIntent{OperationId: "fact-b", Domain: intent.Domain, Revision: 2, + PreviousSnapshot: a.Snapshot, ExpectedFloor: a.Floor, Available: proto.Bool(false)} + b := stage(withdrawal) + blocked("withdrawal pending") + f.stop(t) + f.start(t) + if retry := stage(withdrawal); !proto.Equal(retry, b) { + t.Fatal("restart or lost stage reply changed the durable barrier") + } + blocked("withdrawal pending after restart") + resolve(b) + blocked("withdrawal resolved") + + restoration := &pb.HardFactIntent{OperationId: "fact-a-again", Domain: intent.Domain, Revision: 3, + PreviousSnapshot: b.Snapshot, ExpectedFloor: b.Floor, Available: proto.Bool(true)} + aAgain := stage(restoration) + if aAgain.Snapshot == a.Snapshot || aAgain.PendingPrefix == a.PendingPrefix { + t.Fatal("A-B-A reused an old cut") + } + resolve(a) + blocked("old exact receipt replay cannot clear a newer pending barrier") + resolve(aAgain) + _, err := f.client.Execute(ctx, f.plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }) + if err != nil || f.primary.Load() != 1 || f.backup.Load() != 0 { + t.Fatalf("restored fact did not permit normal guarded provider execution: %v", err) + } +} diff --git a/proto/gateway/v1/gateway.proto b/proto/gateway/v1/gateway.proto index 97552659..5d2debf9 100644 --- a/proto/gateway/v1/gateway.proto +++ b/proto/gateway/v1/gateway.proto @@ -29,6 +29,9 @@ service Gateway { rpc RegisterPublicationReview(DeltaReview) returns (ReviewRegistrationReceipt); rpc InspectSourceAuthority(Empty) returns (SourceAuthorityView); rpc RotateSourceAuthority(SourceRotationRequest) returns (SourceRotationReceipt); + // Dedicated deployment-admitted feed. Resolve accepts only the exact durable barrier. + rpc StageHardFact(HardFactIntent) returns (HardFactBarrier); + rpc ResolveHardFact(HardFactBarrier) returns (FactBarrierResolution); // Preparation only. Actual ingress/source state selects an installed original; // request labels cannot supply authority, replacement source or module paths. rpc CompileSource(ProducerRequest) returns (CompiledSource); @@ -52,6 +55,30 @@ message TelemetrySnapshot { } message Empty {} message ProducerRequest { string producer = 1; } +message HardFactIntent { + string operation_id = 1; + string domain = 2; + uint64 source_epoch = 3; + uint64 revision = 4; + string previous_snapshot = 5; + uint64 expected_floor = 6; + optional bool available = 7; +} +message HardFactBarrier { + string operation_id = 1; + uint64 source_epoch = 2; + uint64 revision = 3; + string snapshot = 4; + uint64 floor = 5; + string pending_prefix = 6; +} +message FactBarrierResolution { + HardFactBarrier barrier = 1; + repeated string affected = 2; + uint64 floor = 3; + string previous_pending_prefix = 4; + optional string remaining_pending_prefix = 5; +} message GovernanceSelection { string schema = 1; string family = 2; repeated string open_nodes = 3; } message SourceArtifact { GovernanceSelection governance = 1; repeated Task tasks = 2; repeated ProviderPlan plans = 3; PublishRequest publication = 4; } // Source authority here is knowledge at response admission, never a later permit. From 4f7116b48567a8fde12866375e76b6962c1fb3bd Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 21:00:50 +0800 Subject: [PATCH 027/105] Run Governor observations on the bounded source owner --- crates/governance/src/host/client.rs | 34 ++++++++++++++- crates/governance/src/host/mod.rs | 1 + crates/governance/src/host/owner.rs | 63 ++++++++++++++++++++++++--- crates/governance/src/host/request.rs | 6 ++- crates/governance/src/host/state.rs | 22 ++++++++++ crates/governance/src/lib.rs | 4 +- crates/governance/tests/unit/host.rs | 38 ++++++++++++++++ 7 files changed, 159 insertions(+), 9 deletions(-) diff --git a/crates/governance/src/host/client.rs b/crates/governance/src/host/client.rs index b5c6366c..ef4911bb 100644 --- a/crates/governance/src/host/client.rs +++ b/crates/governance/src/host/client.rs @@ -53,12 +53,14 @@ impl SourceClient { phase: Mutex::new(Phase::Queued), }); let (reply, receiver) = oneshot::channel(); + let cancel = self.shared.shutdown.child_token(); let work = Work { original, expected, state: state.clone(), reply, slot, + cancel: cancel.clone(), }; let closed = self.shared.gate(); if *closed { @@ -70,7 +72,37 @@ impl SourceClient { mpsc::error::TrySendError::Full(_) => SourceJobError::Busy, mpsc::error::TrySendError::Closed(_) => SourceJobError::Closed, })?; - Ok(SourceJob::new(receiver, self.shared.clone(), state)) + Ok(SourceJob::new(receiver, self.shared.clone(), state, cancel)) + } + /// Submit a detached ledger observation on the same bounded Scheme owner. + pub async fn derive(&self, input: crate::GovernorCut) -> Result, SourceJobError> { + let slot = self + .capacity + .clone() + .try_acquire_owned() + .map_err(|_| SourceJobError::Busy)?; + let (reply, receiver) = oneshot::channel(); + { + let closed = self.shared.gate(); + if *closed { + return Err(SourceJobError::Closed); + } + self.sender + .try_send(Command::Derive { + input: Box::new(input), + reply, + _slot: slot, + }) + .map_err(|error| match error { + mpsc::error::TrySendError::Full(_) => SourceJobError::Busy, + mpsc::error::TrySendError::Closed(_) => SourceJobError::Closed, + })?; + } + tokio::select! { + biased; + _ = self.shared.shutdown.cancelled() => Err(SourceJobError::Closed), + result = receiver => result.map_err(|_| SourceJobError::Closed)?.map_err(SourceJobError::from), + } } /// Close admission and wake callers/owner. This is not drain acknowledgment; /// an active synchronous compiler must return and clean its VM naturally. diff --git a/crates/governance/src/host/mod.rs b/crates/governance/src/host/mod.rs index e12c98e3..1154ddbe 100644 --- a/crates/governance/src/host/mod.rs +++ b/crates/governance/src/host/mod.rs @@ -10,4 +10,5 @@ mod state; pub use client::{SourceClient, source_lane}; pub use owner::SourceInbox; pub use request::{SourceJob, SourceJobError}; +pub use state::GovernorCut; use state::{Command, Phase, Reply, Shared, State, Work}; diff --git a/crates/governance/src/host/owner.rs b/crates/governance/src/host/owner.rs index f6f15790..9c187d3d 100644 --- a/crates/governance/src/host/owner.rs +++ b/crates/governance/src/host/owner.rs @@ -7,6 +7,7 @@ use super::{Command, Phase, Reply, Shared, SourceJobError, Work}; use crate::{OwnedSource, SourceError}; use std::sync::Arc; use tokio::sync::mpsc; +use tokio_util::sync::CancellationToken; /// Move this receiver to the existing tracked blocking owner before constructing /// its VM. The compiler can borrow that thread-affine, non-Send runtime. pub struct SourceInbox { @@ -17,9 +18,36 @@ impl SourceInbox { /// Run synchronous approved compilation. No lock is held during foreign /// calls or content comparison. Finish/VM cleanup must precede owner join ack. /// This does not sandbox arbitrary callbacks or implement source authenticity. - pub fn run( + pub fn run(self, compile: impl FnMut(&OwnedSource) -> Result) { + self.run_with_governor( + compile, + |owner, original| owner(original), + |_, _| Err(SourceError::Contract), + ); + } + /// Run compilation and Governor derivation on the same affine owner. + pub fn run_with_governor( + self, + owner: C, + mut compile: impl FnMut(&mut C, &OwnedSource) -> Result, + derive: impl FnMut(&mut C, &crate::GovernorCut) -> Result, SourceError>, + ) { + self.run_with_cancellable_governor( + owner, + |owner, original, _| compile(owner, original), + derive, + ); + } + /// Pass the request cancellation token into a cooperative compiler. + pub fn run_with_cancellable_governor( mut self, - mut compile: impl FnMut(&OwnedSource) -> Result, + mut owner: C, + mut compile: impl FnMut( + &mut C, + &OwnedSource, + &CancellationToken, + ) -> Result, + mut derive: impl FnMut(&mut C, &crate::GovernorCut) -> Result, SourceError>, ) { while let Some(command) = self.receiver.blocking_recv() { if *self.shared.gate() { @@ -27,17 +55,41 @@ impl SourceInbox { } match command { Command::Stop => break, - Command::Compile(work) => self.execute(*work, &mut compile), + Command::Compile(work) => self.execute(*work, &mut |original, cancel| { + compile(&mut owner, original, cancel) + }), + Command::Derive { + input, + reply, + _slot, + } => { + self.execute_derivation(reply, || derive(&mut owner, &input)); + } } if *self.shared.gate() { break; } } + drop(owner); + } + fn execute_derivation( + &self, + reply: tokio::sync::oneshot::Sender, SourceError>>, + derive: impl FnOnce() -> Result, SourceError>, + ) { + if reply.is_closed() { + return; + } + let result = derive(); + if matches!(result, Err(SourceError::Scheme)) { + self.shared.stop(); + } + let _ = reply.send(result); } fn execute( &self, work: Work, - compile: &mut impl FnMut(&OwnedSource) -> Result, + compile: &mut impl FnMut(&OwnedSource, &CancellationToken) -> Result, ) { { let closed = self.shared.gate(); @@ -47,7 +99,7 @@ impl SourceInbox { } *phase = Phase::Running; } - let result = compile(&work.original) + let result = compile(&work.original, &work.cancel) .and_then(|candidate| work.expected.bind(candidate)) .map_err(SourceJobError::from); if matches!(result, Err(SourceJobError::Source(SourceError::Scheme))) { @@ -69,6 +121,7 @@ impl SourceInbox { }); } } + impl Drop for SourceInbox { fn drop(&mut self) { self.shared.stop(); diff --git a/crates/governance/src/host/request.rs b/crates/governance/src/host/request.rs index 8453ed4e..95e98c6b 100644 --- a/crates/governance/src/host/request.rs +++ b/crates/governance/src/host/request.rs @@ -12,7 +12,7 @@ use std::{ task::{Context, Poll}, }; use tokio::sync::oneshot; -use tokio_util::sync::WaitForCancellationFutureOwned; +use tokio_util::sync::{CancellationToken, WaitForCancellationFutureOwned}; /// Scheduling failures contain no source content or permission claims. #[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)] pub enum SourceJobError { @@ -36,6 +36,7 @@ pub struct SourceJob { shared: Arc, state: Arc, shutdown: Pin>, + cancel: CancellationToken, finished: bool, } impl SourceJob { @@ -43,6 +44,7 @@ impl SourceJob { receiver: oneshot::Receiver, shared: Arc, state: Arc, + cancel: CancellationToken, ) -> Self { let shutdown = Box::pin(shared.shutdown.clone().cancelled_owned()); Self { @@ -50,6 +52,7 @@ impl SourceJob { shared, state, shutdown, + cancel, finished: false, } } @@ -63,6 +66,7 @@ impl SourceJob { *phase = Phase::Cancelled; } } + self.cancel.cancel(); self.receiver.close(); } fn claim(&self, reply: Reply) -> Result { diff --git a/crates/governance/src/host/state.rs b/crates/governance/src/host/state.rs index 89388073..ca201a98 100644 --- a/crates/governance/src/host/state.rs +++ b/crates/governance/src/host/state.rs @@ -62,8 +62,30 @@ pub(super) struct Work { pub(super) state: Arc, pub(super) reply: oneshot::Sender, pub(super) slot: OwnedSemaphorePermit, + pub(super) cancel: CancellationToken, +} +/// Fixed Governor facts, detached from the authoritative ledger cut. +#[derive(serde::Serialize)] +pub struct GovernorCut { + pub nodes: Vec, + pub edges: Vec<(String, String)>, + pub complete: Vec, + pub available: Vec, + pub pending: Vec, + pub choice_arms: Vec, + pub choice_join: Vec, + pub choice_result: Vec, + pub choice_decided: Vec, + pub nested_selectors: Vec<[String; 3]>, + pub nested_results: Vec<(String, String)>, + pub nested_decisions: Vec<(String, String)>, } pub(super) enum Command { + Derive { + input: Box, + reply: oneshot::Sender, crate::SourceError>>, + _slot: OwnedSemaphorePermit, + }, Compile(Box), Stop, } diff --git a/crates/governance/src/lib.rs b/crates/governance/src/lib.rs index 48229b93..c757b07f 100644 --- a/crates/governance/src/lib.rs +++ b/crates/governance/src/lib.rs @@ -7,13 +7,13 @@ extern crate self as weaver_governance; mod binding; mod catalog; -mod hard_fact; mod host; mod source; pub use binding::{BoundSource, SourceExpectation}; +mod hard_fact; pub use catalog::{ApprovedProducer, CatalogError, ProducerCatalog, ProducerClient}; pub use hard_fact::derive_fact_impact; -pub use host::{SourceClient, SourceInbox, SourceJob, SourceJobError, source_lane}; +pub use host::{GovernorCut, SourceClient, SourceInbox, SourceJob, SourceJobError, source_lane}; pub use source::{MAX_SOURCE_BYTES, OwnedSource, SourceData, SourceError, SourceSelection}; #[cfg(feature = "scheme-vm")] diff --git a/crates/governance/tests/unit/host.rs b/crates/governance/tests/unit/host.rs index d5683296..dc6ff581 100644 --- a/crates/governance/tests/unit/host.rs +++ b/crates/governance/tests/unit/host.rs @@ -132,6 +132,44 @@ fn cancelled_running_work_keeps_its_slot_until_natural_return() { owner.finish().expect("natural finish"); } #[test] +fn active_compiler_observes_both_request_and_owner_cancellation() { + for close_owner in [false, true] { + let (entered, started) = mpsc::channel(); + let (release, wait) = mpsc::channel(); + let owner = Owner::start(1, move |inbox| { + inbox.run_with_cancellable_governor( + (), + |_, source, cancel| { + entered.send(cancel.clone()).expect("active compiler token"); + wait.recv().expect("release compiler"); + copied(source) + }, + |_, _| Err(SourceError::Contract), + ) + }); + let release = Release(Some(release)); + let mut job = owner.client.submit(original()).expect("admitted"); + let cancel = started + .recv_timeout(Duration::from_secs(5)) + .expect("running"); + assert!(!cancel.is_cancelled()); + if close_owner { + owner.client.close(); + } else { + job.cancel(); + } + assert!(cancel.is_cancelled()); + let expected = if close_owner { + SourceJobError::Closed + } else { + SourceJobError::Cancelled + }; + assert!(matches!(runtime().block_on(job), Err(error) if error == expected)); + drop(release); + owner.finish().expect("natural finish"); + } +} +#[test] fn cancelled_queued_work_does_not_enter_the_compiler() { let (entered, started) = mpsc::channel(); let (release, wait) = mpsc::channel(); From 9c96a9fe928f3f0b90571b19b1a58e6a41fac000 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 21:12:22 +0800 Subject: [PATCH 028/105] Retain the failing Provider subtest from native Go events --- go/internal/devrunner/plan.go | 2 +- go/internal/devrunner/retention.go | 66 ++++++++++++++++++++++++- go/internal/devrunner/retention_test.go | 22 +++++++++ 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index 7d6f0f00..6da6954e 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -141,7 +141,7 @@ func Plan(goBinary string) []Stage { {"source-owner-quint-safety", "quint", []string{"run", "dev/proofs/quint/SourceOwner.qnt", "--main", "SourceOwner", "--invariant", "safe", "--max-samples", "1000", "--max-steps", "60", "--seed", "293"}}, {"go-provider-server-build", "cargo", []string{"build", "-p", "weaver-server", "--bin", "weaver-server", "--features", "arrow", "--locked", "--offline", "-j", "4"}}, {"go-provider-observer-build", "cargo", []string{"test", "-p", "weaver-server", "--lib", "--features", "arrow", "--locked", "--offline", "-j", "4", "--no-run"}}, - {"go-provider-grpc-integration", goBinary, []string{"-C", "go", "test", "-count=1", "-race", "-tags=integration", "-timeout=10m", "./dev", "-run", "TestProvider", "-skip", providerSpecReviewCase, "-v"}}, + {"go-provider-grpc-integration", goBinary, []string{"-C", "go", "test", "-json", "-count=1", "-race", "-tags=integration", "-timeout=10m", "./dev", "-run", "TestProvider", "-skip", providerSpecReviewCase}}, {"policy-provider-spec-integration", goBinary, []string{"-C", "go", "test", "-count=1", "-race", "-tags=integration", "-timeout=4m", "./dev", "-run", providerSpecReviewCase, "-v"}}, {"control-bundle-pbt", goBinary, []string{"-C", "go", "test", "./internal/config", "-run", "^$", "-fuzz", "FuzzSourceBundleCannotExpandOriginalSelection", "-fuzztime=3s"}}, {"authority-publication-quint-tests", "quint", []string{"test", "dev/proofs/quint/AuthorityPublication.qnt", "--main", "AuthorityPublication", "--seed", "293", "--match", "^authority[A-Z]"}}, diff --git a/go/internal/devrunner/retention.go b/go/internal/devrunner/retention.go index 48129cc8..5c4b9c80 100644 --- a/go/internal/devrunner/retention.go +++ b/go/internal/devrunner/retention.go @@ -15,6 +15,7 @@ import ( "io" "os" "path/filepath" + "slices" ) const failureTailBytes int64 = 4096 @@ -67,7 +68,7 @@ func summarizeOutput(directory string, result *Result) error { } // Preserve the first causal diagnostic as well as the final status. // A passing test suffix must not erase an earlier failing case. - head, err := firstFailureExcerpt(file) + head, err := failureExcerpt(file, slices.Contains(result.Args, "-json")) if err != nil { return err } @@ -87,6 +88,65 @@ func summarizeOutput(directory string, result *Result) error { return nil } +func failureExcerpt(file io.ReadSeeker, goJSON bool) ([]byte, error) { + if goJSON { + head, err := firstGoTestFailure(file) + if err != nil || len(head) != 0 { + return head, err + } + if _, err := file.Seek(0, io.SeekStart); err != nil { + return nil, err + } + } + return firstFailureExcerpt(file) +} + +type goTestEvent struct { + Action, Test, Output string +} + +func firstGoTestFailure(file io.ReadSeeker) ([]byte, error) { + stream := bufio.NewScanner(file) + var failed string + for stream.Scan() { + var event goTestEvent + if json.Unmarshal(stream.Bytes(), &event) == nil && event.Action == "fail" && event.Test != "" { + failed = event.Test + break + } + } + if failed == "" { + return nil, stream.Err() + } + if _, err := file.Seek(0, io.SeekStart); err != nil { + return nil, err + } + const limit = 2048 + header := fmt.Appendf(nil, "Go test failed: %s\n", failed) + if len(header) >= limit { + return header[:limit], nil + } + available := limit - len(header) + var output []byte + stream = bufio.NewScanner(file) + for stream.Scan() { + var event goTestEvent + if json.Unmarshal(stream.Bytes(), &event) != nil || event.Test != failed { + continue + } + if event.Action == "fail" { + break + } + if event.Action == "output" { + output = append(output, event.Output...) + if len(output) > available { + output = append(output[:0], output[len(output)-available:]...) + } + } + } + return append(header, output...), stream.Err() +} + func firstFailureExcerpt(input io.Reader) ([]byte, error) { reader := bufio.NewReaderSize(input, 4096) var excerpt, preceding []byte @@ -98,7 +158,9 @@ func firstFailureExcerpt(input io.Reader) ([]byte, error) { bytes.Contains(fragment, []byte("control readiness:")) || bytes.Contains(fragment, []byte("negative control")) || bytes.HasPrefix(fragment, []byte("panic: test timed out after ")) || - bytes.HasPrefix(fragment, []byte("SIGQUIT: quit")) + bytes.HasPrefix(fragment, []byte("SIGQUIT: quit")) || + bytes.Contains(fragment, []byte(`"Output":"panic: test timed out after `)) || + bytes.Contains(fragment, []byte(`"Output":"SIGQUIT: quit`)) if len(excerpt) == 0 && marker { // Go prints t.Fatal diagnostics before the FAIL marker. Keep a // bounded preceding window rather than retaining only later passes. diff --git a/go/internal/devrunner/retention_test.go b/go/internal/devrunner/retention_test.go index a24a1ce1..9a347903 100644 --- a/go/internal/devrunner/retention_test.go +++ b/go/internal/devrunner/retention_test.go @@ -140,6 +140,28 @@ func TestFailureSummaryRetainsFirstCauseBeforePassingSuffix(t *testing.T) { } } +func TestGoTestFailureRetainsTheFailedSubtest(t *testing.T) { + directory := t.TempDir() + output := `{"Action":"output","Test":"TestGate/early","Output":"native cut was not observed\n"} +` + strings.Repeat(`{"Action":"output","Test":"TestGate/selected","Output":"passing sibling\n"} +`, 100) + `{"Action":"fail","Test":"TestGate/early"} +{"Action":"fail","Test":"TestGate"} +` + if err := os.WriteFile(filepath.Join(directory, "suite.log"), []byte(output), 0600); err != nil { + t.Fatal(err) + } + result := Result{Status: "FAIL", Log: "suite.log", Args: []string{"test", "-json"}} + if err := summarizeOutput(directory, &result); err != nil { + t.Fatal(err) + } + cause, _, _ := strings.Cut(result.FailureTail, "[... final output ...]") + if !strings.Contains(cause, "TestGate/early") || + !strings.Contains(cause, "native cut was not observed") || + strings.Contains(cause, "passing sibling") || len(result.FailureTail) > int(failureTailBytes) { + t.Fatalf("failed subtest evidence lost: %q", cause) + } +} + func FuzzFailureExcerptRetainsPrecedingDiagnostic(f *testing.F) { f.Add(uint16(0), uint16(0)) f.Add(uint16(8191), uint16(8191)) From 318429ffaf91d9ec41de07b8ce7b70ccb84d0b67 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 21:19:46 +0800 Subject: [PATCH 029/105] Carry sealed Workflow topology through the source boundary --- crates/governance/src/catalog/text_size.rs | 9 + crates/governance/src/scheme_input/records.rs | 59 +- crates/governance/src/scheme_input/values.rs | 8 + crates/governance/src/source.rs | 31 +- crates/governance/tests/unit/fixture.rs | 2 + crates/server/src/source_artifact.rs | 17 + crates/server/tests/unit/governance_owner.rs | 2 + go/api/gateway/v1/gateway.pb.go | 747 +++++++++++------- go/internal/config/bundle.go | 95 ++- go/internal/config/freeze.go | 15 + go/internal/controlplane/source_compile.go | 12 + proto/gateway/v1/gateway.proto | 4 +- 12 files changed, 676 insertions(+), 325 deletions(-) diff --git a/crates/governance/src/catalog/text_size.rs b/crates/governance/src/catalog/text_size.rs index 9020ba53..6ecbd0b0 100644 --- a/crates/governance/src/catalog/text_size.rs +++ b/crates/governance/src/catalog/text_size.rs @@ -36,11 +36,20 @@ pub(super) fn text_bytes(data: &SourceData) -> Option { schema, family, open_nodes, + workflow_edges, + workflow_selectors, } = governance; let mut bytes = Bytes(0); bytes.add(schema)?; bytes.add(family)?; bytes.strings(open_nodes)?; + for (child, parent) in workflow_edges { + bytes.add(child)?; + bytes.add(parent)?; + } + for selector in workflow_selectors { + bytes.strings(selector)?; + } for task in tasks { let Task { family, diff --git a/crates/governance/src/scheme_input/records.rs b/crates/governance/src/scheme_input/records.rs index d319cbb1..89d678a9 100644 --- a/crates/governance/src/scheme_input/records.rs +++ b/crates/governance/src/scheme_input/records.rs @@ -19,16 +19,7 @@ pub fn root_source<'r>(vm: &'r GerbilRuntime, source: &OwnedSource) -> Result(vm: &'r GerbilRuntime, source: &OwnedSource) -> Result>>()?, )?; + let publication = root_publication(&input, publication)?; + input.record(vec![ + ("governance", selection), + ("tasks", tasks), + ("plans", plans), + ("publication", publication), + ]) +} + +fn root_selection<'r>(input: &Input<'r>, governance: &SourceSelection) -> Result> { + let SourceSelection { + schema, + family, + open_nodes, + workflow_edges, + workflow_selectors, + } = governance; + let mut selection = vec![ + ("schema", input.text(schema)?), + ("family", input.text(family)?), + ("open_nodes", input.strings(open_nodes)?), + ]; + if !workflow_edges.is_empty() { + selection.push(("workflow_edges", input.edges(workflow_edges)?)); + } + if !workflow_selectors.is_empty() { + selection.push(( + "workflow_selectors", + input.vector( + workflow_selectors + .iter() + .map(|row| input.strings(row)) + .collect::>>()?, + )?, + )); + } + input.record(selection) +} + +fn root_publication<'r>(input: &Input<'r>, publication: &Publication) -> Result> { let Publication { operation_id, expected_revision, @@ -57,13 +88,7 @@ pub fn root_source<'r>(vm: &'r GerbilRuntime, source: &OwnedSource) -> Result(input: &Input<'r>, task: &Task) -> Result> { let Task { diff --git a/crates/governance/src/scheme_input/values.rs b/crates/governance/src/scheme_input/values.rs index 411bc646..337557a5 100644 --- a/crates/governance/src/scheme_input/values.rs +++ b/crates/governance/src/scheme_input/values.rs @@ -85,6 +85,14 @@ impl<'r> Input<'r> { )? .into_object()) } + pub(super) fn edges(&self, edges: &[(String, String)]) -> Result> { + self.vector( + edges + .iter() + .map(|(child, parent)| self.vector(vec![self.text(child)?, self.text(parent)?])) + .collect::>>()?, + ) + } pub(super) fn strings(&self, values: &[String]) -> Result> { if values.len() > 64 { return Err(SourceError::Bound); diff --git a/crates/governance/src/source.rs b/crates/governance/src/source.rs index ab313c7e..75d459dd 100644 --- a/crates/governance/src/source.rs +++ b/crates/governance/src/source.rs @@ -30,6 +30,10 @@ pub struct SourceSelection { pub schema: String, pub family: String, pub open_nodes: Vec, + #[serde(default)] + pub workflow_edges: Vec<(String, String)>, + #[serde(default)] + pub workflow_selectors: Vec<[String; 3]>, } #[derive(Clone, PartialEq, Eq, Deserialize)] #[serde(deny_unknown_fields)] @@ -82,7 +86,32 @@ fn validate(wire: &SourceData) -> Result<(), SourceError> { .map_err(|_| SourceError::Contract)?; let selected: BTreeSet<_> = wire.governance.open_nodes.iter().collect(); let original: BTreeSet<_> = task.nodes.iter().collect(); - if wire.governance.schema != "agentic-ai-lab.loop-governor.v1" + let supported = match wire.governance.schema.as_str() { + "agentic-ai-lab.loop-governor.v1" => wire.governance.workflow_edges.is_empty(), + weaver_contracts::SESSION_WORKFLOW_SCHEMA => { + selected.len() >= 2 && wire.governance.workflow_edges.is_empty() + } + weaver_contracts::SESSION_NESTED_SCHEMA => weaver_contracts::validate_session_selectors( + &wire.governance.open_nodes, + &wire.governance.workflow_edges, + &wire.governance.workflow_selectors, + ) + .is_ok(), + weaver_contracts::SESSION_CHOICE_SCHEMA => weaver_contracts::validate_session_choice( + &wire.governance.open_nodes, + &wire.governance.workflow_edges, + ) + .is_ok(), + weaver_contracts::SESSION_DAG_SCHEMA => weaver_contracts::validate_session_dag( + &wire.governance.open_nodes, + &wire.governance.workflow_edges, + ) + .is_ok(), + _ => false, + }; + if !supported + || (wire.governance.schema != weaver_contracts::SESSION_NESTED_SCHEMA + && !wire.governance.workflow_selectors.is_empty()) || wire.governance.family != task.family || selected.len() != wire.governance.open_nodes.len() || selected != original diff --git a/crates/governance/tests/unit/fixture.rs b/crates/governance/tests/unit/fixture.rs index 47ab1ced..6fdec521 100644 --- a/crates/governance/tests/unit/fixture.rs +++ b/crates/governance/tests/unit/fixture.rs @@ -21,6 +21,8 @@ pub fn source() -> SourceData { governance: SourceSelection { schema: "agentic-ai-lab.loop-governor.v1".into(), family: "f".into(), + workflow_edges: vec![], + workflow_selectors: vec![], open_nodes: vec!["infer".into(), "next".into()], }, tasks: vec![task], diff --git a/crates/server/src/source_artifact.rs b/crates/server/src/source_artifact.rs index c4c17af7..aa16831d 100644 --- a/crates/server/src/source_artifact.rs +++ b/crates/server/src/source_artifact.rs @@ -17,6 +17,8 @@ pub(crate) fn artifact(bound: &BoundSource) -> pb::SourceArtifact { schema, family, open_nodes, + workflow_edges, + workflow_selectors, } = governance; let Publication { operation_id, @@ -30,6 +32,21 @@ pub(crate) fn artifact(bound: &BoundSource) -> pb::SourceArtifact { schema: schema.clone(), family: family.clone(), open_nodes: open_nodes.clone(), + workflow_selectors: workflow_selectors + .iter() + .map(|[selector, left, right]| pb::WorkflowSelector { + selector: selector.clone(), + left: left.clone(), + right: right.clone(), + }) + .collect(), + workflow_edges: workflow_edges + .iter() + .map(|(dependent, dependency)| pb::WorkflowEdge { + dependent: dependent.clone(), + dependency: dependency.clone(), + }) + .collect(), }), tasks: tasks.iter().map(task).collect(), plans: plans.iter().map(plan).collect(), diff --git a/crates/server/tests/unit/governance_owner.rs b/crates/server/tests/unit/governance_owner.rs index 66b34ca8..7993ef37 100644 --- a/crates/server/tests/unit/governance_owner.rs +++ b/crates/server/tests/unit/governance_owner.rs @@ -30,6 +30,8 @@ fn original() -> OwnedSource { governance: weaver_governance::SourceSelection { schema: "agentic-ai-lab.loop-governor.v1".into(), family: task.family.clone(), + workflow_edges: vec![], + workflow_selectors: vec![], open_nodes: task.nodes.clone(), }, tasks: vec![task], diff --git a/go/api/gateway/v1/gateway.pb.go b/go/api/gateway/v1/gateway.pb.go index dd748065..f58dde43 100644 --- a/go/api/gateway/v1/gateway.pb.go +++ b/go/api/gateway/v1/gateway.pb.go @@ -661,18 +661,132 @@ func (x *FactBarrierResolution) GetRemainingPendingPrefix() string { return "" } -type GovernanceSelection struct { +type WorkflowEdge struct { + state protoimpl.MessageState `protogen:"open.v1"` + Dependent string `protobuf:"bytes,1,opt,name=dependent,proto3" json:"dependent,omitempty"` + Dependency string `protobuf:"bytes,2,opt,name=dependency,proto3" json:"dependency,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WorkflowEdge) Reset() { + *x = WorkflowEdge{} + mi := &file_gateway_v1_gateway_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WorkflowEdge) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WorkflowEdge) ProtoMessage() {} + +func (x *WorkflowEdge) ProtoReflect() protoreflect.Message { + mi := &file_gateway_v1_gateway_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WorkflowEdge.ProtoReflect.Descriptor instead. +func (*WorkflowEdge) Descriptor() ([]byte, []int) { + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{6} +} + +func (x *WorkflowEdge) GetDependent() string { + if x != nil { + return x.Dependent + } + return "" +} + +func (x *WorkflowEdge) GetDependency() string { + if x != nil { + return x.Dependency + } + return "" +} + +type WorkflowSelector struct { state protoimpl.MessageState `protogen:"open.v1"` - Schema string `protobuf:"bytes,1,opt,name=schema,proto3" json:"schema,omitempty"` - Family string `protobuf:"bytes,2,opt,name=family,proto3" json:"family,omitempty"` - OpenNodes []string `protobuf:"bytes,3,rep,name=open_nodes,json=openNodes,proto3" json:"open_nodes,omitempty"` + Selector string `protobuf:"bytes,1,opt,name=selector,proto3" json:"selector,omitempty"` + Left string `protobuf:"bytes,2,opt,name=left,proto3" json:"left,omitempty"` + Right string `protobuf:"bytes,3,opt,name=right,proto3" json:"right,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } +func (x *WorkflowSelector) Reset() { + *x = WorkflowSelector{} + mi := &file_gateway_v1_gateway_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WorkflowSelector) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WorkflowSelector) ProtoMessage() {} + +func (x *WorkflowSelector) ProtoReflect() protoreflect.Message { + mi := &file_gateway_v1_gateway_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WorkflowSelector.ProtoReflect.Descriptor instead. +func (*WorkflowSelector) Descriptor() ([]byte, []int) { + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{7} +} + +func (x *WorkflowSelector) GetSelector() string { + if x != nil { + return x.Selector + } + return "" +} + +func (x *WorkflowSelector) GetLeft() string { + if x != nil { + return x.Left + } + return "" +} + +func (x *WorkflowSelector) GetRight() string { + if x != nil { + return x.Right + } + return "" +} + +type GovernanceSelection struct { + state protoimpl.MessageState `protogen:"open.v1"` + Schema string `protobuf:"bytes,1,opt,name=schema,proto3" json:"schema,omitempty"` + Family string `protobuf:"bytes,2,opt,name=family,proto3" json:"family,omitempty"` + OpenNodes []string `protobuf:"bytes,3,rep,name=open_nodes,json=openNodes,proto3" json:"open_nodes,omitempty"` + WorkflowEdges []*WorkflowEdge `protobuf:"bytes,4,rep,name=workflow_edges,json=workflowEdges,proto3" json:"workflow_edges,omitempty"` + WorkflowSelectors []*WorkflowSelector `protobuf:"bytes,5,rep,name=workflow_selectors,json=workflowSelectors,proto3" json:"workflow_selectors,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + func (x *GovernanceSelection) Reset() { *x = GovernanceSelection{} - mi := &file_gateway_v1_gateway_proto_msgTypes[6] + mi := &file_gateway_v1_gateway_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -684,7 +798,7 @@ func (x *GovernanceSelection) String() string { func (*GovernanceSelection) ProtoMessage() {} func (x *GovernanceSelection) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[6] + mi := &file_gateway_v1_gateway_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -697,7 +811,7 @@ func (x *GovernanceSelection) ProtoReflect() protoreflect.Message { // Deprecated: Use GovernanceSelection.ProtoReflect.Descriptor instead. func (*GovernanceSelection) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{6} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{8} } func (x *GovernanceSelection) GetSchema() string { @@ -721,6 +835,20 @@ func (x *GovernanceSelection) GetOpenNodes() []string { return nil } +func (x *GovernanceSelection) GetWorkflowEdges() []*WorkflowEdge { + if x != nil { + return x.WorkflowEdges + } + return nil +} + +func (x *GovernanceSelection) GetWorkflowSelectors() []*WorkflowSelector { + if x != nil { + return x.WorkflowSelectors + } + return nil +} + type SourceArtifact struct { state protoimpl.MessageState `protogen:"open.v1"` Governance *GovernanceSelection `protobuf:"bytes,1,opt,name=governance,proto3" json:"governance,omitempty"` @@ -733,7 +861,7 @@ type SourceArtifact struct { func (x *SourceArtifact) Reset() { *x = SourceArtifact{} - mi := &file_gateway_v1_gateway_proto_msgTypes[7] + mi := &file_gateway_v1_gateway_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -745,7 +873,7 @@ func (x *SourceArtifact) String() string { func (*SourceArtifact) ProtoMessage() {} func (x *SourceArtifact) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[7] + mi := &file_gateway_v1_gateway_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -758,7 +886,7 @@ func (x *SourceArtifact) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceArtifact.ProtoReflect.Descriptor instead. func (*SourceArtifact) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{7} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{9} } func (x *SourceArtifact) GetGovernance() *GovernanceSelection { @@ -801,7 +929,7 @@ type CompiledSource struct { func (x *CompiledSource) Reset() { *x = CompiledSource{} - mi := &file_gateway_v1_gateway_proto_msgTypes[8] + mi := &file_gateway_v1_gateway_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -813,7 +941,7 @@ func (x *CompiledSource) String() string { func (*CompiledSource) ProtoMessage() {} func (x *CompiledSource) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[8] + mi := &file_gateway_v1_gateway_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -826,7 +954,7 @@ func (x *CompiledSource) ProtoReflect() protoreflect.Message { // Deprecated: Use CompiledSource.ProtoReflect.Descriptor instead. func (*CompiledSource) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{8} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{10} } func (x *CompiledSource) GetProducer() string { @@ -860,7 +988,7 @@ type OperationKey struct { func (x *OperationKey) Reset() { *x = OperationKey{} - mi := &file_gateway_v1_gateway_proto_msgTypes[9] + mi := &file_gateway_v1_gateway_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -872,7 +1000,7 @@ func (x *OperationKey) String() string { func (*OperationKey) ProtoMessage() {} func (x *OperationKey) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[9] + mi := &file_gateway_v1_gateway_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -885,7 +1013,7 @@ func (x *OperationKey) ProtoReflect() protoreflect.Message { // Deprecated: Use OperationKey.ProtoReflect.Descriptor instead. func (*OperationKey) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{9} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{11} } func (x *OperationKey) GetFamily() string { @@ -912,7 +1040,7 @@ type Route struct { func (x *Route) Reset() { *x = Route{} - mi := &file_gateway_v1_gateway_proto_msgTypes[10] + mi := &file_gateway_v1_gateway_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -924,7 +1052,7 @@ func (x *Route) String() string { func (*Route) ProtoMessage() {} func (x *Route) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[10] + mi := &file_gateway_v1_gateway_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -937,7 +1065,7 @@ func (x *Route) ProtoReflect() protoreflect.Message { // Deprecated: Use Route.ProtoReflect.Descriptor instead. func (*Route) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{10} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{12} } func (x *Route) GetTarget() string { @@ -972,7 +1100,7 @@ type ProviderPlan struct { func (x *ProviderPlan) Reset() { *x = ProviderPlan{} - mi := &file_gateway_v1_gateway_proto_msgTypes[11] + mi := &file_gateway_v1_gateway_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -984,7 +1112,7 @@ func (x *ProviderPlan) String() string { func (*ProviderPlan) ProtoMessage() {} func (x *ProviderPlan) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[11] + mi := &file_gateway_v1_gateway_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -997,7 +1125,7 @@ func (x *ProviderPlan) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderPlan.ProtoReflect.Descriptor instead. func (*ProviderPlan) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{11} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{13} } func (x *ProviderPlan) GetFamily() string { @@ -1082,7 +1210,7 @@ type ProviderRequest struct { func (x *ProviderRequest) Reset() { *x = ProviderRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[12] + mi := &file_gateway_v1_gateway_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1094,7 +1222,7 @@ func (x *ProviderRequest) String() string { func (*ProviderRequest) ProtoMessage() {} func (x *ProviderRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[12] + mi := &file_gateway_v1_gateway_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1107,7 +1235,7 @@ func (x *ProviderRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderRequest.ProtoReflect.Descriptor instead. func (*ProviderRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{12} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{14} } func (x *ProviderRequest) GetPlan() *ProviderPlan { @@ -1148,7 +1276,7 @@ type ProviderCatalogSnapshot struct { func (x *ProviderCatalogSnapshot) Reset() { *x = ProviderCatalogSnapshot{} - mi := &file_gateway_v1_gateway_proto_msgTypes[13] + mi := &file_gateway_v1_gateway_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1160,7 +1288,7 @@ func (x *ProviderCatalogSnapshot) String() string { func (*ProviderCatalogSnapshot) ProtoMessage() {} func (x *ProviderCatalogSnapshot) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[13] + mi := &file_gateway_v1_gateway_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1173,7 +1301,7 @@ func (x *ProviderCatalogSnapshot) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderCatalogSnapshot.ProtoReflect.Descriptor instead. func (*ProviderCatalogSnapshot) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{13} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{15} } func (x *ProviderCatalogSnapshot) GetVersion() string { @@ -1199,7 +1327,7 @@ type ProviderCatalogChange struct { func (x *ProviderCatalogChange) Reset() { *x = ProviderCatalogChange{} - mi := &file_gateway_v1_gateway_proto_msgTypes[14] + mi := &file_gateway_v1_gateway_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1211,7 +1339,7 @@ func (x *ProviderCatalogChange) String() string { func (*ProviderCatalogChange) ProtoMessage() {} func (x *ProviderCatalogChange) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[14] + mi := &file_gateway_v1_gateway_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1224,7 +1352,7 @@ func (x *ProviderCatalogChange) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderCatalogChange.ProtoReflect.Descriptor instead. func (*ProviderCatalogChange) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{14} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{16} } func (x *ProviderCatalogChange) GetRecord() []byte { @@ -1246,7 +1374,7 @@ type Event struct { func (x *Event) Reset() { *x = Event{} - mi := &file_gateway_v1_gateway_proto_msgTypes[15] + mi := &file_gateway_v1_gateway_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1258,7 +1386,7 @@ func (x *Event) String() string { func (*Event) ProtoMessage() {} func (x *Event) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[15] + mi := &file_gateway_v1_gateway_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1271,7 +1399,7 @@ func (x *Event) ProtoReflect() protoreflect.Message { // Deprecated: Use Event.ProtoReflect.Descriptor instead. func (*Event) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{15} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{17} } func (x *Event) GetSequence() uint64 { @@ -1313,7 +1441,7 @@ type ArrowBatch struct { func (x *ArrowBatch) Reset() { *x = ArrowBatch{} - mi := &file_gateway_v1_gateway_proto_msgTypes[16] + mi := &file_gateway_v1_gateway_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1325,7 +1453,7 @@ func (x *ArrowBatch) String() string { func (*ArrowBatch) ProtoMessage() {} func (x *ArrowBatch) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[16] + mi := &file_gateway_v1_gateway_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1338,7 +1466,7 @@ func (x *ArrowBatch) ProtoReflect() protoreflect.Message { // Deprecated: Use ArrowBatch.ProtoReflect.Descriptor instead. func (*ArrowBatch) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{16} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{18} } func (x *ArrowBatch) GetIpc() []byte { @@ -1377,7 +1505,7 @@ type ProviderFrame struct { func (x *ProviderFrame) Reset() { *x = ProviderFrame{} - mi := &file_gateway_v1_gateway_proto_msgTypes[17] + mi := &file_gateway_v1_gateway_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1389,7 +1517,7 @@ func (x *ProviderFrame) String() string { func (*ProviderFrame) ProtoMessage() {} func (x *ProviderFrame) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[17] + mi := &file_gateway_v1_gateway_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1402,7 +1530,7 @@ func (x *ProviderFrame) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderFrame.ProtoReflect.Descriptor instead. func (*ProviderFrame) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{17} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{19} } func (x *ProviderFrame) GetTarget() string { @@ -1476,7 +1604,7 @@ type ProviderReceipt struct { func (x *ProviderReceipt) Reset() { *x = ProviderReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[18] + mi := &file_gateway_v1_gateway_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1488,7 +1616,7 @@ func (x *ProviderReceipt) String() string { func (*ProviderReceipt) ProtoMessage() {} func (x *ProviderReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[18] + mi := &file_gateway_v1_gateway_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1501,7 +1629,7 @@ func (x *ProviderReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderReceipt.ProtoReflect.Descriptor instead. func (*ProviderReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{18} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{20} } func (x *ProviderReceipt) GetFamily() string { @@ -1580,7 +1708,7 @@ type Task struct { func (x *Task) Reset() { *x = Task{} - mi := &file_gateway_v1_gateway_proto_msgTypes[19] + mi := &file_gateway_v1_gateway_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1592,7 +1720,7 @@ func (x *Task) String() string { func (*Task) ProtoMessage() {} func (x *Task) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[19] + mi := &file_gateway_v1_gateway_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1605,7 +1733,7 @@ func (x *Task) ProtoReflect() protoreflect.Message { // Deprecated: Use Task.ProtoReflect.Descriptor instead. func (*Task) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{19} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{21} } func (x *Task) GetFamily() string { @@ -1705,7 +1833,7 @@ type ProviderProfile struct { func (x *ProviderProfile) Reset() { *x = ProviderProfile{} - mi := &file_gateway_v1_gateway_proto_msgTypes[20] + mi := &file_gateway_v1_gateway_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1717,7 +1845,7 @@ func (x *ProviderProfile) String() string { func (*ProviderProfile) ProtoMessage() {} func (x *ProviderProfile) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[20] + mi := &file_gateway_v1_gateway_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1730,7 +1858,7 @@ func (x *ProviderProfile) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderProfile.ProtoReflect.Descriptor instead. func (*ProviderProfile) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{20} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{22} } func (x *ProviderProfile) GetId() string { @@ -1777,7 +1905,7 @@ type RegisterTaskRequest struct { func (x *RegisterTaskRequest) Reset() { *x = RegisterTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[21] + mi := &file_gateway_v1_gateway_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1789,7 +1917,7 @@ func (x *RegisterTaskRequest) String() string { func (*RegisterTaskRequest) ProtoMessage() {} func (x *RegisterTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[21] + mi := &file_gateway_v1_gateway_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1802,7 +1930,7 @@ func (x *RegisterTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{21} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{23} } func (x *RegisterTaskRequest) GetTask() *Task { @@ -1824,7 +1952,7 @@ type DomainBinding struct { func (x *DomainBinding) Reset() { *x = DomainBinding{} - mi := &file_gateway_v1_gateway_proto_msgTypes[22] + mi := &file_gateway_v1_gateway_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1836,7 +1964,7 @@ func (x *DomainBinding) String() string { func (*DomainBinding) ProtoMessage() {} func (x *DomainBinding) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[22] + mi := &file_gateway_v1_gateway_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1849,7 +1977,7 @@ func (x *DomainBinding) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainBinding.ProtoReflect.Descriptor instead. func (*DomainBinding) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{22} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{24} } func (x *DomainBinding) GetOrigin() string { @@ -1894,7 +2022,7 @@ type DomainStamp struct { func (x *DomainStamp) Reset() { *x = DomainStamp{} - mi := &file_gateway_v1_gateway_proto_msgTypes[23] + mi := &file_gateway_v1_gateway_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1906,7 +2034,7 @@ func (x *DomainStamp) String() string { func (*DomainStamp) ProtoMessage() {} func (x *DomainStamp) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[23] + mi := &file_gateway_v1_gateway_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1919,7 +2047,7 @@ func (x *DomainStamp) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainStamp.ProtoReflect.Descriptor instead. func (*DomainStamp) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{23} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{25} } func (x *DomainStamp) GetOrigin() string { @@ -1978,7 +2106,7 @@ type DomainView struct { func (x *DomainView) Reset() { *x = DomainView{} - mi := &file_gateway_v1_gateway_proto_msgTypes[24] + mi := &file_gateway_v1_gateway_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1990,7 +2118,7 @@ func (x *DomainView) String() string { func (*DomainView) ProtoMessage() {} func (x *DomainView) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[24] + mi := &file_gateway_v1_gateway_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2003,7 +2131,7 @@ func (x *DomainView) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainView.ProtoReflect.Descriptor instead. func (*DomainView) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{24} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{26} } func (x *DomainView) GetFamily() string { @@ -2059,7 +2187,7 @@ type RegisterDomainTaskRequest struct { func (x *RegisterDomainTaskRequest) Reset() { *x = RegisterDomainTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[25] + mi := &file_gateway_v1_gateway_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2071,7 +2199,7 @@ func (x *RegisterDomainTaskRequest) String() string { func (*RegisterDomainTaskRequest) ProtoMessage() {} func (x *RegisterDomainTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[25] + mi := &file_gateway_v1_gateway_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2084,7 +2212,7 @@ func (x *RegisterDomainTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterDomainTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterDomainTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{25} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{27} } func (x *RegisterDomainTaskRequest) GetTask() *Task { @@ -2119,7 +2247,7 @@ type TaskAdmission struct { func (x *TaskAdmission) Reset() { *x = TaskAdmission{} - mi := &file_gateway_v1_gateway_proto_msgTypes[26] + mi := &file_gateway_v1_gateway_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2131,7 +2259,7 @@ func (x *TaskAdmission) String() string { func (*TaskAdmission) ProtoMessage() {} func (x *TaskAdmission) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[26] + mi := &file_gateway_v1_gateway_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2144,7 +2272,7 @@ func (x *TaskAdmission) ProtoReflect() protoreflect.Message { // Deprecated: Use TaskAdmission.ProtoReflect.Descriptor instead. func (*TaskAdmission) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{26} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{28} } func (x *TaskAdmission) GetTaskKey() string { @@ -2180,7 +2308,7 @@ type RegisterOriginalTaskRequest struct { func (x *RegisterOriginalTaskRequest) Reset() { *x = RegisterOriginalTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[27] + mi := &file_gateway_v1_gateway_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2192,7 +2320,7 @@ func (x *RegisterOriginalTaskRequest) String() string { func (*RegisterOriginalTaskRequest) ProtoMessage() {} func (x *RegisterOriginalTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[27] + mi := &file_gateway_v1_gateway_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2205,7 +2333,7 @@ func (x *RegisterOriginalTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterOriginalTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterOriginalTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{27} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{29} } func (x *RegisterOriginalTaskRequest) GetTask() *Task { @@ -2250,7 +2378,7 @@ type TaskAdmissionReceipt struct { func (x *TaskAdmissionReceipt) Reset() { *x = TaskAdmissionReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[28] + mi := &file_gateway_v1_gateway_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2262,7 +2390,7 @@ func (x *TaskAdmissionReceipt) String() string { func (*TaskAdmissionReceipt) ProtoMessage() {} func (x *TaskAdmissionReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[28] + mi := &file_gateway_v1_gateway_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2275,7 +2403,7 @@ func (x *TaskAdmissionReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use TaskAdmissionReceipt.ProtoReflect.Descriptor instead. func (*TaskAdmissionReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{28} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{30} } func (x *TaskAdmissionReceipt) GetOperationId() string { @@ -2330,7 +2458,7 @@ type FamilyAliasRequest struct { func (x *FamilyAliasRequest) Reset() { *x = FamilyAliasRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[29] + mi := &file_gateway_v1_gateway_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2342,7 +2470,7 @@ func (x *FamilyAliasRequest) String() string { func (*FamilyAliasRequest) ProtoMessage() {} func (x *FamilyAliasRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[29] + mi := &file_gateway_v1_gateway_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2355,7 +2483,7 @@ func (x *FamilyAliasRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FamilyAliasRequest.ProtoReflect.Descriptor instead. func (*FamilyAliasRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{29} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{31} } func (x *FamilyAliasRequest) GetFamily() string { @@ -2389,7 +2517,7 @@ type DomainMigration struct { func (x *DomainMigration) Reset() { *x = DomainMigration{} - mi := &file_gateway_v1_gateway_proto_msgTypes[30] + mi := &file_gateway_v1_gateway_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2401,7 +2529,7 @@ func (x *DomainMigration) String() string { func (*DomainMigration) ProtoMessage() {} func (x *DomainMigration) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[30] + mi := &file_gateway_v1_gateway_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2414,7 +2542,7 @@ func (x *DomainMigration) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainMigration.ProtoReflect.Descriptor instead. func (*DomainMigration) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{30} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{32} } func (x *DomainMigration) GetOperationId() string { @@ -2495,7 +2623,7 @@ type DomainMigrationReceipt struct { func (x *DomainMigrationReceipt) Reset() { *x = DomainMigrationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[31] + mi := &file_gateway_v1_gateway_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2507,7 +2635,7 @@ func (x *DomainMigrationReceipt) String() string { func (*DomainMigrationReceipt) ProtoMessage() {} func (x *DomainMigrationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[31] + mi := &file_gateway_v1_gateway_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2520,7 +2648,7 @@ func (x *DomainMigrationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainMigrationReceipt.ProtoReflect.Descriptor instead. func (*DomainMigrationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{31} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{33} } func (x *DomainMigrationReceipt) GetOperationId() string { @@ -2583,7 +2711,7 @@ type RegisterPublishedTaskRequest struct { func (x *RegisterPublishedTaskRequest) Reset() { *x = RegisterPublishedTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[32] + mi := &file_gateway_v1_gateway_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2595,7 +2723,7 @@ func (x *RegisterPublishedTaskRequest) String() string { func (*RegisterPublishedTaskRequest) ProtoMessage() {} func (x *RegisterPublishedTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[32] + mi := &file_gateway_v1_gateway_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2608,7 +2736,7 @@ func (x *RegisterPublishedTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterPublishedTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterPublishedTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{32} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{34} } func (x *RegisterPublishedTaskRequest) GetTask() *Task { @@ -2638,7 +2766,7 @@ type PublishRequest struct { func (x *PublishRequest) Reset() { *x = PublishRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[33] + mi := &file_gateway_v1_gateway_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2650,7 +2778,7 @@ func (x *PublishRequest) String() string { func (*PublishRequest) ProtoMessage() {} func (x *PublishRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[33] + mi := &file_gateway_v1_gateway_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2663,7 +2791,7 @@ func (x *PublishRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PublishRequest.ProtoReflect.Descriptor instead. func (*PublishRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{33} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{35} } func (x *PublishRequest) GetExpectedRevision() uint64 { @@ -2714,7 +2842,7 @@ type PublicationReceipt struct { func (x *PublicationReceipt) Reset() { *x = PublicationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[34] + mi := &file_gateway_v1_gateway_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2726,7 +2854,7 @@ func (x *PublicationReceipt) String() string { func (*PublicationReceipt) ProtoMessage() {} func (x *PublicationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[34] + mi := &file_gateway_v1_gateway_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2739,7 +2867,7 @@ func (x *PublicationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationReceipt.ProtoReflect.Descriptor instead. func (*PublicationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{34} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{36} } func (x *PublicationReceipt) GetOperationId() string { @@ -2787,7 +2915,7 @@ type PublicationKey struct { func (x *PublicationKey) Reset() { *x = PublicationKey{} - mi := &file_gateway_v1_gateway_proto_msgTypes[35] + mi := &file_gateway_v1_gateway_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2799,7 +2927,7 @@ func (x *PublicationKey) String() string { func (*PublicationKey) ProtoMessage() {} func (x *PublicationKey) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[35] + mi := &file_gateway_v1_gateway_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2812,7 +2940,7 @@ func (x *PublicationKey) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationKey.ProtoReflect.Descriptor instead. func (*PublicationKey) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{35} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{37} } func (x *PublicationKey) GetOperationId() string { @@ -2839,7 +2967,7 @@ type SourceAuthorityView struct { func (x *SourceAuthorityView) Reset() { *x = SourceAuthorityView{} - mi := &file_gateway_v1_gateway_proto_msgTypes[36] + mi := &file_gateway_v1_gateway_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2851,7 +2979,7 @@ func (x *SourceAuthorityView) String() string { func (*SourceAuthorityView) ProtoMessage() {} func (x *SourceAuthorityView) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[36] + mi := &file_gateway_v1_gateway_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2864,7 +2992,7 @@ func (x *SourceAuthorityView) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceAuthorityView.ProtoReflect.Descriptor instead. func (*SourceAuthorityView) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{36} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{38} } func (x *SourceAuthorityView) GetEpoch() uint64 { @@ -2894,7 +3022,7 @@ type SourceRotationRequest struct { func (x *SourceRotationRequest) Reset() { *x = SourceRotationRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[37] + mi := &file_gateway_v1_gateway_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2906,7 +3034,7 @@ func (x *SourceRotationRequest) String() string { func (*SourceRotationRequest) ProtoMessage() {} func (x *SourceRotationRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[37] + mi := &file_gateway_v1_gateway_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2919,7 +3047,7 @@ func (x *SourceRotationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceRotationRequest.ProtoReflect.Descriptor instead. func (*SourceRotationRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{37} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{39} } func (x *SourceRotationRequest) GetOperationId() string { @@ -2962,7 +3090,7 @@ type SourceRotationReceipt struct { func (x *SourceRotationReceipt) Reset() { *x = SourceRotationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[38] + mi := &file_gateway_v1_gateway_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2974,7 +3102,7 @@ func (x *SourceRotationReceipt) String() string { func (*SourceRotationReceipt) ProtoMessage() {} func (x *SourceRotationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[38] + mi := &file_gateway_v1_gateway_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2987,7 +3115,7 @@ func (x *SourceRotationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceRotationReceipt.ProtoReflect.Descriptor instead. func (*SourceRotationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{38} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{40} } func (x *SourceRotationReceipt) GetOperationId() string { @@ -3031,7 +3159,7 @@ type AuthorityParent struct { func (x *AuthorityParent) Reset() { *x = AuthorityParent{} - mi := &file_gateway_v1_gateway_proto_msgTypes[39] + mi := &file_gateway_v1_gateway_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3043,7 +3171,7 @@ func (x *AuthorityParent) String() string { func (*AuthorityParent) ProtoMessage() {} func (x *AuthorityParent) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[39] + mi := &file_gateway_v1_gateway_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3056,7 +3184,7 @@ func (x *AuthorityParent) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthorityParent.ProtoReflect.Descriptor instead. func (*AuthorityParent) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{39} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{41} } func (x *AuthorityParent) GetRevision() uint64 { @@ -3100,7 +3228,7 @@ type ReviewAuthority struct { func (x *ReviewAuthority) Reset() { *x = ReviewAuthority{} - mi := &file_gateway_v1_gateway_proto_msgTypes[40] + mi := &file_gateway_v1_gateway_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3112,7 +3240,7 @@ func (x *ReviewAuthority) String() string { func (*ReviewAuthority) ProtoMessage() {} func (x *ReviewAuthority) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[40] + mi := &file_gateway_v1_gateway_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3125,7 +3253,7 @@ func (x *ReviewAuthority) ProtoReflect() protoreflect.Message { // Deprecated: Use ReviewAuthority.ProtoReflect.Descriptor instead. func (*ReviewAuthority) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{40} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{42} } func (x *ReviewAuthority) GetAudience() string { @@ -3174,7 +3302,7 @@ type PublicationReview struct { func (x *PublicationReview) Reset() { *x = PublicationReview{} - mi := &file_gateway_v1_gateway_proto_msgTypes[41] + mi := &file_gateway_v1_gateway_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3186,7 +3314,7 @@ func (x *PublicationReview) String() string { func (*PublicationReview) ProtoMessage() {} func (x *PublicationReview) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[41] + mi := &file_gateway_v1_gateway_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3199,7 +3327,7 @@ func (x *PublicationReview) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationReview.ProtoReflect.Descriptor instead. func (*PublicationReview) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{41} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{43} } func (x *PublicationReview) GetPublication() *PublicationKey { @@ -3239,7 +3367,7 @@ type DeltaReview struct { func (x *DeltaReview) Reset() { *x = DeltaReview{} - mi := &file_gateway_v1_gateway_proto_msgTypes[42] + mi := &file_gateway_v1_gateway_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3251,7 +3379,7 @@ func (x *DeltaReview) String() string { func (*DeltaReview) ProtoMessage() {} func (x *DeltaReview) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[42] + mi := &file_gateway_v1_gateway_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3264,7 +3392,7 @@ func (x *DeltaReview) ProtoReflect() protoreflect.Message { // Deprecated: Use DeltaReview.ProtoReflect.Descriptor instead. func (*DeltaReview) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{42} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{44} } func (x *DeltaReview) GetReview() *PublicationReview { @@ -3335,7 +3463,7 @@ type PublicationReviewContext struct { func (x *PublicationReviewContext) Reset() { *x = PublicationReviewContext{} - mi := &file_gateway_v1_gateway_proto_msgTypes[43] + mi := &file_gateway_v1_gateway_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3347,7 +3475,7 @@ func (x *PublicationReviewContext) String() string { func (*PublicationReviewContext) ProtoMessage() {} func (x *PublicationReviewContext) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[43] + mi := &file_gateway_v1_gateway_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3360,7 +3488,7 @@ func (x *PublicationReviewContext) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationReviewContext.ProtoReflect.Descriptor instead. func (*PublicationReviewContext) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{43} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{45} } func (x *PublicationReviewContext) GetPublication() *PublicationKey { @@ -3401,7 +3529,7 @@ type ReviewRegistrationReceipt struct { func (x *ReviewRegistrationReceipt) Reset() { *x = ReviewRegistrationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[44] + mi := &file_gateway_v1_gateway_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3413,7 +3541,7 @@ func (x *ReviewRegistrationReceipt) String() string { func (*ReviewRegistrationReceipt) ProtoMessage() {} func (x *ReviewRegistrationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[44] + mi := &file_gateway_v1_gateway_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3426,7 +3554,7 @@ func (x *ReviewRegistrationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use ReviewRegistrationReceipt.ProtoReflect.Descriptor instead. func (*ReviewRegistrationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{44} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{46} } func (x *ReviewRegistrationReceipt) GetPublication() *PublicationKey { @@ -3456,7 +3584,7 @@ type MeterCredentialRotation struct { func (x *MeterCredentialRotation) Reset() { *x = MeterCredentialRotation{} - mi := &file_gateway_v1_gateway_proto_msgTypes[45] + mi := &file_gateway_v1_gateway_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3468,7 +3596,7 @@ func (x *MeterCredentialRotation) String() string { func (*MeterCredentialRotation) ProtoMessage() {} func (x *MeterCredentialRotation) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[45] + mi := &file_gateway_v1_gateway_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3481,7 +3609,7 @@ func (x *MeterCredentialRotation) ProtoReflect() protoreflect.Message { // Deprecated: Use MeterCredentialRotation.ProtoReflect.Descriptor instead. func (*MeterCredentialRotation) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{45} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{47} } func (x *MeterCredentialRotation) GetTenant() string { @@ -3528,7 +3656,7 @@ type MeterCredentialEpoch struct { func (x *MeterCredentialEpoch) Reset() { *x = MeterCredentialEpoch{} - mi := &file_gateway_v1_gateway_proto_msgTypes[46] + mi := &file_gateway_v1_gateway_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3540,7 +3668,7 @@ func (x *MeterCredentialEpoch) String() string { func (*MeterCredentialEpoch) ProtoMessage() {} func (x *MeterCredentialEpoch) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[46] + mi := &file_gateway_v1_gateway_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3553,7 +3681,7 @@ func (x *MeterCredentialEpoch) ProtoReflect() protoreflect.Message { // Deprecated: Use MeterCredentialEpoch.ProtoReflect.Descriptor instead. func (*MeterCredentialEpoch) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{46} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{48} } func (x *MeterCredentialEpoch) GetEpoch() uint64 { @@ -3584,7 +3712,7 @@ type MeteringReceipt struct { func (x *MeteringReceipt) Reset() { *x = MeteringReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[47] + mi := &file_gateway_v1_gateway_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3596,7 +3724,7 @@ func (x *MeteringReceipt) String() string { func (*MeteringReceipt) ProtoMessage() {} func (x *MeteringReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[47] + mi := &file_gateway_v1_gateway_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3609,7 +3737,7 @@ func (x *MeteringReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use MeteringReceipt.ProtoReflect.Descriptor instead. func (*MeteringReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{47} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{49} } func (x *MeteringReceipt) GetAudience() string { @@ -3714,7 +3842,7 @@ type MeteringApplication struct { func (x *MeteringApplication) Reset() { *x = MeteringApplication{} - mi := &file_gateway_v1_gateway_proto_msgTypes[48] + mi := &file_gateway_v1_gateway_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3726,7 +3854,7 @@ func (x *MeteringApplication) String() string { func (*MeteringApplication) ProtoMessage() {} func (x *MeteringApplication) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[48] + mi := &file_gateway_v1_gateway_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3739,7 +3867,7 @@ func (x *MeteringApplication) ProtoReflect() protoreflect.Message { // Deprecated: Use MeteringApplication.ProtoReflect.Descriptor instead. func (*MeteringApplication) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{48} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{50} } func (x *MeteringApplication) GetApplication() string { @@ -3777,7 +3905,7 @@ type ProviderOAuthChange struct { func (x *ProviderOAuthChange) Reset() { *x = ProviderOAuthChange{} - mi := &file_gateway_v1_gateway_proto_msgTypes[49] + mi := &file_gateway_v1_gateway_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3789,7 +3917,7 @@ func (x *ProviderOAuthChange) String() string { func (*ProviderOAuthChange) ProtoMessage() {} func (x *ProviderOAuthChange) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[49] + mi := &file_gateway_v1_gateway_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3802,7 +3930,7 @@ func (x *ProviderOAuthChange) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderOAuthChange.ProtoReflect.Descriptor instead. func (*ProviderOAuthChange) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{49} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{51} } func (x *ProviderOAuthChange) GetAction() isProviderOAuthChange_Action { @@ -3881,7 +4009,7 @@ type ProviderOAuthGrant struct { func (x *ProviderOAuthGrant) Reset() { *x = ProviderOAuthGrant{} - mi := &file_gateway_v1_gateway_proto_msgTypes[50] + mi := &file_gateway_v1_gateway_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3893,7 +4021,7 @@ func (x *ProviderOAuthGrant) String() string { func (*ProviderOAuthGrant) ProtoMessage() {} func (x *ProviderOAuthGrant) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[50] + mi := &file_gateway_v1_gateway_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3906,7 +4034,7 @@ func (x *ProviderOAuthGrant) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderOAuthGrant.ProtoReflect.Descriptor instead. func (*ProviderOAuthGrant) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{50} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{52} } func (x *ProviderOAuthGrant) GetIssuer() string { @@ -4004,7 +4132,7 @@ type ProviderOAuthIssuerRotation struct { func (x *ProviderOAuthIssuerRotation) Reset() { *x = ProviderOAuthIssuerRotation{} - mi := &file_gateway_v1_gateway_proto_msgTypes[51] + mi := &file_gateway_v1_gateway_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4016,7 +4144,7 @@ func (x *ProviderOAuthIssuerRotation) String() string { func (*ProviderOAuthIssuerRotation) ProtoMessage() {} func (x *ProviderOAuthIssuerRotation) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[51] + mi := &file_gateway_v1_gateway_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4029,7 +4157,7 @@ func (x *ProviderOAuthIssuerRotation) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderOAuthIssuerRotation.ProtoReflect.Descriptor instead. func (*ProviderOAuthIssuerRotation) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{51} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{53} } func (x *ProviderOAuthIssuerRotation) GetExpectedEpoch() uint64 { @@ -4094,12 +4222,23 @@ const file_gateway_v1_gateway_proto_rawDesc = "" + "\x05floor\x18\x03 \x01(\x04R\x05floor\x126\n" + "\x17previous_pending_prefix\x18\x04 \x01(\tR\x15previousPendingPrefix\x12=\n" + "\x18remaining_pending_prefix\x18\x05 \x01(\tH\x00R\x16remainingPendingPrefix\x88\x01\x01B\x1b\n" + - "\x19_remaining_pending_prefix\"d\n" + + "\x19_remaining_pending_prefix\"L\n" + + "\fWorkflowEdge\x12\x1c\n" + + "\tdependent\x18\x01 \x01(\tR\tdependent\x12\x1e\n" + + "\n" + + "dependency\x18\x02 \x01(\tR\n" + + "dependency\"X\n" + + "\x10WorkflowSelector\x12\x1a\n" + + "\bselector\x18\x01 \x01(\tR\bselector\x12\x12\n" + + "\x04left\x18\x02 \x01(\tR\x04left\x12\x14\n" + + "\x05right\x18\x03 \x01(\tR\x05right\"\x80\x02\n" + "\x13GovernanceSelection\x12\x16\n" + "\x06schema\x18\x01 \x01(\tR\x06schema\x12\x16\n" + "\x06family\x18\x02 \x01(\tR\x06family\x12\x1d\n" + "\n" + - "open_nodes\x18\x03 \x03(\tR\topenNodes\"\x83\x02\n" + + "open_nodes\x18\x03 \x03(\tR\topenNodes\x12F\n" + + "\x0eworkflow_edges\x18\x04 \x03(\v2\x1f.weaver.gateway.v1.WorkflowEdgeR\rworkflowEdges\x12R\n" + + "\x12workflow_selectors\x18\x05 \x03(\v2#.weaver.gateway.v1.WorkflowSelectorR\x11workflowSelectors\"\x83\x02\n" + "\x0eSourceArtifact\x12F\n" + "\n" + "governance\x18\x01 \x01(\v2&.weaver.gateway.v1.GovernanceSelectionR\n" + @@ -4446,7 +4585,7 @@ func file_gateway_v1_gateway_proto_rawDescGZIP() []byte { } var file_gateway_v1_gateway_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_gateway_v1_gateway_proto_msgTypes = make([]protoimpl.MessageInfo, 56) +var file_gateway_v1_gateway_proto_msgTypes = make([]protoimpl.MessageInfo, 58) var file_gateway_v1_gateway_proto_goTypes = []any{ (Encoding)(0), // 0: weaver.gateway.v1.Encoding (PublicationOutcome)(0), // 1: weaver.gateway.v1.PublicationOutcome @@ -4458,159 +4597,163 @@ var file_gateway_v1_gateway_proto_goTypes = []any{ (*HardFactIntent)(nil), // 7: weaver.gateway.v1.HardFactIntent (*HardFactBarrier)(nil), // 8: weaver.gateway.v1.HardFactBarrier (*FactBarrierResolution)(nil), // 9: weaver.gateway.v1.FactBarrierResolution - (*GovernanceSelection)(nil), // 10: weaver.gateway.v1.GovernanceSelection - (*SourceArtifact)(nil), // 11: weaver.gateway.v1.SourceArtifact - (*CompiledSource)(nil), // 12: weaver.gateway.v1.CompiledSource - (*OperationKey)(nil), // 13: weaver.gateway.v1.OperationKey - (*Route)(nil), // 14: weaver.gateway.v1.Route - (*ProviderPlan)(nil), // 15: weaver.gateway.v1.ProviderPlan - (*ProviderRequest)(nil), // 16: weaver.gateway.v1.ProviderRequest - (*ProviderCatalogSnapshot)(nil), // 17: weaver.gateway.v1.ProviderCatalogSnapshot - (*ProviderCatalogChange)(nil), // 18: weaver.gateway.v1.ProviderCatalogChange - (*Event)(nil), // 19: weaver.gateway.v1.Event - (*ArrowBatch)(nil), // 20: weaver.gateway.v1.ArrowBatch - (*ProviderFrame)(nil), // 21: weaver.gateway.v1.ProviderFrame - (*ProviderReceipt)(nil), // 22: weaver.gateway.v1.ProviderReceipt - (*Task)(nil), // 23: weaver.gateway.v1.Task - (*ProviderProfile)(nil), // 24: weaver.gateway.v1.ProviderProfile - (*RegisterTaskRequest)(nil), // 25: weaver.gateway.v1.RegisterTaskRequest - (*DomainBinding)(nil), // 26: weaver.gateway.v1.DomainBinding - (*DomainStamp)(nil), // 27: weaver.gateway.v1.DomainStamp - (*DomainView)(nil), // 28: weaver.gateway.v1.DomainView - (*RegisterDomainTaskRequest)(nil), // 29: weaver.gateway.v1.RegisterDomainTaskRequest - (*TaskAdmission)(nil), // 30: weaver.gateway.v1.TaskAdmission - (*RegisterOriginalTaskRequest)(nil), // 31: weaver.gateway.v1.RegisterOriginalTaskRequest - (*TaskAdmissionReceipt)(nil), // 32: weaver.gateway.v1.TaskAdmissionReceipt - (*FamilyAliasRequest)(nil), // 33: weaver.gateway.v1.FamilyAliasRequest - (*DomainMigration)(nil), // 34: weaver.gateway.v1.DomainMigration - (*DomainMigrationReceipt)(nil), // 35: weaver.gateway.v1.DomainMigrationReceipt - (*RegisterPublishedTaskRequest)(nil), // 36: weaver.gateway.v1.RegisterPublishedTaskRequest - (*PublishRequest)(nil), // 37: weaver.gateway.v1.PublishRequest - (*PublicationReceipt)(nil), // 38: weaver.gateway.v1.PublicationReceipt - (*PublicationKey)(nil), // 39: weaver.gateway.v1.PublicationKey - (*SourceAuthorityView)(nil), // 40: weaver.gateway.v1.SourceAuthorityView - (*SourceRotationRequest)(nil), // 41: weaver.gateway.v1.SourceRotationRequest - (*SourceRotationReceipt)(nil), // 42: weaver.gateway.v1.SourceRotationReceipt - (*AuthorityParent)(nil), // 43: weaver.gateway.v1.AuthorityParent - (*ReviewAuthority)(nil), // 44: weaver.gateway.v1.ReviewAuthority - (*PublicationReview)(nil), // 45: weaver.gateway.v1.PublicationReview - (*DeltaReview)(nil), // 46: weaver.gateway.v1.DeltaReview - (*PublicationReviewContext)(nil), // 47: weaver.gateway.v1.PublicationReviewContext - (*ReviewRegistrationReceipt)(nil), // 48: weaver.gateway.v1.ReviewRegistrationReceipt - (*MeterCredentialRotation)(nil), // 49: weaver.gateway.v1.MeterCredentialRotation - (*MeterCredentialEpoch)(nil), // 50: weaver.gateway.v1.MeterCredentialEpoch - (*MeteringReceipt)(nil), // 51: weaver.gateway.v1.MeteringReceipt - (*MeteringApplication)(nil), // 52: weaver.gateway.v1.MeteringApplication - (*ProviderOAuthChange)(nil), // 53: weaver.gateway.v1.ProviderOAuthChange - (*ProviderOAuthGrant)(nil), // 54: weaver.gateway.v1.ProviderOAuthGrant - (*ProviderOAuthIssuerRotation)(nil), // 55: weaver.gateway.v1.ProviderOAuthIssuerRotation - nil, // 56: weaver.gateway.v1.Task.EndpointsEntry - nil, // 57: weaver.gateway.v1.Task.BodyDigestsEntry - nil, // 58: weaver.gateway.v1.Task.NodeCostBoundsEntry - nil, // 59: weaver.gateway.v1.Task.StreamContractsEntry + (*WorkflowEdge)(nil), // 10: weaver.gateway.v1.WorkflowEdge + (*WorkflowSelector)(nil), // 11: weaver.gateway.v1.WorkflowSelector + (*GovernanceSelection)(nil), // 12: weaver.gateway.v1.GovernanceSelection + (*SourceArtifact)(nil), // 13: weaver.gateway.v1.SourceArtifact + (*CompiledSource)(nil), // 14: weaver.gateway.v1.CompiledSource + (*OperationKey)(nil), // 15: weaver.gateway.v1.OperationKey + (*Route)(nil), // 16: weaver.gateway.v1.Route + (*ProviderPlan)(nil), // 17: weaver.gateway.v1.ProviderPlan + (*ProviderRequest)(nil), // 18: weaver.gateway.v1.ProviderRequest + (*ProviderCatalogSnapshot)(nil), // 19: weaver.gateway.v1.ProviderCatalogSnapshot + (*ProviderCatalogChange)(nil), // 20: weaver.gateway.v1.ProviderCatalogChange + (*Event)(nil), // 21: weaver.gateway.v1.Event + (*ArrowBatch)(nil), // 22: weaver.gateway.v1.ArrowBatch + (*ProviderFrame)(nil), // 23: weaver.gateway.v1.ProviderFrame + (*ProviderReceipt)(nil), // 24: weaver.gateway.v1.ProviderReceipt + (*Task)(nil), // 25: weaver.gateway.v1.Task + (*ProviderProfile)(nil), // 26: weaver.gateway.v1.ProviderProfile + (*RegisterTaskRequest)(nil), // 27: weaver.gateway.v1.RegisterTaskRequest + (*DomainBinding)(nil), // 28: weaver.gateway.v1.DomainBinding + (*DomainStamp)(nil), // 29: weaver.gateway.v1.DomainStamp + (*DomainView)(nil), // 30: weaver.gateway.v1.DomainView + (*RegisterDomainTaskRequest)(nil), // 31: weaver.gateway.v1.RegisterDomainTaskRequest + (*TaskAdmission)(nil), // 32: weaver.gateway.v1.TaskAdmission + (*RegisterOriginalTaskRequest)(nil), // 33: weaver.gateway.v1.RegisterOriginalTaskRequest + (*TaskAdmissionReceipt)(nil), // 34: weaver.gateway.v1.TaskAdmissionReceipt + (*FamilyAliasRequest)(nil), // 35: weaver.gateway.v1.FamilyAliasRequest + (*DomainMigration)(nil), // 36: weaver.gateway.v1.DomainMigration + (*DomainMigrationReceipt)(nil), // 37: weaver.gateway.v1.DomainMigrationReceipt + (*RegisterPublishedTaskRequest)(nil), // 38: weaver.gateway.v1.RegisterPublishedTaskRequest + (*PublishRequest)(nil), // 39: weaver.gateway.v1.PublishRequest + (*PublicationReceipt)(nil), // 40: weaver.gateway.v1.PublicationReceipt + (*PublicationKey)(nil), // 41: weaver.gateway.v1.PublicationKey + (*SourceAuthorityView)(nil), // 42: weaver.gateway.v1.SourceAuthorityView + (*SourceRotationRequest)(nil), // 43: weaver.gateway.v1.SourceRotationRequest + (*SourceRotationReceipt)(nil), // 44: weaver.gateway.v1.SourceRotationReceipt + (*AuthorityParent)(nil), // 45: weaver.gateway.v1.AuthorityParent + (*ReviewAuthority)(nil), // 46: weaver.gateway.v1.ReviewAuthority + (*PublicationReview)(nil), // 47: weaver.gateway.v1.PublicationReview + (*DeltaReview)(nil), // 48: weaver.gateway.v1.DeltaReview + (*PublicationReviewContext)(nil), // 49: weaver.gateway.v1.PublicationReviewContext + (*ReviewRegistrationReceipt)(nil), // 50: weaver.gateway.v1.ReviewRegistrationReceipt + (*MeterCredentialRotation)(nil), // 51: weaver.gateway.v1.MeterCredentialRotation + (*MeterCredentialEpoch)(nil), // 52: weaver.gateway.v1.MeterCredentialEpoch + (*MeteringReceipt)(nil), // 53: weaver.gateway.v1.MeteringReceipt + (*MeteringApplication)(nil), // 54: weaver.gateway.v1.MeteringApplication + (*ProviderOAuthChange)(nil), // 55: weaver.gateway.v1.ProviderOAuthChange + (*ProviderOAuthGrant)(nil), // 56: weaver.gateway.v1.ProviderOAuthGrant + (*ProviderOAuthIssuerRotation)(nil), // 57: weaver.gateway.v1.ProviderOAuthIssuerRotation + nil, // 58: weaver.gateway.v1.Task.EndpointsEntry + nil, // 59: weaver.gateway.v1.Task.BodyDigestsEntry + nil, // 60: weaver.gateway.v1.Task.NodeCostBoundsEntry + nil, // 61: weaver.gateway.v1.Task.StreamContractsEntry } var file_gateway_v1_gateway_proto_depIdxs = []int32{ 8, // 0: weaver.gateway.v1.FactBarrierResolution.barrier:type_name -> weaver.gateway.v1.HardFactBarrier - 10, // 1: weaver.gateway.v1.SourceArtifact.governance:type_name -> weaver.gateway.v1.GovernanceSelection - 23, // 2: weaver.gateway.v1.SourceArtifact.tasks:type_name -> weaver.gateway.v1.Task - 15, // 3: weaver.gateway.v1.SourceArtifact.plans:type_name -> weaver.gateway.v1.ProviderPlan - 37, // 4: weaver.gateway.v1.SourceArtifact.publication:type_name -> weaver.gateway.v1.PublishRequest - 40, // 5: weaver.gateway.v1.CompiledSource.authority:type_name -> weaver.gateway.v1.SourceAuthorityView - 11, // 6: weaver.gateway.v1.CompiledSource.artifact:type_name -> weaver.gateway.v1.SourceArtifact - 14, // 7: weaver.gateway.v1.ProviderPlan.routes:type_name -> weaver.gateway.v1.Route - 15, // 8: weaver.gateway.v1.ProviderRequest.plan:type_name -> weaver.gateway.v1.ProviderPlan - 0, // 9: weaver.gateway.v1.ProviderRequest.encoding:type_name -> weaver.gateway.v1.Encoding - 19, // 10: weaver.gateway.v1.ProviderFrame.event:type_name -> weaver.gateway.v1.Event - 20, // 11: weaver.gateway.v1.ProviderFrame.arrow:type_name -> weaver.gateway.v1.ArrowBatch - 56, // 12: weaver.gateway.v1.Task.endpoints:type_name -> weaver.gateway.v1.Task.EndpointsEntry - 57, // 13: weaver.gateway.v1.Task.body_digests:type_name -> weaver.gateway.v1.Task.BodyDigestsEntry - 58, // 14: weaver.gateway.v1.Task.node_cost_bounds:type_name -> weaver.gateway.v1.Task.NodeCostBoundsEntry - 59, // 15: weaver.gateway.v1.Task.stream_contracts:type_name -> weaver.gateway.v1.Task.StreamContractsEntry - 24, // 16: weaver.gateway.v1.Task.provider_profile:type_name -> weaver.gateway.v1.ProviderProfile - 23, // 17: weaver.gateway.v1.RegisterTaskRequest.task:type_name -> weaver.gateway.v1.Task - 27, // 18: weaver.gateway.v1.DomainView.stamp:type_name -> weaver.gateway.v1.DomainStamp - 23, // 19: weaver.gateway.v1.RegisterDomainTaskRequest.task:type_name -> weaver.gateway.v1.Task - 26, // 20: weaver.gateway.v1.RegisterDomainTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding - 39, // 21: weaver.gateway.v1.RegisterDomainTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey - 23, // 22: weaver.gateway.v1.RegisterOriginalTaskRequest.task:type_name -> weaver.gateway.v1.Task - 26, // 23: weaver.gateway.v1.RegisterOriginalTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding - 30, // 24: weaver.gateway.v1.RegisterOriginalTaskRequest.admission:type_name -> weaver.gateway.v1.TaskAdmission - 39, // 25: weaver.gateway.v1.RegisterOriginalTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey - 23, // 26: weaver.gateway.v1.RegisterPublishedTaskRequest.task:type_name -> weaver.gateway.v1.Task - 39, // 27: weaver.gateway.v1.RegisterPublishedTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey - 1, // 28: weaver.gateway.v1.PublicationReceipt.outcome:type_name -> weaver.gateway.v1.PublicationOutcome - 2, // 29: weaver.gateway.v1.SourceRotationReceipt.outcome:type_name -> weaver.gateway.v1.SourceRotationOutcome - 40, // 30: weaver.gateway.v1.SourceRotationReceipt.authority:type_name -> weaver.gateway.v1.SourceAuthorityView - 39, // 31: weaver.gateway.v1.PublicationReview.publication:type_name -> weaver.gateway.v1.PublicationKey - 43, // 32: weaver.gateway.v1.PublicationReview.parent:type_name -> weaver.gateway.v1.AuthorityParent - 45, // 33: weaver.gateway.v1.DeltaReview.review:type_name -> weaver.gateway.v1.PublicationReview - 3, // 34: weaver.gateway.v1.DeltaReview.disposition:type_name -> weaver.gateway.v1.DeltaDisposition - 39, // 35: weaver.gateway.v1.PublicationReviewContext.publication:type_name -> weaver.gateway.v1.PublicationKey - 43, // 36: weaver.gateway.v1.PublicationReviewContext.parent:type_name -> weaver.gateway.v1.AuthorityParent - 44, // 37: weaver.gateway.v1.PublicationReviewContext.reviewer:type_name -> weaver.gateway.v1.ReviewAuthority - 40, // 38: weaver.gateway.v1.PublicationReviewContext.source:type_name -> weaver.gateway.v1.SourceAuthorityView - 39, // 39: weaver.gateway.v1.ReviewRegistrationReceipt.publication:type_name -> weaver.gateway.v1.PublicationKey - 54, // 40: weaver.gateway.v1.ProviderOAuthChange.grant:type_name -> weaver.gateway.v1.ProviderOAuthGrant - 55, // 41: weaver.gateway.v1.ProviderOAuthChange.rotate_issuer:type_name -> weaver.gateway.v1.ProviderOAuthIssuerRotation - 16, // 42: weaver.gateway.v1.Gateway.ExecuteProvider:input_type -> weaver.gateway.v1.ProviderRequest - 13, // 43: weaver.gateway.v1.Gateway.Inspect:input_type -> weaver.gateway.v1.OperationKey - 49, // 44: weaver.gateway.v1.Gateway.RotateMeterCredential:input_type -> weaver.gateway.v1.MeterCredentialRotation - 13, // 45: weaver.gateway.v1.Gateway.InspectTerminalUsage:input_type -> weaver.gateway.v1.OperationKey - 51, // 46: weaver.gateway.v1.Gateway.ApplyMetering:input_type -> weaver.gateway.v1.MeteringReceipt - 25, // 47: weaver.gateway.v1.Gateway.RegisterTask:input_type -> weaver.gateway.v1.RegisterTaskRequest - 36, // 48: weaver.gateway.v1.Gateway.RegisterPublishedTask:input_type -> weaver.gateway.v1.RegisterPublishedTaskRequest - 29, // 49: weaver.gateway.v1.Gateway.RegisterDomainTask:input_type -> weaver.gateway.v1.RegisterDomainTaskRequest - 31, // 50: weaver.gateway.v1.Gateway.RegisterOriginalTask:input_type -> weaver.gateway.v1.RegisterOriginalTaskRequest - 33, // 51: weaver.gateway.v1.Gateway.RegisterFamilyAlias:input_type -> weaver.gateway.v1.FamilyAliasRequest - 34, // 52: weaver.gateway.v1.Gateway.MigrateExecutionDomains:input_type -> weaver.gateway.v1.DomainMigration - 13, // 53: weaver.gateway.v1.Gateway.InspectExecutionDomains:input_type -> weaver.gateway.v1.OperationKey - 37, // 54: weaver.gateway.v1.Gateway.PublishAuthority:input_type -> weaver.gateway.v1.PublishRequest - 37, // 55: weaver.gateway.v1.Gateway.StageAuthority:input_type -> weaver.gateway.v1.PublishRequest - 39, // 56: weaver.gateway.v1.Gateway.InspectPublication:input_type -> weaver.gateway.v1.PublicationKey - 37, // 57: weaver.gateway.v1.Gateway.StageReviewedAuthority:input_type -> weaver.gateway.v1.PublishRequest - 39, // 58: weaver.gateway.v1.Gateway.InspectPublicationReview:input_type -> weaver.gateway.v1.PublicationKey - 46, // 59: weaver.gateway.v1.Gateway.RegisterPublicationReview:input_type -> weaver.gateway.v1.DeltaReview - 5, // 60: weaver.gateway.v1.Gateway.InspectSourceAuthority:input_type -> weaver.gateway.v1.Empty - 41, // 61: weaver.gateway.v1.Gateway.RotateSourceAuthority:input_type -> weaver.gateway.v1.SourceRotationRequest - 7, // 62: weaver.gateway.v1.Gateway.StageHardFact:input_type -> weaver.gateway.v1.HardFactIntent - 8, // 63: weaver.gateway.v1.Gateway.ResolveHardFact:input_type -> weaver.gateway.v1.HardFactBarrier - 6, // 64: weaver.gateway.v1.Gateway.CompileSource:input_type -> weaver.gateway.v1.ProducerRequest - 5, // 65: weaver.gateway.v1.Gateway.InspectProviderCatalog:input_type -> weaver.gateway.v1.Empty - 18, // 66: weaver.gateway.v1.Gateway.PublishProviderCatalog:input_type -> weaver.gateway.v1.ProviderCatalogChange - 5, // 67: weaver.gateway.v1.Gateway.InspectTelemetry:input_type -> weaver.gateway.v1.Empty - 53, // 68: weaver.gateway.v1.Gateway.ChangeProviderOAuth:input_type -> weaver.gateway.v1.ProviderOAuthChange - 21, // 69: weaver.gateway.v1.Gateway.ExecuteProvider:output_type -> weaver.gateway.v1.ProviderFrame - 22, // 70: weaver.gateway.v1.Gateway.Inspect:output_type -> weaver.gateway.v1.ProviderReceipt - 50, // 71: weaver.gateway.v1.Gateway.RotateMeterCredential:output_type -> weaver.gateway.v1.MeterCredentialEpoch - 51, // 72: weaver.gateway.v1.Gateway.InspectTerminalUsage:output_type -> weaver.gateway.v1.MeteringReceipt - 52, // 73: weaver.gateway.v1.Gateway.ApplyMetering:output_type -> weaver.gateway.v1.MeteringApplication - 5, // 74: weaver.gateway.v1.Gateway.RegisterTask:output_type -> weaver.gateway.v1.Empty - 5, // 75: weaver.gateway.v1.Gateway.RegisterPublishedTask:output_type -> weaver.gateway.v1.Empty - 5, // 76: weaver.gateway.v1.Gateway.RegisterDomainTask:output_type -> weaver.gateway.v1.Empty - 32, // 77: weaver.gateway.v1.Gateway.RegisterOriginalTask:output_type -> weaver.gateway.v1.TaskAdmissionReceipt - 28, // 78: weaver.gateway.v1.Gateway.RegisterFamilyAlias:output_type -> weaver.gateway.v1.DomainView - 35, // 79: weaver.gateway.v1.Gateway.MigrateExecutionDomains:output_type -> weaver.gateway.v1.DomainMigrationReceipt - 28, // 80: weaver.gateway.v1.Gateway.InspectExecutionDomains:output_type -> weaver.gateway.v1.DomainView - 38, // 81: weaver.gateway.v1.Gateway.PublishAuthority:output_type -> weaver.gateway.v1.PublicationReceipt - 39, // 82: weaver.gateway.v1.Gateway.StageAuthority:output_type -> weaver.gateway.v1.PublicationKey - 38, // 83: weaver.gateway.v1.Gateway.InspectPublication:output_type -> weaver.gateway.v1.PublicationReceipt - 39, // 84: weaver.gateway.v1.Gateway.StageReviewedAuthority:output_type -> weaver.gateway.v1.PublicationKey - 47, // 85: weaver.gateway.v1.Gateway.InspectPublicationReview:output_type -> weaver.gateway.v1.PublicationReviewContext - 48, // 86: weaver.gateway.v1.Gateway.RegisterPublicationReview:output_type -> weaver.gateway.v1.ReviewRegistrationReceipt - 40, // 87: weaver.gateway.v1.Gateway.InspectSourceAuthority:output_type -> weaver.gateway.v1.SourceAuthorityView - 42, // 88: weaver.gateway.v1.Gateway.RotateSourceAuthority:output_type -> weaver.gateway.v1.SourceRotationReceipt - 8, // 89: weaver.gateway.v1.Gateway.StageHardFact:output_type -> weaver.gateway.v1.HardFactBarrier - 9, // 90: weaver.gateway.v1.Gateway.ResolveHardFact:output_type -> weaver.gateway.v1.FactBarrierResolution - 12, // 91: weaver.gateway.v1.Gateway.CompileSource:output_type -> weaver.gateway.v1.CompiledSource - 17, // 92: weaver.gateway.v1.Gateway.InspectProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot - 17, // 93: weaver.gateway.v1.Gateway.PublishProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot - 4, // 94: weaver.gateway.v1.Gateway.InspectTelemetry:output_type -> weaver.gateway.v1.TelemetrySnapshot - 5, // 95: weaver.gateway.v1.Gateway.ChangeProviderOAuth:output_type -> weaver.gateway.v1.Empty - 69, // [69:96] is the sub-list for method output_type - 42, // [42:69] is the sub-list for method input_type - 42, // [42:42] is the sub-list for extension type_name - 42, // [42:42] is the sub-list for extension extendee - 0, // [0:42] is the sub-list for field type_name + 10, // 1: weaver.gateway.v1.GovernanceSelection.workflow_edges:type_name -> weaver.gateway.v1.WorkflowEdge + 11, // 2: weaver.gateway.v1.GovernanceSelection.workflow_selectors:type_name -> weaver.gateway.v1.WorkflowSelector + 12, // 3: weaver.gateway.v1.SourceArtifact.governance:type_name -> weaver.gateway.v1.GovernanceSelection + 25, // 4: weaver.gateway.v1.SourceArtifact.tasks:type_name -> weaver.gateway.v1.Task + 17, // 5: weaver.gateway.v1.SourceArtifact.plans:type_name -> weaver.gateway.v1.ProviderPlan + 39, // 6: weaver.gateway.v1.SourceArtifact.publication:type_name -> weaver.gateway.v1.PublishRequest + 42, // 7: weaver.gateway.v1.CompiledSource.authority:type_name -> weaver.gateway.v1.SourceAuthorityView + 13, // 8: weaver.gateway.v1.CompiledSource.artifact:type_name -> weaver.gateway.v1.SourceArtifact + 16, // 9: weaver.gateway.v1.ProviderPlan.routes:type_name -> weaver.gateway.v1.Route + 17, // 10: weaver.gateway.v1.ProviderRequest.plan:type_name -> weaver.gateway.v1.ProviderPlan + 0, // 11: weaver.gateway.v1.ProviderRequest.encoding:type_name -> weaver.gateway.v1.Encoding + 21, // 12: weaver.gateway.v1.ProviderFrame.event:type_name -> weaver.gateway.v1.Event + 22, // 13: weaver.gateway.v1.ProviderFrame.arrow:type_name -> weaver.gateway.v1.ArrowBatch + 58, // 14: weaver.gateway.v1.Task.endpoints:type_name -> weaver.gateway.v1.Task.EndpointsEntry + 59, // 15: weaver.gateway.v1.Task.body_digests:type_name -> weaver.gateway.v1.Task.BodyDigestsEntry + 60, // 16: weaver.gateway.v1.Task.node_cost_bounds:type_name -> weaver.gateway.v1.Task.NodeCostBoundsEntry + 61, // 17: weaver.gateway.v1.Task.stream_contracts:type_name -> weaver.gateway.v1.Task.StreamContractsEntry + 26, // 18: weaver.gateway.v1.Task.provider_profile:type_name -> weaver.gateway.v1.ProviderProfile + 25, // 19: weaver.gateway.v1.RegisterTaskRequest.task:type_name -> weaver.gateway.v1.Task + 29, // 20: weaver.gateway.v1.DomainView.stamp:type_name -> weaver.gateway.v1.DomainStamp + 25, // 21: weaver.gateway.v1.RegisterDomainTaskRequest.task:type_name -> weaver.gateway.v1.Task + 28, // 22: weaver.gateway.v1.RegisterDomainTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding + 41, // 23: weaver.gateway.v1.RegisterDomainTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey + 25, // 24: weaver.gateway.v1.RegisterOriginalTaskRequest.task:type_name -> weaver.gateway.v1.Task + 28, // 25: weaver.gateway.v1.RegisterOriginalTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding + 32, // 26: weaver.gateway.v1.RegisterOriginalTaskRequest.admission:type_name -> weaver.gateway.v1.TaskAdmission + 41, // 27: weaver.gateway.v1.RegisterOriginalTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey + 25, // 28: weaver.gateway.v1.RegisterPublishedTaskRequest.task:type_name -> weaver.gateway.v1.Task + 41, // 29: weaver.gateway.v1.RegisterPublishedTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey + 1, // 30: weaver.gateway.v1.PublicationReceipt.outcome:type_name -> weaver.gateway.v1.PublicationOutcome + 2, // 31: weaver.gateway.v1.SourceRotationReceipt.outcome:type_name -> weaver.gateway.v1.SourceRotationOutcome + 42, // 32: weaver.gateway.v1.SourceRotationReceipt.authority:type_name -> weaver.gateway.v1.SourceAuthorityView + 41, // 33: weaver.gateway.v1.PublicationReview.publication:type_name -> weaver.gateway.v1.PublicationKey + 45, // 34: weaver.gateway.v1.PublicationReview.parent:type_name -> weaver.gateway.v1.AuthorityParent + 47, // 35: weaver.gateway.v1.DeltaReview.review:type_name -> weaver.gateway.v1.PublicationReview + 3, // 36: weaver.gateway.v1.DeltaReview.disposition:type_name -> weaver.gateway.v1.DeltaDisposition + 41, // 37: weaver.gateway.v1.PublicationReviewContext.publication:type_name -> weaver.gateway.v1.PublicationKey + 45, // 38: weaver.gateway.v1.PublicationReviewContext.parent:type_name -> weaver.gateway.v1.AuthorityParent + 46, // 39: weaver.gateway.v1.PublicationReviewContext.reviewer:type_name -> weaver.gateway.v1.ReviewAuthority + 42, // 40: weaver.gateway.v1.PublicationReviewContext.source:type_name -> weaver.gateway.v1.SourceAuthorityView + 41, // 41: weaver.gateway.v1.ReviewRegistrationReceipt.publication:type_name -> weaver.gateway.v1.PublicationKey + 56, // 42: weaver.gateway.v1.ProviderOAuthChange.grant:type_name -> weaver.gateway.v1.ProviderOAuthGrant + 57, // 43: weaver.gateway.v1.ProviderOAuthChange.rotate_issuer:type_name -> weaver.gateway.v1.ProviderOAuthIssuerRotation + 18, // 44: weaver.gateway.v1.Gateway.ExecuteProvider:input_type -> weaver.gateway.v1.ProviderRequest + 15, // 45: weaver.gateway.v1.Gateway.Inspect:input_type -> weaver.gateway.v1.OperationKey + 51, // 46: weaver.gateway.v1.Gateway.RotateMeterCredential:input_type -> weaver.gateway.v1.MeterCredentialRotation + 15, // 47: weaver.gateway.v1.Gateway.InspectTerminalUsage:input_type -> weaver.gateway.v1.OperationKey + 53, // 48: weaver.gateway.v1.Gateway.ApplyMetering:input_type -> weaver.gateway.v1.MeteringReceipt + 27, // 49: weaver.gateway.v1.Gateway.RegisterTask:input_type -> weaver.gateway.v1.RegisterTaskRequest + 38, // 50: weaver.gateway.v1.Gateway.RegisterPublishedTask:input_type -> weaver.gateway.v1.RegisterPublishedTaskRequest + 31, // 51: weaver.gateway.v1.Gateway.RegisterDomainTask:input_type -> weaver.gateway.v1.RegisterDomainTaskRequest + 33, // 52: weaver.gateway.v1.Gateway.RegisterOriginalTask:input_type -> weaver.gateway.v1.RegisterOriginalTaskRequest + 35, // 53: weaver.gateway.v1.Gateway.RegisterFamilyAlias:input_type -> weaver.gateway.v1.FamilyAliasRequest + 36, // 54: weaver.gateway.v1.Gateway.MigrateExecutionDomains:input_type -> weaver.gateway.v1.DomainMigration + 15, // 55: weaver.gateway.v1.Gateway.InspectExecutionDomains:input_type -> weaver.gateway.v1.OperationKey + 39, // 56: weaver.gateway.v1.Gateway.PublishAuthority:input_type -> weaver.gateway.v1.PublishRequest + 39, // 57: weaver.gateway.v1.Gateway.StageAuthority:input_type -> weaver.gateway.v1.PublishRequest + 41, // 58: weaver.gateway.v1.Gateway.InspectPublication:input_type -> weaver.gateway.v1.PublicationKey + 39, // 59: weaver.gateway.v1.Gateway.StageReviewedAuthority:input_type -> weaver.gateway.v1.PublishRequest + 41, // 60: weaver.gateway.v1.Gateway.InspectPublicationReview:input_type -> weaver.gateway.v1.PublicationKey + 48, // 61: weaver.gateway.v1.Gateway.RegisterPublicationReview:input_type -> weaver.gateway.v1.DeltaReview + 5, // 62: weaver.gateway.v1.Gateway.InspectSourceAuthority:input_type -> weaver.gateway.v1.Empty + 43, // 63: weaver.gateway.v1.Gateway.RotateSourceAuthority:input_type -> weaver.gateway.v1.SourceRotationRequest + 7, // 64: weaver.gateway.v1.Gateway.StageHardFact:input_type -> weaver.gateway.v1.HardFactIntent + 8, // 65: weaver.gateway.v1.Gateway.ResolveHardFact:input_type -> weaver.gateway.v1.HardFactBarrier + 6, // 66: weaver.gateway.v1.Gateway.CompileSource:input_type -> weaver.gateway.v1.ProducerRequest + 5, // 67: weaver.gateway.v1.Gateway.InspectProviderCatalog:input_type -> weaver.gateway.v1.Empty + 20, // 68: weaver.gateway.v1.Gateway.PublishProviderCatalog:input_type -> weaver.gateway.v1.ProviderCatalogChange + 5, // 69: weaver.gateway.v1.Gateway.InspectTelemetry:input_type -> weaver.gateway.v1.Empty + 55, // 70: weaver.gateway.v1.Gateway.ChangeProviderOAuth:input_type -> weaver.gateway.v1.ProviderOAuthChange + 23, // 71: weaver.gateway.v1.Gateway.ExecuteProvider:output_type -> weaver.gateway.v1.ProviderFrame + 24, // 72: weaver.gateway.v1.Gateway.Inspect:output_type -> weaver.gateway.v1.ProviderReceipt + 52, // 73: weaver.gateway.v1.Gateway.RotateMeterCredential:output_type -> weaver.gateway.v1.MeterCredentialEpoch + 53, // 74: weaver.gateway.v1.Gateway.InspectTerminalUsage:output_type -> weaver.gateway.v1.MeteringReceipt + 54, // 75: weaver.gateway.v1.Gateway.ApplyMetering:output_type -> weaver.gateway.v1.MeteringApplication + 5, // 76: weaver.gateway.v1.Gateway.RegisterTask:output_type -> weaver.gateway.v1.Empty + 5, // 77: weaver.gateway.v1.Gateway.RegisterPublishedTask:output_type -> weaver.gateway.v1.Empty + 5, // 78: weaver.gateway.v1.Gateway.RegisterDomainTask:output_type -> weaver.gateway.v1.Empty + 34, // 79: weaver.gateway.v1.Gateway.RegisterOriginalTask:output_type -> weaver.gateway.v1.TaskAdmissionReceipt + 30, // 80: weaver.gateway.v1.Gateway.RegisterFamilyAlias:output_type -> weaver.gateway.v1.DomainView + 37, // 81: weaver.gateway.v1.Gateway.MigrateExecutionDomains:output_type -> weaver.gateway.v1.DomainMigrationReceipt + 30, // 82: weaver.gateway.v1.Gateway.InspectExecutionDomains:output_type -> weaver.gateway.v1.DomainView + 40, // 83: weaver.gateway.v1.Gateway.PublishAuthority:output_type -> weaver.gateway.v1.PublicationReceipt + 41, // 84: weaver.gateway.v1.Gateway.StageAuthority:output_type -> weaver.gateway.v1.PublicationKey + 40, // 85: weaver.gateway.v1.Gateway.InspectPublication:output_type -> weaver.gateway.v1.PublicationReceipt + 41, // 86: weaver.gateway.v1.Gateway.StageReviewedAuthority:output_type -> weaver.gateway.v1.PublicationKey + 49, // 87: weaver.gateway.v1.Gateway.InspectPublicationReview:output_type -> weaver.gateway.v1.PublicationReviewContext + 50, // 88: weaver.gateway.v1.Gateway.RegisterPublicationReview:output_type -> weaver.gateway.v1.ReviewRegistrationReceipt + 42, // 89: weaver.gateway.v1.Gateway.InspectSourceAuthority:output_type -> weaver.gateway.v1.SourceAuthorityView + 44, // 90: weaver.gateway.v1.Gateway.RotateSourceAuthority:output_type -> weaver.gateway.v1.SourceRotationReceipt + 8, // 91: weaver.gateway.v1.Gateway.StageHardFact:output_type -> weaver.gateway.v1.HardFactBarrier + 9, // 92: weaver.gateway.v1.Gateway.ResolveHardFact:output_type -> weaver.gateway.v1.FactBarrierResolution + 14, // 93: weaver.gateway.v1.Gateway.CompileSource:output_type -> weaver.gateway.v1.CompiledSource + 19, // 94: weaver.gateway.v1.Gateway.InspectProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot + 19, // 95: weaver.gateway.v1.Gateway.PublishProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot + 4, // 96: weaver.gateway.v1.Gateway.InspectTelemetry:output_type -> weaver.gateway.v1.TelemetrySnapshot + 5, // 97: weaver.gateway.v1.Gateway.ChangeProviderOAuth:output_type -> weaver.gateway.v1.Empty + 71, // [71:98] is the sub-list for method output_type + 44, // [44:71] is the sub-list for method input_type + 44, // [44:44] is the sub-list for extension type_name + 44, // [44:44] is the sub-list for extension extendee + 0, // [0:44] is the sub-list for field type_name } func init() { file_gateway_v1_gateway_proto_init() } @@ -4620,15 +4763,15 @@ func file_gateway_v1_gateway_proto_init() { } file_gateway_v1_gateway_proto_msgTypes[3].OneofWrappers = []any{} file_gateway_v1_gateway_proto_msgTypes[5].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[17].OneofWrappers = []any{ + file_gateway_v1_gateway_proto_msgTypes[19].OneofWrappers = []any{ (*ProviderFrame_Event)(nil), (*ProviderFrame_Arrow)(nil), } - file_gateway_v1_gateway_proto_msgTypes[33].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[34].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[39].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[40].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[49].OneofWrappers = []any{ + file_gateway_v1_gateway_proto_msgTypes[35].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[36].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[41].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[42].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[51].OneofWrappers = []any{ (*ProviderOAuthChange_Grant)(nil), (*ProviderOAuthChange_RevokeTokenHash)(nil), (*ProviderOAuthChange_RotateIssuer)(nil), @@ -4639,7 +4782,7 @@ func file_gateway_v1_gateway_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_gateway_v1_gateway_proto_rawDesc), len(file_gateway_v1_gateway_proto_rawDesc)), NumEnums: 4, - NumMessages: 56, + NumMessages: 58, NumExtensions: 0, NumServices: 1, }, diff --git a/go/internal/config/bundle.go b/go/internal/config/bundle.go index 4f464280..439fc58b 100644 --- a/go/internal/config/bundle.go +++ b/go/internal/config/bundle.go @@ -28,11 +28,21 @@ type Bundle struct { // Governance is the native governor's selected handoff, not a runtime permit. // This source profile publishes one original family per governor handoff. type Governance struct { - Schema string `json:"schema"` - Family string `json:"family"` - OpenNodes []string `json:"open_nodes"` + Schema string `json:"schema"` + Family string `json:"family"` + OpenNodes []string `json:"open_nodes"` + WorkflowEdges [][2]string `json:"workflow_edges,omitempty"` + WorkflowSelectors [][3]string `json:"workflow_selectors,omitempty"` } +const SessionNestedSchema = "weaver.session-nested.v1" + +const SessionChoiceSchema = "weaver.session-choice.v1" + +const SessionDAGSchema = "weaver.session-dag.v1" + +const SessionWorkflowSchema = "weaver.session-workflow.v1" + func DecodeBundle(data []byte, format ProfileFormat) (Bundle, error) { var zero Bundle if len(data) == 0 || len(data) > 8<<20 { @@ -53,7 +63,10 @@ func (b Bundle) Validate() error { if len(b.Tasks) != 1 || len(b.Plans) == 0 || len(b.Plans) > 64 { return errors.New("source inventory bound") } - if b.Governance.Schema != "agentic-ai-lab.loop-governor.v1" || b.Governance.Family != b.Tasks[0].Family || len(b.Governance.OpenNodes) != len(b.Plans) || len(b.Tasks[0].Nodes) != len(b.Plans) { + supported := b.Governance.Schema == "agentic-ai-lab.loop-governor.v1" || + (b.Governance.Schema == SessionWorkflowSchema && len(b.Plans) >= 2) || + ((b.Governance.Schema == SessionDAGSchema || b.Governance.Schema == SessionChoiceSchema || b.Governance.Schema == SessionNestedSchema) && len(b.Governance.WorkflowEdges) > 0 && len(b.Governance.WorkflowEdges) <= 64) + if !supported || b.Governance.Family != b.Tasks[0].Family || len(b.Governance.OpenNodes) != len(b.Plans) || len(b.Tasks[0].Nodes) != len(b.Plans) { return errors.New("Governor source handoff binding") } selected := map[string]bool{} @@ -63,6 +76,9 @@ func (b Bundle) Validate() error { } selected[node] = true } + if err := b.Governance.validateWorkflowEdges(); err != nil { + return err + } for _, node := range b.Tasks[0].Nodes { if !selected[node] { return errors.New("task exceeds governor selection") @@ -101,6 +117,77 @@ func (b Bundle) Validate() error { return nil } +func (g Governance) validateWorkflowEdges() error { + if g.Schema == SessionNestedSchema { + if len(g.WorkflowSelectors) == 0 || len(g.WorkflowSelectors) > 31 { + return errors.New("nested Session selector count") + } + entries := make(map[string]bool) + for i, choice := range g.WorkflowSelectors { + if i > 0 && g.WorkflowSelectors[i-1][0] >= choice[0] { + return errors.New("nested Session selector order") + } + for _, entry := range choice[1:] { + parents := 0 + for _, edge := range g.WorkflowEdges { + if edge[0] == entry { + if edge[1] != choice[0] { + return errors.New("nested Session entry parent") + } + parents++ + } + } + if parents != 1 || entries[entry] { + return errors.New("nested Session entry") + } + entries[entry] = true + } + } + } else if len(g.WorkflowSelectors) != 0 { + return errors.New("selectors require nested Session") + } + if g.Schema != SessionDAGSchema && g.Schema != SessionChoiceSchema && g.Schema != SessionNestedSchema { + if len(g.WorkflowEdges) != 0 { + return errors.New("workflow edges require Session DAG") + } + return nil + } + position := make(map[string]int, len(g.OpenNodes)) + for i, node := range g.OpenNodes { + position[node] = i + } + connected := make(map[string]bool, len(g.OpenNodes)) + var previous [2]string + for i, edge := range g.WorkflowEdges { + child, childOK := position[edge[0]] + parent, parentOK := position[edge[1]] + if !childOK || !parentOK || parent >= child || + (i > 0 && (previous[0] > edge[0] || (previous[0] == edge[0] && previous[1] >= edge[1]))) { + return errors.New("invalid Session DAG edge") + } + connected[edge[0]] = true + previous = edge + } + if g.Schema == SessionChoiceSchema { + if len(g.OpenNodes) != 4 || len(g.WorkflowEdges) != 4 { + return errors.New("conditional Session shape") + } + root, left, right, join := g.OpenNodes[0], g.OpenNodes[1], g.OpenNodes[2], g.OpenNodes[3] + for _, edge := range g.WorkflowEdges { + if edge != [2]string{left, root} && edge != [2]string{right, root} && + edge != [2]string{join, left} && edge != [2]string{join, right} { + return errors.New("conditional Session edge") + } + } + } + for _, node := range g.OpenNodes[1:] { + if !connected[node] { + return errors.New("disconnected Session DAG step") + } + } + return nil +} + func (b Bundle) View() v1.View { revision := uint64(0) if b.Publication.ExpectedRevision != nil { diff --git a/go/internal/config/freeze.go b/go/internal/config/freeze.go index a872b6a9..1cf72c3d 100644 --- a/go/internal/config/freeze.go +++ b/go/internal/config/freeze.go @@ -24,6 +24,8 @@ func FreezeBundle(input Bundle) (Bundle, error) { } result := input result.Governance.OpenNodes = slices.Clone(input.Governance.OpenNodes) + result.Governance.WorkflowEdges = slices.Clone(input.Governance.WorkflowEdges) + result.Governance.WorkflowSelectors = slices.Clone(input.Governance.WorkflowSelectors) result.Publication = input.Publication.Clone() result.Tasks = make([]v1.Task, len(input.Tasks)) for index, t := range input.Tasks { @@ -106,6 +108,19 @@ func sourceTextBound(input Bundle) bool { if !strings([]string{input.Governance.Schema, input.Governance.Family, input.Publication.OperationID, input.Publication.Policy, input.Publication.Schema}) || !strings(input.Governance.OpenNodes) { return false } + if len(input.Governance.WorkflowEdges) > 64 || len(input.Governance.WorkflowSelectors) > 31 { + return false + } + for _, edge := range input.Governance.WorkflowEdges { + if !strings(edge[:]) { + return false + } + } + for _, selector := range input.Governance.WorkflowSelectors { + if !strings(selector[:]) { + return false + } + } if r := input.Publication.Review; r != nil { if !strings([]string{r.Audience, r.SourceIdentityDigest, r.Signature, r.Delta, r.Review.Artifact, r.Review.Publication.OperationID, r.Review.Publication.Digest, string(r.Disposition)}) { return false diff --git a/go/internal/controlplane/source_compile.go b/go/internal/controlplane/source_compile.go index d3a21152..126df314 100644 --- a/go/internal/controlplane/source_compile.go +++ b/go/internal/controlplane/source_compile.go @@ -46,6 +46,18 @@ func compiledBundle(input *pb.SourceArtifact) (config.Bundle, error) { } bundle := config.Bundle{Governance: config.Governance{Schema: g.Schema, Family: g.Family, OpenNodes: g.OpenNodes}, Publication: v1.Publication{OperationID: p.OperationId, ExpectedRevision: cloneRevision(p.ExpectedRevision), Fence: p.Fence, Policy: p.Policy, Schema: p.Schema}} + for _, edge := range g.WorkflowEdges { + if edge == nil || unknownFields(edge) { + return zero, errors.New("compiled workflow edge") + } + bundle.Governance.WorkflowEdges = append(bundle.Governance.WorkflowEdges, [2]string{edge.Dependent, edge.Dependency}) + } + for _, choice := range g.WorkflowSelectors { + if choice == nil || unknownFields(choice) { + return zero, errors.New("compiled workflow selector") + } + bundle.Governance.WorkflowSelectors = append(bundle.Governance.WorkflowSelectors, [3]string{choice.Selector, choice.Left, choice.Right}) + } for _, t := range input.Tasks { if t == nil || unknownFields(t) { return zero, errors.New("compiled task missing") diff --git a/proto/gateway/v1/gateway.proto b/proto/gateway/v1/gateway.proto index 5d2debf9..0948499f 100644 --- a/proto/gateway/v1/gateway.proto +++ b/proto/gateway/v1/gateway.proto @@ -79,7 +79,9 @@ message FactBarrierResolution { string previous_pending_prefix = 4; optional string remaining_pending_prefix = 5; } -message GovernanceSelection { string schema = 1; string family = 2; repeated string open_nodes = 3; } +message WorkflowEdge { string dependent = 1; string dependency = 2; } +message WorkflowSelector { string selector = 1; string left = 2; string right = 3; } +message GovernanceSelection { string schema = 1; string family = 2; repeated string open_nodes = 3; repeated WorkflowEdge workflow_edges = 4; repeated WorkflowSelector workflow_selectors = 5; } message SourceArtifact { GovernanceSelection governance = 1; repeated Task tasks = 2; repeated ProviderPlan plans = 3; PublishRequest publication = 4; } // Source authority here is knowledge at response admission, never a later permit. message CompiledSource { string producer = 1; SourceAuthorityView authority = 2; SourceArtifact artifact = 3; } From 1c09d9962fbb66a03afab0ea4f168afa1f414e40 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 21:21:12 +0800 Subject: [PATCH 030/105] Use SysML for the production Go dependency boundary --- Project.sysml | 1 + go/dev/runtime_boundary_test.go | 43 ++++++++++--------- go/dev/workspace_test.go | 76 --------------------------------- 3 files changed, 24 insertions(+), 96 deletions(-) diff --git a/Project.sysml b/Project.sysml index f25d6d86..5c7550e0 100644 --- a/Project.sysml +++ b/Project.sysml @@ -115,6 +115,7 @@ package WeaverProject { part 'gerbil.pkg' : RuntimeInput; part 'github.com/HardenedLinux/weaver/go/dev' : ForbiddenRuntimeReference; part 'github.com/HardenedLinux/weaver/go/internal/devrunner' : ForbiddenRuntimeReference; + part 'github.com/Open-MBEE/OpenSysML' : ForbiddenRuntimeReference; part ':hardenedlinux/weaver/dev' : ForbiddenRuntimeReference; part 'weaver-dev' : ForbiddenRuntimeReference; doc /* Rust src/build inputs derive from Layout.RustPackage. Go inputs diff --git a/go/dev/runtime_boundary_test.go b/go/dev/runtime_boundary_test.go index 39b1335e..a95023c8 100644 --- a/go/dev/runtime_boundary_test.go +++ b/go/dev/runtime_boundary_test.go @@ -201,33 +201,36 @@ func TestProjectArchitectureRuntimeAssetBoundary(t *testing.T) { inputs = append(inputs, build) } } + patterns := make([]string, 0, len(entries)) for _, entry := range entries { relative, err := filepath.Rel(filepath.Join(repository, "go"), filepath.Join(repository, entry)) if err != nil { t.Fatal(err) } - stream := json.NewDecoder(bytes.NewReader(tool(t, filepath.Join(runtime.GOROOT(), "bin/go"), "-C", "go", "list", "-deps", "-json", "./"+filepath.ToSlash(relative)))) - for { - var pkg struct { - Dir, ImportPath string - GoFiles, CgoFiles, IgnoredGoFiles []string - } - if err := stream.Decode(&pkg); err != nil { - if err == io.EOF { - break - } - t.Fatal(err) - } - if err := boundary.reference(repository, pkg.Dir, pkg.ImportPath); err != nil { - t.Fatal(err) + patterns = append(patterns, "./"+filepath.ToSlash(relative)) + } + args := append([]string{"-C", "go", "list", "-deps", "-json"}, patterns...) + stream := json.NewDecoder(bytes.NewReader(tool(t, filepath.Join(runtime.GOROOT(), "bin/go"), args...))) + for { + var pkg struct { + Dir, ImportPath string + GoFiles, CgoFiles, IgnoredGoFiles []string + } + if err := stream.Decode(&pkg); err != nil { + if err == io.EOF { + break } - if insidePath(pkg.Dir, repository) { - for _, name := range append(append(pkg.GoFiles, pkg.CgoFiles...), pkg.IgnoredGoFiles...) { - if strings.HasSuffix(name, "_test.go") { - continue - } - inputs = append(inputs, filepath.Join(pkg.Dir, name)) + t.Fatal(err) + } + if err := boundary.reference(repository, pkg.Dir, pkg.ImportPath); err != nil { + t.Fatal(err) + } + if insidePath(pkg.Dir, repository) { + for _, name := range append(append(pkg.GoFiles, pkg.CgoFiles...), pkg.IgnoredGoFiles...) { + if strings.HasSuffix(name, "_test.go") { + continue } + inputs = append(inputs, filepath.Join(pkg.Dir, name)) } } } diff --git a/go/dev/workspace_test.go b/go/dev/workspace_test.go index 3881a56c..0afec8d3 100644 --- a/go/dev/workspace_test.go +++ b/go/dev/workspace_test.go @@ -5,20 +5,15 @@ package dev import ( - "bufio" "bytes" "context" "encoding/json" - "math/rand" "os" "os/exec" "path/filepath" "regexp" - "runtime" - "strconv" "strings" "testing" - "testing/quick" "time" "github.com/HardenedLinux/weaver/go/internal/devrunner" @@ -158,25 +153,6 @@ func TestCargoWorkspaceAndDevelopmentGates(t *testing.T) { if !known { t.Fatalf("unmapped crate: %s", p.Name) } - data, err := os.ReadFile(p.ManifestPath) - if err != nil { - t.Fatal(err) - } - scan := bufio.NewScanner(strings.NewReader(string(data))) - dependencies := false - for scan.Scan() { - line := strings.TrimSpace(strings.SplitN(scan.Text(), "#", 2)[0]) - if strings.HasPrefix(line, "[") { - dependencies = strings.Contains(line, "dependencies") - continue - } - if dependencies && line != "" && !inheritedDependency.MatchString(line) { - t.Fatalf("dependency not inherited from workspace: %s: %s", p.Name, line) - } - } - if err := scan.Err(); err != nil { - t.Fatal(err) - } actual := map[string]bool{} asp, criterion := 0, 0 for _, d := range p.Dependencies { @@ -277,55 +253,3 @@ func TestCargoWorkspaceAndDevelopmentGates(t *testing.T) { } } } -func TestSysMLSDKIsAbsentFromProductionBuild(t *testing.T) { - goBinary := filepath.Join(runtime.GOROOT(), "bin/go") - commands := strings.Fields(string(tool(t, goBinary, "-C", "go", "list", "./cmd/..."))) - production := 0 - for _, command := range commands { - // The development owner intentionally captures SDK views in-process. - // Every other command, including future commands, remains covered. - if strings.HasSuffix(command, "/cmd/weaver-dev") { - continue - } - production++ - t.Run(command, func(t *testing.T) { - deps := tool(t, goBinary, "-C", "go", "list", "-deps", command) - if strings.Contains(string(deps), "github.com/Open-MBEE/OpenSysML") { - t.Fatal("development SDK leaked into production command graph") - } - }) - } - if production == 0 { - t.Fatal("no production commands were checked") - } -} - -// Canonical member declarations may select workspace features without becoming -// optional. Source/version/path overrides remain forbidden; Cargo metadata above -// independently resolves every member and checks its actual dependency graph. -var inheritedDependency = regexp.MustCompile(`^[A-Za-z0-9_-]+(?:\.workspace\s*=\s*true|\s*=\s*\{\s*workspace\s*=\s*true(?:,\s*optional\s*=\s*true)?(?:,\s*features\s*=\s*\["[A-Za-z0-9_/-]+"(?:,\s*"[A-Za-z0-9_/-]+")*\])?\s*\})\s*$`) - -func TestCargoWorkspaceInheritanceForms(t *testing.T) { - check := func(selector uint8) bool { - gap := strings.Repeat(" ", int(selector%4)) - feature := "commit-observer-" + strconv.Itoa(int(selector)) - base := "weaver-ledger = {" + gap + "workspace = true" - optional := "" - if selector&1 != 0 { - optional = ", optional = true" - } - valid := base + optional + ", features = [\"" + feature + "\"]" + gap + "}" - if !inheritedDependency.MatchString(valid) || !inheritedDependency.MatchString("weaver-ledger.workspace = true") { - return false - } - for _, override := range []string{`version = "1"`, `path = "../ledger"`, `git = "https://example.invalid/ledger"`, `workspace = false`} { - if inheritedDependency.MatchString("weaver-ledger = {"+override+"}") || inheritedDependency.MatchString(base+", "+override+"}") { - return false - } - } - return true - } - if err := quick.Check(check, &quick.Config{MaxCount: 64, Rand: rand.New(rand.NewSource(293))}); err != nil { - t.Fatal(err) - } -} From 6ebab133fc2472641ca15f685089e310e4e893b0 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 21:36:19 +0800 Subject: [PATCH 031/105] Use Lab Gerbil ASCENT for hard fact impact --- Cargo.lock | 84 +------------------- Cargo.toml | 1 - Project.sysml | 1 + crates/governance/Cargo.toml | 1 - crates/governance/src/hard_fact.rs | 61 -------------- crates/governance/src/host/client.rs | 17 +++- crates/governance/src/host/mod.rs | 2 +- crates/governance/src/host/owner.rs | 9 ++- crates/governance/src/host/state.rs | 11 ++- crates/governance/src/lib.rs | 6 +- crates/governance/src/program/compiler.rs | 15 ++++ crates/governance/src/program/linked.rs | 10 +++ crates/governance/src/scheme.rs | 15 ++-- crates/governance/src/scheme_input/mod.rs | 2 +- crates/governance/src/scheme_input/values.rs | 24 +++--- crates/server/src/governance_deployment.rs | 20 +++-- crates/server/src/governance_owner.rs | 31 +++++++- crates/server/src/grpc.rs | 24 +++--- crates/server/src/runtime.rs | 9 +++ dev/sysml/PolicyEvidenceDesign.sysml | 7 +- dev/sysml/runtime-trace.json | 2 +- go/dev/provider_hard_fact_test.go | 5 +- scheme/gateway/compiled.ss | 9 ++- scheme/gateway/program.ss | 33 +++++++- t/gateway-fact-impact-test.ss | 17 ++++ 25 files changed, 217 insertions(+), 199 deletions(-) delete mode 100644 crates/governance/src/hard_fact.rs create mode 100644 t/gateway-fact-impact-test.ss diff --git a/Cargo.lock b/Cargo.lock index b2291862..b258b958 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,12 +79,6 @@ dependencies = [ "cc", ] -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - [[package]] name = "allocator-api2" version = "0.4.0" @@ -305,47 +299,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "ascent" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b69c5a0326edc45aea8469a51f84be0ff28ea1e3a4d087665468793be061682" -dependencies = [ - "ascent_base", - "ascent_macro", - "boxcar", - "cfg-if", - "hashbrown 0.14.5", - "pastey", - "rustc-hash 2.1.3", - "web-time", -] - -[[package]] -name = "ascent_base" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "792af0babe403e49368d8717763605fe978b3a1eb7d51b52e3d0a5cb97e6eb74" -dependencies = [ - "pastey", -] - -[[package]] -name = "ascent_macro" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac2662b20bf37fd66d21687c0ef91f1c64320a7ca985a34d1c3e60cc9ba940a" -dependencies = [ - "ascent_base", - "derive-syn-parse", - "duplicate", - "itertools 0.15.0", - "petgraph 0.8.3", - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "ascii-canvas" version = "4.0.0" @@ -709,12 +662,6 @@ dependencies = [ "cfg_aliases", ] -[[package]] -name = "boxcar" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c99613cb3cd7429889a08dfcf651721ca971c86afa30798461f8eee994de47" - [[package]] name = "branches" version = "0.4.6" @@ -1451,17 +1398,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "derive-syn-parse" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "digest" version = "0.10.7" @@ -1502,12 +1438,6 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" -[[package]] -name = "duplicate" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e92f10a49176cbffacaedabfaa11d51db1ea0f80a83c26e1873b43cd1742c24" - [[package]] name = "dyn-clone" version = "1.0.20" @@ -2042,16 +1972,6 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2 0.2.21", -] - [[package]] name = "hashbrown" version = "0.15.5" @@ -3445,7 +3365,6 @@ dependencies = [ "fixedbitset", "hashbrown 0.15.5", "indexmap 2.14.2", - "serde", ] [[package]] @@ -5270,7 +5189,7 @@ dependencies = [ "aegis", "aes", "aes-gcm", - "allocator-api2 0.4.0", + "allocator-api2", "antithesis_sdk", "arc-swap", "aristo", @@ -5759,7 +5678,6 @@ dependencies = [ name = "weaver-governance" version = "0.1.0" dependencies = [ - "ascent", "asp-rust", "criterion", "gerbil-scheme", diff --git a/Cargo.toml b/Cargo.toml index 4e470031..d31ddac5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,6 @@ edition = "2024" license = "LGPL-2.1-or-later AND Apache-2.0" [workspace.dependencies] -ascent = { version = "=0.8.1", default-features = false } weaver-contracts = { path = "crates/contracts" } weaver-governance = { path = "crates/governance" } weaver-policy = { path = "crates/policy" } diff --git a/Project.sysml b/Project.sysml index 5c7550e0..1686fdd2 100644 --- a/Project.sysml +++ b/Project.sysml @@ -730,6 +730,7 @@ package WeaverProject { fixture. This object supplies no publication or send authority. */ } part 't/gateway-contracts-test.ss' : File; + part 't/gateway-fact-impact-test.ss' : File; part 't/governance-test.ss' : File; part 't/policy-test.ss' : File; part 't/fixtures/governed-control.ss' : File { diff --git a/crates/governance/Cargo.toml b/crates/governance/Cargo.toml index 7a508c34..9c7c402b 100644 --- a/crates/governance/Cargo.toml +++ b/crates/governance/Cargo.toml @@ -14,7 +14,6 @@ scheme-program = ["scheme-vm", "dep:gerbil-scheme-sys", "dep:weaver-policy-ffi"] scheme-qualification = ["scheme-program"] [dependencies] -ascent.workspace = true weaver-contracts.workspace = true serde.workspace = true thiserror.workspace = true diff --git a/crates/governance/src/hard_fact.rs b/crates/governance/src/hard_fact.rs deleted file mode 100644 index 516a3c9b..00000000 --- a/crates/governance/src/hard_fact.rs +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors -// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 - -//! Closed impact rules over a deployment-admitted original task. -use ascent::ascent; -use weaver_contracts::{Error, FactWork, Result}; - -ascent! { - struct FactImpact; - relation depends(String, String); - relation changed(String); - relation affected(String); - affected(node) <-- changed(node); - affected(dependent) <-- depends(dependent, node), affected(node); -} - -/// Native evaluation is bounded by the admitted finite input graph. No source -/// mutation, authority observation or permission grant occurs in this function. -pub fn derive_fact_impact(work: &FactWork) -> Result> { - if work.dependencies.len() > 64 { - return Err(Error::Invalid("fact impact graph bound")); - } - let mut program = FactImpact { - depends: work.dependencies.clone(), - changed: vec![(work.root.clone(),)], - ..Default::default() - }; - program.run(); - let mut affected: Vec<_> = program.affected.into_iter().map(|(node,)| node).collect(); - affected.sort_unstable(); - Ok(affected) -} - -#[cfg(test)] -#[test] -fn hard_fact_impact_is_transitive_and_handles_cycles() { - let work = FactWork { - barrier: weaver_contracts::FactBarrier { - operation_id: "test".into(), - source_epoch: 0, - revision: 1, - snapshot: String::new(), - floor: 1, - pending_prefix: String::new(), - }, - expected_floor: 1, - pending_prefix: String::new(), - root: "root".into(), - dependencies: vec![ - ("direct".into(), "root".into()), - ("transitive".into(), "direct".into()), - ("root".into(), "transitive".into()), - ("unrelated".into(), "other".into()), - ], - available: false, - }; - assert_eq!( - derive_fact_impact(&work).expect("fixed point"), - ["direct", "root", "transitive"] - ); -} diff --git a/crates/governance/src/host/client.rs b/crates/governance/src/host/client.rs index ef4911bb..c8b462df 100644 --- a/crates/governance/src/host/client.rs +++ b/crates/governance/src/host/client.rs @@ -76,6 +76,21 @@ impl SourceClient { } /// Submit a detached ledger observation on the same bounded Scheme owner. pub async fn derive(&self, input: crate::GovernorCut) -> Result, SourceJobError> { + self.evaluate(crate::Derivation::Governor(Box::new(input))) + .await + } + /// Ask the same Scheme owner for the impact of an already persisted intent. + pub async fn fact_impact( + &self, + work: &weaver_contracts::FactWork, + ) -> Result, SourceJobError> { + self.evaluate(crate::Derivation::FactImpact { + root: work.root.clone(), + dependencies: work.dependencies.clone(), + }) + .await + } + async fn evaluate(&self, input: crate::Derivation) -> Result, SourceJobError> { let slot = self .capacity .clone() @@ -89,7 +104,7 @@ impl SourceClient { } self.sender .try_send(Command::Derive { - input: Box::new(input), + input, reply, _slot: slot, }) diff --git a/crates/governance/src/host/mod.rs b/crates/governance/src/host/mod.rs index 1154ddbe..542e8510 100644 --- a/crates/governance/src/host/mod.rs +++ b/crates/governance/src/host/mod.rs @@ -10,5 +10,5 @@ mod state; pub use client::{SourceClient, source_lane}; pub use owner::SourceInbox; pub use request::{SourceJob, SourceJobError}; -pub use state::GovernorCut; use state::{Command, Phase, Reply, Shared, State, Work}; +pub use state::{Derivation, GovernorCut}; diff --git a/crates/governance/src/host/owner.rs b/crates/governance/src/host/owner.rs index 9c187d3d..88170271 100644 --- a/crates/governance/src/host/owner.rs +++ b/crates/governance/src/host/owner.rs @@ -30,12 +30,15 @@ impl SourceInbox { self, owner: C, mut compile: impl FnMut(&mut C, &OwnedSource) -> Result, - derive: impl FnMut(&mut C, &crate::GovernorCut) -> Result, SourceError>, + mut derive: impl FnMut(&mut C, &crate::GovernorCut) -> Result, SourceError>, ) { self.run_with_cancellable_governor( owner, |owner, original, _| compile(owner, original), - derive, + |owner, input| match input { + crate::Derivation::Governor(cut) => derive(owner, cut), + crate::Derivation::FactImpact { .. } => Err(SourceError::Contract), + }, ); } /// Pass the request cancellation token into a cooperative compiler. @@ -47,7 +50,7 @@ impl SourceInbox { &OwnedSource, &CancellationToken, ) -> Result, - mut derive: impl FnMut(&mut C, &crate::GovernorCut) -> Result, SourceError>, + mut derive: impl FnMut(&mut C, &crate::Derivation) -> Result, SourceError>, ) { while let Some(command) = self.receiver.blocking_recv() { if *self.shared.gate() { diff --git a/crates/governance/src/host/state.rs b/crates/governance/src/host/state.rs index ca201a98..4f002d35 100644 --- a/crates/governance/src/host/state.rs +++ b/crates/governance/src/host/state.rs @@ -80,9 +80,18 @@ pub struct GovernorCut { pub nested_results: Vec<(String, String)>, pub nested_decisions: Vec<(String, String)>, } +/// Inert observations evaluated by the existing linked Scheme owner. +#[derive(serde::Serialize)] +pub enum Derivation { + Governor(Box), + FactImpact { + root: String, + dependencies: Vec<(String, String)>, + }, +} pub(super) enum Command { Derive { - input: Box, + input: Derivation, reply: oneshot::Sender, crate::SourceError>>, _slot: OwnedSemaphorePermit, }, diff --git a/crates/governance/src/lib.rs b/crates/governance/src/lib.rs index c757b07f..37f7c007 100644 --- a/crates/governance/src/lib.rs +++ b/crates/governance/src/lib.rs @@ -10,10 +10,10 @@ mod catalog; mod host; mod source; pub use binding::{BoundSource, SourceExpectation}; -mod hard_fact; pub use catalog::{ApprovedProducer, CatalogError, ProducerCatalog, ProducerClient}; -pub use hard_fact::derive_fact_impact; -pub use host::{GovernorCut, SourceClient, SourceInbox, SourceJob, SourceJobError, source_lane}; +pub use host::{ + Derivation, GovernorCut, SourceClient, SourceInbox, SourceJob, SourceJobError, source_lane, +}; pub use source::{MAX_SOURCE_BYTES, OwnedSource, SourceData, SourceError, SourceSelection}; #[cfg(feature = "scheme-vm")] diff --git a/crates/governance/src/program/compiler.rs b/crates/governance/src/program/compiler.rs index 09a9d944..aed36bed 100644 --- a/crates/governance/src/program/compiler.rs +++ b/crates/governance/src/program/compiler.rs @@ -24,6 +24,21 @@ impl SchemeCompiler { } Ok(Self { runtime }) } + pub fn evaluate(&mut self, input: &crate::Derivation) -> Result, SourceError> { + match input { + crate::Derivation::Governor(_) => Err(SourceError::Contract), + crate::Derivation::FactImpact { root, dependencies } => { + let input = crate::scheme_input::values::Input::new(&self.runtime); + let root = input.record(vec![ + ("root", input.text(root)?), + ("dependencies", input.edges(dependencies)?), + ])?; + let output = + linked::fact_impact(&self.runtime, &root).map_err(|_| SourceError::Scheme)?; + crate::scheme::materialize(output) + } + } + } /// Compilation is inert preparation; the source lane independently binds /// this result to its retained original before any caller can claim it. pub fn compile(&mut self, original: &OwnedSource) -> Result { diff --git a/crates/governance/src/program/linked.rs b/crates/governance/src/program/linked.rs index 880f5291..7a982a1c 100644 --- a/crates/governance/src/program/linked.rs +++ b/crates/governance/src/program/linked.rs @@ -11,6 +11,7 @@ unsafe extern "C" { fn ___LNK_weaver__governance__program( ctx: *mut gerbil_scheme_sys::GerbilGlobalState, ) -> *mut gerbil_scheme_sys::GerbilModuleOrLink; + fn weaver_hard_fact_impact_v1(root: i64) -> i64; fn weaver_capture_source_v1(root: i64) -> i64; fn weaver_governance_ready_v1(root: i64) -> i64; } @@ -42,3 +43,12 @@ pub(super) fn capture<'r>( let export = unsafe { runtime.bind_object_export(weaver_capture_source_v1) }?; export.call(input).into_result() } + +pub(super) fn fact_impact<'r>( + runtime: &'r GerbilRuntime, + input: &RootedSchemeObject<'_>, +) -> Result, GerbilError> { + // SAFETY: fixed same-graph rooted call transfers one fresh result root. + let export = unsafe { runtime.bind_object_export(weaver_hard_fact_impact_v1) }?; + export.call(input).into_result() +} diff --git a/crates/governance/src/scheme.rs b/crates/governance/src/scheme.rs index e6cc28ef..871eb65f 100644 --- a/crates/governance/src/scheme.rs +++ b/crates/governance/src/scheme.rs @@ -4,12 +4,12 @@ //! Scheme object conversion using the pinned Gerbil's GC-rooted APIs. //! No JSON text, unrooted object word, or VM borrow enters OwnedSource. -use crate::{MAX_SOURCE_BYTES, OwnedSource, SourceData, SourceError}; +use crate::{MAX_SOURCE_BYTES, OwnedSource, SourceError}; use gerbil_scheme::{ BigIntegerBuffer, CollectionKind, IdentifierBuffer, IdentifierKind, ObjectKind, RootedObjectBatch, RootedSchemeObject, SchemeScalar, }; -use serde::de::{self, Deserialize, DeserializeSeed, MapAccess, SeqAccess, Visitor}; +use serde::de::{self, DeserializeSeed, MapAccess, SeqAccess, Visitor}; use std::collections::BTreeSet; /// Materialize and bind to the original retained before the approved call. @@ -49,16 +49,21 @@ impl SchemeDeserializer<'_, '_> { /// Approved producer supplies a stable typed snapshot. Gerbil table copies are /// shallow; limits bound traversal, not arbitrary hostile VM allocation. pub fn materialize_source(source: RootedSchemeObject<'_>) -> Result { + OwnedSource::from_source(materialize(source)?) +} + +pub(crate) fn materialize( + source: RootedSchemeObject<'_>, +) -> Result { let mut limits = Limits { bytes: MAX_SOURCE_BYTES, nodes: 16384, }; - let data = SourceData::deserialize(SchemeDeserializer { + T::deserialize(SchemeDeserializer { value: source, limits: &mut limits, depth: 0, - })?; - OwnedSource::from_source(data) + }) } struct Sequence<'r, 'a> { entries: RootedObjectBatch<'r>, diff --git a/crates/governance/src/scheme_input/mod.rs b/crates/governance/src/scheme_input/mod.rs index 2d10c665..3a7f9c58 100644 --- a/crates/governance/src/scheme_input/mod.rs +++ b/crates/governance/src/scheme_input/mod.rs @@ -4,5 +4,5 @@ //! Typed, fallible Rust-to-Scheme construction on the VM owner thread. mod records; -mod values; +pub(crate) mod values; pub use records::root_source; diff --git a/crates/governance/src/scheme_input/values.rs b/crates/governance/src/scheme_input/values.rs index 337557a5..a32d4f3a 100644 --- a/crates/governance/src/scheme_input/values.rs +++ b/crates/governance/src/scheme_input/values.rs @@ -8,9 +8,9 @@ use gerbil_scheme::{ BinaryInteger, CollectionKind, GerbilRuntime, IdentifierKind, RootedSchemeObject, TableEquality, }; use std::{cell::Cell, collections::BTreeMap}; -pub(super) type Object<'r> = RootedSchemeObject<'r>; -pub(super) type Result = std::result::Result; -pub(super) struct Input<'r> { +pub(crate) type Object<'r> = RootedSchemeObject<'r>; +pub(crate) type Result = std::result::Result; +pub(crate) struct Input<'r> { vm: &'r GerbilRuntime, bytes: Cell, nodes: Cell, @@ -19,7 +19,7 @@ fn scheme_result(value: std::result::Result) - value.map_err(|_| SourceError::Scheme) } impl<'r> Input<'r> { - pub(super) fn new(vm: &'r GerbilRuntime) -> Self { + pub(crate) fn new(vm: &'r GerbilRuntime) -> Self { Self { vm, bytes: Cell::new(MAX_SOURCE_BYTES), @@ -40,12 +40,12 @@ impl<'r> Input<'r> { ); Ok(()) } - pub(super) fn text(&self, value: &str) -> Result> { + pub(crate) fn text(&self, value: &str) -> Result> { self.node()?; self.bytes(value.len())?; Ok(scheme_result(self.vm.string_from_utf8(value))?.into_object()) } - pub(super) fn number(&self, value: u64) -> Result> { + pub(crate) fn number(&self, value: u64) -> Result> { self.node()?; let mut bytes = value.to_le_bytes().to_vec(); while bytes.last() == Some(&0) { @@ -54,7 +54,7 @@ impl<'r> Input<'r> { let integer = BinaryInteger::new(false, bytes).map_err(|_| SourceError::Contract)?; scheme_result(self.vm.big_integer(&integer)) } - pub(super) fn record(&self, fields: Vec<(&'static str, Object<'r>)>) -> Result> { + pub(crate) fn record(&self, fields: Vec<(&'static str, Object<'r>)>) -> Result> { self.node()?; if fields.len() > 64 { return Err(SourceError::Bound); @@ -72,7 +72,7 @@ impl<'r> Input<'r> { .collect(); scheme_result(self.vm.hash_table(TableEquality::Structural, &entries)) } - pub(super) fn vector(&self, values: Vec>) -> Result> { + pub(crate) fn vector(&self, values: Vec>) -> Result> { self.node()?; if values.len() > 64 { return Err(SourceError::Bound); @@ -85,7 +85,7 @@ impl<'r> Input<'r> { )? .into_object()) } - pub(super) fn edges(&self, edges: &[(String, String)]) -> Result> { + pub(crate) fn edges(&self, edges: &[(String, String)]) -> Result> { self.vector( edges .iter() @@ -93,7 +93,7 @@ impl<'r> Input<'r> { .collect::>>()?, ) } - pub(super) fn strings(&self, values: &[String]) -> Result> { + pub(crate) fn strings(&self, values: &[String]) -> Result> { if values.len() > 64 { return Err(SourceError::Bound); } @@ -104,10 +104,10 @@ impl<'r> Input<'r> { .collect::>>()?, ) } - pub(super) fn texts(&self, values: &BTreeMap) -> Result> { + pub(crate) fn texts(&self, values: &BTreeMap) -> Result> { self.mapping(values, |value| self.text(value)) } - pub(super) fn numbers(&self, values: &BTreeMap) -> Result> { + pub(crate) fn numbers(&self, values: &BTreeMap) -> Result> { self.mapping(values, |value| self.number(*value)) } fn mapping( diff --git a/crates/server/src/governance_deployment.rs b/crates/server/src/governance_deployment.rs index 92980bbf..fbb3893f 100644 --- a/crates/server/src/governance_deployment.rs +++ b/crates/server/src/governance_deployment.rs @@ -30,6 +30,11 @@ pub(crate) async fn start( catalog: Option, ) -> Result> { let Some(catalog) = catalog else { + if runtime.fact_feed().is_some() { + return Err(Error::Invalid( + "hard fact feed requires the linked Scheme owner", + )); + } return Ok(None); }; #[cfg(not(feature = "scheme-program"))] @@ -57,11 +62,16 @@ async fn start_compiler( .map_err(|_| Error::Conflict("compiler owner budget"))?, ); let worker = runtime - .start_governance(slot, capacity, || { - let mut compiler = weaver_governance::SchemeCompiler::initialize() - .map_err(|_| Error::Conflict("approved Scheme program unavailable"))?; - Ok(move |source: &weaver_governance::OwnedSource| compiler.compile(source)) - }) + .start_governance_with_governor( + slot, + capacity, + || { + weaver_governance::SchemeCompiler::initialize() + .map_err(|_| Error::Conflict("approved Scheme program unavailable")) + }, + |compiler, source, _| compiler.compile(source), + weaver_governance::SchemeCompiler::evaluate, + ) .await?; worker.publish_producers(catalog)?; Ok(worker) diff --git a/crates/server/src/governance_owner.rs b/crates/server/src/governance_owner.rs index 37475761..0994ac16 100644 --- a/crates/server/src/governance_owner.rs +++ b/crates/server/src/governance_owner.rs @@ -33,6 +33,35 @@ impl RuntimeOwner { F: FnOnce() -> Result + Send + 'static, C: FnMut(&OwnedSource) -> std::result::Result + 'static, { + self.start_governance_with_governor( + slot, + capacity, + initialize, + |compiler, original, _| compiler(original), + |_, _| Err(SourceError::Contract), + ) + .await + } + + pub(crate) async fn start_governance_with_governor( + &self, + slot: Arc, + capacity: NonZeroUsize, + initialize: impl FnOnce() -> Result + Send + 'static, + compile: impl FnMut( + &mut C, + &OwnedSource, + &tokio_util::sync::CancellationToken, + ) -> std::result::Result + + Send + + 'static, + derive: impl FnMut( + &mut C, + &weaver_governance::Derivation, + ) -> std::result::Result, SourceError> + + Send + + 'static, + ) -> Result { let (client, inbox) = source_lane(capacity); self.attach_governance(client.clone())?; let mut starting = self.shutdown_guard(); @@ -51,7 +80,7 @@ impl RuntimeOwner { return Ok(()); } // run drops the compiler (and its VM) before the tracked task ends. - inbox.run(compiler); + inbox.run_with_cancellable_governor(compiler, compile, derive); Ok(()) })?; let initialized = receiver diff --git a/crates/server/src/grpc.rs b/crates/server/src/grpc.rs index a3248133..9a38374d 100644 --- a/crates/server/src/grpc.rs +++ b/crates/server/src/grpc.rs @@ -352,18 +352,22 @@ impl pb::gateway_server::Gateway for Gateway { let result = match source.prepare_fact(caller.clone(), barrier).await? { weaver_ledger::FactPreparation::Resolved(resolution) => resolution, weaver_ledger::FactPreparation::Pending(work) => { - let slot = self.admission.observation()?; - let job = self + let _slot = self.admission.observation()?; + let affected = self .runtime - .spawn_blocking(slot, move |_| { - let affected = weaver_governance::derive_fact_impact(&work)?; - Ok((work, affected)) - }) - .map_err(status)?; - let (work, affected) = job + .governor() + .map_err(status)? + .fact_impact(&work) .await - .map_err(|_| Status::unavailable("hard fact derivation interrupted"))? - .map_err(status)?; + .map_err(|error| match error { + weaver_governance::SourceJobError::Busy => { + Status::resource_exhausted("hard fact derivation lane full") + } + weaver_governance::SourceJobError::Source(_) => { + Status::failed_precondition("hard fact derivation rejected") + } + _ => Status::unavailable("hard fact derivation interrupted"), + })?; source.resolve_fact(caller, work, affected).await? } }; diff --git a/crates/server/src/runtime.rs b/crates/server/src/runtime.rs index db0869a1..81450fde 100644 --- a/crates/server/src/runtime.rs +++ b/crates/server/src/runtime.rs @@ -127,6 +127,15 @@ impl RuntimeOwner { run(cancel) })) } + pub(crate) fn governor(&self) -> Result { + self.inner + .gate + .lock() + .map_err(|_| Error::Conflict("runtime owner poisoned"))? + .governance + .clone() + .ok_or(Error::Conflict("governance owner unavailable")) + } pub(crate) fn attach_governance(&self, client: SourceClient) -> Result<()> { let mut state = self .inner diff --git a/dev/sysml/PolicyEvidenceDesign.sysml b/dev/sysml/PolicyEvidenceDesign.sysml index 96776570..5400fcb2 100644 --- a/dev/sysml/PolicyEvidenceDesign.sysml +++ b/dev/sysml/PolicyEvidenceDesign.sysml @@ -443,9 +443,10 @@ package PolicyEvidenceDesign { not covered by a fixed-fact Policy delta. Lost replies recover the original outcome. Continuations reuse the existing canonical-family contract and cannot erase pending intent or reset original domains. - The local availability profile runs a bounded native ASCENT closure - on the retained graph. Only the oldest intent can install, and an - appended intent invalidates the earlier computation's prefix. */ + The linked Weaver Scheme owner evaluates the bounded impact closure + using the Gerbil ASCENT package supplied by Agentic AI Lab. Owner + unavailability leaves the barrier pending. Only the oldest intent + can install, and a new intent invalidates the earlier work's prefix. */ } item def PublicationCommand { doc /* At the existing publication CAS, compare operation/digest and the diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index 4077bcdc..bba68ab2 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -568,7 +568,7 @@ {"id":"DurableRangeProgressJoin","witnesses":[{"file":"crates/ledger/src/stream_progress.rs","pattern":"fn message"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_message_cursor_cannot_hide_consumed_range"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_progress_cannot_release_old_writer_or_connection"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run restoredUnknownProjectionBlocksAdmissionTest"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run unknownResetDuplicatesRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unresolved_tail_blocks_admission","declaration":"Weaver.StreamingExecution.RangeProgress.unresolved_tail_blocks_admission"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem changed_progress_cannot_execute","declaration":"Weaver.StreamingExecution.RangeProgress.changed_progress_cannot_execute"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem joined_execution_preserves_safety","declaration":"Weaver.StreamingExecution.RangeProgress.joined_execution_preserves_safety"}]}, {"id":"TursoAdmissionAtomicity","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"pub fn begin"},{"file":"crates/ledger/src/exposure_manifest.rs","pattern":"fn verified_members"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn failed_commit_releases_writer_and_poisoned_session_cannot_reenter"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn duplicate_claim_members_cannot_be_normalized_out_of_recovery"},{"file":"go/dev/workspace_test.go","pattern":"func TestProjectArchitectureStorageUsesMRRDataTursoOnly"},{"file":"dev/proofs/quint/TursoAdmission.qnt","pattern":"run tornCommitRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem storage_step_retains_admission_safety","declaration":"Weaver.RuntimeAdmission.Persistence.storage_step_retains_admission_safety"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem committed_consume_survives_reply_loss_and_restart","declaration":"Weaver.RuntimeAdmission.Persistence.committed_consume_survives_reply_loss_and_restart"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem commit_itself_does_not_send","declaration":"Weaver.RuntimeAdmission.Persistence.commit_itself_does_not_send"}]}, {"id":"SessionWorkflowFrontier","witnesses":[ - {"file":"crates/governance/src/hard_fact.rs","pattern":"fn derive_fact_impact"}, + {"file":"scheme/gateway/program.ss","pattern":"def \\(hard-fact-affected"}, {"file":"go/dev/provider_hard_fact_test.go","pattern":"func TestProviderControlHardFactWithdrawalRestartAndABA"}, {"file":"crates/ledger/src/provider_workflow.rs","pattern":"fn bind_winner"}, {"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn provider_workflow_rechecks_prepared_floor_and_frontier_before_one_reservation"}, diff --git a/go/dev/provider_hard_fact_test.go b/go/dev/provider_hard_fact_test.go index ae159482..ad971c00 100644 --- a/go/dev/provider_hard_fact_test.go +++ b/go/dev/provider_hard_fact_test.go @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 -//go:build integration && !windows +//go:build integration && schemeintegration && !windows package dev @@ -64,9 +64,8 @@ func hardFactFeedSetting(t *testing.T, f *fixture, family, root string, dependen func TestProviderControlHardFactWithdrawalRestartAndABA(t *testing.T) { f := newFixture(t, completeSSE, false) - f.stop(t) f.env = append(f.env, hardFactFeedSetting(t, f, f.plan.Family, f.plan.Node, [][2]string{}, nil, "", nil)) - f.start(t) + compiledControlSources(false).configure(t, f, controlBundle(t, f)) ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second) defer cancel() diff --git a/scheme/gateway/compiled.ss b/scheme/gateway/compiled.ss index dcc9fb8f..d2a28fc5 100644 --- a/scheme/gateway/compiled.ss +++ b/scheme/gateway/compiled.ss @@ -7,7 +7,7 @@ (import :std/ffi (only-in :clan/poo/object .get) :gerbil-scheme-rust/scheme/runtime - (only-in "./program.ss" make-gateway-program) + (only-in "./program.ss" make-gateway-program hard-fact-affected) (only-in "./snapshot.ss" scheme-value->source-data source-data->scheme-value)) (export install-gateway-producer!) (def source-program (make-gateway-program)) @@ -22,7 +22,14 @@ (with-catch (lambda (_) #f) (lambda () (source-data->scheme-value ((.get source-program capture) (scheme-value->source-data value)))))) +(def (fact-impact-request value) + (with-catch (lambda (_) #f) + (lambda () + (source-data->scheme-value (hard-fact-affected (scheme-value->source-data value)))))) (begin-foreign + (c-define (fact-impact-root root) (int64) int64 "weaver_hard_fact_impact_v1" "extern" + (gerbil-scheme-rust/scheme/runtime#gerbil-rs-rooted-call root + hardenedlinux/weaver/scheme/gateway/compiled#fact-impact-request)) (c-define (capture-root root) (int64) int64 "weaver_capture_source_v1" "extern" (gerbil-scheme-rust/scheme/runtime#gerbil-rs-rooted-call root hardenedlinux/weaver/scheme/gateway/compiled#capture-request)) diff --git a/scheme/gateway/program.ss b/scheme/gateway/program.ss index 50bd5507..242a3688 100644 --- a/scheme/gateway/program.ss +++ b/scheme/gateway/program.ss @@ -4,12 +4,15 @@ ;;; One owner-local approved source producer. This is a lifecycle contract, ;;; not a Governance DSL, module loader, publisher or execution authority. -(import (only-in :clan/poo/object .o seal-object!) +(import (only-in :clan/poo/object .o .get .ref seal-object!) (only-in :clan/poo/mop validate) + (only-in :std/list/list delete-duplicates/hash) + (only-in :gerbil-ascent/program/interface relational-program gerbil-ascent-open-session + gerbil-ascent-session-run) (only-in "./types.ss" GatewayProgram) (only-in "./contracts.ss" GatewayArtifact) (only-in "./snapshot.ss" copy-source-data)) -(export make-gateway-program) +(export make-gateway-program hard-fact-affected) (def (make-gateway-program) (let ((gate (make-mutex 'weaver-gateway-program)) @@ -62,3 +65,29 @@ (seal-object! (validate GatewayProgram (seal-object! (.o install: install-program! capture: capture-source close: close-program!)))))) + +;;; The Rust ledger supplies the detached graph after persisting the intent. +;;; Dense IDs keep external names out of the evaluator's atom space. +(def (hard-fact-affected cut) + (def root (.get cut root)) + (def dependencies (.get cut dependencies)) + (unless (<= (length dependencies) 64) (error "Hard fact dependency bound")) + (def names (list->vector (list-sort string Date: Sat, 7 Nov 2026 21:42:32 +0800 Subject: [PATCH 032/105] Share Gateway impact rules at Scheme expansion --- dev/sysml/PolicyEvidenceDesign.sysml | 16 +++++++++++++--- scheme/gateway/program.ss | 24 +++++++++++++++--------- t/gateway-fact-impact-test.ss | 21 ++++++++++++++++++--- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/dev/sysml/PolicyEvidenceDesign.sysml b/dev/sysml/PolicyEvidenceDesign.sysml index 5400fcb2..21bc070e 100644 --- a/dev/sysml/PolicyEvidenceDesign.sysml +++ b/dev/sysml/PolicyEvidenceDesign.sysml @@ -366,6 +366,13 @@ package PolicyEvidenceDesign { backend/rule/query/input/limit semantics to factProjectionClosure; equal rows do not make evidence interchangeable. Incomplete, timed-out or out-of-scope nonmembership is unknown, never an allow/no-execution. */ + doc /* Use the admitted Gerbil ASCENT Datalog rules inside the Scheme/POO + owner for impact, candidate eligibility and Workflow readiness. + Compose shared clauses at package expansion where possible. Each + consumer binds its own query and input scope. A retained Session may + replace source relations on the same rule and topology identity. + A changed rule or topology requires fresh admission, and a candidate + always carries the current input cut. */ attribute backend : DerivationBackend; attribute engineClosure : String; attribute queryIdentity : String; @@ -752,9 +759,12 @@ package PolicyEvidenceDesign { deployment can still bind one edge. For a fork/join Workflow the prepared source binds the ordered nodes and every graph edge. The live Scheme Governor uses ASCENT to select candidates from detached - ledger observations. Each proposal joins the complete release of - all immediate predecessors and one current fact version. A join - retains one winner, claim and reservation across recovery. */ + ledger observations. A conditional route joins the complete + selector release to its structured result. At a conditional join + only predecessors activated by durable branch decisions count. + Each proposal joins its required complete releases to one current + fact version. A join retains one winner, claim and reservation across + recovery. */ } item def SourceCommand { item policyPublication : PublicationCommand[0..1]; diff --git a/scheme/gateway/program.ss b/scheme/gateway/program.ss index 242a3688..7d7133f3 100644 --- a/scheme/gateway/program.ss +++ b/scheme/gateway/program.ss @@ -12,7 +12,7 @@ (only-in "./types.ss" GatewayProgram) (only-in "./contracts.ss" GatewayArtifact) (only-in "./snapshot.ss" copy-source-data)) -(export make-gateway-program hard-fact-affected) +(export make-gateway-program hard-fact-affected gateway-impact-program) (def (make-gateway-program) (let ((gate (make-mutex 'weaver-gateway-program)) @@ -66,6 +66,19 @@ (validate GatewayProgram (seal-object! (.o install: install-program! capture: capture-source close: close-program!)))))) +;;; Expand shared clauses into one ASCENT program. Each consumer supplies its +;;; own admitted rows, limits and optional views over the impact relation. +(defrules gateway-impact-program () + ((_ (edges seeds) (input-bound derived-bound output-bound) clause ...) + (relational-program + (relation depends (dependent dependency) edges) + (relation changed (subject) seeds) + (relation affected (subject) '()) + (rule (affected ?s) (changed ?s)) + (rule (affected ?d) (depends ?d ?s) (affected ?s)) + clause ... + (limits input-bound derived-bound output-bound)))) + ;;; The Rust ledger supplies the detached graph after persisting the intent. ;;; Dense IDs keep external names out of the evaluator's atom space. (def (hard-fact-affected cut) @@ -79,14 +92,7 @@ (iota (vector-length names))) (def changed (list (list (hash-ref ids root)))) (def edges (map (lambda (edge) (map (lambda (name) (hash-ref ids name)) edge)) dependencies)) - (def program - (relational-program - (relation depends (dependent dependency) edges) - (relation changed (node) changed) - (relation affected (node) '()) - (rule (affected ?n) (changed ?n)) - (rule (affected ?d) (depends ?d ?n) (affected ?n)) - (limits 65 65 130))) + (def program (gateway-impact-program (edges changed) (65 65 130))) (def result (gerbil-ascent-session-run (gerbil-ascent-open-session program))) (unless (eq? (.ref result 'finished) #t) (error "Hard fact derivation incomplete")) (list-sort string Date: Sat, 7 Nov 2026 21:52:28 +0800 Subject: [PATCH 033/105] Separate linked Scheme image builds from Go recovery tests --- Project.sysml | 8 +++++++- go/internal/devrunner/plan.go | 3 ++- go/internal/devrunner/runner.go | 6 ++++-- go/internal/devrunner/scheme_tools_test.go | 7 +++++++ 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Project.sysml b/Project.sysml index 1686fdd2..c89b9a6f 100644 --- a/Project.sysml +++ b/Project.sysml @@ -242,7 +242,13 @@ package WeaverProject { image authority. The integration package keeps its ten-minute timeout and all existing recovery and natural-exit gates. */ } - part scheme : VerificationSuite { part 'check-scheme' : VerificationMode; } + part scheme : VerificationSuite { + part 'check-scheme' : VerificationMode; + doc /* Prepare the qualification image through Cargo before Go + streaming tests. Bound the image build and Go suite separately. + Retain native Go failure events with the stage receipt. The + provider recovery and natural-exit deadlines govern runtime. */ + } part architecture : VerificationSuite { part 'check-architecture' : VerificationMode; } part policy : VerificationSuite { part 'check-policy' : VerificationMode; diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index 6da6954e..c439cfb4 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -227,7 +227,8 @@ func Stages(mode, goBinary string) ([]Stage, error) { {"scheme-unit-tests", schemeTool(), []string{"test", "-g", "-v", "5", "t"}}, {"scheme-source-integration-tests", schemeTool(), []string{"test", "-g", "-v", "5", "t/integration"}}, {"scheme-rooted-sdk-integration", "cargo", []string{"test", "-p", "weaver-governance", "-p", "weaver-governance-build", "-p", "weaver-server", "--features", "weaver-governance/scheme-qualification,weaver-server/governance-qualification", "--locked", "--offline"}}, - {"scheme-grpc-stream-integration", goBinary, []string{"-C", "go", "test", "-count=1", "-race", "-tags=integration,schemeintegration", "./dev", "-run", "^TestProviderControl", "-v"}}, + {"scheme-provider-server-build", "cargo", []string{"build", "-p", "weaver-server", "--bin", "weaver-server", "--features", "arrow,governance-qualification", "--locked", "--offline", "-j", "4"}}, + {"scheme-grpc-stream-integration", goBinary, []string{"-C", "go", "test", "-parallel=4", "-json", "-count=1", "-race", "-tags=integration,schemeintegration", "-timeout=10m", "./dev", "-run", "^TestProviderControl", "-skip", "^TestProviderControlGovernorPerformance$"}}, }, nil case "bench-execution": return []Stage{ diff --git a/go/internal/devrunner/runner.go b/go/internal/devrunner/runner.go index 5813a0ed..4259607b 100644 --- a/go/internal/devrunner/runner.go +++ b/go/internal/devrunner/runner.go @@ -30,7 +30,8 @@ type Stage struct { } func (stage Stage) providerBuild() bool { - return stage.Name == "go-provider-server-build" || stage.Name == "go-provider-observer-build" + return stage.Name == "go-provider-server-build" || stage.Name == "go-provider-observer-build" || + stage.Name == "scheme-provider-server-build" } type Result struct { @@ -178,7 +179,8 @@ func Run(ctx context.Context, config Config, output io.Writer) (report string, r break } var result Result - if (stage.Name == "go-provider-grpc-integration" || stage.Name == "policy-provider-spec-integration") && + if (stage.Name == "go-provider-grpc-integration" || stage.Name == "policy-provider-spec-integration" || + stage.Name == "scheme-grpc-stream-integration") && providerBuildFailure != "" { result = Result{Name: stage.Name, Status: "SKIP", Binary: stage.Binary, Args: stage.Args, Error: "required native build did not pass: " + providerBuildFailure} diff --git a/go/internal/devrunner/scheme_tools_test.go b/go/internal/devrunner/scheme_tools_test.go index ee4f67d2..305a5c45 100644 --- a/go/internal/devrunner/scheme_tools_test.go +++ b/go/internal/devrunner/scheme_tools_test.go @@ -89,11 +89,18 @@ func TestSchemeQualificationStaysWithPreparedSchemeOwner(t *testing.T) { t.Fatal(err) } found := false + imagePrepared := false for _, stage := range stages { if stage.Name == "scheme-rooted-sdk-integration" { args := strings.Join(stage.Args, " ") found = strings.Contains(args, "weaver-governance/scheme-qualification") && strings.Contains(args, "weaver-server/governance-qualification") && strings.Contains(args, "-p weaver-server") } + if stage.Name == "scheme-provider-server-build" { + imagePrepared = stage.providerBuild() + } + if stage.Name == "scheme-grpc-stream-integration" && !imagePrepared { + t.Fatal("Scheme Go integration has no preceding qualification image build") + } } if !found { t.Fatal("prepared Scheme owner lost native SDK qualification") From 784d6695c1769687aeea160a0f20f1a4f6442917 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 21:56:50 +0800 Subject: [PATCH 034/105] Fetch retained Parser source objects for the native Scheme suite --- .github/workflows/verify-suite.yml | 10 ++++++++++ Project.sysml | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index ae43617c..b674abe9 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -85,6 +85,16 @@ jobs: GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil run: | command -v timeout + # Parser PR #13 was squash-merged. Its retained head contains the + # source objects still named by Lab's native package declaration. + # Fetch them only for Parser. Gerbil still selects the declared SHA. + parser_sources="$RUNNER_TEMP/weaver-parser-source.gitconfig" + git config --file "$parser_sources" remote.origin.fetch \ + '+refs/pull/13/head:refs/remotes/origin/weaver-parser-source' + config_slot="${GIT_CONFIG_COUNT:-0}" + export "GIT_CONFIG_KEY_$config_slot=includeIf.hasconfig:remote.*.url:https://github.com/tao3k/gerbil-parser.git.path" + export "GIT_CONFIG_VALUE_$config_slot=$parser_sources" + export GIT_CONFIG_COUNT="$((config_slot + 1))" gerbil deps --install - name: Verify declared suite id: verify_suite diff --git a/Project.sysml b/Project.sysml index c89b9a6f..02eefb2d 100644 --- a/Project.sysml +++ b/Project.sysml @@ -247,7 +247,10 @@ package WeaverProject { doc /* Prepare the qualification image through Cargo before Go streaming tests. Bound the image build and Go suite separately. Retain native Go failure events with the stage receipt. The - provider recovery and natural-exit deadlines govern runtime. */ + provider recovery and natural-exit deadlines govern runtime. + Git may fetch Parser's retained source reference to recover + objects after squash merge. Native Gerbil package declarations + still select the exact revisions. */ } part architecture : VerificationSuite { part 'check-architecture' : VerificationMode; } part policy : VerificationSuite { From 6b32391b52795420821c276e9f9020d4f19ee80b Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 22:17:58 +0800 Subject: [PATCH 035/105] Isolate authenticated hard-fact RPC handling --- crates/server/src/grpc.rs | 79 ++---------------------- crates/server/src/grpc_hard_fact.rs | 94 +++++++++++++++++++++++++++++ crates/server/src/lib.rs | 1 + 3 files changed, 101 insertions(+), 73 deletions(-) create mode 100644 crates/server/src/grpc_hard_fact.rs diff --git a/crates/server/src/grpc.rs b/crates/server/src/grpc.rs index 9a38374d..51cb1a81 100644 --- a/crates/server/src/grpc.rs +++ b/crates/server/src/grpc.rs @@ -23,6 +23,7 @@ use tonic::{Request, Response, Status}; use weaver_broker::ProviderTransport; use weaver_contracts::Error; use weaver_ledger::Ledger; + #[derive(Clone)] pub(crate) struct Gateway { pub(crate) config: ServerConfig, @@ -41,18 +42,6 @@ enum Ingress { Operation, Source(SourceOwner), } -impl Gateway { - fn fact_barrier(barrier: weaver_contracts::FactBarrier) -> pb::HardFactBarrier { - pb::HardFactBarrier { - operation_id: barrier.operation_id, - source_epoch: barrier.source_epoch, - revision: barrier.revision, - snapshot: barrier.snapshot, - floor: barrier.floor, - pending_prefix: barrier.pending_prefix, - } - } -} impl Ingress { fn role(&self) -> RpcRole { match self { @@ -310,23 +299,8 @@ impl pb::gateway_server::Gateway for Gateway { request: Request, ) -> Result, Status> { let caller = self.source_identity(&request)?; - let change = request.into_inner(); - let intent = weaver_contracts::FactIntent { - operation_id: change.operation_id, - domain: change.domain, - source_epoch: change.source_epoch, - revision: change.revision, - previous_snapshot: change.previous_snapshot, - expected_floor: change.expected_floor, - available: change.available.ok_or(Status::invalid_argument( - "explicit hard fact value required", - ))?, - }; - intent - .snapshot() - .map_err(|_| Status::invalid_argument("invalid hard fact intent"))?; - let barrier = self.ingress.source()?.stage_fact(caller, intent).await?; - Ok(Response::new(Self::fact_barrier(barrier))) + self.stage_fact_request(self.ingress.source()?, caller, request.into_inner()) + .await } async fn resolve_hard_fact( @@ -334,51 +308,10 @@ impl pb::gateway_server::Gateway for Gateway { request: Request, ) -> Result, Status> { let caller = self.source_identity(&request)?; - let key = request.into_inner(); - weaver_contracts::identifier(&key.operation_id) - .map_err(|_| Status::invalid_argument("invalid hard fact identity"))?; - if key.snapshot.len() != 64 || key.pending_prefix.len() != 64 { - return Err(Status::invalid_argument("invalid hard fact barrier")); - } - let barrier = weaver_contracts::FactBarrier { - operation_id: key.operation_id, - source_epoch: key.source_epoch, - revision: key.revision, - snapshot: key.snapshot, - floor: key.floor, - pending_prefix: key.pending_prefix, - }; - let source = self.ingress.source()?; - let result = match source.prepare_fact(caller.clone(), barrier).await? { - weaver_ledger::FactPreparation::Resolved(resolution) => resolution, - weaver_ledger::FactPreparation::Pending(work) => { - let _slot = self.admission.observation()?; - let affected = self - .runtime - .governor() - .map_err(status)? - .fact_impact(&work) - .await - .map_err(|error| match error { - weaver_governance::SourceJobError::Busy => { - Status::resource_exhausted("hard fact derivation lane full") - } - weaver_governance::SourceJobError::Source(_) => { - Status::failed_precondition("hard fact derivation rejected") - } - _ => Status::unavailable("hard fact derivation interrupted"), - })?; - source.resolve_fact(caller, work, affected).await? - } - }; - Ok(Response::new(pb::FactBarrierResolution { - barrier: Some(Self::fact_barrier(result.barrier)), - affected: result.affected, - floor: result.floor, - previous_pending_prefix: result.previous_pending_prefix, - remaining_pending_prefix: result.remaining_pending_prefix, - })) + self.resolve_fact_request(self.ingress.source()?, caller, request.into_inner()) + .await } + async fn inspect_telemetry( &self, request: Request, diff --git a/crates/server/src/grpc_hard_fact.rs b/crates/server/src/grpc_hard_fact.rs new file mode 100644 index 00000000..7de2729a --- /dev/null +++ b/crates/server/src/grpc_hard_fact.rs @@ -0,0 +1,94 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Authenticated hard-fact RPC projection through the existing source lanes. +use crate::{grpc::Gateway, grpc_contracts::status, pb, source_owner::SourceOwner}; +use tonic::{Response, Status}; +use weaver_contracts::SourceIdentity; + +impl Gateway { + fn fact_barrier(barrier: weaver_contracts::FactBarrier) -> pb::HardFactBarrier { + pb::HardFactBarrier { + operation_id: barrier.operation_id, + source_epoch: barrier.source_epoch, + revision: barrier.revision, + snapshot: barrier.snapshot, + floor: barrier.floor, + pending_prefix: barrier.pending_prefix, + } + } + + pub(crate) async fn stage_fact_request( + &self, + source: &SourceOwner, + caller: SourceIdentity, + change: pb::HardFactIntent, + ) -> Result, Status> { + let intent = weaver_contracts::FactIntent { + operation_id: change.operation_id, + domain: change.domain, + source_epoch: change.source_epoch, + revision: change.revision, + previous_snapshot: change.previous_snapshot, + expected_floor: change.expected_floor, + available: change.available.ok_or(Status::invalid_argument( + "explicit hard fact value required", + ))?, + }; + intent + .snapshot() + .map_err(|_| Status::invalid_argument("invalid hard fact intent"))?; + let barrier = source.stage_fact(caller, intent).await?; + Ok(Response::new(Self::fact_barrier(barrier))) + } + + pub(crate) async fn resolve_fact_request( + &self, + source: &SourceOwner, + caller: SourceIdentity, + key: pb::HardFactBarrier, + ) -> Result, Status> { + weaver_contracts::identifier(&key.operation_id) + .map_err(|_| Status::invalid_argument("invalid hard fact identity"))?; + if key.snapshot.len() != 64 || key.pending_prefix.len() != 64 { + return Err(Status::invalid_argument("invalid hard fact barrier")); + } + let barrier = weaver_contracts::FactBarrier { + operation_id: key.operation_id, + source_epoch: key.source_epoch, + revision: key.revision, + snapshot: key.snapshot, + floor: key.floor, + pending_prefix: key.pending_prefix, + }; + let result = match source.prepare_fact(caller.clone(), barrier).await? { + weaver_ledger::FactPreparation::Resolved(resolution) => resolution, + weaver_ledger::FactPreparation::Pending(work) => { + let _slot = self.admission.observation()?; + let affected = self + .runtime + .governor() + .map_err(status)? + .fact_impact(&work) + .await + .map_err(|error| match error { + weaver_governance::SourceJobError::Busy => { + Status::resource_exhausted("hard fact derivation lane full") + } + weaver_governance::SourceJobError::Source(_) => { + Status::failed_precondition("hard fact derivation rejected") + } + _ => Status::unavailable("hard fact derivation interrupted"), + })?; + source.resolve_fact(caller, work, affected).await? + } + }; + Ok(Response::new(pb::FactBarrierResolution { + barrier: Some(Self::fact_barrier(result.barrier)), + affected: result.affected, + floor: result.floor, + previous_pending_prefix: result.previous_pending_prefix, + remaining_pending_prefix: result.remaining_pending_prefix, + })) + } +} diff --git a/crates/server/src/lib.rs b/crates/server/src/lib.rs index 5ca3fec5..b49fc977 100644 --- a/crates/server/src/lib.rs +++ b/crates/server/src/lib.rs @@ -16,6 +16,7 @@ mod grpc_config; mod grpc_contracts; mod grpc_delivery; mod grpc_delivery_producer; +mod grpc_hard_fact; mod grpc_listeners; mod grpc_output; mod grpc_provider; From 7d8fb771164e0e1e8c0212c0f7bbd9ed60a4a9fc Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 22:21:00 +0800 Subject: [PATCH 036/105] Seal single-provider preparation through natural retirement --- crates/governance/src/catalog/admission.rs | 5 + crates/server/src/governance_deployment.rs | 23 ++++ crates/server/src/governance_owner.rs | 11 +- crates/server/src/grpc.rs | 50 ++++++-- crates/server/src/lib.rs | 1 + crates/server/src/runtime.rs | 32 +++++ crates/server/src/single_provider.rs | 122 +++++++++++++++++++ crates/server/tests/unit/governance_owner.rs | 88 +++++++++++++ go/dev/provider_program_deployment_test.go | 37 ++++++ 9 files changed, 357 insertions(+), 12 deletions(-) create mode 100644 crates/server/src/single_provider.rs diff --git a/crates/governance/src/catalog/admission.rs b/crates/governance/src/catalog/admission.rs index f494231b..8d9bdadb 100644 --- a/crates/governance/src/catalog/admission.rs +++ b/crates/governance/src/catalog/admission.rs @@ -53,6 +53,11 @@ pub struct ProducerCatalog { pub(super) entries: BTreeMap, } impl ProducerCatalog { + /// Whether this catalog admits exactly one independently bound provider task. + pub fn is_single_provider(&self) -> bool { + self.entries.len() == 1 + } + /// Refuse aliases for one original family and conflicting publication IDs. /// Total copied text is bounded separately from native constructor traversal. pub fn from_entries(entries: Vec) -> Result { diff --git a/crates/server/src/governance_deployment.rs b/crates/server/src/governance_deployment.rs index fbb3893f..ead9c6a7 100644 --- a/crates/server/src/governance_deployment.rs +++ b/crates/server/src/governance_deployment.rs @@ -29,12 +29,27 @@ pub(crate) async fn start( runtime: &ServiceRuntime, catalog: Option, ) -> Result> { + let retire = match std::env::var("WEAVER_GOVERNANCE_RETIRE_ON_ACTIVATION") { + Ok(value) if value == "1" => true, + Err(std::env::VarError::NotPresent) => false, + _ => return Err(Error::Invalid("single-provider lifecycle setting")), + }; + if retire && runtime.fact_feed().is_some() { + return Err(Error::Invalid( + "compiler retirement requires a deployment without a hard fact feed", + )); + } let Some(catalog) = catalog else { if runtime.fact_feed().is_some() { return Err(Error::Invalid( "hard fact feed requires the linked Scheme owner", )); } + if retire { + return Err(Error::Invalid( + "single-provider lifecycle requires a catalog", + )); + } return Ok(None); }; #[cfg(not(feature = "scheme-program"))] @@ -44,6 +59,14 @@ pub(crate) async fn start( } #[cfg(feature = "scheme-program")] { + if retire { + if !catalog.is_single_provider() { + return Err(Error::Invalid( + "single-provider lifecycle requires exactly one producer", + )); + } + runtime.enable_single_provider()?; + } let capacity = std::thread::available_parallelism() .map_err(|_| Error::Invalid("host compiler budget"))?; start_compiler(runtime, catalog, capacity).await.map(Some) diff --git a/crates/server/src/governance_owner.rs b/crates/server/src/governance_owner.rs index 0994ac16..e8d96bc6 100644 --- a/crates/server/src/governance_owner.rs +++ b/crates/server/src/governance_owner.rs @@ -64,11 +64,11 @@ impl RuntimeOwner { ) -> Result { let (client, inbox) = source_lane(capacity); self.attach_governance(client.clone())?; + let runtime = self.clone(); let mut starting = self.shutdown_guard(); - let exit = self.shutdown_guard(); + let mut exit = self.shutdown_guard(); let (ready, receiver) = oneshot::channel(); let job = self.spawn_blocking(slot, move |_| { - let _exit = exit; let compiler = match initialize() { Ok(compiler) => compiler, Err(error) => { @@ -81,6 +81,13 @@ impl RuntimeOwner { } // run drops the compiler (and its VM) before the tracked task ends. inbox.run_with_cancellable_governor(compiler, compile, derive); + if let Some(lifecycle) = runtime.single_provider() + && lifecycle.retirement_requested() + { + exit.disarm(); + eprintln!("weaver governance stage=compiler-retired"); + lifecycle.acknowledge_retirement(); + } Ok(()) })?; let initialized = receiver diff --git a/crates/server/src/grpc.rs b/crates/server/src/grpc.rs index 51cb1a81..c9dbdcf5 100644 --- a/crates/server/src/grpc.rs +++ b/crates/server/src/grpc.rs @@ -23,7 +23,6 @@ use tonic::{Request, Response, Status}; use weaver_broker::ProviderTransport; use weaver_contracts::Error; use weaver_ledger::Ledger; - #[derive(Clone)] pub(crate) struct Gateway { pub(crate) config: ServerConfig, @@ -567,6 +566,27 @@ impl pb::gateway_server::Gateway for Gateway { .map_err(|_| Status::invalid_argument("producer name invalid"))?; let source = self.ingress.source()?; let before = source.authority(caller.clone()).await?; + let lifecycle = self.runtime.single_provider(); + let _prepare = match lifecycle { + Some(lifecycle) => Some( + lifecycle + .prepare + .try_lock() + .map_err(|_| Status::resource_exhausted("provider preparation in progress"))?, + ), + None => None, + }; + if let Some(prepared) = lifecycle.and_then(|lifecycle| lifecycle.ready.get()) { + if prepared.producer != producer || prepared.authority != before { + return Err(Status::permission_denied( + "prepared provider binding changed", + )); + } + if self.runtime.closing() { + return Err(Status::unavailable("source compilation closed")); + } + return Ok(Response::new(prepared.reply())); + } let client = self .runtime .producers() @@ -594,7 +614,7 @@ impl pb::gateway_server::Gateway for Gateway { } let reply = pb::CompiledSource { producer, - authority: Some(crate::source_identity::view(after)?), + authority: Some(crate::source_identity::view(after.clone())?), artifact: Some(crate::source_artifact::artifact(&bound)), }; if prost::Message::encoded_len(&reply) > 4 * 1024 * 1024 { @@ -602,6 +622,14 @@ impl pb::gateway_server::Gateway for Gateway { "compiled source exceeds RPC response bound", )); } + if let Some(lifecycle) = lifecycle { + let prepared = + crate::single_provider::Prepared::new(&reply, after, bound).map_err(status)?; + lifecycle + .ready + .set(prepared) + .map_err(|_| Status::internal("provider preparation already sealed"))?; + } self.runtime .telemetry() .record(weaver_telemetry::Signal::CompilationSucceeded); @@ -737,11 +765,10 @@ impl pb::gateway_server::Gateway for Gateway { ) -> std::result::Result, Status> { let caller = self.source_identity(&request)?; let change = request.into_inner(); - let receipt = self - .ingress - .source()? + let source = self.ingress.source()?; + let receipt = source .publish( - caller, + caller.clone(), weaver_contracts::Publication { operation_id: change.operation_id, expected_revision: change.expected_revision, @@ -751,6 +778,8 @@ impl pb::gateway_server::Gateway for Gateway { }, ) .await?; + self.retire_prepared_provider(source, caller, &receipt) + .await?; Ok(Response::new(publication_receipt(receipt))) } async fn stage_reviewed_authority( @@ -823,11 +852,10 @@ impl pb::gateway_server::Gateway for Gateway { ) -> std::result::Result, Status> { let caller = self.source_identity(&request)?; let key = request.into_inner(); - let receipt = self - .ingress - .source()? + let source = self.ingress.source()?; + let receipt = source .inspect( - caller, + caller.clone(), weaver_contracts::PublicationKey { operation_id: key.operation_id, digest: key.digest, @@ -837,6 +865,8 @@ impl pb::gateway_server::Gateway for Gateway { .ok_or(Status::not_found( "publication decision not observed; absence is not abort", ))?; + self.retire_prepared_provider(source, caller, &receipt) + .await?; Ok(Response::new(publication_receipt(receipt))) } async fn inspect_provider_catalog( diff --git a/crates/server/src/lib.rs b/crates/server/src/lib.rs index b49fc977..b49fd9c9 100644 --- a/crates/server/src/lib.rs +++ b/crates/server/src/lib.rs @@ -29,6 +29,7 @@ mod review_wire; mod rpc_security; mod runtime; mod shutdown; +mod single_provider; mod source_artifact; mod source_identity; mod source_owner; diff --git a/crates/server/src/runtime.rs b/crates/server/src/runtime.rs index 81450fde..22b47ccc 100644 --- a/crates/server/src/runtime.rs +++ b/crates/server/src/runtime.rs @@ -23,6 +23,7 @@ struct Inner { closed: AtomicBool, cancel: CancellationToken, tasks: TaskTracker, + single_provider: OnceLock, fact_feed: OnceLock, } struct AdmissionState { @@ -81,6 +82,7 @@ impl RuntimeOwner { closed: AtomicBool::new(false), cancel: CancellationToken::new(), tasks: TaskTracker::new(), + single_provider: OnceLock::new(), fact_feed: OnceLock::new(), }), } @@ -94,6 +96,36 @@ impl RuntimeOwner { pub(crate) fn fact_feed(&self) -> Option<&weaver_contracts::FactFeed> { self.inner.fact_feed.get() } + #[cfg(any(feature = "scheme-program", test))] + pub(crate) fn enable_single_provider(&self) -> Result<()> { + self.inner + .single_provider + .set(crate::single_provider::SingleProvider::default()) + .map_err(|_| Error::Conflict("single-provider lifecycle already installed")) + } + pub(crate) fn single_provider(&self) -> Option<&crate::single_provider::SingleProvider> { + self.inner.single_provider.get() + } + pub(crate) async fn retire_single_provider(&self) -> Result<()> { + let lifecycle = self + .single_provider() + .ok_or(Error::Conflict("single-provider lifecycle unavailable"))?; + let client = self + .inner + .gate + .lock() + .map_err(|_| Error::Conflict("runtime owner poisoned"))? + .governance + .clone() + .ok_or(Error::Conflict("governance owner unavailable"))?; + lifecycle.request_retirement(); + client.close(); + tokio::select! { + biased; + _ = lifecycle.retired() => Ok(()), + _ = self.cancellation() => Err(Error::Conflict("governance retirement interrupted")), + } + } /// Bounded local observations only; callers acquire no authority capability. pub fn telemetry(&self) -> &Arc { &self.inner.telemetry diff --git a/crates/server/src/single_provider.rs b/crates/server/src/single_provider.rs new file mode 100644 index 00000000..8527b266 --- /dev/null +++ b/crates/server/src/single_provider.rs @@ -0,0 +1,122 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! One startup preparation, exact durable activation, and natural compiler retirement. +use crate::{grpc::Gateway, grpc_contracts::status, pb, source_owner::SourceOwner}; +use std::sync::OnceLock; +use tokio::sync::Mutex; +use tokio_util::sync::CancellationToken; +use tonic::Status; +use weaver_contracts::{PublicationOutcome, PublicationReceipt, SourceAuthority, SourceIdentity}; +use weaver_governance::BoundSource; + +#[derive(Default)] +pub(crate) struct SingleProvider { + pub(crate) prepare: Mutex<()>, + pub(crate) ready: OnceLock, + retire: CancellationToken, + retired: CancellationToken, +} + +pub(crate) struct Prepared { + pub(crate) producer: String, + pub(crate) authority: SourceAuthority, + wire_authority: Option, + bound: BoundSource, + operation_id: String, + digest: String, + revision: u64, + fence: u64, +} + +impl Prepared { + pub(crate) fn new( + reply: &pb::CompiledSource, + authority: SourceAuthority, + bound: BoundSource, + ) -> weaver_contracts::Result { + let publication = bound.source().publication(); + let revision = match publication.expected_revision { + Some(previous) => previous + .checked_add(1) + .filter(|next| *next <= weaver_contracts::MAX_CREDITS) + .ok_or(weaver_contracts::Error::Invalid( + "publication revision exhausted", + ))?, + None => 0, + }; + let digest = publication.digest()?; + Ok(Self { + producer: reply.producer.clone(), + wire_authority: reply.authority.clone(), + operation_id: publication.operation_id.clone(), + digest, + revision, + fence: publication.fence, + authority, + bound, + }) + } + + pub(crate) fn reply(&self) -> pb::CompiledSource { + pb::CompiledSource { + producer: self.producer.clone(), + authority: self.wire_authority.clone(), + artifact: Some(crate::source_artifact::artifact(&self.bound)), + } + } + + pub(crate) fn matches_commit(&self, receipt: &PublicationReceipt) -> bool { + receipt.outcome == PublicationOutcome::Committed + && receipt.operation_id == self.operation_id + && receipt.digest == self.digest + && receipt.revision == Some(self.revision) + && receipt.fence == Some(self.fence) + } +} + +impl SingleProvider { + pub(crate) fn request_retirement(&self) { + self.retire.cancel(); + } + + pub(crate) fn retirement_requested(&self) -> bool { + self.retire.is_cancelled() + } + + pub(crate) fn acknowledge_retirement(&self) { + self.retired.cancel(); + } + + pub(crate) async fn retired(&self) { + self.retired.cancelled().await; + } +} + +impl Gateway { + pub(super) async fn retire_prepared_provider( + &self, + source: &SourceOwner, + caller: SourceIdentity, + receipt: &PublicationReceipt, + ) -> Result<(), Status> { + let Some(prepared) = self + .runtime + .single_provider() + .and_then(|lifecycle| lifecycle.ready.get()) + else { + return Ok(()); + }; + if prepared.matches_commit(receipt) + && prepared.authority.identity == caller + && prepared.authority == source.authority(caller).await? + { + self.runtime + .retire_single_provider() + .await + .map_err(status)?; + } + Ok(()) + } +} diff --git a/crates/server/tests/unit/governance_owner.rs b/crates/server/tests/unit/governance_owner.rs index 7993ef37..e0462c90 100644 --- a/crates/server/tests/unit/governance_owner.rs +++ b/crates/server/tests/unit/governance_owner.rs @@ -46,6 +46,94 @@ fn original() -> OwnedSource { }) .expect("original source") } +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] +async fn single_provider_retirement_joins_cleanup_without_closing_ingress() { + let runtime = ServiceRuntime::new(); + runtime.enable_single_provider().expect("lifecycle enabled"); + let (_, slot) = budget(); + let (owned, mut cleaned) = oneshot::channel::<()>(); + let (entered, started) = oneshot::channel(); + let (release, wait) = mpsc::channel(); + let worker = runtime + .start_governance(slot, capacity(), move || { + let mut entered = Some(entered); + Ok(move |source: &OwnedSource| { + let _keep = &owned; + if let Some(entered) = entered.take() { + let _ = entered.send(()); + } + wait.recv_timeout(Duration::from_secs(3)) + .map_err(|_| SourceError::Scheme)?; + copy(source) + }) + }) + .await + .expect("worker started"); + let job = worker + .client() + .submit(original()) + .expect("accepted original"); + tokio::time::timeout(Duration::from_secs(3), started) + .await + .expect("call started") + .expect("entered"); + let retiring = runtime.retire_single_provider(); + tokio::pin!(retiring); + tokio::select! { + result = &mut retiring => panic!("retired before active call returned: {result:?}"), + result = job => assert!(matches!(result, Err(weaver_governance::SourceJobError::Closed))), + } + assert!(matches!( + cleaned.try_recv(), + Err(oneshot::error::TryRecvError::Empty) + )); + release.send(()).expect("release native call"); + retiring.await.expect("retired"); + assert!(matches!( + cleaned.try_recv(), + Err(oneshot::error::TryRecvError::Closed) + )); + assert!(!runtime.closing()); + assert!(matches!( + worker.client().submit(original()), + Err(weaver_governance::SourceJobError::Closed) + )); + worker.finish().await.expect("joined"); +} + +#[test] +fn single_provider_activation_requires_the_exact_committed_cut() { + use weaver_contracts::{PublicationOutcome, PublicationReceipt}; + + let original = original(); + let publication = original.publication(); + let bound = weaver_governance::SourceExpectation::capture(&original) + .bind(original.clone()) + .expect("bound original"); + let prepared = crate::single_provider::Prepared::new(&Default::default(), authority(), bound) + .expect("prepared"); + let receipt = PublicationReceipt { + operation_id: publication.operation_id.clone(), + digest: publication.digest().expect("publication"), + outcome: PublicationOutcome::Committed, + revision: Some(1), + fence: Some(publication.fence), + }; + assert!(prepared.matches_commit(&receipt)); + assert!(!prepared.matches_commit(&PublicationReceipt { + outcome: PublicationOutcome::Rejected, + ..receipt.clone() + })); + assert!(!prepared.matches_commit(&PublicationReceipt { + digest: "0".repeat(64), + ..receipt.clone() + })); + assert!(!prepared.matches_commit(&PublicationReceipt { + revision: Some(0), + ..receipt + })); +} + fn authority() -> weaver_contracts::SourceAuthority { weaver_contracts::SourceAuthority { epoch: 1, diff --git a/go/dev/provider_program_deployment_test.go b/go/dev/provider_program_deployment_test.go index c3548e53..9b241101 100644 --- a/go/dev/provider_program_deployment_test.go +++ b/go/dev/provider_program_deployment_test.go @@ -65,6 +65,43 @@ func TestProviderControlCompiledProgramRevocationAndRestart(t *testing.T) { exerciseControlPolicies(t, "json", nil, compiledControlSources(false)) } +func TestProviderControlSingleProviderRetiresCompilerAfterActivation(t *testing.T) { + f := newFixture(t, completeSSE, false) + bundle := controlBundle(t, f) + f.env = append(f.env, "WEAVER_GOVERNANCE_RETIRE_ON_ACTIVATION=1") + policy := compiledControlSources(false) + policy.configure(t, f, bundle) + ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second) + defer cancel() + prepared, err := f.admin.CompileSource(ctx, policy.producer) + if err != nil { + t.Fatal(err) + } + retired := func() bool { + data, err := os.ReadFile(filepath.Join(f.directory, "server.log")) + if err != nil { + t.Fatal(err) + } + return strings.Contains(string(data), "weaver governance stage=compiler-retired") + } + if retired() { + t.Fatal("preparation retired before publication") + } + c := newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")) + c.useProducer(policy.producer) + c.start(t) + if !retired() { + t.Fatal("activation did not await compiler cleanup") + } + replayed, err := f.admin.CompileSource(ctx, policy.producer) + if err != nil || !proto.Equal(prepared, replayed) { + t.Fatalf("retired preparation replay changed: %v", err) + } + if _, err := c.client.Execute(ctx, bundle.Plans[0], pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }); err != nil || f.primary.Load() != 1 { + t.Fatalf("activated provider unavailable after compiler retirement: %v", err) + } +} + func TestProviderControlCompiledProgramSharedBudgetRejectsConcurrentSendAndSDKRetry(t *testing.T) { exerciseControlSharedBudgetPolicies(t, nil, compiledControlSources(false)) } From 53493e7d0c673ff458925028b985bfcd851b554d Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 22:32:50 +0800 Subject: [PATCH 037/105] Use optimized incremental Cargo profiles --- Cargo.toml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index d31ddac5..561771a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,3 +79,11 @@ dbg_macro = "deny" todo = "deny" unimplemented = "deny" +[profile.dev] +opt-level = 1 +incremental = true + +[profile.release] +opt-level = 3 +incremental = true + From 87a47c933b97a5012e94b975af13c79cfb2ffbcc Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 22:38:48 +0800 Subject: [PATCH 038/105] Import ASCENT rule and Session owners directly --- scheme/gateway/program.ss | 4 ++-- t/gateway-fact-impact-test.ss | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scheme/gateway/program.ss b/scheme/gateway/program.ss index 7d7133f3..a735fe42 100644 --- a/scheme/gateway/program.ss +++ b/scheme/gateway/program.ss @@ -7,8 +7,8 @@ (import (only-in :clan/poo/object .o .get .ref seal-object!) (only-in :clan/poo/mop validate) (only-in :std/list/list delete-duplicates/hash) - (only-in :gerbil-ascent/program/interface relational-program gerbil-ascent-open-session - gerbil-ascent-session-run) + (only-in :gerbil-ascent/program/scheme-language relational-program) + (only-in :gerbil-ascent/program/session gerbil-ascent-open-session gerbil-ascent-session-run) (only-in "./types.ss" GatewayProgram) (only-in "./contracts.ss" GatewayArtifact) (only-in "./snapshot.ss" copy-source-data)) diff --git a/t/gateway-fact-impact-test.ss b/t/gateway-fact-impact-test.ss index f4ddba0c..de5845f4 100644 --- a/t/gateway-fact-impact-test.ss +++ b/t/gateway-fact-impact-test.ss @@ -4,7 +4,7 @@ (import :std/test (only-in :clan/poo/object .o .ref) - (only-in :gerbil-ascent/program/interface gerbil-ascent-open-session + (only-in :gerbil-ascent/program/session gerbil-ascent-open-session gerbil-ascent-session-run gerbil-ascent-session-replace-sources!) (only-in ../scheme/gateway/program hard-fact-affected gateway-impact-program)) (export gateway-fact-impact-test) From 2d273f8be94d3ddcc4739f692f39dbf95e012eaf Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 22:42:53 +0800 Subject: [PATCH 039/105] Admit explicit Governor successors from sealed plans --- crates/governance/src/catalog/admission.rs | 11 ++++ crates/server/src/governance_deployment.rs | 23 +++++-- crates/server/src/grpc_provider.rs | 16 +++-- crates/server/src/single_provider.rs | 70 ++++++++++++++++++++-- dev/sysml/PolicyEvidenceDesign.sysml | 7 ++- go/dev/provider_program_deployment_test.go | 63 +++++++++++++++++++ 6 files changed, 173 insertions(+), 17 deletions(-) diff --git a/crates/governance/src/catalog/admission.rs b/crates/governance/src/catalog/admission.rs index 8d9bdadb..7e387d0d 100644 --- a/crates/governance/src/catalog/admission.rs +++ b/crates/governance/src/catalog/admission.rs @@ -58,6 +58,17 @@ impl ProducerCatalog { self.entries.len() == 1 } + /// Match a deployment edge to the independent compiled-source original. + pub fn admits_workflow(&self, family: &str, edge: &weaver_contracts::ProviderWorkflow) -> bool { + self.is_single_provider() + && self.entries.values().next().is_some_and(|entry| { + let task = entry.original.task(); + task.family == family + && task.nodes.contains(&edge.predecessor) + && task.nodes.contains(&edge.successor) + }) + } + /// Refuse aliases for one original family and conflicting publication IDs. /// Total copied text is bounded separately from native constructor traversal. pub fn from_entries(entries: Vec) -> Result { diff --git a/crates/server/src/governance_deployment.rs b/crates/server/src/governance_deployment.rs index ead9c6a7..a2d2bb3f 100644 --- a/crates/server/src/governance_deployment.rs +++ b/crates/server/src/governance_deployment.rs @@ -34,10 +34,25 @@ pub(crate) async fn start( Err(std::env::VarError::NotPresent) => false, _ => return Err(Error::Invalid("single-provider lifecycle setting")), }; - if retire && runtime.fact_feed().is_some() { - return Err(Error::Invalid( - "compiler retirement requires a deployment without a hard fact feed", - )); + if let Some(feed) = runtime.fact_feed() { + match &feed.workflow { + Some(edge) + if retire + && catalog + .as_ref() + .is_some_and(|catalog| catalog.admits_workflow(&feed.family, edge)) => {} + Some(_) => { + return Err(Error::Invalid( + "workflow requires the single compiled provider original", + )); + } + None if retire => { + return Err(Error::Invalid( + "compiler retirement requires a deployment without a hard fact feed", + )); + } + None => {} + } } let Some(catalog) = catalog else { if runtime.fact_feed().is_some() { diff --git a/crates/server/src/grpc_provider.rs b/crates/server/src/grpc_provider.rs index bab9ee61..96309a70 100644 --- a/crates/server/src/grpc_provider.rs +++ b/crates/server/src/grpc_provider.rs @@ -37,6 +37,7 @@ impl Gateway { .plan .ok_or(Status::invalid_argument("plan missing"))?, )?; + let predecessor = self.workflow_predecessor(&plan)?; let cursor = weaver_ledger::DeliveryCursor::new(&plan).map_err(status)?; let (sender, receiver) = mpsc::channel(crate::grpc_output::DELIVERY_QUEUE_CAPACITY); let cancelled = CancellationToken::new(); @@ -123,8 +124,10 @@ impl Gateway { crate::grpc_output::take_handoffs(); crate::grpc_output::take_deliveries(); } - let execution = weaver_broker::execute_catalog_provider_with_oauth( - + let progression = predecessor.as_ref() + .map(|predecessor| ledger.prepare_provider_progression(predecessor, &plan)) + .transpose()?; + let execution = weaver_broker::execute_provider_progression( &mut ledger, weaver_broker::ProviderExecution { plan: &plan, @@ -133,9 +136,12 @@ impl Gateway { batch_rows: request.batch_rows as usize, }, &mut output, - weaver_broker::ProviderExecutionAuthority { - catalog: &request.catalog_version, - oauth: oauth.as_ref(), + weaver_broker::ProviderExecutionAdmission { + authority: weaver_broker::ProviderExecutionAuthority { + catalog: &request.catalog_version, + oauth: oauth.as_ref(), + }, + progression: progression.as_ref(), }, ); #[cfg(test)] diff --git a/crates/server/src/single_provider.rs b/crates/server/src/single_provider.rs index 8527b266..296a3bcb 100644 --- a/crates/server/src/single_provider.rs +++ b/crates/server/src/single_provider.rs @@ -8,7 +8,9 @@ use std::sync::OnceLock; use tokio::sync::Mutex; use tokio_util::sync::CancellationToken; use tonic::Status; -use weaver_contracts::{PublicationOutcome, PublicationReceipt, SourceAuthority, SourceIdentity}; +use weaver_contracts::{ + ProviderPlan, PublicationOutcome, PublicationReceipt, SourceAuthority, SourceIdentity, +}; use weaver_governance::BoundSource; #[derive(Default)] @@ -17,6 +19,7 @@ pub(crate) struct SingleProvider { pub(crate) ready: OnceLock, retire: CancellationToken, retired: CancellationToken, + live: CancellationToken, } pub(crate) struct Prepared { @@ -95,23 +98,78 @@ impl SingleProvider { } impl Gateway { + pub(crate) fn workflow_predecessor( + &self, + successor: &ProviderPlan, + ) -> Result, Status> { + let Some((feed, edge)) = self + .runtime + .fact_feed() + .filter(|feed| feed.family == successor.family) + .and_then(|feed| feed.workflow.as_ref().map(|edge| (feed, edge))) + .filter(|(_, edge)| edge.successor == successor.node) + else { + return Ok(None); + }; + let source = self + .runtime + .single_provider() + .filter(|lifecycle| lifecycle.live.is_cancelled()) + .and_then(|lifecycle| lifecycle.ready.get()) + .map(|prepared| prepared.bound.source()) + .ok_or(Status::failed_precondition( + "compiled workflow has not activated", + ))?; + let selection = &source.data().governance; + if selection.family != feed.family + || !selection.open_nodes.contains(&edge.predecessor) + || !selection.open_nodes.contains(&successor.node) + { + return Err(Status::failed_precondition( + "Governor workflow selection changed", + )); + } + let admitted = |node: &str| { + source + .plans() + .iter() + .find(|plan| plan.family == selection.family && plan.node == node) + .ok_or(Status::failed_precondition( + "compiled workflow plan missing", + )) + }; + if admitted(&successor.node)? != successor { + return Err(Status::failed_precondition( + "successor differs from compiled original", + )); + } + Ok(Some(admitted(&edge.predecessor)?.clone())) + } + pub(super) async fn retire_prepared_provider( &self, source: &SourceOwner, caller: SourceIdentity, receipt: &PublicationReceipt, ) -> Result<(), Status> { - let Some(prepared) = self - .runtime - .single_provider() - .and_then(|lifecycle| lifecycle.ready.get()) - else { + let Some(lifecycle) = self.runtime.single_provider() else { + return Ok(()); + }; + let Some(prepared) = lifecycle.ready.get() else { return Ok(()); }; if prepared.matches_commit(receipt) && prepared.authority.identity == caller && prepared.authority == source.authority(caller).await? { + if self + .runtime + .fact_feed() + .is_some_and(|feed| feed.workflow.is_some()) + { + lifecycle.live.cancel(); + return Ok(()); + } self.runtime .retire_single_provider() .await diff --git a/dev/sysml/PolicyEvidenceDesign.sysml b/dev/sysml/PolicyEvidenceDesign.sysml index 21bc070e..47e5f76e 100644 --- a/dev/sysml/PolicyEvidenceDesign.sysml +++ b/dev/sysml/PolicyEvidenceDesign.sysml @@ -755,8 +755,11 @@ package PolicyEvidenceDesign { guarded local receiver. Durable completion wakes reconciliation. On restart after reactivation, existing operation receipts identify the first missing or queued successor. A wake carries no authority - and an unknown operation stops progression. The legacy Governor - deployment can still bind one edge. For a fork/join Workflow the + and an unknown operation stops progression. An explicit Governor + edge retains the linked owner for authenticated hard-fact projection + after exact activation. The prepared original remains sealed, and + the successor must match its immutable plan and complete predecessor + release. For a fork/join Workflow the prepared source binds the ordered nodes and every graph edge. The live Scheme Governor uses ASCENT to select candidates from detached ledger observations. A conditional route joins the complete diff --git a/go/dev/provider_program_deployment_test.go b/go/dev/provider_program_deployment_test.go index 9b241101..6ef6be80 100644 --- a/go/dev/provider_program_deployment_test.go +++ b/go/dev/provider_program_deployment_test.go @@ -102,6 +102,69 @@ func TestProviderControlSingleProviderRetiresCompilerAfterActivation(t *testing. } } +func TestProviderControlCompiledGovernorSuccessorUsesCompleteRelease(t *testing.T) { + f := newFixture(t, completeSSE, false) + bundle := controlBundle(t, f) + predecessor, successor := bundle.Plans[0], bundle.Plans[1] + f.env = append(f.env, "WEAVER_GOVERNANCE_RETIRE_ON_ACTIVATION=1", + hardFactFeedSetting(t, f, predecessor.Family, predecessor.Node, + [][2]string{{successor.Node, predecessor.Node}}, + map[string]string{"predecessor": predecessor.Node, "successor": successor.Node}, "", nil)) + policy := compiledControlSources(false) + policy.configure(t, f, bundle) + c := newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")) + c.useProducer(policy.producer) + c.start(t) + ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second) + defer cancel() + a := &pb.HardFactIntent{OperationId: "workflow-fact-a", Domain: "availability", + Revision: 1, PreviousSnapshot: strings.Repeat("0", 64), Available: proto.Bool(true)} + stage := func(intent *pb.HardFactIntent) *pb.HardFactBarrier { + t.Helper() + key, err := f.admin.RPC.StageHardFact(f.admin.Context(ctx), intent) + if err != nil { + t.Fatal(err) + } + return key + } + resolve := func(key *pb.HardFactBarrier) { + t.Helper() + result, err := f.admin.RPC.ResolveHardFact(f.admin.Context(ctx), key) + if err != nil || strings.Join(result.GetAffected(), ",") != "infer,next" { + t.Fatalf("native transitive impact: %v %v", result, err) + } + } + attempt := func(plan v1.ProviderPlan) error { + _, err := c.client.Execute(ctx, plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }) + return err + } + barrier := stage(a) + resolve(barrier) + if err := attempt(successor); status.Code(err) != codes.FailedPrecondition || f.primary.Load() != 0 { + t.Fatalf("successor advanced before response completion: %v", err) + } + if err := attempt(predecessor); err != nil || f.primary.Load() != 1 { + t.Fatalf("predecessor did not complete: %v", err) + } + nextFact := stage(&pb.HardFactIntent{OperationId: "workflow-fact-b", Domain: a.Domain, + Revision: 2, PreviousSnapshot: barrier.Snapshot, ExpectedFloor: barrier.Floor, + Available: proto.Bool(true)}) + if err := attempt(successor); status.Code(err) != codes.FailedPrecondition || f.primary.Load() != 1 { + t.Fatalf("successor crossed pending fact floor: %v", err) + } + resolve(nextFact) + if err := attempt(successor); err != nil || f.primary.Load() != 2 { + t.Fatalf("completed release did not admit the exact successor: %v", err) + } + if err := attempt(successor); err == nil || f.primary.Load() != 2 || f.backup.Load() != 0 { + t.Fatal("successor replay reset the original claim") + } + receipt, err := c.client.RPC.Inspect(c.client.Context(ctx), &pb.OperationKey{Family: successor.Family, Node: successor.Node}) + if err != nil || receipt.GetState() != "complete" || receipt.GetHeld() != 8 { + t.Fatalf("successor completion or retained shared hold: %v %v", receipt, err) + } +} + func TestProviderControlCompiledProgramSharedBudgetRejectsConcurrentSendAndSDKRetry(t *testing.T) { exerciseControlSharedBudgetPolicies(t, nil, compiledControlSources(false)) } From da6a012ea8bd7b933bc253fe49830b62fe50e806 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 22:51:43 +0800 Subject: [PATCH 040/105] Use four native Scheme build workers in verification --- .github/workflows/verify-suite.yml | 2 ++ go/internal/devrunner/runner.go | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index b674abe9..2be1a4a1 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -29,6 +29,8 @@ jobs: env: GOTOOLCHAIN: local WEAVER_VERIFY_SUITE: ${{ inputs.suite }} + # Gerbil std/make defaults to serial compilation without this setting. + GERBIL_BUILD_CORES: '4' steps: - name: Check out committed source id: checkout diff --git a/go/internal/devrunner/runner.go b/go/internal/devrunner/runner.go index 4259607b..54b17909 100644 --- a/go/internal/devrunner/runner.go +++ b/go/internal/devrunner/runner.go @@ -16,7 +16,6 @@ import ( "path/filepath" "runtime" "sort" - "strconv" "time" ) @@ -169,7 +168,7 @@ func Run(ctx context.Context, config Config, output io.Writer) (report string, r if inherited := os.Getenv("PKG_CONFIG_PATH"); inherited != "" { settings["PKG_CONFIG_PATH"] += string(os.PathListSeparator) + inherited } - settings["GERBIL_BUILD_CORES"] = strconv.Itoa(runtime.NumCPU()) + settings["GERBIL_BUILD_CORES"] = "4" environment = Environment(settings) } var providerBuildFailure string From 84a9c1fb346f5db8de45e5ddc2ee14c7fb3c5c8d Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 22:56:03 +0800 Subject: [PATCH 041/105] Bound parallel Go verification tests to four workers --- go/internal/devrunner/ci_test.go | 4 ++++ go/internal/devrunner/plan.go | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/go/internal/devrunner/ci_test.go b/go/internal/devrunner/ci_test.go index 6628f104..870c01b3 100644 --- a/go/internal/devrunner/ci_test.go +++ b/go/internal/devrunner/ci_test.go @@ -7,6 +7,7 @@ package devrunner import ( "context" "io" + "slices" "testing" ) @@ -31,6 +32,9 @@ func TestModularCISuitesPreserveUnifiedGateCoverage(t *testing.T) { t.Fatal(err) } for _, stage := range stages { + if stage.Binary == "go" && slices.Contains(stage.Args, "test") && !slices.Contains(stage.Args, "-parallel=4") { + t.Fatalf("expected four Go test workers for %s", stage.Name) + } if covered[stage.Name] && stage.Name != "project-architecture" && stage.Name != "workflow-contract" && !stage.providerBuild() { t.Fatalf("unintended duplicated check %s", stage.Name) } diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index c439cfb4..70ad3d49 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -7,6 +7,7 @@ package devrunner import ( "fmt" "os" + "slices" ) const rustRuntimeFeatures = "weaver-server/arrow,weaver-governance/scheme-vm" @@ -152,7 +153,20 @@ func Plan(goBinary string) []Stage { {"semantic-boundary-quint-safety", "quint", []string{"run", "dev/proofs/quint/LlmPolicyContinuation.qnt", "--main", "LlmPolicyContinuation", "--step", "boundaryStep", "--invariant", "safety", "--max-samples", "1000", "--max-steps", "60", "--seed", "293", "--verbosity", "0"}}, } } + +const testParallelism = "4" + func Stages(mode, goBinary string) ([]Stage, error) { + stages, err := stagesForMode(mode, goBinary) + for i, stage := range stages { + if stage.Binary == goBinary && len(stage.Args) >= 3 && stage.Args[0] == "-C" && stage.Args[2] == "test" { + stages[i].Args = slices.Insert(stage.Args, 3, "-parallel="+testParallelism) + } + } + return stages, err +} + +func stagesForMode(mode, goBinary string) ([]Stage, error) { switch mode { case "bootstrap": return []Stage{ @@ -179,7 +193,7 @@ func Stages(mode, goBinary string) ([]Stage, error) { } return append(selected, Stage{"storage-grpc-integration", goBinary, []string{"-C", "go", "test", "-count=1", "-race", "-tags=integration", "./dev", "-run", "^TestProvider", "-v"}}), nil case "bootstrap-build", "bootstrap-proofs": - stages, err := Stages("bootstrap", goBinary) + stages, err := stagesForMode("bootstrap", goBinary) if err != nil { return nil, err } @@ -228,7 +242,7 @@ func Stages(mode, goBinary string) ([]Stage, error) { {"scheme-source-integration-tests", schemeTool(), []string{"test", "-g", "-v", "5", "t/integration"}}, {"scheme-rooted-sdk-integration", "cargo", []string{"test", "-p", "weaver-governance", "-p", "weaver-governance-build", "-p", "weaver-server", "--features", "weaver-governance/scheme-qualification,weaver-server/governance-qualification", "--locked", "--offline"}}, {"scheme-provider-server-build", "cargo", []string{"build", "-p", "weaver-server", "--bin", "weaver-server", "--features", "arrow,governance-qualification", "--locked", "--offline", "-j", "4"}}, - {"scheme-grpc-stream-integration", goBinary, []string{"-C", "go", "test", "-parallel=4", "-json", "-count=1", "-race", "-tags=integration,schemeintegration", "-timeout=10m", "./dev", "-run", "^TestProviderControl", "-skip", "^TestProviderControlGovernorPerformance$"}}, + {"scheme-grpc-stream-integration", goBinary, []string{"-C", "go", "test", "-json", "-count=1", "-race", "-tags=integration,schemeintegration", "-timeout=10m", "./dev", "-run", "^TestProviderControl", "-skip", "^TestProviderControlGovernorPerformance$"}}, }, nil case "bench-execution": return []Stage{ From a9ee27188b76b4b09ddb785dcf61429520d99780 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 23:00:53 +0800 Subject: [PATCH 042/105] Retain native Scheme dependency deadline outcomes --- .github/workflows/verify-suite.yml | 13 +++++++++++-- Project.sysml | 3 +++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 2be1a4a1..cd706f9e 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -82,7 +82,9 @@ jobs: - name: Install declared Scheme dependencies id: scheme_dependencies if: inputs.suite == 'check-scheme' - timeout-minutes: 12 + # The native watchdog owns the existing 12-minute limit. Leave time + # for GitHub to retain its exit status before the outer cutoff. + timeout-minutes: 13 env: GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil run: | @@ -97,7 +99,13 @@ jobs: export "GIT_CONFIG_KEY_$config_slot=includeIf.hasconfig:remote.*.url:https://github.com/tao3k/gerbil-parser.git.path" export "GIT_CONFIG_VALUE_$config_slot=$parser_sources" export GIT_CONFIG_COUNT="$((config_slot + 1))" - gerbil deps --install + if timeout --verbose --kill-after=5s 12m gerbil deps --install; then + status=0 + else + status=$? + fi + printf 'exit_code=%s\n' "$status" >> "$GITHUB_OUTPUT" + exit "$status" - name: Verify declared suite id: verify_suite if: inputs.suite != 'check-scheme' @@ -136,6 +144,7 @@ jobs: "os": ${{ toJSON(runner.os) }}, "arch": ${{ toJSON(runner.arch) }}, "status": ${{ toJSON(job.status) }}, + "schemeDependencyExitCode": ${{ steps.scheme_dependencies.outputs.exit_code || 'null' }}, "phases": { "checkout": ${{ toJSON(steps.checkout.outcome || 'skipped') }}, "source": ${{ toJSON(steps.source.outcome || 'skipped') }}, diff --git a/Project.sysml b/Project.sysml index 02eefb2d..69945be6 100644 --- a/Project.sysml +++ b/Project.sysml @@ -246,6 +246,9 @@ package WeaverProject { part 'check-scheme' : VerificationMode; doc /* Prepare the qualification image through Cargo before Go streaming tests. Bound the image build and Go suite separately. + Native package installation defaults to four build workers and + has a twelve-minute watchdog. Retain the exit code in the job + receipt. Retain native Go failure events with the stage receipt. The provider recovery and natural-exit deadlines govern runtime. Git may fetch Parser's retained source reference to recover From a22229df3995839d59a6edc9d01d4586b8b3b8e2 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 23:09:33 +0800 Subject: [PATCH 043/105] Preserve Governor wake under source lane contention --- crates/governance/src/host/client.rs | 20 +++++++---- crates/governance/tests/unit/host.rs | 52 ++++++++++++++++++++++++++++ dev/sysml/PolicyEvidenceDesign.sysml | 4 ++- 3 files changed, 68 insertions(+), 8 deletions(-) diff --git a/crates/governance/src/host/client.rs b/crates/governance/src/host/client.rs index c8b462df..4cf0de83 100644 --- a/crates/governance/src/host/client.rs +++ b/crates/governance/src/host/client.rs @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 -//! Nonblocking source admission; capacity covers queued, active and ready data. +//! Bounded source admission; capacity covers queued, active and ready data. use super::{Command, Phase, Shared, SourceInbox, SourceJob, SourceJobError, State, Work}; use crate::{OwnedSource, SourceExpectation}; use std::{ @@ -74,7 +74,7 @@ impl SourceClient { })?; Ok(SourceJob::new(receiver, self.shared.clone(), state, cancel)) } - /// Submit a detached ledger observation on the same bounded Scheme owner. + /// Wait for space on the bounded Scheme owner so a Session wake is not lost. pub async fn derive(&self, input: crate::GovernorCut) -> Result, SourceJobError> { self.evaluate(crate::Derivation::Governor(Box::new(input))) .await @@ -91,11 +91,17 @@ impl SourceClient { .await } async fn evaluate(&self, input: crate::Derivation) -> Result, SourceJobError> { - let slot = self - .capacity - .clone() - .try_acquire_owned() - .map_err(|_| SourceJobError::Busy)?; + let capacity = self.capacity.clone(); + let slot = match &input { + crate::Derivation::Governor(_) => tokio::select! { + biased; + _ = self.shared.shutdown.cancelled() => return Err(SourceJobError::Closed), + slot = capacity.acquire_owned() => slot.map_err(|_| SourceJobError::Closed)?, + }, + crate::Derivation::FactImpact { .. } => capacity + .try_acquire_owned() + .map_err(|_| SourceJobError::Busy)?, + }; let (reply, receiver) = oneshot::channel(); { let closed = self.shared.gate(); diff --git a/crates/governance/tests/unit/host.rs b/crates/governance/tests/unit/host.rs index dc6ff581..364d322f 100644 --- a/crates/governance/tests/unit/host.rs +++ b/crates/governance/tests/unit/host.rs @@ -103,6 +103,58 @@ fn ready_results_keep_capacity_until_observed_and_close_fences_delivery() { )); owner.finish().expect("drained"); } + +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] +async fn governor_observation_waits_for_capacity_or_shutdown() { + for close_owner in [false, true] { + let owner = Owner::start(1, |inbox| { + inbox.run_with_governor( + (), + |_, source| copied(source), + |_, cut| Ok(cut.pending.clone()), + ); + }); + let job = owner + .client + .submit(original()) + .expect("occupy the only slot"); + let observation = owner.client.derive(crate::GovernorCut { + nodes: vec!["next".into()], + edges: vec![], + complete: vec![], + available: vec!["next".into()], + pending: vec!["next".into()], + choice_arms: vec![], + choice_join: vec![], + choice_result: vec![], + choice_decided: vec![], + nested_selectors: vec![], + nested_results: vec![], + nested_decisions: vec![], + }); + tokio::pin!(observation); + assert!(matches!( + observation + .as_mut() + .poll(&mut Context::from_waker(Waker::noop())), + Poll::Pending + )); + if close_owner { + owner.client.close(); + } else { + job.await.expect("release the source slot"); + } + let result = tokio::time::timeout(Duration::from_secs(3), observation) + .await + .expect("waiting Governor resumes"); + if close_owner { + assert_eq!(result, Err(SourceJobError::Closed)); + } else { + assert_eq!(result.expect("derived"), ["next"]); + } + } +} + #[test] fn cancelled_running_work_keeps_its_slot_until_natural_return() { let (entered, started) = mpsc::channel(); diff --git a/dev/sysml/PolicyEvidenceDesign.sysml b/dev/sysml/PolicyEvidenceDesign.sysml index 47e5f76e..07fa17a5 100644 --- a/dev/sysml/PolicyEvidenceDesign.sysml +++ b/dev/sysml/PolicyEvidenceDesign.sysml @@ -762,7 +762,9 @@ package PolicyEvidenceDesign { release. For a fork/join Workflow the prepared source binds the ordered nodes and every graph edge. The live Scheme Governor uses ASCENT to select candidates from detached - ledger observations. A conditional route joins the complete + ledger observations. A reconciliation waits for bounded Governor + capacity or owner shutdown. The ledger rechecks the detached cut + before admission. A conditional route joins the complete selector release to its structured result. At a conditional join only predecessors activated by durable branch decisions count. Each proposal joins its required complete releases to one current From 26d029f07ea2ce5819a38540d4fb0152054efff4 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 23:15:13 +0800 Subject: [PATCH 044/105] Bind Scheme integration to a frozen release executable --- dev/sysml/ControlActivation.sysml | 4 ++ go/dev/cargo_artifact_test.go | 68 ++++++++++++++++++++++--- go/dev/provider_fixture_test.go | 35 ++++++++++--- go/dev/provider_scheme_features_test.go | 2 +- 4 files changed, 92 insertions(+), 17 deletions(-) diff --git a/dev/sysml/ControlActivation.sysml b/dev/sysml/ControlActivation.sysml index 2cf641ea..13ec7279 100644 --- a/dev/sysml/ControlActivation.sysml +++ b/dev/sysml/ControlActivation.sysml @@ -60,6 +60,10 @@ package ControlActivation { arbitrary external source fidelity or exclude filesystem ABA. The retired Go linked-source checker is not native evidence for the current path. Actual FFI/gRPC qualification remains independent. */ + doc /* A Scheme release qualification names the application module + and source. A prebuilt executable is admitted by the frozen + release SHA-256. The fixture launches only its verified private + copy, leaving site approval and replay custody to their owners. */ doc /* Local Go startup phases distinguish configuration readiness, authority connections/reconciliation and issuing Serve; only the actual authenticated channel proves readiness. Go deployment never diff --git a/go/dev/cargo_artifact_test.go b/go/dev/cargo_artifact_test.go index 4f5bbbaf..bee25677 100644 --- a/go/dev/cargo_artifact_test.go +++ b/go/dev/cargo_artifact_test.go @@ -139,21 +139,38 @@ func FuzzCargoExecutablePreservesReportedPath(f *testing.F) { }) } -// Standard Go benchmark selection also selects an optimized provider image. -// Ordinary integration tests keep their default debug assertions. Artifact -// paths still come from Cargo JSON, never a guessed target/profile directory. -func providerCargoBuildArgs(features, benchmark string) []string { +// The existing deployment inputs select the release Scheme graph. Ordinary +// qualification keeps its debug-only producer and the Cargo artifact check. +const providerSchemeQualificationFeatures = "arrow,governance-qualification" +const providerSchemeReleaseFeatures = "arrow,scheme-program" + +func providerCargoBuildArgs(features, benchmark string, lookup func(string) (string, bool)) ([]string, bool, error) { + application, applicationSet := lookup("WEAVER_GOVERNANCE_APPLICATION") + source, sourceSet := lookup("WEAVER_GOVERNANCE_APPLICATION_SOURCE") + optimized := benchmark != "" + if applicationSet || sourceSet { + if !applicationSet || !sourceSet || application == "" || source == "" { + return nil, false, errors.New("release Scheme integration requires both application inputs") + } + if features != providerSchemeQualificationFeatures { + return nil, false, errors.New("release Scheme integration requires the schemeintegration tag") + } + features = providerSchemeReleaseFeatures + optimized = true + } else if optimized && features == providerSchemeQualificationFeatures { + return nil, false, errors.New("release Scheme integration requires an explicit application") + } args := []string{"build", "-p", "weaver-server", "--bin", "weaver-server", "--features", features, "--locked", "--offline", "--message-format=json-render-diagnostics"} - if benchmark != "" { + if optimized { args = append(args, "--release") } - return args + return args, optimized, nil } func TestProviderBenchmarkUsesOptimizedRustImage(t *testing.T) { for _, benchmark := range []string{"", "^BenchmarkGatewayStreamingPair$", "."} { - args := providerCargoBuildArgs("arrow", benchmark) - if slices.Contains(args, "--release") != (benchmark != "") { + args, optimized, err := providerCargoBuildArgs("arrow", benchmark, func(string) (string, bool) { return "", false }) + if err != nil || optimized != (benchmark != "") || slices.Contains(args, "--release") != optimized { t.Fatal("incorrect runtime measurement profile", args) } for _, required := range []string{"--locked", "--offline", "--message-format=json-render-diagnostics"} { @@ -164,6 +181,41 @@ func TestProviderBenchmarkUsesOptimizedRustImage(t *testing.T) { } } +func TestSchemeIntegrationReleaseRequiresExplicitApplication(t *testing.T) { + const module = "WEAVER_GOVERNANCE_APPLICATION" + const source = "WEAVER_GOVERNANCE_APPLICATION_SOURCE" + for _, tc := range []struct { + name, features, benchmark string + env map[string]string + wantFeatures string + optimized bool + }{ + {name: "debug qualification", features: "arrow,governance-qualification", wantFeatures: "arrow,governance-qualification"}, + {name: "release application", features: "arrow,governance-qualification", env: map[string]string{module: "weaver/provider", source: "/provider.ss"}, wantFeatures: "arrow,scheme-program", optimized: true}, + {name: "missing binding", features: "arrow,governance-qualification", env: map[string]string{module: "weaver/provider"}}, + {name: "empty binding", features: "arrow,governance-qualification", env: map[string]string{module: "weaver/provider", source: ""}}, + {name: "qualification benchmark", features: "arrow,governance-qualification", benchmark: "."}, + {name: "missing tag", features: "arrow", env: map[string]string{module: "weaver/provider", source: "/provider.ss"}}, + } { + t.Run(tc.name, func(t *testing.T) { + args, optimized, err := providerCargoBuildArgs(tc.features, tc.benchmark, func(key string) (string, bool) { + value, exists := tc.env[key] + return value, exists + }) + if tc.wantFeatures == "" { + if err == nil || len(args) != 0 { + t.Fatal("invalid selection emitted a Cargo command", args, err) + } + return + } + if err != nil || optimized != tc.optimized || slices.Contains(args, "--release") != optimized || + !slices.Contains(args, tc.wantFeatures) || (optimized && slices.Contains(args, "arrow,governance-qualification")) { + t.Fatal("invalid Scheme integration build selection", args, err) + } + }) + } +} + func TestCargoOptimizedArtifactRequiresActualProfile(t *testing.T) { const record = `{"reason":"compiler-artifact","target":{"name":"gateway","kind":["bench"]},"profile":{"test":true,"opt_level":"3","debug_assertions":false},"executable":"/reported/gateway"}` for _, tc := range []struct { diff --git a/go/dev/provider_fixture_test.go b/go/dev/provider_fixture_test.go index cb99173b..c6307518 100644 --- a/go/dev/provider_fixture_test.go +++ b/go/dev/provider_fixture_test.go @@ -58,8 +58,13 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) } benchmark := flag.Lookup("test.bench").Value.String() + args, optimized, err := providerCargoBuildArgs(providerRuntimeFeatures, benchmark, os.LookupEnv) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } profile := "dev" - if benchmark != "" { + if optimized { profile = "release" } _, source, _, ok := runtime.Caller(0) @@ -67,13 +72,22 @@ func TestMain(m *testing.M) { os.Exit(1) } repo := filepath.Clean(filepath.Join(filepath.Dir(source), "../..")) - cmd := exec.Command("cargo", providerCargoBuildArgs(providerRuntimeFeatures, benchmark)...) - cmd.Dir = repo - cmd.Stderr = os.Stderr - executable, err := buildCargoExecutable(cmd, cargoTarget{Name: "weaver-server", Kind: "bin", Optimized: benchmark != ""}) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) + expected, frozen := os.LookupEnv("WEAVER_TEST_PROVIDER_IMAGE_SHA256") + executable, prebuilt := os.LookupEnv("WEAVER_TEST_PREBUILT_PROVIDER_IMAGE") + if prebuilt { + if !optimized || !frozen || expected == "" || !filepath.IsAbs(executable) { + fmt.Fprintln(os.Stderr, "prebuilt provider image requires an absolute path and a frozen release SHA-256") + os.Exit(1) + } + } else { + cmd := exec.Command("cargo", args...) + cmd.Dir = repo + cmd.Stderr = os.Stderr + executable, err = buildCargoExecutable(cmd, cargoTarget{Name: "weaver-server", Kind: "bin", Optimized: optimized}) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } } directory, err := os.MkdirTemp("", "weaver-control-build-*") if err != nil { @@ -88,6 +102,11 @@ func TestMain(m *testing.M) { os.Exit(1) } fmt.Fprintf(os.Stderr, "test-owned provider image sha256=%s profile=%s\n", digest, profile) + if frozen && (!optimized || digest != expected) { + os.RemoveAll(directory) + fmt.Fprintln(os.Stderr, "test-owned release image differs from the frozen SHA-256") + os.Exit(1) + } controlBinary = filepath.Join(directory, "weaver-control") controlArgs := []string{"-C", "go", "build", "-mod=readonly"} if benchmark == "" { diff --git a/go/dev/provider_scheme_features_test.go b/go/dev/provider_scheme_features_test.go index 0a4817f8..0681cf2f 100644 --- a/go/dev/provider_scheme_features_test.go +++ b/go/dev/provider_scheme_features_test.go @@ -8,4 +8,4 @@ package dev // The explicit qualification graph tests production ABI/lifecycle code without // pretending that the fixture Governor/Profile is a production application. -const providerRuntimeFeatures = "arrow,governance-qualification" +const providerRuntimeFeatures = providerSchemeQualificationFeatures From 969b4cfb094778f460560ec64d0c825f9495300e Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 23:25:24 +0800 Subject: [PATCH 045/105] Keep dependency optimization out of cold dev builds --- Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 561771a5..d1b8d859 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,6 +83,10 @@ unimplemented = "deny" opt-level = 1 incremental = true +# Keep cold development builds bounded while optimizing workspace code. +[profile.dev.package."*"] +opt-level = 0 + [profile.release] opt-level = 3 incremental = true From 35ceb393f025d9e2aa5708a0532ec669a99cc87b Mon Sep 17 00:00:00 2001 From: guangtao Date: Sat, 7 Nov 2026 23:59:15 +0800 Subject: [PATCH 046/105] Build the selected Weaver Scheme source closure --- .github/workflows/verify-suite.yml | 51 ++- Project.sysml | 13 +- build.ss | 89 +++-- crates/governance-build/src/program.rs | 21 +- crates/governance-build/src/tooling.rs | 42 ++- dev/sysml/ControlActivation.sysml | 2 +- dev/sysml/runtime-trace.json | 5 +- gerbil.pkg | 4 +- go/internal/devrunner/plan.go | 3 +- go/internal/devrunner/runner.go | 18 +- go/internal/devrunner/scheme_result_test.go | 54 +-- go/internal/devrunner/scheme_tools_test.go | 8 +- init.ss | 2 + scheme/gateway/build.ss | 13 + scheme/gateway/compiled.ss | 27 +- scheme/gateway/contracts.ss | 6 +- scheme/gateway/derivation-types.ss | 42 +++ scheme/gateway/derivation.ss | 196 +++++++++++ scheme/gateway/func.ss | 321 +++++++++++++++++- scheme/gateway/interface.ss | 5 +- scheme/gateway/objects.ss | 4 +- scheme/gateway/program.ss | 7 +- scheme/gateway/provider-program.ss | 73 ++++ scheme/gateway/provider-source.ss | 71 ++++ scheme/gateway/types.ss | 10 +- scheme/governance/interface.ss | 1 + scheme/governance/types.ss | 12 +- scheme/policy/build.ss | 12 + scheme/policy/interface.ss | 4 +- scheme/policy/types.ss | 3 +- t/fixtures/governed-control.ss | 51 ++- t/gateway-contracts-test.ss | 23 +- t/gateway-derivation-test.ss | 210 ++++++++++++ t/gateway-governor-retained-test.ss | 62 ++++ t/integration/governed-control-test.ss | 20 +- .../module-selection/module-selection-test.ss | 149 ++++++++ t/qualification/module-selection/use.ss | 66 ++++ 37 files changed, 1534 insertions(+), 166 deletions(-) create mode 100644 scheme/gateway/build.ss create mode 100644 scheme/gateway/derivation-types.ss create mode 100644 scheme/gateway/derivation.ss create mode 100644 scheme/gateway/provider-program.ss create mode 100644 scheme/gateway/provider-source.ss create mode 100644 scheme/policy/build.ss create mode 100644 t/gateway-derivation-test.ss create mode 100644 t/gateway-governor-retained-test.ss create mode 100644 t/qualification/module-selection/module-selection-test.ss create mode 100644 t/qualification/module-selection/use.ss diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index cd706f9e..7dfee059 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -79,7 +79,7 @@ jobs: run: | brew install coreutils echo "$(brew --prefix coreutils)/libexec/gnubin" >> "$GITHUB_PATH" - - name: Install declared Scheme dependencies + - name: Prepare the Weaver Scheme source closure id: scheme_dependencies if: inputs.suite == 'check-scheme' # The native watchdog owns the existing 12-minute limit. Leave time @@ -89,23 +89,42 @@ jobs: GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil run: | command -v timeout - # Parser PR #13 was squash-merged. Its retained head contains the - # source objects still named by Lab's native package declaration. - # Fetch them only for Parser. Gerbil still selects the declared SHA. - parser_sources="$RUNNER_TEMP/weaver-parser-source.gitconfig" - git config --file "$parser_sources" remote.origin.fetch \ - '+refs/pull/13/head:refs/remotes/origin/weaver-parser-source' - config_slot="${GIT_CONFIG_COUNT:-0}" - export "GIT_CONFIG_KEY_$config_slot=includeIf.hasconfig:remote.*.url:https://github.com/tao3k/gerbil-parser.git.path" - export "GIT_CONFIG_VALUE_$config_slot=$parser_sources" - export GIT_CONFIG_COUNT="$((config_slot + 1))" - if timeout --verbose --kill-after=5s 12m gerbil deps --install; then - status=0 + export scheme_sources="$RUNNER_TEMP/weaver-scheme-sources" + if timeout --verbose --kill-after=5s 12m bash -se -o pipefail <<'SOURCE_CLOSURE'; then + fetch_source() { + local package=$1 pin=$2 destination=$3 revision=${2##*@} + [[ "$pin" == "$package@$revision" && "$revision" =~ ^[0-9a-f]{40}$ ]] + git init --quiet "$destination" + git -C "$destination" fetch --quiet --depth=1 --no-tags "https://$package.git" "$revision" + git -C "$destination" checkout --quiet --detach FETCH_HEAD + test "$(git -C "$destination" rev-parse HEAD)" = "$revision" + } + + lab=github.com/tao3k/agentic-ai-lab + ascent=github.com/tao3k/gerbil-ascent + lab_source="$scheme_sources/lab" + ascent_source="$scheme_sources/imports/gerbil-ascent" + mkdir -p "$scheme_sources/imports" + fetch_source "$lab" "$(gerbil deps)" "$lab_source" + ascent_pin=$(cd "$lab_source" && gerbil deps | grep "^$ascent@") + fetch_source "$ascent" "$ascent_pin" "$ascent_source" + core_pin=$(cd "$ascent_source" && gerbil deps) + [[ "$core_pin" =~ ^github\.com/tao3k/gebril-yuanxu@[0-9a-f]{40}$ ]] + + # Core supplies the compiler and POO. Lab and ASCENT supply the + # source selected by Weaver; their unrelated build products stay out. + gerbil pkg install "$core_pin" + gerbil pkg link "$lab" "$lab_source" + gerbil pkg link "$ascent" "$ascent_source" + export GERBIL_LOADPATH="$GERBIL_PATH/lib:$scheme_sources/imports" + ./build.ss prepare-governor-library + SOURCE_CLOSURE + dependency_exit_code=0 else - status=$? + dependency_exit_code=$? fi - printf 'exit_code=%s\n' "$status" >> "$GITHUB_OUTPUT" - exit "$status" + printf 'exit_code=%s\n' "$dependency_exit_code" >> "$GITHUB_OUTPUT" + exit "$dependency_exit_code" - name: Verify declared suite id: verify_suite if: inputs.suite != 'check-scheme' diff --git a/Project.sysml b/Project.sysml index 69945be6..0339a84c 100644 --- a/Project.sysml +++ b/Project.sysml @@ -246,14 +246,15 @@ package WeaverProject { part 'check-scheme' : VerificationMode; doc /* Prepare the qualification image through Cargo before Go streaming tests. Bound the image build and Go suite separately. - Native package installation defaults to four build workers and - has a twelve-minute watchdog. Retain the exit code in the job - receipt. + Resolve Lab and ASCENT sources from native package declarations. + Gerbil prepares the pinned Core and POO compiler dependencies. + ASCENT's selected Program build supplies native linker inputs. + Dependency preparation defaults to four workers and has a + twelve-minute watchdog with its exit code in the job receipt. + Run the selected package Build with a separate two-minute bound. Retain native Go failure events with the stage receipt. The provider recovery and natural-exit deadlines govern runtime. - Git may fetch Parser's retained source reference to recover - objects after squash merge. Native Gerbil package declarations - still select the exact revisions. */ + Unrelated producer products stay outside this source closure. */ } part architecture : VerificationSuite { part 'check-architecture' : VerificationMode; } part policy : VerificationSuite { diff --git a/build.ss b/build.ss index b1f27cad..fcd2a745 100755 --- a/build.ss +++ b/build.ss @@ -10,41 +10,76 @@ (begin-syntax (register-module-build-source! (path-directory (this-source-file)) 'hardenedlinux/weaver)) (import (only-in :clan/poo/object .get) - (only-in :std/make pkg-config-cflags pkg-config-libs) - (only-in :gerbil/expander import-module expander-context-id) + (only-in :std/source this-source-file) + (only-in :std/build-script defbuild-script) + (only-in :gerbil/tools/gxpkg pkg-root-dir) + (only-in :gerbil/expander eval-syntax import-module expander-context-id) (only-in :gerbil/compiler compile-module) - (only-in :yuanxu/module-system/building/script defbuild-script) + (only-in :yuanxu/module-system/building/interface call-with-init-build-spec) + (only-in :yuanxu/module-system/building/products build-output-directory + current-build-module-roots current-build-source-directory) + (only-in :yuanxu/module-system/building/source-package register-module-build-source!) + (only-in :yuanxu/module-system/source/observations current-module-source-observer) (only-in "./init.ss" hardenedlinux/weaver.init.exports)) -(def policy-package (getenv "WEAVER_POLICY_PKG_CONFIG_PACKAGE" "weaver-policy-ffi")) -(def (package-spec (extra '())) - ((.get hardenedlinux/weaver.init.exports std-make-spec) - (append (list `(gxc: "scheme/policy/cedar-ffi" - "-cc-options" ,(pkg-config-cflags policy-package) - "-ld-options" ,(pkg-config-libs policy-package)) - ;; Cross-language fixtures are libraries too: the standard package build - ;; owns their expansion instead of repeating it during each bootstrap. - '(gxc: "t/fixtures/governed-control") - '(gxc: "t/fixtures/control-inputs")) extra))) +(export main) + +(def (run-build args entry prepare) + (def output (build-output-directory)) + (def (dispatch spec native-args (prefix #f)) + (def (this-source-file) + (let (directory (current-build-source-directory)) + (if directory (path-expand (path-strip-directory entry) directory) entry))) + (defbuild-script spec libdir: output prefix: prefix) + (apply main native-args)) + (call-with-init-build-spec prepare dispatch args output entry)) + +(def (compile-package args) + (run-build args (this-source-file) + (lambda () ((.get hardenedlinux/weaver.init.exports std-make-spec) '())))) + +;; The pinned producer's Program root owns its Scheme library closure. +(def (prepare-governor-library) + (def source (path-normalize (path-expand "github.com/tao3k/gerbil-ascent/" (pkg-root-dir)))) + (register-module-build-source! source 'gerbil-ascent) + (parameterize ((current-directory source) (current-build-module-roots '(program))) + (eval-syntax `(import (only-in ,(path-expand "init.ss" source) gerbil-ascent.init.exports))) + (def exports (eval 'gerbil-ascent.init.exports)) + (run-build '("compile") (path-expand "build.ss" source) + (lambda () ((.get exports std-make-spec) '()))))) + +;; Cargo needs the inputs already read by the package owner to invalidate its +;; build script. Files created under OUT_DIR are products of the same build. +(def (compile-package-for-cargo args) + (def outputs (path-expand "" (getenv "OUT_DIR"))) + (def inputs (make-hash-table)) + (def (observe key _) + (match key + (['file-read _ path] + (unless (string-prefix? outputs path) + (hash-put! inputs path #t))) + (else (void)))) + (begin0 + (parameterize ((current-module-source-observer observe)) + (compile-package args)) + (hash-for-each + (lambda (path _) + (when (file-exists? path) + (displayln "cargo:rerun-if-changed=" path))) + inputs))) -;; The native SDK invokes this same package entry with typed arguments. -;; Compilation stays in the package declaration; no Rust-generated Scheme code. (def (main . args) (match args - (["program" source expected-module] - (let () - (defbuild-script - (package-spec (list '(gxc: "scheme/gateway/compiled"))) - force: #t) - (main "compile")) - ;; The explicit operator application may live in a different source package. - ;; It is compiled as that source, never relabeled as a Weaver retained module. + (["prepare-governor-library"] (prepare-governor-library)) + (["compile-approved-program" source expected-module] + ;; An operator can approve a source in a different package. (compile-module source [output-dir: (path-expand "lib" (gerbil-path)) invoke-gsc: #f optimize: #t static: #t]) (unless (equal? (symbol->string (expander-context-id (import-module source))) expected-module) (error "approved application root mismatch"))) - (else - (let () - (defbuild-script (package-spec)) - (apply main args))))) + (["compile"] + (if (getenv "CARGO_FEATURE_SCHEME_PROGRAM" #f) + (compile-package-for-cargo args) + (compile-package args))) + (else (compile-package args)))) diff --git a/crates/governance-build/src/program.rs b/crates/governance-build/src/program.rs index 26c1ac28..108fda3f 100644 --- a/crates/governance-build/src/program.rs +++ b/crates/governance-build/src/program.rs @@ -9,13 +9,17 @@ use gerbil_scheme_aot_build::{ ProgramArchiveRequest, build_program_archive_with_contract, discover_gambit_gsc_from_env, }; use std::{env, path::PathBuf}; -struct Progress; -impl ProgramArchiveObserver for Progress { +struct Progress<'a> { + output: &'a std::path::Path, +} +impl ProgramArchiveObserver for Progress<'_> { fn observe(&self, event: ProgramArchiveObservation<'_>) { eprintln!("governance-program: {event}"); } fn observe_source_input(&self, path: &std::path::Path) { - println!("cargo:rerun-if-changed={}", path.display()); + if !path.starts_with(self.output) { + println!("cargo:rerun-if-changed={}", path.display()); + } } } struct BuildPaths { @@ -56,14 +60,7 @@ impl BuildPaths { ) .expect("approved application module") }; - for source in [ - root.join("build.ss"), - root.join("init.ss"), - root.join("scheme"), - application.source().to_path_buf(), - ] { - println!("cargo:rerun-if-changed={}", source.display()); - } + println!("cargo:rerun-if-changed={}", application.source().display()); let out = PathBuf::from(env::var_os("OUT_DIR").expect("Cargo output")); let stage = out.join("program"); std::fs::create_dir_all(&stage).expect("program staging"); @@ -104,7 +101,7 @@ impl BuildPaths { header_files: &headers, }], }, - &Progress, + &Progress { output: &self.out }, ) .expect("native program archive"); for directive in receipt.cargo_directives { diff --git a/crates/governance-build/src/tooling.rs b/crates/governance-build/src/tooling.rs index 121383ac..addddf1f 100644 --- a/crates/governance-build/src/tooling.rs +++ b/crates/governance-build/src/tooling.rs @@ -52,18 +52,40 @@ impl PackageTooling { } fn compile_application(&self, runtime: &Runtime, request: &ProgramStageRequest<'_>) { assert_eq!( - (self.run_package_main)( - runtime, - request.package, - &[ - "program", - request.application_source, - request.application_module - ] - ) - .expect("package build"), + (self.build_package)(runtime, request.package).expect("Weaver package build"), 0 ); + // The standard Gateway Build owns this first-party module. Only the + // configured application at the exact package path can use its output. + if request.application_module == "hardenedlinux/weaver/scheme/gateway/provider-program" + && Path::new(request.application_source) + == Path::new(request.package).join("scheme/gateway/provider-program.ss") + { + return; + } + let compile = |source: &str, module: &str| { + assert_eq!( + (self.run_package_main)( + runtime, + request.package, + &["compile-approved-program", source, module], + ) + .expect("application module build"), + 0 + ); + }; + if request.application_module == crate::application::QUALIFICATION_APPLICATION { + // The existing debug image imports this helper. Native Scheme tests + // load their own sources and do not use this image build. + let control = + Path::new(request.application_source).with_file_name("governed-control.ss"); + println!("cargo:rerun-if-changed={}", control.display()); + compile( + control.to_str().expect("qualification control source"), + crate::application::QUALIFICATION_CONTROL, + ); + } + compile(request.application_source, request.application_module); } fn stage_application(&self, runtime: &Runtime, request: &ProgramStageRequest<'_>) { assert_eq!( diff --git a/dev/sysml/ControlActivation.sysml b/dev/sysml/ControlActivation.sysml index 13ec7279..35b5e8be 100644 --- a/dev/sysml/ControlActivation.sysml +++ b/dev/sysml/ControlActivation.sysml @@ -37,7 +37,7 @@ package ControlActivation { Governance scope exposes only typed assess; it cannot override Governor selection with an open callback. A selected step still needs an accepted assessment, publication and current final-use authority. */ - doc /* Each Scheme scope uses an evidence-bearing YuanxuContract whose value-contract delegates shape and normalization to concrete Record and Function descriptors. Wire records are sealed, counters and credits are exact bounded integers, and Go and Rust independently validate the same artifact. Contract validity is required before registration and grants no execution authority. */ + doc /* Each Scheme scope uses a native POO Type/Record with concrete Function descriptors. Core normalization and selected Feature obligations apply to the same final receiver. Module scope Types do not add .classify, .obligations or .admit evidence hooks; Yuanxu owns value-admission evidence and currentness, while domain evidence Contracts remain separate. Wire records are sealed, counters and credits are exact bounded integers, and Go and Rust independently validate the same artifact. Contract validity is required before registration and grants no execution authority. */ } requirement def SourceStartupObservation { doc /* Package declarations and installed dependency state belong to diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index bba68ab2..80bb9452 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -343,11 +343,12 @@ {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run missingGovernorCounterexampleTest"}, {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_cannot_replace_governor","declaration":"Weaver.PolicyBridge.governance_cannot_replace_governor"}, {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governor_cannot_replace_governance","declaration":"Weaver.PolicyBridge.governor_cannot_replace_governance"}, - {"file":"scheme/governance/types.ss","pattern":"YuanxuContract. value-contract:"}, + {"file":"scheme/governance/types.ss","pattern":"def GovernanceScopeContract\\s+\\(\\.cc \\(Record"}, {"file":"scheme/gateway/contracts.ss","pattern":"def GatewayArtifact"}, {"file":"t/gateway-contracts-test.ss","pattern":"def gateway-contracts-test"}, {"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityUncompiledSourceCannotRegisterTest"}, - {"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"}]}, + {"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"}, + {"file":"t/gateway-contracts-test.ss","pattern":"module scopes use native POO Types and refuse evidence protocol hooks"}]}, {"id":"GovernancePolicyProjection","witnesses":[ {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrApprovalCannotOutliveExposureProjectionRollbackTest"}, {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrCommitReplyLossAndReplayCannotMintAnotherTicketTest"}, diff --git a/gerbil.pkg b/gerbil.pkg index 42c3cb4c..1a914641 100644 --- a/gerbil.pkg +++ b/gerbil.pkg @@ -4,5 +4,5 @@ ;;; Agentic AI Lab owns its transitive package dependencies. (package: hardenedlinux/weaver - prelude: :yuanxu/module-system/source/module-prelude - depend: ("github.com/tao3k/agentic-ai-lab@aeac4f4c12b1722f992da9354695b611d3e0851f")) + prelude: :tao3k/yuanxu/prelude + depend: ("github.com/tao3k/agentic-ai-lab@95d7a6d3ae9a7258358ec72cae0ef1cbe5c1d975")) diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index 70ad3d49..ec4cb499 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -234,11 +234,12 @@ func stagesForMode(mode, goBinary string) ([]Stage, error) { {"scheme-policy-library", "cargo", []string{"build", "-p", "weaver-policy-ffi", "--locked", "--offline"}}, {"scheme-policy-preflight", "cargo", []string{"test", "-p", "weaver-policy-ffi", "--lib", "--benches", "--locked", "--offline"}}, {"scheme-policy-pkg-config", "cargo", []string{"run", "-p", "weaver-policy-ffi", "--example", "policy_pkg_config", "--locked", "--offline"}}, - {"scheme-module-build", schemeTool(), []string{"build", "-g"}}, + {"scheme-module-build", "./build.ss", []string{"compile", "--debug"}}, {"scheme-build-environment-tests", goBinary, []string{"-C", "go", "test", "-count=1", "-race", "-tags=schemeintegration", "./internal/devrunner", "-run", "^(Test(SchemePkgConfig|SchemeTool|SchemePackageResult|SchemeTestInventory|SchemeUsesPackageTestEntry|SourceInputsWithArchived)|FuzzSchemePackageResultProtocol)", "-v"}}, // Package tools own discovery, execution and result reporting. Historical // direct-gxi image experiments are not a prerequisite for gerbil test. {"scheme-unit-tests", schemeTool(), []string{"test", "-g", "-v", "5", "t"}}, + {"scheme-module-selection-integration", schemeTool(), []string{"test", "-g", "-v", "5", "t/qualification/module-selection"}}, {"scheme-source-integration-tests", schemeTool(), []string{"test", "-g", "-v", "5", "t/integration"}}, {"scheme-rooted-sdk-integration", "cargo", []string{"test", "-p", "weaver-governance", "-p", "weaver-governance-build", "-p", "weaver-server", "--features", "weaver-governance/scheme-qualification,weaver-server/governance-qualification", "--locked", "--offline"}}, {"scheme-provider-server-build", "cargo", []string{"build", "-p", "weaver-server", "--bin", "weaver-server", "--features", "arrow,governance-qualification", "--locked", "--offline", "-j", "4"}}, diff --git a/go/internal/devrunner/runner.go b/go/internal/devrunner/runner.go index 54b17909..11a7e678 100644 --- a/go/internal/devrunner/runner.go +++ b/go/internal/devrunner/runner.go @@ -264,20 +264,30 @@ func runStageCapture(ctx context.Context, root, directory string, environment [] return runStageObserved(ctx, root, directory, environment, stage, streamSchemeOutput, nil) } -// Package functionality has a whole-suite budget; native Runtime is measured separately. -const schemePackageTestTimeout = time.Minute +// Package tests and the cold/hot build integration have separate budgets. +const ( + schemeModuleBuildTimeout = 2 * time.Minute + schemePackageTestTimeout = time.Minute + schemeModuleSelectionTimeout = 2 * time.Minute +) func runStageObserved(ctx context.Context, root, directory string, environment []string, stage Stage, streamSchemeOutput bool, onStart func(int)) Result { tests := "" + testTimeout := schemePackageTestTimeout + deadline := time.Duration(0) switch stage.Name { + case "scheme-module-build": + deadline = schemeModuleBuildTimeout case "scheme-unit-tests": tests = "t" case "scheme-source-integration-tests": tests = "t/integration" + case "scheme-module-selection-integration": + tests = "t/qualification/module-selection" + testTimeout = schemeModuleSelectionTimeout } - deadline := time.Duration(0) if tests != "" { - deadline = schemePackageTestTimeout + deadline = testTimeout } if stage.providerBuild() { deadline = 5 * time.Minute diff --git a/go/internal/devrunner/scheme_result_test.go b/go/internal/devrunner/scheme_result_test.go index 6bdbb706..2543f311 100644 --- a/go/internal/devrunner/scheme_result_test.go +++ b/go/internal/devrunner/scheme_result_test.go @@ -197,29 +197,35 @@ func TestSchemeUsesPackageTestEntry(t *testing.T) { } func TestSchemePackageResultIntegrationCannotBorrowUnitReceipt(t *testing.T) { - root := schemeResultRoot(t) - directory := filepath.Join(root, "t/integration") - if err := os.Mkdir(directory, 0700); err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(directory, "library-test.ss"), nil, 0600); err != nil { - t.Fatal(err) - } - binary, err := os.Executable() - if err != nil { - t.Fatal(err) - } - for _, valid := range []bool{false, true} { - body := schemeTranscript(20) - if valid { - body = strings.ReplaceAll(body, "t/library-test.ss", "t/integration/library-test.ss") - } - result := runStage(context.Background(), root, t.TempDir(), - Environment(map[string]string{"WEAVER_TEST_TOOL": "success"}), - Stage{Name: "scheme-source-integration-tests", Binary: binary, - Args: []string{"-test.run=^TestToolProcess$", "--", body}}) - if result.ExitCode == nil || *result.ExitCode != 0 || (result.Status == "PASS") != valid { - t.Fatal("integration accepted a different module inventory", valid, result) - } + for _, entry := range []struct{ stage, directory string }{ + {"scheme-source-integration-tests", "t/integration"}, + {"scheme-module-selection-integration", "t/qualification/module-selection"}, + } { + t.Run(entry.stage, func(t *testing.T) { + root := schemeResultRoot(t) + directory := filepath.Join(root, entry.directory) + if err := os.MkdirAll(directory, 0700); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(directory, "library-test.ss"), nil, 0600); err != nil { + t.Fatal(err) + } + binary, err := os.Executable() + if err != nil { + t.Fatal(err) + } + for _, valid := range []bool{false, true} { + body := schemeTranscript(20) + if valid { + body = strings.ReplaceAll(body, "t/library-test.ss", entry.directory+"/library-test.ss") + } + result := runStage(context.Background(), root, t.TempDir(), + Environment(map[string]string{"WEAVER_TEST_TOOL": "success"}), + Stage{Name: entry.stage, Binary: binary, Args: []string{"-test.run=^TestToolProcess$", "--", body}}) + if result.ExitCode == nil || *result.ExitCode != 0 || (result.Status == "PASS") != valid { + t.Fatal("integration accepted a different module inventory", valid, result) + } + } + }) } } diff --git a/go/internal/devrunner/scheme_tools_test.go b/go/internal/devrunner/scheme_tools_test.go index 305a5c45..d22c6a05 100644 --- a/go/internal/devrunner/scheme_tools_test.go +++ b/go/internal/devrunner/scheme_tools_test.go @@ -135,8 +135,14 @@ func TestSchemeVerificationUsesOnlyPublicPackageEntries(t *testing.T) { if stage.Binary == schemeTool() { entries[stage.Name] = args } + if stage.Name == "scheme-module-build" { + if stage.Binary != "./build.ss" || args != "compile --debug" { + t.Fatalf("Scheme build must use the selected native entry: %v", stage) + } + entries[stage.Name] = args + } } - if len(entries) != 3 || entries["scheme-source-integration-tests"] != "test -g -v 5 t/integration" || entries["scheme-module-build"] != "build -g" || entries["scheme-unit-tests"] != "test -g -v 5 t" { + if len(entries) != 4 || entries["scheme-module-selection-integration"] != "test -g -v 5 t/qualification/module-selection" || entries["scheme-source-integration-tests"] != "test -g -v 5 t/integration" || entries["scheme-unit-tests"] != "test -g -v 5 t" { t.Fatalf("unexpected Scheme package lifecycle: %v", entries) } } diff --git a/init.ss b/init.ss index 43ef25c9..31ca332b 100644 --- a/init.ss +++ b/init.ss @@ -5,6 +5,8 @@ ;;; Yuanxu owns discovery, selection, admission and generation currentness. (import :yuanxu/module-system/selection/init-syntax) (yuanxu! + :load-modules "modules" package: "github.com/tao3k/agentic-ai-lab" mode: explicit rename: Lab + (governance) :load-modules "./scheme" mode: explicit rename: Weaver (governance) (policy) diff --git a/scheme/gateway/build.ss b/scheme/gateway/build.ss new file mode 100644 index 00000000..c8ce5709 --- /dev/null +++ b/scheme/gateway/build.ss @@ -0,0 +1,13 @@ +;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +;;; +;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +(export Build) +(def Build + (.o kind: 'module/build + roots: (if (getenv "CARGO_FEATURE_SCHEME_PROGRAM" #f) + (if (equal? (getenv "WEAVER_GOVERNANCE_APPLICATION" "") + "hardenedlinux/weaver/scheme/gateway/provider-program") + '("provider-source" "compiled" "provider-program") + '("provider-source" "compiled")) + '("provider-source")))) diff --git a/scheme/gateway/compiled.ss b/scheme/gateway/compiled.ss index d2a28fc5..bf172694 100644 --- a/scheme/gateway/compiled.ss +++ b/scheme/gateway/compiled.ss @@ -7,6 +7,7 @@ (import :std/ffi (only-in :clan/poo/object .get) :gerbil-scheme-rust/scheme/runtime + (only-in "./func.ss" governor-ready-steps make-retained-governor gateway-source-cancelled?) (only-in "./program.ss" make-gateway-program hard-fact-affected) (only-in "./snapshot.ss" scheme-value->source-data source-data->scheme-value)) (export install-gateway-producer!) @@ -17,16 +18,40 @@ (set! installed? #t) #t) (def (ready _) installed?) +(def capture-cancel-callback #f) +(def (install-capture-cancel! callback) (set! capture-cancel-callback callback)) +(extern capture-cancelled) (def (capture-request value) ;; Semantic decline is a valid false result, not a failed root transfer. (with-catch (lambda (_) #f) (lambda () - (source-data->scheme-value ((.get source-program capture) (scheme-value->source-data value)))))) + (parameterize ((gateway-source-cancelled? + (and capture-cancel-callback + (lambda () (not (zero? (capture-cancelled capture-cancel-callback))))))) + (source-data->scheme-value ((.get source-program capture) (scheme-value->source-data value))))))) +(def retained-governor? (equal? "1" (getenv "WEAVER_TEST_GOVERNOR_RETAINED" "0"))) +(def derive-governor (if retained-governor? (make-retained-governor) governor-ready-steps)) +(when (getenv "WEAVER_TEST_GOVERNOR_TIMING" #f) + (let (port (current-error-port)) + (display (if retained-governor? "weaver-governor-mode retained\n" "weaver-governor-mode fresh\n") port) + (force-output port))) +(def (derive-request value) + (with-catch (lambda (_) #f) + (lambda () + (source-data->scheme-value (derive-governor (scheme-value->source-data value)))))) (def (fact-impact-request value) (with-catch (lambda (_) #f) (lambda () (source-data->scheme-value (hard-fact-affected (scheme-value->source-data value)))))) (begin-foreign + (namespace ("hardenedlinux/weaver/scheme/gateway/compiled#" capture-cancelled)) + (define capture-cancelled + (c-lambda ((pointer void)) int "___return((*(int (**)(void))___arg1)());")) + (c-define (install-cancel callback) ((pointer void)) void "weaver_install_source_cancel_v1" "extern" + (hardenedlinux/weaver/scheme/gateway/compiled#install-capture-cancel! callback)) + (c-define (derive-root root) (int64) int64 "weaver_governor_ready_steps_v1" "extern" + (gerbil-scheme-rust/scheme/runtime#gerbil-rs-rooted-call root + hardenedlinux/weaver/scheme/gateway/compiled#derive-request)) (c-define (fact-impact-root root) (int64) int64 "weaver_hard_fact_impact_v1" "extern" (gerbil-scheme-rust/scheme/runtime#gerbil-rs-rooted-call root hardenedlinux/weaver/scheme/gateway/compiled#fact-impact-request)) diff --git a/scheme/gateway/contracts.ss b/scheme/gateway/contracts.ss index 96a99b0f..a7797e19 100644 --- a/scheme/gateway/contracts.ss +++ b/scheme/gateway/contracts.ss @@ -9,7 +9,7 @@ (only-in :clan/poo/number UIntN) (only-in :hardenedlinux/weaver/scheme/policy/types CedarPolicySource CedarSchemaSource)) (export GatewayArtifact GatewaySourceInput TaskContract ProviderPlanContract PublicationContract - ProviderProfileContract ProviderRouteContract Identifier Counter Credits) + ProviderProfileContract ProviderRouteContract Identifier Counter Credits Digest) ;;; Preserve exact JSON integer tokens above 2^53; the default Integer JSON ;;; encoder intentionally uses strings there, which this wire schema forbids. @@ -80,7 +80,9 @@ identity: 'weaver/gateway/source-input sealed: #t)) (def GovernorHandoff (.cc (Record schema: (list String) family: (list Identifier) - open_nodes: (list (List Identifier))) identity: 'weaver/governor-handoff sealed: #t)) + open_nodes: (list (List Identifier)) + workflow_edges: (list (List (List Identifier)) optional: #t) + workflow_selectors: (list (List (List Identifier)) optional: #t)) identity: 'weaver/governor-handoff sealed: #t)) (def GatewayArtifact (.cc (Record governance: (list GovernorHandoff) tasks: (list (List TaskContract)) plans: (list (List ProviderPlanContract)) publication: (list PublicationContract)) diff --git a/scheme/gateway/derivation-types.ss b/scheme/gateway/derivation-types.ss new file mode 100644 index 00000000..8d6a5571 --- /dev/null +++ b/scheme/gateway/derivation-types.ss @@ -0,0 +1,42 @@ +;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +;;; +;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +;;; Data-only advisory derivation. No field is an execution capability. +(import (only-in :clan/poo/object .cc) + (only-in :clan/poo/mop Function Bool) + (only-in :clan/poo/type Record List String Enum) + "./contracts.ss") +(export GatewayDependency GatewayDerivationRequest GatewayDerivationResult + GatewayDerivation GatewayPreparation) + +(def GatewayDependency + (.cc (Record dependent: (list Identifier) dependency: (list Identifier)) + identity: 'weaver/gateway/dependency sealed: #t)) +(def GatewayDerivationRequest + (.cc (Record source: (list GatewayArtifact) + dependencies: (list (List GatewayDependency)) changed: (list (List Identifier))) + identity: 'weaver/gateway/derivation-request sealed: #t)) +(def DeclaredCandidate + (.cc (Record node: (list Identifier) target: (list Identifier) model: (list String)) + identity: 'weaver/gateway/declared-candidate sealed: #t)) +(def OfferExplanation + (.cc (Record node: (list Identifier) target: (list Identifier) model: (list String) + declared_node: (list Bool) declared_target: (list Bool) declared_model: (list Bool)) + identity: 'weaver/gateway/offer-explanation sealed: #t)) +(def GatewayDerivationResult + (.cc (Record source_digest: (list Digest) request_digest: (list Digest) + family: (list Identifier) generation: (list Counter) + rule_profile: (list String) limit_profile: (list String) + complete: (list (Enum #t)) execution_authorized: (list (Enum #f)) + candidates: (list (List DeclaredCandidate)) explanations: (list (List OfferExplanation)) + affected: (list (List Identifier)) affected_nodes: (list (List Identifier))) + identity: 'weaver/gateway/advisory-result sealed: #t)) +(def GatewayDerivation + (.cc (Record derive: (list (Function (list GatewayDerivationResult) (list GatewayDerivationRequest))) + matches?: (list (Function (list Bool) (list GatewayDerivationRequest GatewayDerivationResult))) + invalidate: (list (Function (list Bool) '())) close: (list (Function (list Bool) '()))) + identity: 'weaver/gateway/derivation sealed: #t)) +(def GatewayPreparation + (.cc (Record source: (list GatewayArtifact) derivation: (list GatewayDerivationResult)) + identity: 'weaver/gateway/preparation sealed: #t)) diff --git a/scheme/gateway/derivation.ss b/scheme/gateway/derivation.ss new file mode 100644 index 00000000..9eec53d8 --- /dev/null +++ b/scheme/gateway/derivation.ss @@ -0,0 +1,196 @@ +;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +;;; +;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +;;; Fixed, finite application rules over detached integer projections. ASCENT +;;; owns evaluation/replacement; this adapter owns the existing Gateway image. +(import (only-in :clan/poo/object .o .get .ref seal-object!) + (only-in :clan/poo/mop validate json<-) + (only-in :std/encoding/json json->string JSONWriteOptions) + (only-in :std/crypto/digest sha256) + (only-in :std/encoding/hex hex-encode) + (only-in :std/list/list delete-duplicates/hash append-map) + (only-in :gerbil-ascent/program/session gerbil-ascent-open-session + gerbil-ascent-session-run gerbil-ascent-session-replace-sources!) + "./contracts.ss" "./derivation-types.ss" + (only-in "./program.ss" gateway-impact-program) + (only-in "./snapshot.ss" copy-source-data)) +(export make-gateway-derivation derive-gateway-source gateway-derivation-request) + +;;; These bounds qualify this closed advisory kernel, not the Gateway's budget +;;; or a wall-clock deadline. There are no callbacks, generators or new atoms in +;;; its recursive rule. Existing capture size/depth bounds apply independently. +(def +input-facts+ 4096) +(def +rule-profile+ "weaver.gateway.declared-offers-impact.v1") +(def +limit-profile+ "input:4096;derived:8192;output:12288;capture:existing") +(def (canonical contract value) + ;; Private callers supply detached values already admitted by owned/Record + ;; contracts. No foreign callback can mutate them during serialization. + (json->string (json<- contract value) (JSONWriteOptions sort-keys: #t))) +(def (digest text) (hex-encode (sha256 (string->utf8 text)))) +(def (owned contract value) (validate contract (copy-source-data (validate contract value)))) +(def (unique-sorted values) (list-sort string (apply + (map (lambda (entry) (length (cdr entry))) raw)) +input-facts+) + (error "Gateway derivation input fact bound")) + ;; A per-cut dictionary admits immutable integers into ASCENT. Never intern + ;; attacker-selected identifiers or retain mutable nested host values. Every + ;; source relation is replaced together if the dictionary changes. + (def names (unique-sorted (append-map (lambda (entry) (apply append (cdr entry))) raw))) + (def ids (make-hash-table)) + (for-each (lambda (name index) (hash-put! ids name index)) names (iota (length names))) + (values task raw (list->vector names) + (map (lambda (entry) (cons (car entry) + (map (lambda (row) (map (lambda (name) (hash-ref ids name)) row)) + (cdr entry)))) raw))) + +(def (make-program inputs) + (def (rows name) (cdr (assq name inputs))) + (gateway-impact-program ((rows 'depends) (rows 'changed)) (4096 8192 12288) + (relation operation (node) (rows 'operation)) + (relation offer (node target model) (rows 'offer)) + (relation declared-node (node) (rows 'declared-node)) + (relation declared-target (target) (rows 'declared-target)) + (relation declared-model (model) (rows 'declared-model)) + (relation candidate (node target model) '()) + (relation affected-node (node) '()) + (rule (candidate ?n ?t ?m) (offer ?n ?t ?m) (declared-node ?n) + (declared-target ?t) (declared-model ?m)) + (rule (affected-node ?n) (operation ?n) (affected ?n)))) + +(def (make-report request request-image task raw names result report-generation) + (unless (eq? (.ref result 'finished) #t) + (error "Gateway derivation did not complete")) + (def (rows name) ((.ref result 'rows-of) name)) + (def (decode index) (vector-ref names index)) + (def (member? value values) (if (member value values) #t #f)) + (def (declared? name value) (member? (list value) (cdr (assq name raw)))) + ;; Canonicalize presentation independently of evaluator iteration order. + (def candidate-rows (rows 'candidate)) + (def offers (delete-duplicates/hash (cdr (assq 'offer raw)))) + (def (rowstring JSONWriteOptions) (only-in :yuanxu/module-system/interface yuanxu-load-modules) + (only-in :yuanxu/module-system/source/admission module-source-measure-operation) (only-in :agentic-ai-lab/modules/loop-engine/control/governor loop-governor->contract) + (only-in :agentic-ai-lab/modules/session/objects-core agentic-ai-lab-session? agentic-ai-lab-session-id) + (only-in :yuanxu/modules/funflow/control-plane/flow admit-flow flow-name flow-steps branch-step? branch-step-name branch-step-left branch-step-right) + (only-in :yuanxu/modules/funflow/control-plane/task task? task-name task-kind task-request-operation) (only-in :hardenedlinux/weaver/scheme/governance/types GovernanceAssessmentContext) (only-in :hardenedlinux/weaver/scheme/governance/capture governance-profile-snapshot) (only-in :hardenedlinux/weaver/scheme/policy/types PolicyProjection) (only-in :hardenedlinux/weaver/scheme/policy/func validate-policy-projection!) + (only-in :gerbil-ascent/program/scheme-language relational-program) + (only-in :gerbil-ascent/program/session gerbil-ascent-open-session gerbil-ascent-session-run + gerbil-ascent-session-replace-sources!) (only-in "./capture.ss" deliver-gateway-source) (only-in "./snapshot.ss" copy-source-data) (only-in "./program.ss" make-gateway-program) + (only-in "./derivation.ss" derive-gateway-source) + (only-in "./derivation-types.ss" GatewayPreparation) "./contracts.ss") -(export compile-gateway emit-gateway emit-governed-gateway capture-governed-gateway make-gateway-program governor-open-nodes) +(export compile-gateway prepare-gateway prepare-governed-gateway emit-gateway emit-governed-gateway capture-governed-gateway make-gateway-program governor-open-nodes governor-ready-steps) +(export gateway-source-phase-observer gateway-source-cancelled? make-retained-governor trace-gateway-source-phase) + +;;; Each source-loaded role has its own parameter. Enable the same numeric +;;; diagnostic in both the linked entry and the role only when requested. +(def (trace-gateway-source-phase label) + (let ((port (current-error-port)) (observed (time->seconds (current-time)))) + (display "weaver scheme phase=" port) (display label port) + (display " real=" port) (display (real-time) port) + (display " cpu=" port) (display (cpu-time) port) + (display " wall-us=" port) (display (inexact->exact (floor (* observed 1000000))) port) + (newline port) (force-output port))) + +(def gateway-source-phase-observer + (make-parameter (and (getenv "WEAVER_TEST_GOVERNOR_TIMING" #f) trace-gateway-source-phase))) +(def gateway-source-cancelled? (make-parameter #f)) +(def (source-phase! phase) + (let ((observe (gateway-source-phase-observer))) + (when observe (observe phase)))) + +(def (require-source-open!) + (let ((cancelled? (gateway-source-cancelled?))) + (when (and cancelled? (cancelled?)) + (source-phase! "source-preparation-cancelled") + (error "Gateway source preparation cancelled")))) ;;; Private canonical text for the upstream assessment context and mutation guard. ;;; It is neither an exported artifact nor the Scheme-to-Rust transport. (def (source-assessment-text value) - (json->string (json<- GatewayArtifact (validate GatewayArtifact value)) + (json->string (json<- GatewayArtifact value) (JSONWriteOptions sort-keys: #t))) ;;; Only project upstream symbolic node names to the gateway's wire identifiers. @@ -29,7 +62,213 @@ (def (governor-open-nodes governor states) (map symbol->string (cdr (assq 'open-patterns (loop-governor->contract governor states))))) -(def (compile-gateway governance policy governor profile context states task-values plan-values publication-value) +;;; Compile sequential and fan-out/fan-in Funflow steps into a sealed topology. +;;; Each recursive walk returns the set of leaves needed by the next step. +(def (session-workflow-path context family) + (and (.slot? context 'session) + (let* ((session (.get context session)) + (identity (string->symbol family))) + (unless (and (agentic-ai-lab-session? session) + (eq? identity (agentic-ai-lab-session-id session))) + (error "Workflow Session must name the original family")) + (def workflow (admit-flow (.get session workflow))) + (def nodes '()) + (def edges '()) + (def branched? #f) + (def selectors '()) + (def choice-names (if (.slot? session 'workflow-choices) (.get session workflow-choices) '())) + (def (walk steps previous) + (if (null? steps) previous + (let ((step (car steps))) + (cond + ((branch-step? step) + (set! branched? #t) + (unless (pair? previous) (error "Workflow requires one provider root")) + (let* ((left-steps (flow-steps (branch-step-left step))) + (right-steps (flow-steps (branch-step-right step))) + (name (branch-step-name step)) + (conditional? (memq name choice-names))) + (when conditional? + (unless (and (null? (cdr previous)) (pair? left-steps) (pair? right-steps) + (task? (car left-steps)) (task? (car right-steps))) + (error "Each conditional fork requires a selector and one entry per arm")) + (set! choice-names (remq name choice-names)) + (set! selectors (cons (list (car previous) + (symbol->string (task-name (car left-steps))) + (symbol->string (task-name (car right-steps)))) + selectors))) + (let* ((left (walk left-steps previous)) + (right (walk right-steps previous))) + (when (or (equal? left previous) (equal? right previous)) + (error "Workflow branch requires two nonempty paths")) + (walk (cdr steps) (append left right))))) + ((and (task? step) (eq? (task-kind step) 'external) + (eq? (task-request-operation step) 'weaver-provider-response)) + (let ((node (symbol->string (task-name step)))) + (when (or (member node nodes) (>= (length nodes) 64)) + (error "Workflow node identity")) + (set! nodes (cons node nodes)) + (for-each (lambda (parent) (set! edges (cons (list node parent) edges))) previous) + (walk (cdr steps) (list node)))) + (else (error "Workflow requires external provider tasks")))))) + (unless (eq? (flow-name workflow) identity) (error "Workflow identity")) + (walk (flow-steps workflow) '()) + (unless (and (<= 2 (length nodes) 64) (<= (length edges) 64)) + (error "Workflow bounds")) + (unless (null? choice-names) (error "Unbound conditional fork")) + (def conditional? (and (.slot? session 'workflow-choice) (eq? (.get session workflow-choice) #t))) + (when (and conditional? (not branched?)) (error "Conditional Workflow requires a fork and join")) + (list (reverse nodes) + (and branched? (list-sort + (lambda (a b) (or (stringstring (json<- PolicyProjection value) (JSONWriteOptions sort-keys: #t))) (def policy-inputs (projection-json projection)) (validate-policy-projection! projection (.get publication-image schema) (.get policy validate)) + (source-phase! "source-contract-policy-validated") (require-profile-current!) (let ((bound-context (validate GovernanceAssessmentContext (.o request: (.get context request) source: (string-copy source-text) @@ -92,35 +347,72 @@ model_identity: (.get profile threat-model identity))))) (unless ((.get governance assess) profile bound-context) (error "Governance declined the source handoff")) + (source-phase! "source-contract-governance-assessed") (unless (equal? policy-inputs (projection-json ((.get policy project) profile (string-copy (.get publication-image policy)) (string-copy asset-root)))) (error "Governance Policy inputs changed during assessment")) (require-profile-current!) ;; All delegated callbacks finish before the final caller/image comparison. - (unless (and (equal? source-text (source-assessment-text bundle)) - (equal? source-text (source-assessment-text original)) + (unless (and (equal? source-text (source-assessment-text (validate GatewayArtifact bundle))) + (equal? source-text (source-assessment-text (validate GatewayArtifact original))) + (equal? workflow (session-workflow-path context source-family)) (equal? asset-root (if (.slot? context 'source_root) (.get context source_root) ""))) (error "Governance source changed during assessment")) bundle))) +;;; The ordinary source path now executes the same bounded advisory derivation +;;; exposed by prepare. The typed wire artifact remains exactly the original; +;;; derived candidates never rewrite plans, authorize an effect or settle usage. +(def (prepare-gateway governance policy governor profile context states tasks plans publication) + (def source-image + (module-source-measure-operation 'gateway-source-contracts + (lambda () (compile-gateway-source governance policy governor profile context states tasks plans publication)))) + (source-phase! "source-contracts-checked") + (def advisory + (module-source-measure-operation 'gateway-source-advisory + (lambda () (derive-gateway-source source-image)))) + (source-phase! "source-advisory-derived") + (validate GatewayPreparation (.o source: source-image derivation: advisory))) + +(def (compile-gateway governance policy governor profile context states tasks plans publication) + (.get (prepare-gateway governance policy governor profile context states tasks plans publication) source)) + (def (emit-gateway bundle) (deliver-gateway-source bundle)) ;;; Both delivery modes use one admitted module view and one semantic producer. (def (with-current-gateway init operation) - ;; Use the public callable value rather than a compiler-private keyword entry. - (let* ((view (apply yuanxu-load-modules (list init))) - (gateway (.get view modules Weaver gateway)) + (require-source-open!) + (let* ((view (if (gateway-source-cancelled?) + (yuanxu-load-modules init module-view: + (lambda (_ resolve) + (require-source-open!) + (let ((scope (resolve))) + (require-source-open!) + scope))) + (apply yuanxu-load-modules (list init)))) + (gateway (begin + (source-phase! "source-selection-loaded") + (.get view modules Weaver gateway))) (admit-current (.get view admit-current))) + (source-phase! "source-module-view-loaded") + (require-source-open!) (admit-current) + (source-phase! "source-admitted-before-prepare") (let ((result (operation gateway admit-current))) + (source-phase! "source-delivery-prepared") + (require-source-open!) (admit-current) + (source-phase! "source-admitted-after-prepare") result))) (def (produce-governed-source gateway admit-current governor profile context states tasks plans publication) (let ((bundle ((.get gateway compile) governor profile context states tasks plans publication))) + (source-phase! "source-object-and-advisory-prepared") + (require-source-open!) (admit-current) + (source-phase! "source-admitted-before-delivery") ((.get gateway emit) bundle))) ;;; Scheme source-generation guards qualify compilation, not final execution. @@ -135,3 +427,10 @@ ((.get gateway capture) (lambda () (produce-governed-source gateway admit-current governor profile context states tasks plans publication)))))) + +;;; Rich preparation remains inside the same admitted Yuanxu view. The caller +;;; may inspect advisory evidence; existing emit/capture still accept only source. +(def (prepare-governed-gateway init governor profile context states tasks plans publication) + (with-current-gateway init + (lambda (gateway admit-current) + ((.get gateway prepare) governor profile context states tasks plans publication)))) diff --git a/scheme/gateway/interface.ss b/scheme/gateway/interface.ss index 7539ad5f..f79fb1ed 100644 --- a/scheme/gateway/interface.ss +++ b/scheme/gateway/interface.ss @@ -5,6 +5,7 @@ (import (only-in :yuanxu/module-system/source/declaration .def)) (.def Gateway identity: 'gateway + tags: '(gateway) core: (.o requires: (.o Governance: (.o module-id: 'governance contract: GovernanceScopeContract) @@ -12,5 +13,7 @@ scope-contract: GatewayScopeContract exports: (.o (:: @ Gateway.) - compile: (lambda args (apply compile-gateway Governance Policy args)))) + compile: (lambda args (apply compile-gateway Governance Policy args)) + prepare: (lambda args (apply prepare-gateway Governance Policy args))) + projections: (list Build)) features: (.o)) diff --git a/scheme/gateway/objects.ss b/scheme/gateway/objects.ss index b2522849..80a52dd7 100644 --- a/scheme/gateway/objects.ss +++ b/scheme/gateway/objects.ss @@ -4,6 +4,8 @@ ;;; Dependency scopes are injected by Yuanxu's declaration linker. (import (only-in :clan/poo/object .o) "./func.ss" + (only-in "./derivation.ss" derive-gateway-source make-gateway-derivation) (only-in "./capture.ss" capture-gateway-source)) (export Gateway.) -(def Gateway. (.o emit: emit-gateway capture: capture-gateway-source)) +(def Gateway. (.o emit: emit-gateway capture: capture-gateway-source + derive: derive-gateway-source open-derivation: make-gateway-derivation)) diff --git a/scheme/gateway/program.ss b/scheme/gateway/program.ss index a735fe42..42c056d3 100644 --- a/scheme/gateway/program.ss +++ b/scheme/gateway/program.ss @@ -10,7 +10,6 @@ (only-in :gerbil-ascent/program/scheme-language relational-program) (only-in :gerbil-ascent/program/session gerbil-ascent-open-session gerbil-ascent-session-run) (only-in "./types.ss" GatewayProgram) - (only-in "./contracts.ss" GatewayArtifact) (only-in "./snapshot.ss" copy-source-data)) (export make-gateway-program hard-fact-affected gateway-impact-program) @@ -36,7 +35,9 @@ (def (close-program!) (locked (lambda () (set! phase 'closed) (set! producer #f) #t))) (def (capture-source original) - (let* ((input (copy-source-data (validate GatewayArtifact original))) + ;; GatewayProgram.capture and the installed producer both have typed + ;; arguments/results. Detach their admitted data without a third walk. + (let* ((input (copy-source-data original)) (selected (locked (lambda () @@ -56,7 +57,7 @@ ;; The approved producer performs its existing scoped capture and ;; returns one typed Record. An ambient sink outside the admitted ;; Yuanxu scope need not share that scope's parameter identity. - (let ((result (copy-source-data (validate GatewayArtifact (selected input))))) + (let ((result (copy-source-data (selected input)))) (locked (lambda () (unless (eq? phase 'active) (error "Gateway program closed during capture")) diff --git a/scheme/gateway/provider-program.ss b/scheme/gateway/provider-program.ss new file mode 100644 index 00000000..e36fbe18 --- /dev/null +++ b/scheme/gateway/provider-program.ss @@ -0,0 +1,73 @@ +;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +;;; +;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +;;; Build-selected initializer for Weaver's declared provider workflows. +(import (only-in :std/source this-source-file) + (only-in :clan/poo/object .o .ref) + (only-in :agentic-ai-lab/modules/loop-engine/control/governor make-loop-governor) + (only-in :agentic-ai-lab/modules/governance/interface AgenticAILabGovernanceProfile.) + (only-in :agentic-ai-lab/modules/authorization/providers/cedar/objects agentic-ai-lab-cedar-policy) + (only-in :yuanxu/module-system/source/admission call-with-module-source-operation-measurement) + :hardenedlinux/weaver/scheme/policy/cedar-ffi + (only-in "./compiled.ss" install-gateway-producer!) + (only-in "./func.ss" capture-governed-gateway gateway-source-phase-observer) + "./provider-source.ss") +(export main) +(def (main . _) (void)) + +(def init-file (path-expand "../../init.ss" (path-directory (this-source-file)))) + +;;; Use the existing Reader's private scalar accounting. A diagnostic cannot +;;; supply a callback during admission, retain contexts or change the result. +;;; Keep it separate from ordinary phase timing and report exceptional exits. +(def (capture-source action) + (if (not (getenv "WEAVER_TEST_SOURCE_PROFILE" #f)) (action) + (let ((failed? #f) (failure #f)) + (let-values (((result times) + (call-with-module-source-operation-measurement + (lambda () + (with-catch + (lambda (exception) + (set! failed? #t) (set! failure exception) #f) + action)) + accounting?: 'stages))) + (let (port (current-error-port)) + (hash-for-each + (lambda (key value) + (display "weaver scheme phase=source-profile metric=" port) + (write key port) (display " value=" port) (write value port) + (newline port)) times) + (force-output port)) + (if failed? (raise failure) result))))) + +(def (capture bundle) + (def schema (.ref (.ref bundle 'governance) 'schema)) + (def nested? (equal? schema "weaver.session-nested.v1")) + (def choice? (equal? schema "weaver.session-choice.v1")) + (def dag? (or nested? choice? (equal? schema "weaver.session-dag.v1"))) + (def session? (or dag? (equal? schema "weaver.session-workflow.v1"))) + (unless (or session? (equal? schema "agentic-ai-lab.loop-governor.v1")) + (error "unsupported Weaver provider workflow")) + (def publication (.ref bundle 'publication)) + (def policy (agentic-ai-lab-cedar-policy "weaver/runtime" (.ref publication 'policy))) + (def profile + (.o (:: @ AgenticAILabGovernanceProfile.) + identity: "weaver/source" revision: "1" owner: "source-owner" + policies: (.o runtime: policy))) + (def governor (make-loop-governor 'weaver (provider-source-strategy nested? dag? session?) + (provider-source-budget nested? dag? session?))) + (def context + (if session? + (.o request: 'publish session: (if nested? (nested-workflow-session) (workflow-session dag? choice?))) + (.o request: 'publish))) + (def phase-observer (gateway-source-phase-observer)) + (when phase-observer (phase-observer "compile-begin")) + (begin0 + (capture-source + (lambda () + (capture-governed-gateway init-file governor profile context '() + (.ref bundle 'tasks) (.ref bundle 'plans) publication))) + (when phase-observer (phase-observer "source-captured")))) + +(install-gateway-producer! capture) diff --git a/scheme/gateway/provider-source.ss b/scheme/gateway/provider-source.ss new file mode 100644 index 00000000..fc55fbec --- /dev/null +++ b/scheme/gateway/provider-source.ss @@ -0,0 +1,71 @@ +;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +;;; +;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +;;; Weaver's declared provider workflows and Governor strategy. +(import :agentic-ai-lab/modules/loop-engine/control/strategy + :agentic-ai-lab/modules/loop-engine/control/descriptor + (only-in :agentic-ai-lab/modules/session/objects-core agentic-ai-lab-session-value + agentic-ai-lab-session-lineage agentic-ai-lab-session-placement) + (only-in :yuanxu/modules/funflow/control-plane/flow flow-compose external-flow flow-steps flow-then flow-branch flow-output-contract Fun String PairValue) + (only-in :clan/poo/object .o)) +(export workflow-session nested-workflow-session provider-source-strategy provider-source-budget) + +(def (workflow-session dag? choice?) + (def signature (Fun String <- String)) + (def (step node (type signature)) + (external-flow node 'weaver-provider-response #f type)) + (def routine + (if dag? + (flow-then 'control + (flow-then 'fork (step 'infer) (flow-branch 'branches (step 'next) (step 'side))) + (step 'finish (Fun String <- (PairValue String String)))) + (flow-compose 'control + (apply append (map (lambda (node) (flow-steps (step node))) '(infer next finish))) + signature))) + (.o (:: @ (agentic-ai-lab-session-value 'control '() + (agentic-ai-lab-session-lineage 'control '() 'root) + (agentic-ai-lab-session-placement 'provider))) + workflow: routine workflow-choice: choice?)) + +(def (nested-workflow-session) + (def (provider node (input String)) + (external-flow node 'weaver-provider-response #f (Fun String <- input))) + (def (then-provider name preceding node) + (flow-then name preceding (provider node (flow-output-contract preceding)))) + (def parallel + (flow-then 'parallel-arm (provider 'side) + (flow-branch 'parallel (provider 'fork-a) (provider 'fork-b)))) + (def inner + (then-provider 'inner-join + (flow-then 'inner-start (provider 'gate) + (flow-branch 'inner (provider 'next) parallel)) + 'inner-finish)) + (def routine + (then-provider 'control + (flow-then 'outer-start (provider 'infer) + (flow-branch 'outer inner (provider 'outer-skip))) + 'finish)) + (.o (:: @ (agentic-ai-lab-session-value 'control '() + (agentic-ai-lab-session-lineage 'control '() 'root) + (agentic-ai-lab-session-placement 'provider))) + workflow: routine workflow-choices: '(outer inner))) + +(def (provider-source-strategy nested? dag? session?) + (make-loop-strategy-plan 'weaver-routing + (append (list (make-loop-pattern-descriptor 'infer "Original inference" '((level . l2))) + (make-loop-pattern-descriptor 'next "Original continuation" '((level . l2)))) + (if nested? + (map (lambda (name) (make-loop-pattern-descriptor name "Nested provider step" '((level . l2)))) + '(gate fork-a fork-b inner-finish outer-skip)) + '()) + (if dag? (list (make-loop-pattern-descriptor 'side "Parallel continuation" '((level . l2)))) '()) + (if session? + (list (make-loop-pattern-descriptor 'finish "Original final inference" '((level . l2)))) + '())))) + +(def (provider-source-budget nested? dag? session?) + (cond (nested? '((aggregate-budget . ((max-actionable . 9) (max-attempts . 1))))) + (dag? '((aggregate-budget . ((max-actionable . 4) (max-attempts . 1))))) + (session? '((aggregate-budget . ((max-actionable . 3) (max-attempts . 1))))) + (else '((aggregate-budget . ((max-actionable . 2) (max-attempts . 1))))))) diff --git a/scheme/gateway/types.ss b/scheme/gateway/types.ss index 2efec971..528ea35b 100644 --- a/scheme/gateway/types.ss +++ b/scheme/gateway/types.ss @@ -6,11 +6,11 @@ (import (only-in :clan/poo/object .cc) (only-in :clan/poo/mop Function Bool) (only-in :clan/poo/type Record List Pair Or Symbol String Enum) - (only-in :yuanxu/object-types/contracts YuanxuContract.) (only-in :hardenedlinux/weaver/scheme/governance/types GovernanceScopeContract GovernanceContext AgenticAILabGovernanceProfile) (only-in :agentic-ai-lab/modules/loop-engine/control/governor +loop-governor-type-contract+) (only-in :hardenedlinux/weaver/scheme/policy/types PolicyScopeContract) + (only-in "./derivation-types.ss" GatewayPreparation GatewayDerivation GatewayDerivationResult) "./contracts.ss") (export GatewayScopeContract GovernanceScopeContract PolicyScopeContract GatewaySourceProducer GatewayProgram) ;;; Gateway's typed projection of the upstream governor's state input. Selection @@ -24,11 +24,17 @@ close: (list (Function (list Bool) '()))) identity: 'weaver/gateway/program sealed: #t)) (def GatewayScopeContract - (.cc YuanxuContract. value-contract: (Record + (.cc (Record compile: (list (Function (list GatewayArtifact) (list +loop-governor-type-contract+ AgenticAILabGovernanceProfile GovernanceContext (List GovernorState) (List TaskContract) (List ProviderPlanContract) PublicationContract))) + prepare: (list (Function (list GatewayPreparation) + (list +loop-governor-type-contract+ AgenticAILabGovernanceProfile + GovernanceContext (List GovernorState) + (List TaskContract) (List ProviderPlanContract) PublicationContract))) + derive: (list (Function (list GatewayDerivationResult) (list GatewayArtifact))) + open-derivation: (list (Function (list GatewayDerivation) '())) emit: (list (Function (list Bool) (list GatewayArtifact))) capture: (list (Function (list GatewayArtifact) (list (Function (list Bool) '()))))) identity: 'weaver/gateway/scope)) diff --git a/scheme/governance/interface.ss b/scheme/governance/interface.ss index 31ed13a7..bcb0af7a 100644 --- a/scheme/governance/interface.ss +++ b/scheme/governance/interface.ss @@ -5,5 +5,6 @@ (import (only-in :yuanxu/module-system/source/declaration .def)) (.def Governance identity: 'governance + tags: '(governance) core: (.o requires: (.o) scope-contract: GovernanceScopeContract exports: Governance.) features: (.o)) diff --git a/scheme/governance/types.ss b/scheme/governance/types.ss index 5a2e5a2c..ba844b37 100644 --- a/scheme/governance/types.ss +++ b/scheme/governance/types.ss @@ -4,14 +4,16 @@ ;;; Scheme POO scope Contract for inert governance semantics. (import (only-in :clan/poo/object .cc) - (only-in :clan/poo/mop Function Bool) + (only-in :clan/poo/mop Function Bool Type. define-type) (only-in :clan/poo/type Record List String Symbol Or Enum) - (only-in :yuanxu/object-types/contracts YuanxuContract.) - (only-in :agentic-ai-lab/modules/governance/types AgenticAILabGovernanceProfile)) + (only-in :agentic-ai-lab/modules/governance/types AgenticAILabGovernanceProfile) + (only-in :agentic-ai-lab/modules/session/objects-core agentic-ai-lab-session?)) (export GovernanceScopeContract GovernanceContext GovernanceAssessmentContext AgenticAILabGovernanceProfile GovernanceProfileSnapshot) +(define-type (GovernanceSession @ Type.) .element?: agentic-ai-lab-session?) (def GovernanceContext - (.cc (Record request: (list (Enum publish)) source_root: (list String optional: #t)) + (.cc (Record request: (list (Enum publish)) source_root: (list String optional: #t) + session: (list GovernanceSession optional: #t)) identity: 'weaver/governance/context sealed: #t)) (def GovernanceSource (.cc String sexp: 'GovernanceSource @@ -48,6 +50,6 @@ source_assets: (list (List SourceAssetSnapshot))) identity: 'weaver/governance/profile-snapshot sealed: #t)) (def GovernanceScopeContract - (.cc YuanxuContract. value-contract: (Record + (.cc (Record assess: (list (Function (list Bool) (list AgenticAILabGovernanceProfile GovernanceAssessmentContext)))) identity: 'weaver/governance/scope)) diff --git a/scheme/policy/build.ss b/scheme/policy/build.ss new file mode 100644 index 00000000..fcacafa3 --- /dev/null +++ b/scheme/policy/build.ss @@ -0,0 +1,12 @@ +;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +;;; +;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +(import (only-in :std/make pkg-config-cflags pkg-config-libs)) +(export Build) +(def policy-package (getenv "WEAVER_POLICY_PKG_CONFIG_PACKAGE" "weaver-policy-ffi")) +(def Build + (.o kind: 'module/build + roots: `((gxc: "cedar-ffi" + "-cc-options" ,(pkg-config-cflags policy-package) + "-ld-options" ,(pkg-config-libs policy-package))))) diff --git a/scheme/policy/interface.ss b/scheme/policy/interface.ss index ddcd7ecd..8cd4bf2c 100644 --- a/scheme/policy/interface.ss +++ b/scheme/policy/interface.ss @@ -5,5 +5,7 @@ (import (only-in :yuanxu/module-system/source/declaration .def)) (.def Policy identity: 'policy - core: (.o requires: (.o) scope-contract: PolicyScopeContract exports: Policy.) + tags: '(policy) + core: (.o requires: (.o) scope-contract: PolicyScopeContract exports: Policy. + projections: (list Build)) features: (.o)) diff --git a/scheme/policy/types.ss b/scheme/policy/types.ss index 5841e098..deadd7be 100644 --- a/scheme/policy/types.ss +++ b/scheme/policy/types.ss @@ -5,7 +5,6 @@ ;;; This Contract describes an inert Rust preflight, not an authorization grant. (import (only-in :clan/poo/object .cc) (only-in :clan/poo/mop Function Bool) - (only-in :yuanxu/object-types/contracts YuanxuContract.) (only-in :clan/poo/type Record String) (only-in "./source-bytes.ss" bounded-cedar-source?)) (import (only-in :clan/poo/type List) @@ -21,7 +20,7 @@ (.cc (Record policy: (list CedarPolicySource) inputs: (list (List PolicyDocument)) root: (list String)) identity: 'weaver/policy/projection sealed: #t)) (def PolicyScopeContract - (.cc YuanxuContract. value-contract: + (.cc (Record validate: (list (Function (list Bool) (list CedarPolicySource CedarSchemaSource))) project: (list (Function (list PolicyProjection) (list AgenticAILabGovernanceProfile CedarPolicySource String)))) diff --git a/t/fixtures/governed-control.ss b/t/fixtures/governed-control.ss index 14d49bfa..65fd4005 100644 --- a/t/fixtures/governed-control.ss +++ b/t/fixtures/governed-control.ss @@ -4,44 +4,37 @@ ;;; Native source fixture for cross-language integration; no Go governance DSL. (import :agentic-ai-lab/modules/loop-engine/control/governor - :agentic-ai-lab/modules/loop-engine/control/strategy - :agentic-ai-lab/modules/loop-engine/control/descriptor :agentic-ai-lab/modules/governance/interface (only-in :agentic-ai-lab/modules/authorization/providers/cedar/objects agentic-ai-lab-cedar-policy) + :hardenedlinux/weaver/scheme/gateway/provider-source (only-in :clan/poo/object .o .ref) :hardenedlinux/weaver/scheme/gateway/func) -(export capture-control-fixture) +(export capture-control-fixture prepare-control-fixture) -;;; Local phase evidence only. Labels and SDK clocks contain no source data; -;;; their presence cannot admit an artifact or certify natural process exit. -(def (trace-phase label) - (let ((port (current-error-port)) (observed (time->seconds (current-time)))) - (display "weaver scheme phase=" port) (display label port) - (display " real=" port) (display (real-time) port) - (display " cpu=" port) (display (cpu-time) port) - (display " wall-us=" port) (display (inexact->exact (floor (* observed 1000000))) port) - (newline port) (force-output port))) - -(trace-phase "fixture-module-ready") +(trace-gateway-source-phase "fixture-module-ready") (def (capture-control-fixture init mode tasks plans publication asset-root) (control-fixture init mode tasks plans publication asset-root)) -(def (control-fixture init mode tasks plans publication asset-root) - (trace-phase "fixture-enter") +(def (prepare-control-fixture init mode tasks plans publication asset-root) + (control-fixture init mode tasks plans publication asset-root #t)) + +(def (control-fixture init mode tasks plans publication asset-root (preparation? #f)) + (trace-gateway-source-phase "fixture-enter") (def prefixed? (string-prefix? "capture-" mode)) (when prefixed? (set! mode (substring mode 8 (string-length mode)))) - (def strategy - (make-loop-strategy-plan 'weaver-routing - (list (make-loop-pattern-descriptor 'infer "Original inference" '((level . l2))) - (make-loop-pattern-descriptor 'next "Original continuation" '((level . l2)))))) + (def nested? (equal? mode "session-nested")) + (def choice? (equal? mode "session-choice")) + (def dag? (or nested? choice? (equal? mode "session-dag"))) + (def session? (or dag? (equal? mode "session-workflow"))) + (def strategy (provider-source-strategy nested? dag? session?)) (def overrides (cond ((equal? mode "deny") '((shared-denylist . (infer)) (aggregate-budget . ((max-actionable . 2) (max-attempts . 1))))) ((equal? mode "clip") '((aggregate-budget . ((max-actionable . 1) (max-attempts . 1))))) ((equal? mode "invalid") '((aggregate-budget . ((max-actionable . -1))))) - (else '((aggregate-budget . ((max-actionable . 2) (max-attempts . 1))))))) + (else (provider-source-budget nested? dag? session?)))) (def states (if (equal? mode "collision") '(((acting_on . infer))) '())) (def source-threat-model (if (equal? mode "threat") @@ -58,7 +51,7 @@ ((equal? mode "assets-only") (.o)) (else (.o runtime: native-policy)))) (def asset-values - (if (equal? mode "policy-only") '() + (if (or session? (equal? mode "policy-only")) '() (list (agentic-ai-lab-governance-source (if (equal? mode "policy-identity") "weaver/replacement" "weaver/runtime") (if (equal? mode "asset-traversal") "../policy.cedar" "policy.cedar") @@ -85,9 +78,13 @@ (list (agentic-ai-lab-governance-threat "weaver/other-threat" 'low 'latent (list (agentic-ai-lab-governance-precondition "weaver/input" #f #f)))))) (else assessment)))))) - (trace-phase "compile-begin") - (let ((result (capture-governed-gateway init (make-loop-governor 'weaver strategy overrides) - profile (.o request: 'publish source_root: asset-root) - states tasks plans publication))) - (trace-phase "source-captured") + (trace-gateway-source-phase "compile-begin") + (let ((result (parameterize ((gateway-source-phase-observer trace-gateway-source-phase)) + ((if preparation? prepare-governed-gateway capture-governed-gateway) + init (make-loop-governor 'weaver strategy overrides) + profile (if session? + (.o request: 'publish source_root: asset-root session: (if nested? (nested-workflow-session) (workflow-session dag? choice?))) + (.o request: 'publish source_root: asset-root)) + states tasks plans publication)))) + (trace-gateway-source-phase "source-captured") result)) diff --git a/t/gateway-contracts-test.ss b/t/gateway-contracts-test.ss index dd2d1d13..b6fa7ff9 100644 --- a/t/gateway-contracts-test.ss +++ b/t/gateway-contracts-test.ss @@ -4,8 +4,11 @@ ;;; Scheme owns source contract assertions; Go only schedules this standard suite. (import :std/test - (only-in :clan/poo/object .o .get) - (only-in :clan/poo/mop validate json<- TypeError?) + (only-in :clan/poo/object .o .get .cc) + (only-in :clan/poo/mop validate json<- TypeError? element?) + (only-in :yuanxu/module-system/source/publication ModulePublicationContract) + (only-in ../scheme/gateway/types GatewayScopeContract) + (only-in ../scheme/policy/types PolicyScopeContract) (only-in :std/encoding/json json->string) ../scheme/gateway/contracts ../scheme/governance/types) @@ -13,6 +16,22 @@ (def gateway-contracts-test (test-suite "Gateway source contracts" + (test-case "module scopes use native POO Types and refuse evidence protocol hooks" + (def (publication scope-type) + (.o identity: 'gateway-contract-fixture features: (.o) + core: (.o requires: (.o) scope-contract: scope-type link: void))) + (for-each + (lambda (scope-type) + (check-equal? (element? ModulePublicationContract (publication scope-type)) #t) + (for-each + (lambda (hook) + (check-equal? + (element? ModulePublicationContract (publication (.cc scope-type hook void))) #f)) + '(.classify .obligations .admit))) + (list GovernanceScopeContract PolicyScopeContract GatewayScopeContract)) + (check-exception (validate GovernanceScopeContract (.o assess: #f)) TypeError?) + (check-exception (validate PolicyScopeContract (.o validate: #t project: void)) TypeError?) + (check-exception (validate GatewayScopeContract (.o compile: void)) TypeError?)) (test-case "credits preserve exact JSON numbers above the JavaScript integer range" (check-equal? (validate Credits 9007199254740993) 9007199254740993) (check-equal? (json->string (json<- Credits 9007199254740993)) "9007199254740993") diff --git a/t/gateway-derivation-test.ss b/t/gateway-derivation-test.ss new file mode 100644 index 00000000..5fe39c5a --- /dev/null +++ b/t/gateway-derivation-test.ss @@ -0,0 +1,210 @@ +;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +;;; +;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +(import :std/test + (only-in :std/error Error?) + (only-in :clan/poo/object .o .get object-slots-set!) + (only-in :clan/poo/mop validate sexp<- TypeError?) + (only-in :std/list/list delete-duplicates/hash) + (only-in "./fixtures/control-inputs.ss" control-inputs) + (only-in ../scheme/gateway/contracts GatewayArtifact) + (only-in ../scheme/gateway/derivation-types GatewayDerivationResult GatewayDerivationRequest) + ../scheme/gateway/derivation + (prefix-in :clan/poo/testing/property/generator generator.) + (prefix-in :clan/poo/testing/property property.) + (only-in :clan/poo/testing/property/test check-property)) +(export gateway-derivation-test) + +(def (source) + (def input (control-inputs "{}" "permit(principal,action,resource);")) + (validate GatewayArtifact + (.o (:: @ input) governance: (.o schema: "agentic-ai-lab.loop-governor.v1" + family: "control" open_nodes: '("infer" "next"))))) +(def (data contract value) (sexp<- contract (validate contract value))) +(def (edge dependent-value dependency-value) (.o dependent: dependent-value dependency: dependency-value)) +(def (candidate-rows result) + (map (lambda (row) (list (.get row node) (.get row target) (.get row model))) (.get result candidates))) +(def (attempt thunk) + (with-catch (lambda (failure) (if (Error? failure) #f (raise failure))) thunk)) + +;;; Independent graph traversal oracle, not a second relational rule evaluator. +(def (reachable dependencies changed) + (let walk ((pending changed) (seen '())) + (cond ((null? pending) (list-sort string (.get returned generation) (.get second generation)) #t) + (check-equal? ((.get owner matches?) first-query first) #f) + ((.get owner close))) + (test-case "invalid input and fact overflow preserve the prior accepted result" + (def owner (make-gateway-derivation)) + (def query (gateway-derivation-request (source))) + (def result ((.get owner derive) query)) + (check-exception ((.get owner derive) (.o (:: @ query) unchecked: #t)) TypeError?) + (def large (gateway-derivation-request (.get query source) '() (make-list 4096 "policy"))) + (check-equal? (attempt (lambda () ((.get owner derive) large))) #f) + (check-equal? ((.get owner matches?) query result) #t) + (check-equal? (.get ((.get owner derive) query) generation) (.get result generation)) + ((.get owner close))) + (test-case "explicit invalidation prevents ABA reuse and close is terminal" + (def owner (make-gateway-derivation)) + (def query (gateway-derivation-request (source))) + (def result ((.get owner derive) query)) + ((.get owner invalidate)) + (check-equal? ((.get owner matches?) query result) #f) + (def renewed ((.get owner derive) query)) + (check-equal? (> (.get renewed generation) (.get result generation)) #t) + (check-exception (object-slots-set! owner '()) Error?) + ((.get owner close)) + (check-equal? (attempt (lambda () ((.get owner derive) query))) #f) + (check-equal? (attempt (lambda () ((.get owner matches?) query renewed))) #f)) + (test-case "a different thread cannot use or close the retained owner" + (def owner (make-gateway-derivation)) + (def query (gateway-derivation-request (source))) + (def answer #f) + (def worker (make-thread (lambda () (set! answer (list + (attempt (lambda () ((.get owner derive) query))) + (attempt (lambda () ((.get owner close))))))))) + (thread-start! worker) (thread-join! worker) + (check-equal? answer '(#f #f)) + (check-equal? (.get ((.get owner derive) query) complete) #t) + ((.get owner close))) + (test-case "generated source replacements agree with graph traversal and fresh results" + (def names '("policy" "infer" "next" "unrelated")) + (def (query-for original command) + (def edges + (filter-map (lambda (index) + (and (not (= command index)) + (list (list-ref names index) (list-ref names (modulo (1+ index) 4))))) + '(0 1 2 3))) + (gateway-derivation-request original + (map (lambda (row) (edge (car row) (cadr row))) edges) (list (list-ref names command)))) + ;; The generated commands select exactly four complete input cuts. Solve + ;; each independently once; all 32x8 retained updates still compare against + ;; the fresh oracle for their exact request digest and a separate traversal. + (def fresh-results + (map (lambda (command) + (def fresh-owner (make-gateway-derivation)) + (def fresh ((.get fresh-owner derive) (query-for (source) command))) + ((.get fresh-owner close)) fresh) '(0 1 2 3))) + (def report + (property.check-property + (generator.generator-sequence (make-list 8 (generator.generator-integer 0 3))) + (lambda (commands) + (def owner (make-gateway-derivation)) + (def original (source)) + (def result + (andmap + (lambda (command) + (def query (query-for original command)) + (def edges (map (lambda (item) (list (.get item dependent) (.get item dependency))) + (.get query dependencies))) + (def actual ((.get owner derive) query)) + (def fresh (list-ref fresh-results command)) + (and (equal? (.get actual request_digest) (.get fresh request_digest)) + (equal? (.get actual affected) (reachable edges (.get query changed))) + (equal? (.get actual affected_nodes) (.get fresh affected_nodes)) + (equal? (candidate-rows actual) (candidate-rows fresh)) + (eq? (.get actual execution_authorized) #f))) commands)) + ((.get owner close)) result) + (property.make-specification + (lambda (commands) (and (list? commands) (= (length commands) 8) + (andmap (lambda (n) (and (exact-integer? n) (<= 0 n 3))) commands))) + (lambda (commands) (apply + commands))) + seed: 293 cases: 32 size: 32 shrink-budget: 64)) + (check-property report) + (check-equal? (property.report-accepted report) 32)))) diff --git a/t/gateway-governor-retained-test.ss b/t/gateway-governor-retained-test.ss new file mode 100644 index 00000000..35525070 --- /dev/null +++ b/t/gateway-governor-retained-test.ss @@ -0,0 +1,62 @@ +;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +;;; +;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +(import :std/test + (only-in :clan/poo/object .o) + (only-in "../scheme/gateway/func.ss" governor-ready-steps make-retained-governor)) +(export gateway-governor-retained-test) + +(def graph-nodes '("infer" "gate" "next" "side" "fork-a" "fork-b" "inner-finish" "outer-skip" "finish")) +(def graph-edges + '(("finish" "inner-finish") ("finish" "outer-skip") ("fork-a" "side") ("fork-b" "side") + ("gate" "infer") ("inner-finish" "fork-a") ("inner-finish" "fork-b") + ("inner-finish" "next") ("next" "gate") ("outer-skip" "infer") ("side" "gate"))) +(def selectors '(("gate" "next" "side") ("infer" "gate" "outer-skip"))) +(def left-right '(("infer" "left") ("gate" "right"))) + +(def (cut released waiting observations selected (eligible graph-nodes)) + (.o nodes: graph-nodes edges: graph-edges complete: released + available: eligible pending: waiting nested_selectors: selectors + nested_results: observations nested_decisions: selected)) + +(def gateway-governor-retained-test + (test-suite "Retained Governor cut equivalence" + (test-case "nested selectors, parallel completion, withdrawal and ABA" + (def derive (make-retained-governor)) + (def outer-left (cut '("infer") '("gate" "outer-skip") '(("infer" "left")) '())) + (def unavailable + (cut '("infer") '("gate" "outer-skip") '(("infer" "left")) '() '("gate" "outer-skip"))) + (def trials + (list + (cons outer-left '("gate")) + (cons unavailable '()) + (cons outer-left '("gate")) + (cons outer-left '("gate")) + (cons (cut '("infer") '("gate" "outer-skip") '(("infer" "right")) '()) '("outer-skip")) + (cons (cut '("infer" "gate") '("side" "next") left-right '(("infer" "left"))) '("side")) + (cons (cut '("infer" "gate" "side") '("fork-a" "fork-b" "inner-finish") left-right left-right) + '("fork-a" "fork-b")) + (cons (cut '("infer" "gate" "side" "fork-a") '("fork-b" "inner-finish") left-right left-right) + '("fork-b")) + (cons (cut '("infer" "gate" "side" "fork-a" "fork-b") '("inner-finish" "finish") left-right left-right) + '("inner-finish")) + (cons (cut '("infer" "gate" "side" "fork-a" "fork-b" "inner-finish") '("finish") left-right left-right) + '("finish")))) + (for-each + (lambda (trial) + (def expected (cdr trial)) + (def fresh (list-sort string) targets) + (map (cut string-append "agentic-ai-lab/modules/" <>) + '("authorization/providers/cedar/objects" + "governance/config" + "governance/funs" + "governance/interface" + "governance/objects" + "governance/types" + "loop-engine/control/descriptor" + "loop-engine/control/governor" + "loop-engine/control/governor-core" + "loop-engine/control/governor-core-slot-rows" + "loop-engine/control/governor-policy" + "loop-engine/control/governor-policy-sets" + "loop-engine/control/strategy" + "session/objects-core"))) + (def identities (map string->symbol targets)) + (def (prerequisite-products) + (foldr append '() (map (lambda (directory) (artifact-files identities directory #f)) prerequisites))) + (def installed-before (digests (prerequisite-products))) + (displayln "WEAVER-MODULE-SPEC targets=" (length targets) " scopes=0") + (def sources + (append (list (path-expand "init.ss" root) (path-expand "init.ss" provider)) + (map (lambda (target) + (let* ((local? (string-prefix? "hardenedlinux/weaver/" target)) + (prefix (if local? "hardenedlinux/weaver/" "agentic-ai-lab/"))) + (path-expand (string-append (substring target (string-length prefix) (string-length target)) ".ss") + (if local? root provider)))) targets))) + (def source-before (map module-source-read sources)) + (execution-progress! 'weaver-specification 1) + (call-with-temporary-directory "weaver-selected-" + (lambda (temporary) + (def a (path-expand "a" temporary)) (def b (path-expand "b" temporary)) + (for-each (lambda (state) (create-directory* (path-expand "lib" state))) (list a b)) + (def completed 0) + (def (action state command) + (displayln "WEAVER-MODULE-ACTION environment=" (path-strip-directory state) " command=" command) + (force-output) + (def result + (run-script + (.cc (.get Ops prototypes Script) command: command directory: root + timeout: 120 idle-timeout: 60 progress: make-compiler-progress-reader + environment: (.o GERBIL_PATH: state GAMBOPT: runtime-options GERBIL_BUILD_VERBOSE: "1" + GERBIL_LOADPATH: (string-join (cons (path-expand "lib" state) prerequisites) ":"))) + '() output-port: (current-error-port))) + (set! completed (1+ completed)) (execution-progress! 'weaver-actions completed) + (def output (.get result output)) + (when (ormap (cut string-contains output <>) + '("*** ERROR" "ERROR CASE" "ERROR CHECK" "ERROR HARNESS" "Heap overflow" "Stack overflow")) + (error "Weaver action reported failure" command)) + output) + (def (cold-from-source-plan state) + ;; Use the guarded init plan already measured above for an empty + ;; native output. B's hot build and business use remain independent. + (def output + (call-with-output-string + (lambda (port) + (parameterize ((current-build-output-directory (path-expand "lib" state)) + (current-output-port port) + (current-directory root)) + (weaver-build-main "compile"))))) + (display output) + (force-output) + output) + (for-each + (lambda (state) + (action state (list "gerbil" "pkg" "link" "github.com/tao3k/agentic-ai-lab" provider)) + (def library (path-expand "lib" state)) + (check-equal? (interfaces library) '()) + (check-equal? (compile-events (if (equal? state a) + (action state '("gxi" "build.ss" "compile")) + (cold-from-source-plan state))) targets) + (check-equal? (interfaces library) targets)) (list a b)) + (def b-lib (path-expand "lib" b)) + (def b-products (digests (artifact-files identities b-lib))) + (def sentinel (path-expand "lib/unrelated.ssi" a)) + (call-with-output-file sentinel (lambda (port) (display "unrelated" port))) + (action a '("gxi" "build.ss" "clean")) + (check-equal? (interfaces (path-expand "lib" a)) '("unrelated")) + (check-equal? (digests (artifact-files identities b-lib)) b-products) + (check-equal? (compile-events (action b '("gxi" "build.ss" "compile"))) '()) + (def output (action b '("gxi" "t/qualification/module-selection/use.ss"))) + (check-equal? (and (string-contains output "WEAVER-MODULE-USE-OK") #t) #t) + (check-equal? (map module-source-read sources) source-before) + (check-equal? (digests (prerequisite-products)) installed-before) + (displayln "WEAVER-MODULE-SELECTION-OK targets=" (length targets) + " roots=Lab/Weaver selected=4 scopes-before-build=0 cold=A/B hot=0 clean-isolation=ok source=unchanged")))))) diff --git a/t/qualification/module-selection/use.ss b/t/qualification/module-selection/use.ss new file mode 100644 index 00000000..dcedb97f --- /dev/null +++ b/t/qualification/module-selection/use.ss @@ -0,0 +1,66 @@ +;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 +(import (only-in "../../../init.ss" hardenedlinux/weaver.init.exports) + (only-in :clan/poo/object .get .o .cc .slot?) + (only-in :std/source this-source-file) + (only-in :yuanxu/module-system/source/admission call-with-module-source-operation-measurement) + (only-in :std/misc/ports read-all-as-string) + (only-in :gerbil/runtime/loader list-modules) + (only-in :agentic-ai-lab/modules/governance/interface + agentic-ai-lab-governance-profile?)) +(export main) +(def (main) + (unless (and (procedure? agentic-ai-lab-governance-profile?) + (ormap (lambda (row) + (equal? (car row) "agentic-ai-lab/modules/governance/interface~0")) + (list-modules)) + (not (.slot? hardenedlinux/weaver.init.exports 'Lab))) + (error "Gerbil Governance import or Yuanxu export layout differs")) + (defvalues (lab first) + (call-with-module-source-operation-measurement + (lambda () (.get hardenedlinux/weaver.init.exports modules Lab governance)) accounting?: #f)) + (unless (and (= (hash-ref first '(calls candidate-read) 0) 4) + (= (hash-ref first '(calls scope-factory) 0) 1) + (= (hash-ref first '(calls (scope-factory agentic-ai-lab/modules/governance/interface)) 0) 1) + (= (hash-ref first '(calls (scope-factory hardenedlinux/weaver/scheme/governance/interface)) 0) 0)) + (error "first Lab scope demand constructed an unrelated or conflated owner")) + (defvalues (again repeat) + (call-with-module-source-operation-measurement + (lambda () (.get hardenedlinux/weaver.init.exports modules Lab governance)) accounting?: #f)) + (unless (and (eq? lab again) (zero? (hash-ref repeat '(calls candidate-read) 0)) + (zero? (hash-ref repeat '(calls scope-factory) 0))) + (error "repeated native scope demand did not reuse its POO slot")) + (displayln "WEAVER-MODULE-FIRST-GET declarations=4 scopes=1 repeat-scopes=0") + (def local (.get hardenedlinux/weaver.init.exports modules Weaver governance)) + (unless (and (not (eq? lab local)) + (eq? lab (.get hardenedlinux/weaver.init.exports modules Lab governance)) + (eq? local (.get hardenedlinux/weaver.init.exports modules Weaver governance))) + (error "native roots or repeated scope identities were conflated")) + (def profile (.cc (.get lab Profile) identity: "weaver/selected" revision: "1" owner: "operator")) + (unless (agentic-ai-lab-governance-profile? profile) (error "selected native public Profile rejected its scope value")) + (def context (.o request: 'publish source: "{\"original\":true}" policy_inputs: "[]" + profile_identity: "weaver/selected" profile_revision: "1" profile_owner: "operator" + model_identity: "agentic-ai-lab/governance/threat-model/empty")) + (unless ((.get local assess) profile context) (error "Weaver Governance business assessment failed")) + (def policy (.get hardenedlinux/weaver.init.exports modules Weaver policy)) + (def schema (call-with-input-file + (path-expand "../../../prod/policies/provider/schema.json" (path-directory (this-source-file))) + read-all-as-string)) + (unless ((.get policy validate) "forbid(principal,action,resource);" schema) + (error "selected Cedar FFI business validation failed")) + (def gateway (.get hardenedlinux/weaver.init.exports modules Weaver gateway)) + (unless (procedure? (.get gateway compile)) (error "Gateway business entry is absent")) + (def prefix (string-append (path-strip-trailing-directory-separator + (path-normalize (path-expand "lib" (gerbil-path)))) "/")) + (for-each + (lambda (id) + (unless (ormap (lambda (row) + (and (equal? (car row) id) (string-prefix? prefix (cdr row)))) + (list-modules)) + (error "business runtime did not load its own selected product" id))) + '("agentic-ai-lab/modules/governance/interface~0" + "agentic-ai-lab/modules/governance/types~0" + "agentic-ai-lab/modules/authorization/providers/cedar/objects~0" + "agentic-ai-lab/modules/loop-engine/control/governor-core~0" + "hardenedlinux/weaver/scheme/policy/cedar-ffi~0")) + (displayln "WEAVER-MODULE-USE-OK roots=Lab/Weaver same-leaf=distinct repeat=same governance=ready cedar=valid gateway=present products=own")) From 13df38e24f6b2fcad4c115008791ee90ffdeb2cc Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 00:05:28 +0800 Subject: [PATCH 047/105] Model advisory derivation and governed object lifecycle --- Project.sysml | 2 + dev/proofs/quint/GatewayProgram.qnt | 16 +- dev/sysml/ArchitectureEvolution.sysml | 356 ++++++++++++++++++++++ dev/sysml/ControllerObjectLifecycle.sysml | 239 +++++++++++++++ dev/sysml/PolicyEvidenceDesign.sysml | 4 +- dev/sysml/WeaverExecution.sysml | 10 + dev/sysml/runtime-trace.json | 6 + 7 files changed, 628 insertions(+), 5 deletions(-) create mode 100644 dev/sysml/ArchitectureEvolution.sysml create mode 100644 dev/sysml/ControllerObjectLifecycle.sysml diff --git a/Project.sysml b/Project.sysml index 0339a84c..1d502f0c 100644 --- a/Project.sysml +++ b/Project.sysml @@ -778,6 +778,8 @@ package WeaverProject { part 'dev/sysml/ProviderRpc.sysml' : File; part 'dev/sysml/ControlActivation.sysml' : File; part 'dev/sysml/PolicyEvidenceDesign.sysml' : File; + part 'dev/sysml/ControllerObjectLifecycle.sysml' : File; + part 'dev/sysml/ArchitectureEvolution.sysml' : File; part 'dev/sysml/runtime-trace.json' : File; part '.cache' : IgnoredDirectory; diff --git a/dev/proofs/quint/GatewayProgram.qnt b/dev/proofs/quint/GatewayProgram.qnt index aa420a23..bbaa1597 100644 --- a/dev/proofs/quint/GatewayProgram.qnt +++ b/dev/proofs/quint/GatewayProgram.qnt @@ -5,9 +5,9 @@ // Local Scheme program lifecycle. Rust authenticates the installed graph and // binds the original; neither a closure nor a local result is a send permit. module GatewayProgram { - type State={phase:int,selected:int,original:int,inFlight:int,busy:bool,slot:bool,joined:bool,deliveries:List[bool],hold:int,sends:int,graphMember:bool,rootMatches:bool,catalogBound:bool,runtimeActive:bool,caller:int,image:int,validated:bool} + type State={phase:int,selected:int,original:int,inFlight:int,busy:bool,slot:bool,joined:bool,deliveries:List[bool],hold:int,sends:int,graphMember:bool,rootMatches:bool,catalogBound:bool,runtimeActive:bool,caller:int,image:int,validated:bool,advice:int,adviceGeneration:int,adviceCurrent:bool} var p:State - pure val initial={phase:0,selected:0,original:0,inFlight:0,busy:false,slot:false,joined:false,deliveries:List(),hold:6,sends:0,graphMember:false,rootMatches:false,catalogBound:false,runtimeActive:false,caller:0,image:0,validated:false} + pure val initial={phase:0,selected:0,original:0,inFlight:0,busy:false,slot:false,joined:false,deliveries:List(),hold:6,sends:0,graphMember:false,rootMatches:false,catalogBound:false,runtimeActive:false,caller:0,image:0,validated:false,advice:0,adviceGeneration:0,adviceCurrent:false} action init=p'=initial def safe=(p.validated implies p.image==p.original) and (p.busy==p.slot) and (p.busy==(p.inFlight>0)) and (p.phase==1 implies (p.selected>0 and p.selected==p.original)) and @@ -37,7 +37,17 @@ module GatewayProgram { action freezeImage=all {p.phase==1,not(p.validated),p'=p.with("image",p.caller)} action validateImage=all {p.image>0,p.image==p.original,p'=p.with("validated",true)} action callerChange=p'=p.with("caller",2) - action step=any {freezeImage,validateImage,callerChange,observeGraphMember,matchRoot,bindCatalog,activateRuntime,install(1),install(2),rejectArgument,rejectInstall,installationFailure,begin,close,reenter,finish,failReturn,join} + // Advisory observations are deliberately independent of original binding. + // This finite abstraction models no ASCENT evaluator or completion deadline. + action deriveAdvice(id)=all {p.phase==1,id>0,p'=p.with("advice",id).with("adviceGeneration",p.adviceGeneration+1).with("adviceCurrent",true)} + action invalidateAdvice=p'=p.with("adviceCurrent",false).with("adviceGeneration",p.adviceGeneration+1) + action reuseAdvice=all {p.phase==1,p.adviceCurrent,p'=p} + action step=any {deriveAdvice(1),deriveAdvice(2),invalidateAdvice,reuseAdvice,freezeImage,validateImage,callerChange,observeGraphMember,matchRoot,bindCatalog,activateRuntime,install(1),install(2),rejectArgument,rejectInstall,installationFailure,begin,close,reenter,finish,failReturn,join} + run derivedAdviceCannotChangeImageOrSpendTest=init.then(install(1)).then(freezeImage).then(validateImage).then(deriveAdvice(2)).then(reuseAdvice).then(invalidateAdvice).expect(safe and p.image==1 and p.hold==6 and p.sends==0) + run invalidatedAdviceCannotBeReusedTest=init.then(install(1)).then(deriveAdvice(1)).then(invalidateAdvice).then(reuseAdvice.fail()) + run closedAdviceCannotBeReusedTest=init.then(install(1)).then(deriveAdvice(1)).then(close).then(reuseAdvice.fail()) + action unsafeAdviceAsImage=p'=p.with("image",p.advice) + run adviceAsOriginalCounterexampleTest=init.then(install(1)).then(freezeImage).then(validateImage).then(deriveAdvice(2)).then(unsafeAdviceAsImage).expect(not(safe)) run graphMembershipDoesNotInitializeProducerTest=init.then(observeGraphMember).then(activateRuntime.fail()) run readyWithoutCatalogCannotServeProducerTest=init.then(observeGraphMember).then(install(1)).then(activateRuntime.fail()) run initializedCatalogCanActivateWithoutSpendingTest=init.then(observeGraphMember).then(matchRoot).then(install(1)).then(bindCatalog).then(activateRuntime).expect(safe and p.hold==6 and p.sends==0) diff --git a/dev/sysml/ArchitectureEvolution.sysml b/dev/sysml/ArchitectureEvolution.sysml new file mode 100644 index 00000000..eece87b1 --- /dev/null +++ b/dev/sysml/ArchitectureEvolution.sysml @@ -0,0 +1,356 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +package ArchitectureEvolution { + private import ScalarValues::*; + private import Views::*; + private import StandardViewDefinitions::*; + doc /* Architecture learning and strengthening contracts. This development + model extends ControllerObjectLifecycle and the existing authority model. + Hypotheses, causal mechanisms, costs and falsifiers are first-class review + subjects. Capability availability does not establish integrated behavior + or a performance advantage. Target action allocations do not implement a + runtime, new policy language, second ledger or autonomous self-modification. */ + + enum def EvidenceDomain { enum semantics; enum schedules; enum nativeEffects; enum matchedWorkload; enum operations; } + enum def Finding { enum notExecuted; enum supportsWithinScope; enum counterexample; enum inconclusive; } + enum def Readiness { enum unknown; enum preparing; enum readyWithinScope; enum refused; enum retired; } + item def EvidenceAxis { + attribute domain : EvidenceDomain; + attribute finding : Finding = Finding::notExecuted; + attribute sourceIdentity : String; + attribute witness : String; + attribute scopeAndPremises : String; + doc /* Evidence is a vector over independent domains, not an overall + maturity score. A finite schedule, kernel theorem, native integration + and matched benchmark answer different questions. Preserve failures; + changed sources invalidate dependent acceptance claims. */ + } + item def PreparedObjectReadiness { + item image : PolicyEvidenceDesign::ArtifactImage; + item facts : PolicyEvidenceDesign::FactUseContext; + attribute ownerEpoch : String; + attribute dependencyCut : String; + attribute status : Readiness; + attribute preparationObservation : String; + doc /* Target local preparation evidence for the exact execution owner, + dependencies and image. Parse/capture completion, publication ACK and + open sockets do not establish readiness. Recheck after source/owner + change and at actual use. Readiness is neither durable publication nor + permission; do not wait for a remote dependency while holding a ledger + deciding lock. Existing bounded owner queues and tracked cleanup apply. */ + } + item def ReconciliationCut { + item original : PolicyEvidenceDesign::SemanticCommitment; + item desired : PolicyEvidenceDesign::ConfigurationCommitment; + item observed : PolicyEvidenceDesign::PublishedObservation[0..1]; + item readiness : PreparedObjectReadiness[0..1]; + item facts : PolicyEvidenceDesign::FactUseContext; + doc /* Desired, prepared, authority-committed and actually observed states + have separate coordinates. Lack of observation is unknown. Convergence + needs admitted source availability, bounded successful preparation and + eventual scheduling; an ongoing partition does not promise liveness. + Coalesce recomputation demand only. Original hard-fact intents, + transitions, claims and unknown holds cannot be dropped as superseded. */ + } + item def DecisionExplanation { + item original : PolicyEvidenceDesign::SemanticCommitment; + item derivation : PolicyEvidenceDesign::DerivedFactCandidate[0..1]; + item publication : PolicyEvidenceDesign::PublishedObservation[0..1]; + item effect : PolicyEvidenceDesign::EffectObservation[0..1]; + attribute reasonReferences : String[0..*]; + attribute missingEvidence : String[0..*]; + doc /* Target bounded, authorized data projection of existing receipts + and provenance. Distinguish policy denial, derivation unknown, warmup, + stale facts, capacity refusal and uncertain effects. Redact source + facts and payloads. Sampled telemetry is not a coherent ledger image; + an explanation grants no authority or accounting adjustment. */ + } + action def AssessObjectReadiness { + in item image : PolicyEvidenceDesign::ArtifactImage; + in item facts : PolicyEvidenceDesign::FactUseContext; + out item observation : PreparedObjectReadiness; + } + action def ReconcileObjectSet { + in item cut : ReconciliationCut; + in item candidate : PolicyEvidenceDesign::DerivedFactCandidate; + out item proposal : PolicyEvidenceDesign::SourceCommand[0..1]; + doc /* Scheme composes admitted object behavior and ASCENT candidates; + Go carries observations/publication. Rust decides current authority. + Preserve SourceExpectation equality and independently admitted origin; + semantic selection precedes freeze or uses a qualified SPEC derivation. */ + } + action def PrepareSessionWorkflow { + in item original : PolicyEvidenceDesign::SemanticCommitment; + out item workflow : PolicyEvidenceDesign::PreparedSessionWorkflow; + doc /* Scheme projects a bounded sequence of typed Funflow provider + tasks placed in an Agentic AI Lab Session. The single-provider + specialization captures the order before publication and seals + preparation at exact activation. Hard-fact projection keeps its + linked Scheme owner while the Session is active. */ + } + action def AdvanceGovernedRoutine { + in item original : PolicyEvidenceDesign::SemanticCommitment; + in item workflow : PolicyEvidenceDesign::PreparedSessionWorkflow[0..1]; + in item predecessor : PolicyEvidenceDesign::EffectObservation[1..64]; + in item selector : PolicyEvidenceDesign::ReleasedWorkflowResult[0..31]; + in item facts : PolicyEvidenceDesign::FactUseContext; + out item proposal : PolicyEvidenceDesign::SessionProgressionProposal; + doc /* Reuse AA Session, Yuanxu Funflow and Governor; Rust admission owns + frontier/claim/reservation/outcome atomicity. Configuration convergence + and business-step completion are separate loops sharing Scheme/POO. + For a fork/join, the live Scheme Governor derives ready nodes with + ASCENT from complete releases and current availability. Conditional + routes also match a structured selector result and a durable branch + decision defines the join's active predecessor. Unknown, + partial or wrong-domain observation cannot advance a step. */ + } + action def ExplainObjectDecision { + in item original : PolicyEvidenceDesign::SemanticCommitment; + out item explanation : DecisionExplanation; + } + + part def Improvement { + attribute phase : ControllerObjectLifecycle::Phase; + attribute integration : ControllerObjectLifecycle::Mechanism default = ControllerObjectLifecycle::Mechanism::missingIntegration; + attribute nativeAsset : String; + attribute learningWitness : String; + attribute reuseSeam : String; + attribute causalMechanism : String; + attribute cost : String; + attribute preservedBoundary : String; + attribute falsifier : String; + attribute qualificationOwner : String; + item evidence : EvidenceAxis[0..*]; + doc /* An improvement is a testable design decision. Empty evidence is + unqualified. Source inspection and prior focused runs must retain + their exact cohort and bounded scope; neither fills new runtime gates. */ + } + part def SemanticComposition :> Improvement { + attribute :>> phase = ControllerObjectLifecycle::Phase::preparation; + attribute :>> nativeAsset = "Scheme/POO Profile/Governance/Governor and cedar-poo-spec"; + attribute :>> learningWitness = "Praxis packaged policy composition: 10.13-praxis-envoy-and-ascent.org"; + attribute :>> reuseSeam = "scheme/gateway/func.ss;scheme/policy/func.ss;upstream PolicyModules export/provenance"; + attribute :>> causalMechanism = "One object composition supplies planning, obligations and checked projections across multiple entry paths"; + attribute :>> cost = "Callback determinism, admitted capture closure, unsupported values and compatibility qualification"; + attribute :>> preservedBoundary = "No second Go semantic selector; no whole-object flattening; original binding remains exact"; + attribute :>> falsifier = "Two entry paths disagree on the same admitted object; inherited provenance lost; independent original changes"; + attribute :>> qualificationOwner = "WeaverProject::AssuranceResponsibilities::semantics;WeaverProject::AssuranceResponsibilities::implementation"; + } + part def ConfigurableProgramming :> Improvement { + attribute :>> phase = ControllerObjectLifecycle::Phase::preparation; + attribute :>> nativeAsset = "Scheme/POO profiles and contracts, native Build Packages, typed Gateway source capture and catalog startup"; + attribute :>> learningWitness = "Agent Gateway explicit configuration selection; Praxis shared validation and candidate preparation"; + attribute :>> reuseSeam = "SemanticComposition;AssessObjectReadiness;PrepareSessionWorkflow;PolicyEvidenceDesign::SourceCommand"; + attribute :>> causalMechanism = "Map declarative operator inputs and admitted Scheme profiles to the same typed configuration contract and existing preparation path"; + attribute :>> cost = "Profile compatibility, validation diagnostics, exact provenance and bounded preparation"; + attribute :>> preservedBoundary = "TOML selects an admitted profile and supplies typed inputs; trusted Scheme composes resources and workflows; Cedar, SPEC and the ledger retain effect authority"; + attribute :>> falsifier = "Equivalent inputs disagree on the executable projection or effect behavior; invalid or stale candidates activate; ordinary requests repeat source preparation"; + attribute :>> qualificationOwner = "WeaverProject::AssuranceResponsibilities::semantics;WeaverProject::AssuranceResponsibilities::implementation"; + doc /* Proposed authoring contract. Record input and profile revisions + separately from the prepared projection. Allow a deployment launcher + to set paths and credentials independently of semantic inputs. Use + the same owner, validation and activation path across authoring modes. + Scheme Governor may still derive runtime proposals from current facts. */ + } + part def IncrementalRelations :> Improvement { + attribute :>> integration = ControllerObjectLifecycle::Mechanism::partialIntegration; + attribute :>> phase = ControllerObjectLifecycle::Phase::reuse; + attribute :>> nativeAsset = "Inherited ASCENT retained sessions and AA source/query lifecycle"; + attribute :>> learningWitness = "Envoy delta subscription: https://www.envoyproxy.io/docs/envoy/latest/api-docs/xds_protocol"; + attribute :>> reuseSeam = "scheme/gateway/derivation.ss fixed advisory session;ControllerObjectLifecycle::MaintainObjectRelations;public program/interface and query-provider APIs"; + attribute :>> causalMechanism = "Affected dependency closure bounds recomputation; unrelated object preparation remains reusable"; + attribute :>> cost = "Retained memory, source ordering, deletion and opaque callback fallback; dense changes may favor fresh evaluation"; + attribute :>> preservedBoundary = "Full FactProjectionClosure and immutable nested values; no decision cache"; + attribute :>> falsifier = "Retained and fresh results differ or retained cost exceeds fresh on the declared workload"; + attribute :>> qualificationOwner = "WeaverProject::AssuranceResponsibilities::implementation"; + } + part def DependencyReadiness :> Improvement { + attribute :>> phase = ControllerObjectLifecycle::Phase::replacement; + attribute :>> nativeAsset = "Owned capture, fixed Gerbil owner, source CAS and pending publication"; + attribute :>> learningWitness = "Envoy initialization/warming: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/operations/init"; + attribute :>> reuseSeam = "AssessObjectReadiness;ControllerObjectLifecycle::PrepareObjectReplacement;crates/governance/src/host"; + attribute :>> causalMechanism = "Prepare the exact successor dependency cut before activation; track old-owner retirement separately"; + attribute :>> cost = "Temporary duplicate resources, warmup latency, old calls and bounded drain under failure"; + attribute :>> preservedBoundary = "Last prepared image must still pass current authority; revoked facts cannot be served as last-good permission"; + attribute :>> falsifier = "Ready object has an unprepared dependency, stale owner epoch, or execution after revoke"; + attribute :>> qualificationOwner = "WeaverProject::AssuranceResponsibilities::schedules;WeaverProject::AssuranceResponsibilities::implementation"; + } + part def ObservationDrivenLoops :> Improvement { + attribute :>> integration = ControllerObjectLifecycle::Mechanism::partialIntegration; + attribute :>> phase = ControllerObjectLifecycle::Phase::publication; + attribute :>> nativeAsset = "AA Session, Yuanxu Funflow and Governor plus existing PublishedObservation and EffectObservation"; + attribute :>> learningWitness = "Kubernetes controller pattern: https://kubernetes.io/docs/concepts/architecture/controller/"; + attribute :>> reuseSeam = "ReconcileObjectSet;PrepareSessionWorkflow;AdvanceGovernedRoutine;PolicyEvidenceDesign::SessionProgressionProposal"; + attribute :>> causalMechanism = "Explicit desired/observed discrepancy drives reconciliation; authentic effect observations enable admitted successors"; + attribute :>> cost = "Oscillation, stale observations, fairness and deduplication across two loops"; + attribute :>> preservedBoundary = "Config readiness and business completion remain distinct; local checkpoints never settle or advance authority"; + attribute :>> falsifier = "Lost/duplicated observation creates a second successor, a new original, or clears an unknown hold"; + attribute :>> qualificationOwner = "WeaverProject::AssuranceResponsibilities::schedules;WeaverProject::AssuranceResponsibilities::implementation"; + } + part def DurableInvalidation :> Improvement { + attribute :>> phase = ControllerObjectLifecycle::Phase::invalidation; + attribute :>> nativeAsset = "Rust original authority, pending barrier and mediated actual effects"; + attribute :>> learningWitness = "Prior shared-quota/promotion and bound-mutation experiments: praxis-comparison-20261105/receipt.json"; + attribute :>> reuseSeam = "PolicyEvidenceDesign::HardFactIntent;FactBarrierResolution;existing source lane and ledger transaction"; + attribute :>> causalMechanism = "Preserve authenticated invalidation before recomputation and resolve exact intent prefixes at authority"; + attribute :>> cost = "Unavailable sources may block affected new effects; recoverable projections and storage failover need separate qualification"; + attribute :>> preservedBoundary = "Coalescing cannot erase hard intents; no replay of ambiguous effects; local persistence is not replicated failover"; + attribute :>> falsifier = "Failed subscriber or restart clears pending facts, or recovery permits duplicate consumption"; + attribute :>> qualificationOwner = "WeaverProject::AssuranceResponsibilities::schedules;WeaverProject::AssuranceResponsibilities::implementation"; + } + part def BoundedOperations :> Improvement { + attribute :>> phase = ControllerObjectLifecycle::Phase::preparation; + attribute :>> nativeAsset = "Existing bounded SourceClient lane, provider windows and persistence scheduling"; + attribute :>> learningWitness = "Envoy overload manager: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/operations/overload_manager"; + attribute :>> reuseSeam = "crates/governance/src/host/client.rs;existing execution owners and telemetry"; + attribute :>> causalMechanism = "Owner-specific pressure observations bound accepted work and retained state before exhaustion"; + attribute :>> cost = "Refusal/fairness tradeoffs, stale pressure and cleanup latency; pressure policy is not budget authorization"; + attribute :>> preservedBoundary = "Keep all current limits; no unbounded warmup or background tasks; telemetry cannot grant effects"; + attribute :>> falsifier = "Capacity refusal leaks retained state or starves pending resolution/drain indefinitely under the admitted workload"; + attribute :>> qualificationOwner = "WeaverProject::AssuranceResponsibilities::implementation"; + } + part def GovernorExecutionPerformance :> Improvement { + attribute :>> phase = ControllerObjectLifecycle::Phase::reuse; + attribute :>> nativeAsset = "Fixed Scheme owner, bounded SourceClient, ASCENT Session and durable provider frontier"; + attribute :>> learningWitness = "SDK Mailbox separates native entry from repeated work in one VM"; + attribute :>> reuseSeam = "AdvanceGovernedRoutine;IncrementalRelations;BoundedOperations;Governor release preregistration in 59.64-governance-capture-ownership.org"; + attribute :>> causalMechanism = "Relational reuse targets computation; persistent batches target foreign entry; isolation targets queue delay caused by source preparation"; + attribute :>> cost = "Retained relations, queue residence, invalidation, independent image lifecycle and drain"; + attribute :>> preservedBoundary = "Complete release precedes proposal; exact facts and current frontier govern claim and reservation; coalesce only wakeups"; + attribute :>> falsifier = "Matched workload has no reproducible improvement from durable release to committed reservation, or admission and owner-drain controls regress"; + attribute :>> qualificationOwner = "WeaverProject::AssuranceResponsibilities::implementation"; + doc /* The matched release workload retains the 12-second recovery + window and the 15-second natural exit fence. A readiness timeout + before the workload is a failed trial. Resolve any claimed + interference against owner-entry and committed-frontier traces. + In the sealed single-provider DAG, activation follows preparation. + A later authenticated replay returns the prepared reply. Require + observed new preparation on the active owner or repeatable queue + or FFI pressure before qualifying an Actor or multi-VM candidate. */ + doc /* Formal release samples fix the image, catalog, policy, offered + workload, response gates, arrival schedule and total time budget + before sampling. Match the actual Governor cut and ready-node result + across arms. Separate the first ASCENT open, warm decisions and + natural exits. Preserve owner and observation-window dependence + when defining independent matched blocks. Justify their count and + the within-owner sample count for the required effect and tail + interval. Estimate the natural-stop tail from independent exits. + Freeze the p99 estimator, 95 percent interval method and any + resampling parameters before collecting formal samples. */ + doc /* The local nine-node Session contributes one inner-join and + one outer-join endpoint per owner. Intermediate Governor decisions + measure derivation and can inform its stage costs. Obtain additional + endpoint opportunities from the frozen admitted workload and its + actual owner windows. Keep a separate record of exit opportunities. */ + doc /* A/A requires the 95 percent p99 ratio interval within + [0.90, 1.10]. Retained adoption requires an upper p99 ratio bound + at most 0.90, a median ratio at most 0.90, and an upper natural-stop + p99 ratio bound at most 1.10. Require identical admitted work, the + original capacity controls and no failed or missing trials. + Preserve censored trials at their deadlines. Keep wiring diagnostics + and prelaunch host-admission refusals in their own records. */ + doc /* The deployed image receipt binds the build manifest, the + admitted application source and SDK revision, the approved site + catalog and source authority, and the deployment activation. + Include effective runtime dependency bytes when the native + program resolves a carrier outside the linked image. Record the + loader-selected origin and verify the frozen cut before and after + sampling. A fixture catalog qualifies only its own authority and + offered workload. */ + doc /* The Governor release preregistration in 59.64-governance-capture-ownership.org + requires separate site approval and approved workload records. Freeze + the site manifest, native execution selector and numeric sample plan + before launch. A/A compares fresh with fresh. Only a passing A/A + admits the separately frozen retained A/B on the same release. The + derivation mode is the sole A/B treatment change. */ + } + part def ExplainableDelivery :> Improvement { + attribute :>> integration = ControllerObjectLifecycle::Mechanism::partialIntegration; + attribute :>> phase = ControllerObjectLifecycle::Phase::publication; + attribute :>> nativeAsset = "ASCENT provenance, Cedar reasons, publication/effect receipts and fixed-cardinality telemetry"; + attribute :>> learningWitness = "Praxis deployable policy hooks and inspected Envoy ACK/NACK protocol"; + attribute :>> reuseSeam = "GatewayPreparation exposes bounded declared-candidate and impact reasons;ExplainObjectDecision receipt join and authenticated inspection remain target work"; + attribute :>> causalMechanism = "One original-bound explanation joins why selected, why blocked, source cut and concrete observed outcome"; + attribute :>> cost = "Sensitive provenance, incomplete observations, bounded storage and cohort compatibility"; + attribute :>> preservedBoundary = "Authorized redaction; metrics remain nonauthoritative; no new exporter or listener by default"; + attribute :>> falsifier = "Explanation mislabels unknown as denied/complete or leaks source facts to an unauthorized reader"; + attribute :>> qualificationOwner = "WeaverProject::AssuranceResponsibilities::implementation"; + } + part improvements { + part composition : SemanticComposition; + part configuration : ConfigurableProgramming; + part incrementality : IncrementalRelations; + part readiness : DependencyReadiness; + part loops : ObservationDrivenLoops; + part invalidation : DurableInvalidation; + part operations : BoundedOperations; + part explanation : ExplainableDelivery; + } + + port def CapabilityDependency { out item cut : ReconciliationCut; } + part def Capability { + attribute displayName : String; + attribute responsibility : String; + attribute glyph : String = "model"; + attribute visualRole : String = "semantic"; + port incoming : ~CapabilityDependency; + port outgoing : CapabilityDependency; + } + part def Compose :> Capability { + attribute :>> displayName = "Compose"; + attribute :>> responsibility = "POO + Scheme\nASCENT relations"; + } + part def Prepare :> Capability { + attribute :>> displayName = "Prepare"; + attribute :>> responsibility = "Dependency cut\nBounded owners"; + } + part def Enforce :> Capability { + attribute :>> displayName = "Enforce"; + attribute :>> responsibility = "Cedar + SPEC\nRust final effects"; + } + part def Observe :> Capability { + attribute :>> displayName = "Observe"; + attribute :>> responsibility = "Authentic outcomes\nScoped explanation"; + } + part reinforcement { + part compose : Compose; + part prepare : Prepare; + part enforce : Enforce; + part observe : Observe; + connection derive connect compose.outgoing to prepare.incoming; + connection propose connect prepare.outgoing to enforce.incoming; + connection report connect enforce.outgoing to observe.incoming; + connection reconcile connect observe.outgoing to compose.incoming; + doc /* Capability dependencies and feedback, not new runtime components + or four independent owners. Actions are allocated in WeaverExecution. + Each reuse/adoption hypothesis has its own cost and falsification gate. */ + } + view reinforcingCapabilities { + attribute mappedFile : String = "docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.d2"; + attribute displayTitle : String = "Make architecture capabilities reinforce each other"; + attribute displaySubtitle : String = "Retain semantic richness; qualify preparation, authority and observed outcomes separately."; + attribute displayEyebrow : String = "WEAVER / ARCHITECTURE EVOLUTION"; + attribute readerQuestion : String = "How do our existing strengths compound?"; + attribute designAudience : String = "Architecture and execution contributors"; + attribute designMedium : String = "GitHub at 830 CSS pixels"; + attribute designMessage : String = "Compose, prepare, enforce and observe through existing owners."; + attribute designFocus : String = "compose,enforce"; + attribute visualBands : String = "[[\"compose\"],[\"prepare\"],[\"enforce\"],[\"observe\"]]"; + attribute visualThemes : String = "sketchbook,field-notes,comfortable,reading"; + attribute visualOptions : String = "{\"elk.algorithm\":\"layered\",\"elk.direction\":\"DOWN\",\"elk.edgeRouting\":\"ORTHOGONAL\",\"elk.spacing.nodeNode\":\"16\",\"elk.layered.spacing.nodeNodeBetweenLayers\":\"27\"}"; + attribute visualWidth : Integer = 980; + requirement original : WeaverExecution::OriginalTaskBinding; + requirement currentUse : WeaverExecution::CurrentFinalGuard; + requirement observation : WeaverExecution::TelemetryNoninterference; + expose reinforcement::compose; + expose reinforcement::prepare; + expose reinforcement::enforce; + expose reinforcement::observe; + expose reinforcement::derive; + expose reinforcement::propose; + expose reinforcement::report; + expose reinforcement::reconcile; + render asInterconnectionDiagram; + } +} diff --git a/dev/sysml/ControllerObjectLifecycle.sysml b/dev/sysml/ControllerObjectLifecycle.sysml new file mode 100644 index 00000000..1f61d73c --- /dev/null +++ b/dev/sysml/ControllerObjectLifecycle.sysml @@ -0,0 +1,239 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +package ControllerObjectLifecycle { + private import ScalarValues::*; + private import Views::*; + private import StandardViewDefinitions::*; + doc /* Lifecycle design and implementation assessment of existing owners. + Scheme/POO owns control and high-order execution composition. These action + contracts allocate missing joins; they are not implemented RPCs, another + object runtime, source ledger or authorization state machine. Existing + PolicyEvidenceDesign items and WeaverExecution owners remain authoritative. + Assessment nodes are review subjects, not new runtime services. */ + + enum def Phase { enum preparation; enum publication; enum replacement; enum reuse; enum invalidation; } + enum def Mechanism { enum localImplemented; enum authorityImplemented; enum inheritedAvailable; enum partialIntegration; enum missingIntegration; } + + requirement def BoundedAdvisoryDerivation { + doc /* The default Scheme compile path runs the inherited ASCENT fixed + advisory kernel and preserves the exact GatewayArtifact. Preparation + exposes separate complete declared-candidate/impact explanations. + Integer-only detached projections, 4096 input / 8192 derived / 12288 + output fact limits and existing capture bounds apply. This is a fact + bound, not a wall-clock deadline or a proof of general eligibility. + Retained public sessions replace all projected sources together; + full request/result equality and local generation fence reuse/ABA. + Invalidate/close never clear authority pending facts or unknown holds. + Owner-local advisory output cannot authorize, mutate plans, refund + reservations or create a new independently admitted original. + Qualification separates cold preparation, prepared-owner derivation + and end-to-end semantic recovery. A hot-path contrast must not charge + repeated cold setup to every observation. Retained and fresh modes + use the same prepared release workload and exact source boundaries. + Record the first session open separately from subsequent replacements + on the same topology. A startup mode label does not establish reuse. + Decisions observed in one owner belong to one replication unit. + Match each measured join by the actual detached Governor input and + ready-node result. Report inner and outer join endpoints separately + within the same owner block. The diagnostic digests do not replace + the source version, release receipts or transactional admission checks. + Replication and tail confidence require an explicit sample-size + justification before a new statistical campaign. Freeze offered + load, backpressure and the total budget. Preserve owner clustering + and retain every refusal and timeout. Preserve four + workers, all failures and the existing 12-second recovery / 15-second + natural-exit budgets. Local qualification is not site approval. */ + } + + action def PrepareObject { + in item original : PolicyEvidenceDesign::SemanticCommitment; + out item prepared : PolicyEvidenceDesign::ConfigurationCommitment; + doc /* Reuse POO contracts, admitted Yuanxu scopes, owned capture and + approved Scheme owner preparation. Preserve the independently admitted + original. Native object behavior stays in its Scheme owner; materialize + only the existing checked execution/source projection. + A single registered provider can explicitly select startup retirement. + Preparation seals the original-bound artifact and source epoch. The + exact committed publication, observed by finalization or inspection, + triggers closure of that compiler lane. Retirement acknowledges the + native return and VM cleanup while the operation service stays open. + An authenticated replay observes the same prepared artifact and must + pass current authority checks before use. + A cold owner may reuse compiled roles after the Yuanxu Reader admits + their selected owners, source versions and actual transitive inputs + against the current Module View. The native link manifest identifies + code in the image. Role initialization support, including observed + configuration assets, must be checked by the Reader before use. + Keep the runtime tool catalog separate from the complete compiler + bootstrap specification. Preparing a source must not eagerly load + tooling used only for a build. An explicit build must still admit + its entire native Context and source closure. */ + } + action def MaintainObjectRelations { + in item prepared : PolicyEvidenceDesign::ConfigurationCommitment; + out item candidate : PolicyEvidenceDesign::DerivedFactCandidate; + doc /* Target adapter uses inherited AA/ASCENT retained sessions and + source/query currentness. Complete within the declared scope or return + unknown. No output is a permit, settlement or authenticated fact. */ + } + action def PrepareObjectReplacement { + in item original : PolicyEvidenceDesign::SemanticCommitment; + in item predecessor : PolicyEvidenceDesign::PublishedObservation; + out item successor : PolicyEvidenceDesign::SourceCommand; + doc /* Prepare a new owned source cut without mutating the active image. + Existing source admission, predecessor CAS and outcome recovery decide + activation. GatewayProgram cannot be reinstalled in place. Retire the + old Scheme call/session through its actual owner after pending work is + accounted for; close alone is not natural native completion. */ + } + action def ReuseObjectProjection { + in item retained : PolicyEvidenceDesign::ArtifactImage; + in item current : PolicyEvidenceDesign::FactUseContext; + out item projection : PolicyEvidenceDesign::ArtifactImage; + doc /* Reuse immutable preparation, query results and unchanged relations + under their exact source/rule/query/limit closure. Actual use retains + current Cedar, original claim, budget/history and custody checks. + SourceExpectation equality is not weakened to admit a changed result. */ + } + action def InvalidateObjectProjection { + in item changed : PolicyEvidenceDesign::FactProjectionClosure; + out item candidate : PolicyEvidenceDesign::DerivedFactCandidate; + doc /* Reuse admitted module currentness and inherited AA change feeds + for local invalidation. Permission-relevant changes enter the existing + target hard-fact intent/barrier protocol before fresh use. A missing + callback or failed rebuild cannot clear that pending authority state. + Identical rows after an A-B-A update do not restore an old floor. */ + } + + port def ReviewDependencyPort { + out item contract : PolicyEvidenceDesign::ConfigurationCommitment; + doc /* Typed lifecycle dependency in this review view, not a new wire + protocol or evidence that a runtime transition has been implemented. */ + } + part def Assessment { + attribute phase : Phase; + attribute runtimeMechanism : Mechanism; + attribute upstreamMechanism : Mechanism = Mechanism::inheritedAvailable; + attribute ascentGatewayJoin : Mechanism default = Mechanism::missingIntegration; + attribute sourceOwner : String; + attribute currentSource : String; + attribute inheritedSource : String; + attribute missingJoin : String; + attribute acceptance : String; + attribute displayName : String; + attribute responsibility : String; + attribute glyph : String = "document"; + attribute visualRole : String = "semantic"; + port incoming : ~ReviewDependencyPort; + port outgoing : ReviewDependencyPort; + } + part def Preparation :> Assessment { + attribute :>> ascentGatewayJoin = Mechanism::partialIntegration; + attribute :>> phase = Phase::preparation; + attribute :>> runtimeMechanism = Mechanism::localImplemented; + attribute :>> sourceOwner = "WeaverExecution::SchemeSemanticPublisher"; + attribute :>> displayName = "Prepare"; + attribute :>> responsibility = "Exists: advisory derive\nMissing: object warmup"; + attribute :>> currentSource = "scheme/gateway/program.ss;scheme/gateway/capture.ss;crates/governance/src/program/compiler.rs"; + attribute :>> inheritedSource = "agentic-ai-lab/modules/loop-engine/interface.ss;gerbil-ascent/program/interface.ss"; + attribute :>> missingJoin = "Fixed bounded advisory kernel is connected to default compile and prepare; generic object readiness and dynamic semantic lowering remain separate gates; cold compiled-role reuse needs Reader admission of source and initialization support"; + attribute :>> acceptance = "Typed refusal; one emission; close/reentry fences; exact original; failed derivation leaves prior accepted source; compiled role reuse preserves current selection, transitive source and asset checks"; + } + part def Publication :> Assessment { + attribute :>> phase = Phase::publication; + attribute :>> runtimeMechanism = Mechanism::authorityImplemented; + attribute :>> sourceOwner = "WeaverExecution::GoControlAdapter;WeaverExecution::RustLedger"; + attribute :>> displayName = "Publish"; + attribute :>> responsibility = "Exists: durable CAS\nMissing: fact projection"; + attribute :>> currentSource = "go/internal/controlplane/gateway.go;crates/ledger/src/publication.rs;crates/ledger/src/task_origins.rs"; + attribute :>> inheritedSource = "agentic-ai-lab/modules/temporal-causality/runtime/change-feed.ss;cedar-poo-spec PolicyModules/export/replay"; + attribute :>> missingJoin = "Bind derived closure/completion and recoverable projection to the existing SourceCommand authority path; keep policy composition provenance"; + attribute :>> acceptance = "Lost acknowledgment resolves the same original; unknown never activates; local feed completion is not durable publication"; + } + part def Replacement :> Assessment { + attribute :>> phase = Phase::replacement; + attribute :>> runtimeMechanism = Mechanism::authorityImplemented; + attribute :>> sourceOwner = "WeaverExecution::SchemeSemanticPublisher;WeaverExecution::RustLedger"; + attribute :>> displayName = "Replace"; + attribute :>> responsibility = "Exists: source fencing\nMissing: owner handover"; + attribute :>> currentSource = "scheme/gateway/program.ss;crates/ledger/src/publication_review.rs;crates/governance/src/host/owner.rs"; + attribute :>> inheritedSource = "gerbil-ascent/program/session.ss;agentic-ai-lab/modules/temporal-causality/runtime/change-feed.ss"; + attribute :>> missingJoin = "Prepare a successor in its owner; join accepted session source with authoritative publication and retirement; never reinstall an active GatewayProgram"; + attribute :>> acceptance = "Stale predecessor; failed replacement; A-B-A source; close during callback; pending derivation and native owner retirement"; + } + part def Reuse :> Assessment { + attribute :>> ascentGatewayJoin = Mechanism::partialIntegration; + attribute :>> phase = Phase::reuse; + attribute :>> runtimeMechanism = Mechanism::localImplemented; + attribute :>> sourceOwner = "WeaverExecution::SchemeSemanticPublisher;WeaverExecution::DerivedEvidenceAdapter"; + attribute :>> displayName = "Reuse"; + attribute :>> responsibility = "Exists: retained advice\nMissing: fact authority"; + attribute :>> currentSource = "scheme/gateway/derivation.ss;crates/policy/src/compiled.rs;crates/policy/src/provider.rs;crates/ledger/src/provider_profiles.rs"; + attribute :>> inheritedSource = "gerbil-ascent/program/session.ss;gerbil-ascent/program/update-selection.ss;agentic-ai-lab/modules/ai-agentic-context/query-provider.ss"; + attribute :>> missingJoin = "Owner-scoped fixed advisory session uses full request and immutable integer projections; generic callback closures and hard-fact projection authority remain missing"; + attribute :>> acceptance = "Fresh-vs-retained equality; deletion; rule/limit changes; opaque callbacks; old snapshots unchanged; current effect guard still required"; + } + part def Invalidation :> Assessment { + attribute :>> ascentGatewayJoin = Mechanism::partialIntegration; + attribute :>> phase = Phase::invalidation; + attribute :>> runtimeMechanism = Mechanism::authorityImplemented; + attribute :>> sourceOwner = "WeaverExecution::SchemeSemanticPublisher;WeaverExecution::RustLedger;WeaverExecution::RustFinalBroker"; + attribute :>> displayName = "Invalidate"; + attribute :>> responsibility = "Exists: current guard\nMissing: impact loop"; + attribute :>> currentSource = "scheme/gateway/derivation.ss;scheme/gateway/func.ss;crates/ledger/src/provider.rs;crates/broker/src/provider/range_output.rs"; + attribute :>> inheritedSource = "agentic-ai-lab/modules/ai-agentic-context/query-provider.ss;agentic-ai-lab/modules/temporal-causality/runtime/change-feed.ss"; + attribute :>> missingJoin = "Bridge authenticated source changes to affected object/query closure and high-order task continuation; hard facts retain durable pending barriers"; + attribute :>> acceptance = "Withdrawn source; failed subscriber; incomplete fixed point; source disconnect; revoked unsent tail; unchanged original claim and hold"; + } + + part assessment { + attribute displayName : String = "Existing owners / lifecycle review"; + attribute glyph : String = "model"; + part prepare : Preparation; + part publish : Publication; + part replace : Replacement; + part reuse : Reuse; + part invalidate : Invalidation; + connection prepared connect prepare.outgoing to publish.incoming; + connection current connect publish.outgoing to reuse.incoming; + connection predecessor connect publish.outgoing to replace.incoming; + connection successor connect replace.outgoing to publish.incoming; + connection rebuild connect invalidate.outgoing to prepare.incoming; + connection recheck connect invalidate.outgoing to reuse.incoming; + doc /* Dependencies may branch or recur. This is not a linear five-step + request pipeline; replacement prepares a successor and invalidation + can supersede preparation or retained reuse. */ + } + + view lifecycle { + attribute mappedFile : String = "docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.d2"; + attribute displayTitle : String = "Object lifecycle: existing mechanisms and missing joins"; + attribute displaySubtitle : String = "Scheme/POO controls semantics and high-order execution. ASCENT reuses the inherited derivation path."; + attribute displayEyebrow : String = "WEAVER / CONTROLLER OBJECTS"; + attribute readerQuestion : String = "Where does inherited ASCENT join the existing lifecycle?"; + attribute designAudience : String = "Controller and execution contributors"; + attribute designMedium : String = "Linked English Org and source-derived SVG"; + attribute designMessage : String = "Keep existing owners; complete the lifecycle joins."; + attribute designFocus : String = "prepare,invalidate"; + attribute visualThemes : String = "sketchbook,field-notes,comfortable,reading"; + attribute visualOptions : String = "{\"elk.algorithm\":\"layered\",\"elk.direction\":\"DOWN\",\"elk.edgeRouting\":\"ORTHOGONAL\",\"elk.spacing.nodeNode\":\"16\",\"elk.layered.spacing.nodeNodeBetweenLayers\":\"27\"}"; + attribute visualWidth : Integer = 1120; + requirement sourceContract : ControlActivation::SpecificSourceContracts; + requirement publicationContract : ControlActivation::ControlActivationAcknowledgment; + requirement finalUseContract : WeaverExecution::CurrentFinalGuard; + requirement advisoryContract : BoundedAdvisoryDerivation; + expose assessment::prepare; + expose assessment::publish; + expose assessment::replace; + expose assessment::reuse; + expose assessment::invalidate; + expose assessment::prepared; + expose assessment::current; + expose assessment::predecessor; + expose assessment::successor; + expose assessment::rebuild; + expose assessment::recheck; + render asInterconnectionDiagram; + } +} diff --git a/dev/sysml/PolicyEvidenceDesign.sysml b/dev/sysml/PolicyEvidenceDesign.sysml index 07fa17a5..f09e00ae 100644 --- a/dev/sysml/PolicyEvidenceDesign.sysml +++ b/dev/sysml/PolicyEvidenceDesign.sysml @@ -745,8 +745,8 @@ package PolicyEvidenceDesign { in existing admission; no local-advance then separate claim gap. Use existing claims/outcomes, not a second Session ledger. The single-provider implementation specializes the linear Session - Workflow during Scheme preparation. After activation and retirement, - Rust instantiates the fixed complete-response predicate for each + Workflow during Scheme preparation. After exact activation, Rust + instantiates the fixed complete-response predicate for each adjacent edge with the actual release observation, predecessor winner when applicable, current fact cut and original domain stamp. The provider transaction compares the winner frontier and commits the diff --git a/dev/sysml/WeaverExecution.sysml b/dev/sysml/WeaverExecution.sysml index 11170fb0..819df4e2 100644 --- a/dev/sysml/WeaverExecution.sysml +++ b/dev/sysml/WeaverExecution.sysml @@ -746,6 +746,15 @@ package WeaverExecution { This action grants no publication, consumption or transport right. */ } action deriveCandidate : DeriveSemanticCandidate; + action prepareObject : ControllerObjectLifecycle::PrepareObject; + action replaceObject : ControllerObjectLifecycle::PrepareObjectReplacement; + action reuseObject : ControllerObjectLifecycle::ReuseObjectProjection; + action invalidateObject : ControllerObjectLifecycle::InvalidateObjectProjection; + action assessObjectReadiness : ArchitectureEvolution::AssessObjectReadiness; + action reconcileObjects : ArchitectureEvolution::ReconcileObjectSet; + action prepareSessionWorkflow : ArchitectureEvolution::PrepareSessionWorkflow; + action advanceRoutine : ArchitectureEvolution::AdvanceGovernedRoutine; + action explainObjectDecision : ArchitectureEvolution::ExplainObjectDecision; doc /* Normative semantic allocation: reuse Agentic AI Lab Governor to select admitted original scope and Governance to assess obligations, evidence and source assets. Scheme defines routine meaning, original @@ -1186,6 +1195,7 @@ package WeaverExecution { and local-counter reset. No external exporter is currently enabled. */ } part def DerivedEvidenceAdapter { + action maintainObjectRelations : ControllerObjectLifecycle::MaintainObjectRelations; attribute overviewName : String = "Evidence"; attribute overviewSummary : String = "Bound observations"; attribute displayName : String = "Derived evidence"; diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index 80bb9452..96797d80 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -568,6 +568,12 @@ {"file":"go/dev/provider_bench_test.go","pattern":"func BenchmarkGatewayInspect"}]}, {"id":"DurableRangeProgressJoin","witnesses":[{"file":"crates/ledger/src/stream_progress.rs","pattern":"fn message"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_message_cursor_cannot_hide_consumed_range"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_progress_cannot_release_old_writer_or_connection"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run restoredUnknownProjectionBlocksAdmissionTest"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run unknownResetDuplicatesRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unresolved_tail_blocks_admission","declaration":"Weaver.StreamingExecution.RangeProgress.unresolved_tail_blocks_admission"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem changed_progress_cannot_execute","declaration":"Weaver.StreamingExecution.RangeProgress.changed_progress_cannot_execute"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem joined_execution_preserves_safety","declaration":"Weaver.StreamingExecution.RangeProgress.joined_execution_preserves_safety"}]}, {"id":"TursoAdmissionAtomicity","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"pub fn begin"},{"file":"crates/ledger/src/exposure_manifest.rs","pattern":"fn verified_members"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn failed_commit_releases_writer_and_poisoned_session_cannot_reenter"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn duplicate_claim_members_cannot_be_normalized_out_of_recovery"},{"file":"go/dev/workspace_test.go","pattern":"func TestProjectArchitectureStorageUsesMRRDataTursoOnly"},{"file":"dev/proofs/quint/TursoAdmission.qnt","pattern":"run tornCommitRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem storage_step_retains_admission_safety","declaration":"Weaver.RuntimeAdmission.Persistence.storage_step_retains_admission_safety"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem committed_consume_survives_reply_loss_and_restart","declaration":"Weaver.RuntimeAdmission.Persistence.committed_consume_survives_reply_loss_and_restart"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem commit_itself_does_not_send","declaration":"Weaver.RuntimeAdmission.Persistence.commit_itself_does_not_send"}]}, + {"id":"BoundedAdvisoryDerivation","witnesses":[ + {"file":"scheme/gateway/derivation.ss","pattern":"def \\(make-gateway-derivation"}, + {"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-gateway"}, + {"file":"t/gateway-derivation-test.ss","pattern":"generated source replacements agree with graph traversal and fresh results"}, + {"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run derivedAdviceCannotChangeImageOrSpendTest"}, + {"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run adviceAsOriginalCounterexampleTest"}]}, {"id":"SessionWorkflowFrontier","witnesses":[ {"file":"scheme/gateway/program.ss","pattern":"def \\(hard-fact-affected"}, {"file":"go/dev/provider_hard_fact_test.go","pattern":"func TestProviderControlHardFactWithdrawalRestartAndABA"}, From 3ac7672a0b779301e374a56bfda36371e22ed4a7 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 00:12:55 +0800 Subject: [PATCH 048/105] Use one Cargo graph for Scheme qualification --- Project.sysml | 6 ++++-- go/dev/cargo_artifact_test.go | 14 +++++++++++++- go/internal/devrunner/plan.go | 12 ++++++++++-- go/internal/devrunner/runner.go | 4 +++- go/internal/devrunner/scheme_tools_test.go | 6 ++++-- 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/Project.sysml b/Project.sysml index 1d502f0c..79873c09 100644 --- a/Project.sysml +++ b/Project.sysml @@ -244,8 +244,10 @@ package WeaverProject { } part scheme : VerificationSuite { part 'check-scheme' : VerificationMode; - doc /* Prepare the qualification image through Cargo before Go - streaming tests. Bound the image build and Go suite separately. + doc /* Compile the qualification executable and Rust tests in one + Cargo graph before running the Rust or Go tests. The Go fixture + uses the normal executable reported by that graph. Bound the + native build, Rust tests and Go suite separately. Resolve Lab and ASCENT sources from native package declarations. Gerbil prepares the pinned Core and POO compiler dependencies. ASCENT's selected Program build supplies native linker inputs. diff --git a/go/dev/cargo_artifact_test.go b/go/dev/cargo_artifact_test.go index bee25677..4d357bb5 100644 --- a/go/dev/cargo_artifact_test.go +++ b/go/dev/cargo_artifact_test.go @@ -14,6 +14,8 @@ import ( "strings" "testing" "unicode/utf8" + + "github.com/HardenedLinux/weaver/go/internal/devrunner" ) type cargoTarget struct { @@ -160,6 +162,9 @@ func providerCargoBuildArgs(features, benchmark string, lookup func(string) (str } else if optimized && features == providerSchemeQualificationFeatures { return nil, false, errors.New("release Scheme integration requires an explicit application") } + if features == providerSchemeQualificationFeatures { + return append(devrunner.SchemeQualificationCargoArgs(), "--no-run", "--message-format=json-render-diagnostics"), false, nil + } args := []string{"build", "-p", "weaver-server", "--bin", "weaver-server", "--features", features, "--locked", "--offline", "--message-format=json-render-diagnostics"} if optimized { args = append(args, "--release") @@ -190,7 +195,6 @@ func TestSchemeIntegrationReleaseRequiresExplicitApplication(t *testing.T) { wantFeatures string optimized bool }{ - {name: "debug qualification", features: "arrow,governance-qualification", wantFeatures: "arrow,governance-qualification"}, {name: "release application", features: "arrow,governance-qualification", env: map[string]string{module: "weaver/provider", source: "/provider.ss"}, wantFeatures: "arrow,scheme-program", optimized: true}, {name: "missing binding", features: "arrow,governance-qualification", env: map[string]string{module: "weaver/provider"}}, {name: "empty binding", features: "arrow,governance-qualification", env: map[string]string{module: "weaver/provider", source: ""}}, @@ -216,6 +220,14 @@ func TestSchemeIntegrationReleaseRequiresExplicitApplication(t *testing.T) { } } +func TestSchemeDebugUsesPreparedCargoQualificationGraph(t *testing.T) { + args, optimized, err := providerCargoBuildArgs(providerSchemeQualificationFeatures, "", func(string) (string, bool) { return "", false }) + want := append(devrunner.SchemeQualificationCargoArgs(), "--no-run", "--message-format=json-render-diagnostics") + if err != nil || optimized || !slices.Equal(args, want) { + t.Fatal("debug Scheme integration does not share the prepared Cargo graph", args, err) + } +} + func TestCargoOptimizedArtifactRequiresActualProfile(t *testing.T) { const record = `{"reason":"compiler-artifact","target":{"name":"gateway","kind":["bench"]},"profile":{"test":true,"opt_level":"3","debug_assertions":false},"executable":"/reported/gateway"}` for _, tc := range []struct { diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index ec4cb499..3cfe9d65 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -22,6 +22,14 @@ func schemeTool() string { return "gerbil" } +// SchemeQualificationCargoArgs defines the one Cargo graph for the native +// qualification tests and the executable used by the Go fixtures. +func SchemeQualificationCargoArgs() []string { + return []string{"test", "-p", "weaver-governance", "-p", "weaver-governance-build", "-p", "weaver-server", + "--features", "weaver-governance/scheme-qualification,weaver-server/governance-qualification,weaver-server/arrow", + "--locked", "--offline", "-j", "4"} +} + func Plan(goBinary string) []Stage { return []Stage{ {"rust-environment", "rustc", []string{"-vV"}}, @@ -241,8 +249,8 @@ func stagesForMode(mode, goBinary string) ([]Stage, error) { {"scheme-unit-tests", schemeTool(), []string{"test", "-g", "-v", "5", "t"}}, {"scheme-module-selection-integration", schemeTool(), []string{"test", "-g", "-v", "5", "t/qualification/module-selection"}}, {"scheme-source-integration-tests", schemeTool(), []string{"test", "-g", "-v", "5", "t/integration"}}, - {"scheme-rooted-sdk-integration", "cargo", []string{"test", "-p", "weaver-governance", "-p", "weaver-governance-build", "-p", "weaver-server", "--features", "weaver-governance/scheme-qualification,weaver-server/governance-qualification", "--locked", "--offline"}}, - {"scheme-provider-server-build", "cargo", []string{"build", "-p", "weaver-server", "--bin", "weaver-server", "--features", "arrow,governance-qualification", "--locked", "--offline", "-j", "4"}}, + {"scheme-provider-server-build", "cargo", append(SchemeQualificationCargoArgs(), "--no-run")}, + {"scheme-rooted-sdk-integration", "cargo", SchemeQualificationCargoArgs()}, {"scheme-grpc-stream-integration", goBinary, []string{"-C", "go", "test", "-json", "-count=1", "-race", "-tags=integration,schemeintegration", "-timeout=10m", "./dev", "-run", "^TestProviderControl", "-skip", "^TestProviderControlGovernorPerformance$"}}, }, nil case "bench-execution": diff --git a/go/internal/devrunner/runner.go b/go/internal/devrunner/runner.go index 11a7e678..76e66057 100644 --- a/go/internal/devrunner/runner.go +++ b/go/internal/devrunner/runner.go @@ -179,7 +179,7 @@ func Run(ctx context.Context, config Config, output io.Writer) (report string, r } var result Result if (stage.Name == "go-provider-grpc-integration" || stage.Name == "policy-provider-spec-integration" || - stage.Name == "scheme-grpc-stream-integration") && + stage.Name == "scheme-rooted-sdk-integration" || stage.Name == "scheme-grpc-stream-integration") && providerBuildFailure != "" { result = Result{Name: stage.Name, Status: "SKIP", Binary: stage.Binary, Args: stage.Args, Error: "required native build did not pass: " + providerBuildFailure} @@ -278,6 +278,8 @@ func runStageObserved(ctx context.Context, root, directory string, environment [ switch stage.Name { case "scheme-module-build": deadline = schemeModuleBuildTimeout + case "scheme-rooted-sdk-integration": + deadline = 5 * time.Minute case "scheme-unit-tests": tests = "t" case "scheme-source-integration-tests": diff --git a/go/internal/devrunner/scheme_tools_test.go b/go/internal/devrunner/scheme_tools_test.go index d22c6a05..5295f530 100644 --- a/go/internal/devrunner/scheme_tools_test.go +++ b/go/internal/devrunner/scheme_tools_test.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" "runtime" + "slices" "strings" "testing" ) @@ -93,10 +94,11 @@ func TestSchemeQualificationStaysWithPreparedSchemeOwner(t *testing.T) { for _, stage := range stages { if stage.Name == "scheme-rooted-sdk-integration" { args := strings.Join(stage.Args, " ") - found = strings.Contains(args, "weaver-governance/scheme-qualification") && strings.Contains(args, "weaver-server/governance-qualification") && strings.Contains(args, "-p weaver-server") + found = imagePrepared && slices.Equal(stage.Args, SchemeQualificationCargoArgs()) && + strings.Contains(args, "weaver-governance/scheme-qualification") && strings.Contains(args, "weaver-server/governance-qualification") } if stage.Name == "scheme-provider-server-build" { - imagePrepared = stage.providerBuild() + imagePrepared = stage.providerBuild() && slices.Equal(stage.Args, append(SchemeQualificationCargoArgs(), "--no-run")) } if stage.Name == "scheme-grpc-stream-integration" && !imagePrepared { t.Fatal("Scheme Go integration has no preceding qualification image build") From c6d6ca3b30f65938dffad59b265389a8fe6606e7 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 00:23:35 +0800 Subject: [PATCH 049/105] Use the native build environment consistently --- .github/workflows/verify-suite.yml | 2 ++ .../59-provider-rpc/59.32-build-environment-contract.org | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 7dfee059..dcd61055 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -86,6 +86,8 @@ jobs: # for GitHub to retain its exit status before the outer cutoff. timeout-minutes: 13 env: + # The SDK setup exports the host core count via GITHUB_ENV. + GERBIL_BUILD_CORES: '4' GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil run: | command -v timeout diff --git a/docs/50-59-research-program/59-provider-rpc/59.32-build-environment-contract.org b/docs/50-59-research-program/59-provider-rpc/59.32-build-environment-contract.org index f43ab4a2..a249e396 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.32-build-environment-contract.org +++ b/docs/50-59-research-program/59-provider-rpc/59.32-build-environment-contract.org @@ -21,6 +21,14 @@ Gerbil toolchain-discovered command, explicit relative and absolute selections, links, and rejection of empty or non-executable selections. Optional process sampling requires an explicit =WEAVER_SCHEME_SAMPLER= environment selection. +* Cargo workspace builds +Use =cargo build --locked= for development and =cargo build --release --locked= +for release builds. Weaver's local and CI entry points use Cargo's default +workspace =target/= directory. The root =Cargo.toml= owns both profiles. +Development builds set =opt-level= to 1 for workspace crates and 0 for external +dependencies. Release builds set it to 3. Both profiles enable +incremental compilation for workspace crates. + * Cargo-owned FFI package metadata The Scheme root build obtains flags through the existing public =:std/make= functions =pkg-config-cflags= and =pkg-config-libs=. It does not From b668754c9b547db37edc2413276c9488e06717bb Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 00:35:55 +0800 Subject: [PATCH 050/105] Exercise the published Yuanxu namespace mounts --- t/qualification/module-selection/use.ss | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/t/qualification/module-selection/use.ss b/t/qualification/module-selection/use.ss index dcedb97f..7d6be2bb 100644 --- a/t/qualification/module-selection/use.ss +++ b/t/qualification/module-selection/use.ss @@ -14,11 +14,12 @@ (ormap (lambda (row) (equal? (car row) "agentic-ai-lab/modules/governance/interface~0")) (list-modules)) - (not (.slot? hardenedlinux/weaver.init.exports 'Lab))) + (.slot? hardenedlinux/weaver.init.exports 'Lab) + (.slot? hardenedlinux/weaver.init.exports 'Weaver)) (error "Gerbil Governance import or Yuanxu export layout differs")) (defvalues (lab first) (call-with-module-source-operation-measurement - (lambda () (.get hardenedlinux/weaver.init.exports modules Lab governance)) accounting?: #f)) + (lambda () (.get hardenedlinux/weaver.init.exports Lab governance)) accounting?: #f)) (unless (and (= (hash-ref first '(calls candidate-read) 0) 4) (= (hash-ref first '(calls scope-factory) 0) 1) (= (hash-ref first '(calls (scope-factory agentic-ai-lab/modules/governance/interface)) 0) 1) @@ -26,15 +27,15 @@ (error "first Lab scope demand constructed an unrelated or conflated owner")) (defvalues (again repeat) (call-with-module-source-operation-measurement - (lambda () (.get hardenedlinux/weaver.init.exports modules Lab governance)) accounting?: #f)) + (lambda () (.get hardenedlinux/weaver.init.exports Lab governance)) accounting?: #f)) (unless (and (eq? lab again) (zero? (hash-ref repeat '(calls candidate-read) 0)) (zero? (hash-ref repeat '(calls scope-factory) 0))) (error "repeated native scope demand did not reuse its POO slot")) (displayln "WEAVER-MODULE-FIRST-GET declarations=4 scopes=1 repeat-scopes=0") - (def local (.get hardenedlinux/weaver.init.exports modules Weaver governance)) + (def local (.get hardenedlinux/weaver.init.exports Weaver governance)) (unless (and (not (eq? lab local)) - (eq? lab (.get hardenedlinux/weaver.init.exports modules Lab governance)) - (eq? local (.get hardenedlinux/weaver.init.exports modules Weaver governance))) + (eq? lab (.get hardenedlinux/weaver.init.exports Lab governance)) + (eq? local (.get hardenedlinux/weaver.init.exports Weaver governance))) (error "native roots or repeated scope identities were conflated")) (def profile (.cc (.get lab Profile) identity: "weaver/selected" revision: "1" owner: "operator")) (unless (agentic-ai-lab-governance-profile? profile) (error "selected native public Profile rejected its scope value")) @@ -42,13 +43,13 @@ profile_identity: "weaver/selected" profile_revision: "1" profile_owner: "operator" model_identity: "agentic-ai-lab/governance/threat-model/empty")) (unless ((.get local assess) profile context) (error "Weaver Governance business assessment failed")) - (def policy (.get hardenedlinux/weaver.init.exports modules Weaver policy)) + (def policy (.get hardenedlinux/weaver.init.exports Weaver policy)) (def schema (call-with-input-file (path-expand "../../../prod/policies/provider/schema.json" (path-directory (this-source-file))) read-all-as-string)) (unless ((.get policy validate) "forbid(principal,action,resource);" schema) (error "selected Cedar FFI business validation failed")) - (def gateway (.get hardenedlinux/weaver.init.exports modules Weaver gateway)) + (def gateway (.get hardenedlinux/weaver.init.exports Weaver gateway)) (unless (procedure? (.get gateway compile)) (error "Gateway business entry is absent")) (def prefix (string-append (path-strip-trailing-directory-separator (path-normalize (path-expand "lib" (gerbil-path)))) "/")) From bb743e10d9829cc4ba8cfe7271e5d52e20141c00 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 00:44:37 +0800 Subject: [PATCH 051/105] Advance sealed Session workflows through the Scheme Governor --- crates/governance-build/src/program.rs | 2 + crates/governance/Cargo.toml | 2 +- crates/governance/src/catalog/admission.rs | 24 + crates/governance/src/host/client.rs | 1 + crates/governance/src/host/mod.rs | 1 + crates/governance/src/host/owner.rs | 59 +- crates/governance/src/host/state.rs | 1 + crates/governance/src/program/compiler.rs | 59 +- crates/governance/src/program/linked.rs | 43 +- crates/ledger/src/provider.rs | 30 ++ crates/server/src/admission.rs | 8 + crates/server/src/entrypoint.rs | 4 + crates/server/src/governance_deployment.rs | 58 +- crates/server/src/governance_owner.rs | 2 + crates/server/src/grpc.rs | 34 +- crates/server/src/grpc_provider.rs | 161 +++++- crates/server/src/lib.rs | 1 + crates/server/src/main.rs | 7 + crates/server/src/runtime.rs | 12 + crates/server/src/session_workflow.rs | 307 +++++++++++ crates/server/src/shutdown.rs | 8 + crates/server/src/single_provider.rs | 89 +-- crates/server/src/source_owner.rs | 23 +- crates/server/tests/unit/governance_owner.rs | 1 + dev/sysml/ControlActivation.sysml | 9 + dev/sysml/runtime-trace.json | 24 +- go/dev/provider_control_test.go | 7 +- go/dev/provider_fixture_test.go | 24 +- go/dev/provider_governor_performance_test.go | 215 ++++++++ go/dev/provider_program_deployment_test.go | 537 ++++++++++++++++++- go/dev/provider_workflow_choice_test.go | 226 ++++++++ go/dev/provider_workflow_nested_test.go | 436 +++++++++++++++ t/fixtures/governance-program.ss | 20 +- 33 files changed, 2316 insertions(+), 119 deletions(-) create mode 100644 crates/server/src/session_workflow.rs create mode 100644 go/dev/provider_governor_performance_test.go create mode 100644 go/dev/provider_workflow_choice_test.go create mode 100644 go/dev/provider_workflow_nested_test.go diff --git a/crates/governance-build/src/program.rs b/crates/governance-build/src/program.rs index 108fda3f..79414a9e 100644 --- a/crates/governance-build/src/program.rs +++ b/crates/governance-build/src/program.rs @@ -80,6 +80,8 @@ impl BuildPaths { let headers = [include.join("weaver_policy.h")]; let required = [ "gerbil-scheme-rust/scheme/runtime", + "gerbil-ascent/program/scheme-language", + "gerbil-ascent/program/session", "hardenedlinux/weaver/scheme/gateway/compiled", self.application.module(), ]; diff --git a/crates/governance/Cargo.toml b/crates/governance/Cargo.toml index 9c7c402b..ad0bb291 100644 --- a/crates/governance/Cargo.toml +++ b/crates/governance/Cargo.toml @@ -16,6 +16,7 @@ scheme-qualification = ["scheme-program"] [dependencies] weaver-contracts.workspace = true serde.workspace = true +serde_json.workspace = true thiserror.workspace = true tokio.workspace = true tokio-util.workspace = true @@ -28,7 +29,6 @@ gerbil-scheme = { workspace = true, optional = true } weaver-governance-build.workspace = true [dev-dependencies] -serde_json.workspace = true asp-rust.workspace = true criterion.workspace = true proptest.workspace = true diff --git a/crates/governance/src/catalog/admission.rs b/crates/governance/src/catalog/admission.rs index 7e387d0d..6ec39d38 100644 --- a/crates/governance/src/catalog/admission.rs +++ b/crates/governance/src/catalog/admission.rs @@ -53,6 +53,30 @@ pub struct ProducerCatalog { pub(super) entries: BTreeMap, } impl ProducerCatalog { + pub fn has_session_workflow(&self) -> bool { + self.entries.values().any(|entry| { + matches!( + entry.original.data().governance.schema.as_str(), + weaver_contracts::SESSION_WORKFLOW_SCHEMA + | weaver_contracts::SESSION_DAG_SCHEMA + | weaver_contracts::SESSION_CHOICE_SCHEMA + | weaver_contracts::SESSION_NESTED_SCHEMA + ) + }) + } + + pub fn admits_session_workflow(&self, feed: &weaver_contracts::FactFeed) -> bool { + self.is_single_provider() + && self.entries.values().next().is_some_and(|entry| { + let selection = &entry.original.data().governance; + selection.schema == feed.session_schema() + && (!feed.workflow_dag || selection.workflow_edges == feed.dependencies) + && selection.workflow_selectors == feed.workflow_selectors + && selection.family == feed.family + && selection.open_nodes == feed.workflow_path + }) + } + /// Whether this catalog admits exactly one independently bound provider task. pub fn is_single_provider(&self) -> bool { self.entries.len() == 1 diff --git a/crates/governance/src/host/client.rs b/crates/governance/src/host/client.rs index 4cf0de83..530d2826 100644 --- a/crates/governance/src/host/client.rs +++ b/crates/governance/src/host/client.rs @@ -113,6 +113,7 @@ impl SourceClient { input, reply, _slot: slot, + queued: super::governor_timing().then(std::time::Instant::now), }) .map_err(|error| match error { mpsc::error::TrySendError::Full(_) => SourceJobError::Busy, diff --git a/crates/governance/src/host/mod.rs b/crates/governance/src/host/mod.rs index 542e8510..c46062f8 100644 --- a/crates/governance/src/host/mod.rs +++ b/crates/governance/src/host/mod.rs @@ -9,6 +9,7 @@ mod request; mod state; pub use client::{SourceClient, source_lane}; pub use owner::SourceInbox; +pub(crate) use owner::governor_timing; pub use request::{SourceJob, SourceJobError}; use state::{Command, Phase, Reply, Shared, State, Work}; pub use state::{Derivation, GovernorCut}; diff --git a/crates/governance/src/host/owner.rs b/crates/governance/src/host/owner.rs index 88170271..2c5c37f1 100644 --- a/crates/governance/src/host/owner.rs +++ b/crates/governance/src/host/owner.rs @@ -59,34 +59,66 @@ impl SourceInbox { match command { Command::Stop => break, Command::Compile(work) => self.execute(*work, &mut |original, cancel| { - compile(&mut owner, original, cancel) + if governor_timing() { + trace_compile("begin"); + } + let result = compile(&mut owner, original, cancel); + if governor_timing() { + trace_compile("end"); + } + result }), Command::Derive { input, reply, _slot, - } => { - self.execute_derivation(reply, || derive(&mut owner, &input)); - } + queued, + } => self.execute_derivation(&input, reply, queued, || derive(&mut owner, &input)), } if *self.shared.gate() { break; } } + if governor_timing() { + let wall = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default(); + eprintln!( + "weaver shutdown stage=scheme-owner-drop-begin wall_ns={}", + wall.as_nanos() + ); + } drop(owner); } fn execute_derivation( &self, + input: &crate::Derivation, reply: tokio::sync::oneshot::Sender, SourceError>>, + queued: Option, derive: impl FnOnce() -> Result, SourceError>, ) { if reply.is_closed() { return; } + let started = queued.map(|queued| (queued, std::time::Instant::now())); let result = derive(); if matches!(result, Err(SourceError::Scheme)) { self.shared.stop(); } + if let Some((queued, started)) = started { + let derive_ns = started.elapsed().as_nanos(); + let cut_sha256 = match input { + crate::Derivation::Governor(cut) => trace_digest(cut), + crate::Derivation::FactImpact { .. } => trace_digest(input), + }; + let ready_sha256 = result.as_ref().ok().map(trace_digest); + eprintln!( + "weaver-governor-owner wait_ns={} derive_ns={derive_ns} ok={} cut_sha256={cut_sha256} ready_sha256={}", + started.duration_since(queued).as_nanos(), + result.is_ok(), + ready_sha256.as_deref().unwrap_or("unavailable"), + ); + } let _ = reply.send(result); } fn execute( @@ -125,6 +157,25 @@ impl SourceInbox { } } +fn trace_digest(value: &impl serde::Serialize) -> String { + serde_json::to_string(value) + .map(|json| weaver_contracts::body_digest(&json)) + .unwrap_or_else(|_| "unavailable".to_owned()) +} + +pub(crate) fn governor_timing() -> bool { + static ENABLED: std::sync::OnceLock = std::sync::OnceLock::new(); + *ENABLED.get_or_init(|| std::env::var_os("WEAVER_TEST_GOVERNOR_TIMING").is_some()) +} + +fn trace_compile(phase: &str) { + use std::time::{SystemTime, UNIX_EPOCH}; + let wall = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_nanos(); + eprintln!("weaver-governor-compile {phase} {wall}"); +} impl Drop for SourceInbox { fn drop(&mut self) { self.shared.stop(); diff --git a/crates/governance/src/host/state.rs b/crates/governance/src/host/state.rs index 4f002d35..0e067809 100644 --- a/crates/governance/src/host/state.rs +++ b/crates/governance/src/host/state.rs @@ -94,6 +94,7 @@ pub(super) enum Command { input: Derivation, reply: oneshot::Sender, crate::SourceError>>, _slot: OwnedSemaphorePermit, + queued: Option, }, Compile(Box), Stop, diff --git a/crates/governance/src/program/compiler.rs b/crates/governance/src/program/compiler.rs index aed36bed..8615a080 100644 --- a/crates/governance/src/program/compiler.rs +++ b/crates/governance/src/program/compiler.rs @@ -26,7 +26,7 @@ impl SchemeCompiler { } pub fn evaluate(&mut self, input: &crate::Derivation) -> Result, SourceError> { match input { - crate::Derivation::Governor(_) => Err(SourceError::Contract), + crate::Derivation::Governor(cut) => self.derive(cut), crate::Derivation::FactImpact { root, dependencies } => { let input = crate::scheme_input::values::Input::new(&self.runtime); let root = input.record(vec![ @@ -39,11 +39,66 @@ impl SchemeCompiler { } } } + pub fn derive(&mut self, cut: &crate::GovernorCut) -> Result, SourceError> { + let started = crate::host::governor_timing().then(std::time::Instant::now); + let input = crate::scheme_input::values::Input::new(&self.runtime); + let root = input.record(vec![ + ("nodes", input.strings(&cut.nodes)?), + ("edges", input.edges(&cut.edges)?), + ("complete", input.strings(&cut.complete)?), + ("available", input.strings(&cut.available)?), + ("pending", input.strings(&cut.pending)?), + ("choice_arms", input.strings(&cut.choice_arms)?), + ("choice_join", input.strings(&cut.choice_join)?), + ("choice_result", input.strings(&cut.choice_result)?), + ("choice_decided", input.strings(&cut.choice_decided)?), + ( + "nested_selectors", + input.vector( + cut.nested_selectors + .iter() + .map(|row| input.strings(row)) + .collect::, _>>()?, + )?, + ), + ("nested_results", input.edges(&cut.nested_results)?), + ("nested_decisions", input.edges(&cut.nested_decisions)?), + ])?; + let input_done = started.map(|_| std::time::Instant::now()); + let output = linked::derive(&self.runtime, &root).map_err(|_| SourceError::Scheme)?; + let ffi_done = started.map(|_| std::time::Instant::now()); + let result = crate::scheme::materialize(output); + if let (Some(started), Some(input_done), Some(ffi_done)) = (started, input_done, ffi_done) { + eprintln!( + "weaver-governor-ffi input_ns={} call_ns={} output_ns={}", + input_done.duration_since(started).as_nanos(), + ffi_done.duration_since(input_done).as_nanos(), + ffi_done.elapsed().as_nanos(), + ); + } + result + } /// Compilation is inert preparation; the source lane independently binds /// this result to its retained original before any caller can claim it. pub fn compile(&mut self, original: &OwnedSource) -> Result { + self.compile_bound(original, None) + } + /// The source lane owns this monotonic token for the duration of capture. + pub fn compile_cancellable( + &mut self, + original: &OwnedSource, + cancel: &tokio_util::sync::CancellationToken, + ) -> Result { + self.compile_bound(original, Some(cancel)) + } + fn compile_bound( + &mut self, + original: &OwnedSource, + shutdown: Option<&tokio_util::sync::CancellationToken>, + ) -> Result { let input = root_source(&self.runtime, original)?; - let output = linked::capture(&self.runtime, &input).map_err(|_| SourceError::Scheme)?; + let output = + linked::capture(&self.runtime, &input, shutdown).map_err(|_| SourceError::Scheme)?; materialize_source(output) } } diff --git a/crates/governance/src/program/linked.rs b/crates/governance/src/program/linked.rs index 7a982a1c..a81bc150 100644 --- a/crates/governance/src/program/linked.rs +++ b/crates/governance/src/program/linked.rs @@ -7,20 +7,49 @@ use gerbil_scheme::{ GerbilRuntime, LinkedGerbilProgram, NativeError as GerbilError, RootedSchemeObject, SchemeScalar, }; +use std::cell::RefCell; +use tokio_util::sync::CancellationToken; + +thread_local! { + static CAPTURE_SHUTDOWN: RefCell> = const { RefCell::new(None) }; +} + +// The linked Scheme call is synchronous on this same owner thread. +extern "C" fn capture_cancelled() -> i32 { + i32::from(CAPTURE_SHUTDOWN.with(|slot| { + slot.borrow() + .as_ref() + .is_some_and(CancellationToken::is_cancelled) + })) +} +static CAPTURE_CANCEL_CALLBACK: extern "C" fn() -> i32 = capture_cancelled; + +struct CaptureShutdown(Option); +impl Drop for CaptureShutdown { + fn drop(&mut self) { + CAPTURE_SHUTDOWN.with(|slot| slot.replace(self.0.take())); + } +} unsafe extern "C" { fn ___LNK_weaver__governance__program( ctx: *mut gerbil_scheme_sys::GerbilGlobalState, ) -> *mut gerbil_scheme_sys::GerbilModuleOrLink; + fn weaver_governor_ready_steps_v1(root: i64) -> i64; fn weaver_hard_fact_impact_v1(root: i64) -> i64; fn weaver_capture_source_v1(root: i64) -> i64; fn weaver_governance_ready_v1(root: i64) -> i64; + fn weaver_install_source_cancel_v1(callback: *const std::ffi::c_void); } pub(super) fn initialize() -> Result { // SAFETY: the build owner checks the fixed bridge, explicit application and // pinned Gerbil graph. The generated linker and graph have process lifetime; // the approved initializer must return normally and never finalize the VM. let program = unsafe { LinkedGerbilProgram::from_linker(___LNK_weaver__governance__program) }; - GerbilRuntime::initialize_program(program) + let runtime = GerbilRuntime::initialize_program(program)?; + // SAFETY: this export is in the initialized graph and runs on its owner + // thread. Scheme borrows the address of a process-lived typed callback slot. + unsafe { weaver_install_source_cancel_v1(std::ptr::from_ref(&CAPTURE_CANCEL_CALLBACK).cast()) }; + Ok(runtime) } pub(super) fn ready(runtime: &GerbilRuntime) -> Result { let input = runtime.nil_object()?; @@ -36,7 +65,9 @@ pub(super) fn ready(runtime: &GerbilRuntime) -> Result { pub(super) fn capture<'r>( runtime: &'r GerbilRuntime, input: &RootedSchemeObject<'_>, + shutdown: Option<&CancellationToken>, ) -> Result, GerbilError> { + let _shutdown = CaptureShutdown(CAPTURE_SHUTDOWN.with(|slot| slot.replace(shutdown.cloned()))); // SAFETY: fixed same-graph export uses Gerbil rooted-call, borrows the strong // input only synchronously, catches semantic declines and transfers one // fresh data/false root. It retains no Rust pointer and cannot finalize VM. @@ -44,6 +75,16 @@ pub(super) fn capture<'r>( export.call(input).into_result() } +pub(super) fn derive<'r>( + runtime: &'r GerbilRuntime, + input: &RootedSchemeObject<'_>, +) -> Result, GerbilError> { + // SAFETY: fixed linked rooted call transfers a fresh result. No VM state + // or foreign pointer crosses the owner boundary. + let export = unsafe { runtime.bind_object_export(weaver_governor_ready_steps_v1) }?; + export.call(input).into_result() +} + pub(super) fn fact_impact<'r>( runtime: &'r GerbilRuntime, input: &RootedSchemeObject<'_>, diff --git a/crates/ledger/src/provider.rs b/crates/ledger/src/provider.rs index c77aa552..f3a2411b 100644 --- a/crates/ledger/src/provider.rs +++ b/crates/ledger/src/provider.rs @@ -13,11 +13,36 @@ use crate::persistence::{ProviderScopePhase, WriteScope}; use crate::{Ledger, db, integer}; use admission::{admissible_receipt, store_authorized_provider_plan}; use std::collections::BTreeSet; +use std::{ + sync::OnceLock, + time::{Instant, SystemTime, UNIX_EPOCH}, +}; use weaver_contracts::{ DomainView, Error, ProviderOAuthUse, ProviderPlan, ProviderReceipt, ProviderRoute, ProviderState, Result, Task, }; +fn governor_timing() -> bool { + static ENABLED: OnceLock = OnceLock::new(); + *ENABLED.get_or_init(|| std::env::var_os("WEAVER_TEST_GOVERNOR_TIMING").is_some()) +} + +fn governor_commit_trace(phase: &str, plan: &ProviderPlan, transaction: Option) { + static EPOCH: OnceLock = OnceLock::new(); + if governor_timing() { + let nanos = EPOCH.get_or_init(Instant::now).elapsed().as_nanos(); + let wall = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_nanos(); + let tx_nanos = transaction.map_or(0, |start| start.elapsed().as_nanos()); + eprintln!( + "weaver-governor-commit {phase} {} {} {nanos} {wall} {tx_nanos}", + plan.family, plan.node + ); + } +} + /// Sealed proof obligation for the two progress-only write paths in this module. /// No external caller or other ledger module can construct this token. /// Its transaction may only append fresh ranges/advance next_event, or CAS an @@ -232,6 +257,7 @@ impl Ledger { let publication = self.connection.prepare_provider_publication(&plan.family); let original = self.connection.prepare_provider_original(&plan.family); self.connection.prepare_provider_domain(); + let transaction = (progression.is_some() && governor_timing()).then(Instant::now); let tx = crate::persistence::begin_provider_admission( &mut self.connection, &plan.family, @@ -255,6 +281,9 @@ impl Ledger { )?; crate::provider_workflow::record_admission(&tx, plan, &digest, progression, new_claim)?; tx.commit_provider_admission().map_err(db)?; + if new_claim && progression.is_some() { + governor_commit_trace("reserve", plan, transaction); + } self.provider_receipt(&plan.family, &plan.node)? .ok_or(Error::Conflict("provider receipt missing")) } @@ -426,6 +455,7 @@ impl Ledger { .map_err(db)?; } tx.commit_lifecycle().map_err(db)?; + governor_commit_trace("release", &permit.plan, None); Ok(()) } pub fn provider_receipt(&self, family: &str, node: &str) -> Result> { diff --git a/crates/server/src/admission.rs b/crates/server/src/admission.rs index df71ae4e..3381dd34 100644 --- a/crates/server/src/admission.rs +++ b/crates/server/src/admission.rs @@ -24,6 +24,14 @@ impl Admission { pub(crate) fn execution(&self) -> Result, Status> { acquire(&self.execution) } + pub(crate) async fn session_execution(&self) -> Option> { + self.execution + .clone() + .acquire_owned() + .await + .ok() + .map(Arc::new) + } pub(crate) fn publication(&self) -> Result, Status> { acquire(&self.publication) } diff --git a/crates/server/src/entrypoint.rs b/crates/server/src/entrypoint.rs index 713f4713..13b8e517 100644 --- a/crates/server/src/entrypoint.rs +++ b/crates/server/src/entrypoint.rs @@ -23,8 +23,12 @@ pub(crate) async fn run_on_runtime() -> weaver_contracts::Result<()> { let storage = LedgerCustody::open_with_journal(path, journal) .map_err(|error| weaver_contracts::Error::Storage(error.to_string()))?; let result = crate::run_from_env().await; + crate::shutdown::trace("service-returned"); let closed = storage .close() .map_err(|error| weaver_contracts::Error::Storage(error.to_string())); + if closed.is_ok() { + crate::shutdown::trace("storage-closed"); + } result.and(closed) } diff --git a/crates/server/src/governance_deployment.rs b/crates/server/src/governance_deployment.rs index a2d2bb3f..ca50b29b 100644 --- a/crates/server/src/governance_deployment.rs +++ b/crates/server/src/governance_deployment.rs @@ -34,25 +34,43 @@ pub(crate) async fn start( Err(std::env::VarError::NotPresent) => false, _ => return Err(Error::Invalid("single-provider lifecycle setting")), }; - if let Some(feed) = runtime.fact_feed() { - match &feed.workflow { - Some(edge) - if retire - && catalog - .as_ref() - .is_some_and(|catalog| catalog.admits_workflow(&feed.family, edge)) => {} - Some(_) => { - return Err(Error::Invalid( - "workflow requires the single compiled provider original", - )); - } - None if retire => { - return Err(Error::Invalid( - "compiler retirement requires a deployment without a hard fact feed", - )); - } - None => {} + let session_workflow = runtime + .fact_feed() + .filter(|feed| !feed.workflow_path.is_empty()); + let session_original = catalog + .as_ref() + .filter(|catalog| catalog.has_session_workflow()); + if !match (session_workflow, session_original) { + (None, None) => true, + (Some(feed), Some(catalog)) => { + (retire || feed.workflow_dag) && catalog.admits_session_workflow(feed) } + _ => false, + } { + return Err(Error::Invalid( + "session workflow requires the exact compiled path", + )); + } + if retire + && session_workflow.is_none() + && runtime + .fact_feed() + .is_some_and(|feed| feed.workflow.is_none()) + { + return Err(Error::Invalid( + "compiler retirement requires a deployment without a hard fact feed", + )); + } + if let Some(feed) = runtime.fact_feed() + && let Some(edge) = &feed.workflow + && (!retire + || !catalog + .as_ref() + .is_some_and(|catalog| catalog.admits_workflow(&feed.family, edge))) + { + return Err(Error::Invalid( + "workflow requires the single compiled provider original", + )); } let Some(catalog) = catalog else { if runtime.fact_feed().is_some() { @@ -74,7 +92,7 @@ pub(crate) async fn start( } #[cfg(feature = "scheme-program")] { - if retire { + if retire || session_workflow.is_some_and(|feed| feed.workflow_dag) { if !catalog.is_single_provider() { return Err(Error::Invalid( "single-provider lifecycle requires exactly one producer", @@ -107,7 +125,7 @@ async fn start_compiler( weaver_governance::SchemeCompiler::initialize() .map_err(|_| Error::Conflict("approved Scheme program unavailable")) }, - |compiler, source, _| compiler.compile(source), + weaver_governance::SchemeCompiler::compile_cancellable, weaver_governance::SchemeCompiler::evaluate, ) .await?; diff --git a/crates/server/src/governance_owner.rs b/crates/server/src/governance_owner.rs index e8d96bc6..0a2e427d 100644 --- a/crates/server/src/governance_owner.rs +++ b/crates/server/src/governance_owner.rs @@ -81,12 +81,14 @@ impl RuntimeOwner { } // run drops the compiler (and its VM) before the tracked task ends. inbox.run_with_cancellable_governor(compiler, compile, derive); + crate::shutdown::trace("scheme-owner-cleaned"); if let Some(lifecycle) = runtime.single_provider() && lifecycle.retirement_requested() { exit.disarm(); eprintln!("weaver governance stage=compiler-retired"); lifecycle.acknowledge_retirement(); + runtime.wake_session(); } Ok(()) })?; diff --git a/crates/server/src/grpc.rs b/crates/server/src/grpc.rs index c9dbdcf5..632e36b3 100644 --- a/crates/server/src/grpc.rs +++ b/crates/server/src/grpc.rs @@ -23,6 +23,7 @@ use tonic::{Request, Response, Status}; use weaver_broker::ProviderTransport; use weaver_contracts::Error; use weaver_ledger::Ledger; + #[derive(Clone)] pub(crate) struct Gateway { pub(crate) config: ServerConfig, @@ -84,6 +85,7 @@ pub async fn serve_grpc_with_runtime( Err(error) => Err(error), }; runtime.drain().await; + crate::shutdown::trace("tracked-owners-drained"); result } async fn serve_owned( @@ -92,6 +94,11 @@ async fn serve_owned( runtime: RuntimeOwner, shutdown: impl Future + Send + 'static, ) -> weaver_contracts::Result<()> { + if runtime.session_wakeup().is_some() && settings.provider_oauth.is_some() { + return Err(Error::Invalid( + "automatic Session requires deployment provider credentials", + )); + } let admission = Admission::new(settings.owner.max_in_flight); let slot = admission .publication() @@ -121,6 +128,7 @@ async fn serve_owned( admission, runtime.clone(), ); + let session = operation.clone(); let operation = serve_listener( listeners.operation, operation, @@ -128,16 +136,24 @@ async fn serve_owned( ); let source = serve_listener(listeners.source, source, settings.security.tls); tokio::pin!(operation, source, shutdown); - let result = tokio::select! { - result = &mut operation => { runtime.request_shutdown(); result.and(source.await) }, - result = &mut source => { runtime.request_shutdown(); result.and(operation.await) }, - _ = &mut shutdown => { - runtime.request_shutdown(); - let (operation, source) = tokio::join!(operation, source); - operation.and(source) - }, + let listeners = async { + tokio::select! { + result = &mut operation => { runtime.request_shutdown(); result.and(source.await) }, + result = &mut source => { runtime.request_shutdown(); result.and(operation.await) }, + _ = &mut shutdown => { + crate::shutdown::trace("signal-observed"); + runtime.request_shutdown(); + crate::shutdown::trace("admission-closed"); + let (operation, source) = tokio::join!(operation, source); + crate::shutdown::trace("listeners-drained"); + operation.and(source) + }, + } }; - result.and(source_worker.finish().await) + let (result, ()) = tokio::join!(listeners, session.run_session_workflow()); + let source_result = source_worker.finish().await; + crate::shutdown::trace("source-owner-joined"); + result.and(source_result) } async fn serve_listener( diff --git a/crates/server/src/grpc_provider.rs b/crates/server/src/grpc_provider.rs index 96309a70..9b2aad4a 100644 --- a/crates/server/src/grpc_provider.rs +++ b/crates/server/src/grpc_provider.rs @@ -6,12 +6,92 @@ use crate::grpc::{Gateway, ResponseStream}; use crate::grpc_contracts::{plan, status}; use crate::{grpc_output::Output, pb, rpc_security::RpcRole}; -use tokio::sync::mpsc; +use std::sync::Arc; +use tokio::sync::{OwnedSemaphorePermit, mpsc}; use tokio_util::sync::CancellationToken; use tonic::{Request, Response, Status}; -use weaver_ledger::Ledger; +use weaver_contracts::{ProviderOAuthUse, ProviderPlan}; +use weaver_ledger::{Ledger, WorkflowObservation}; + +pub(crate) struct StreamSettings { + pub arrow: bool, + pub batch_rows: u32, + pub catalog: String, +} + +#[derive(Default)] +pub(crate) struct WorkflowAdmission { + pub predecessors: Vec, + pub observed: Option>, +} impl Gateway { + /// Use the immutable Governor-approved plans from the retired preparation + /// owner. No request supplies an observation, transition or source graph. + fn workflow_predecessors( + &self, + successor: &weaver_contracts::ProviderPlan, + ) -> Result, Status> { + let Some(feed) = self + .runtime + .fact_feed() + .filter(|feed| feed.family == successor.family) + else { + return Ok(Vec::new()); + }; + let predecessors = feed.workflow_predecessors(&successor.node); + let session = !feed.workflow_path.is_empty(); + if predecessors.is_empty() && !session { + return Ok(Vec::new()); + } + let source = self + .runtime + .single_provider() + .filter(|lifecycle| lifecycle.activated()) + .and_then(|lifecycle| lifecycle.ready.get()) + .map(crate::single_provider::Prepared::source) + .ok_or(Status::failed_precondition( + "compiled workflow has not activated", + ))?; + let selection = &source.data().governance; + let matches_path = if session { + selection.schema == feed.session_schema() && selection.open_nodes == feed.workflow_path + } else { + predecessors.iter().all(|node| { + selection + .open_nodes + .iter() + .any(|selected| selected == *node) + }) + }; + if selection.family != feed.family + || !selection.open_nodes.contains(&successor.node) + || !matches_path + { + return Err(Status::failed_precondition( + "Governor workflow selection changed", + )); + } + let admitted = |node: &str| { + source + .plans() + .iter() + .find(|p| p.family == selection.family && p.node == node) + .ok_or(Status::failed_precondition( + "compiled workflow plan missing", + )) + }; + if admitted(&successor.node)? != successor { + return Err(Status::failed_precondition( + "successor differs from compiled original", + )); + } + predecessors + .into_iter() + .map(|node| admitted(node).cloned()) + .collect() + } + pub(super) async fn execute_provider_stream( &self, request: Request, @@ -37,7 +117,48 @@ impl Gateway { .plan .ok_or(Status::invalid_argument("plan missing"))?, )?; - let predecessor = self.workflow_predecessor(&plan)?; + let predecessors = self.workflow_predecessors(&plan)?; + if self + .runtime + .fact_feed() + .is_some_and(|feed| !feed.workflow_path.is_empty() && feed.family == plan.family) + { + if !predecessors.is_empty() { + return Err(Status::failed_precondition( + "Session owns successor execution", + )); + } + } + self.start_provider_stream( + slot, + plan, + WorkflowAdmission { + predecessors, + observed: None, + }, + oauth, + StreamSettings { + arrow, + batch_rows: request.batch_rows, + catalog: request.catalog_version, + }, + ) + .map(Response::new) + } + + pub(crate) fn start_provider_stream( + &self, + slot: Arc, + plan: ProviderPlan, + workflow: WorkflowAdmission, + oauth: Option, + settings: StreamSettings, + ) -> Result { + let StreamSettings { + arrow, + batch_rows, + catalog, + } = settings; let cursor = weaver_ledger::DeliveryCursor::new(&plan).map_err(status)?; let (sender, receiver) = mpsc::channel(crate::grpc_output::DELIVERY_QUEUE_CAPACITY); let cancelled = CancellationToken::new(); @@ -52,6 +173,16 @@ impl Gateway { }; let config = self.config.clone(); let transport = self.transport.clone(); + let wakeup = self + .runtime + .session_wakeup() + .filter(|_| { + self.runtime + .fact_feed() + .is_some_and(|feed| feed.family == plan.family) + }) + .cloned(); + let session_root = wakeup.is_some() && workflow.predecessors.is_empty(); #[cfg(test)] let queued_at = std::time::Instant::now(); let job = self @@ -124,21 +255,24 @@ impl Gateway { crate::grpc_output::take_handoffs(); crate::grpc_output::take_deliveries(); } - let progression = predecessor.as_ref() - .map(|predecessor| ledger.prepare_provider_progression(predecessor, &plan)) - .transpose()?; + let progression = if workflow.predecessors.is_empty() { + None + } else { + Some(ledger.prepare_workflow_candidate(&workflow.predecessors, &plan, workflow.observed.as_deref())?) + }; let execution = weaver_broker::execute_provider_progression( + &mut ledger, weaver_broker::ProviderExecution { plan: &plan, transport: &transport, format: if arrow { "arrow" } else { "protobuf" }, - batch_rows: request.batch_rows as usize, + batch_rows: batch_rows as usize, }, &mut output, weaver_broker::ProviderExecutionAdmission { authority: weaver_broker::ProviderExecutionAuthority { - catalog: &request.catalog_version, + catalog: &catalog, oauth: oauth.as_ref(), }, progression: progression.as_ref(), @@ -238,6 +372,13 @@ impl Gateway { } else { weaver_telemetry::Signal::ProviderFailed }); + // A duplicate root request may prompt reconciliation. Only + // the durable release and current guards can admit an edge. + if (result.is_ok() || session_root) + && let Some(wakeup) = wakeup + { + wakeup.notify_one(); + } if result.is_err() { let _ = sender.try_send(Err(Status::failed_precondition( "provider execution not completed; inspect original operation", @@ -250,11 +391,11 @@ impl Gateway { .telemetry() .record(weaver_telemetry::Signal::ProviderAdmitted); drop(job); // The runtime tracker, not the disconnected caller, owns completion. - Ok(Response::new(ResponseStream::new( + Ok(ResponseStream::new( receiver, cursor, cancelled, self.runtime.cancellation(), - ))) + )) } } diff --git a/crates/server/src/lib.rs b/crates/server/src/lib.rs index b49fd9c9..39163bfa 100644 --- a/crates/server/src/lib.rs +++ b/crates/server/src/lib.rs @@ -28,6 +28,7 @@ mod provider_oauth; mod review_wire; mod rpc_security; mod runtime; +mod session_workflow; mod shutdown; mod single_provider; mod source_artifact; diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs index 92aa1a55..eaa0103e 100644 --- a/crates/server/src/main.rs +++ b/crates/server/src/main.rs @@ -13,4 +13,11 @@ fn main() { eprintln!("{error}"); std::process::exit(1); } + let wall = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default(); + eprintln!( + "weaver shutdown stage=main-returning wall_ns={}", + wall.as_nanos() + ); } diff --git a/crates/server/src/runtime.rs b/crates/server/src/runtime.rs index 22b47ccc..09ad61f7 100644 --- a/crates/server/src/runtime.rs +++ b/crates/server/src/runtime.rs @@ -25,6 +25,7 @@ struct Inner { tasks: TaskTracker, single_provider: OnceLock, fact_feed: OnceLock, + session_wakeup: Arc, } struct AdmissionState { governance: Option, @@ -84,6 +85,7 @@ impl RuntimeOwner { tasks: TaskTracker::new(), single_provider: OnceLock::new(), fact_feed: OnceLock::new(), + session_wakeup: Arc::new(tokio::sync::Notify::new()), }), } } @@ -96,6 +98,16 @@ impl RuntimeOwner { pub(crate) fn fact_feed(&self) -> Option<&weaver_contracts::FactFeed> { self.inner.fact_feed.get() } + pub(crate) fn session_wakeup(&self) -> Option<&Arc> { + self.fact_feed() + .filter(|feed| !feed.workflow_path.is_empty()) + .map(|_| &self.inner.session_wakeup) + } + pub(crate) fn wake_session(&self) { + if let Some(wakeup) = self.session_wakeup() { + wakeup.notify_one(); + } + } #[cfg(any(feature = "scheme-program", test))] pub(crate) fn enable_single_provider(&self) -> Result<()> { self.inner diff --git a/crates/server/src/session_workflow.rs b/crates/server/src/session_workflow.rs new file mode 100644 index 00000000..7a86769e --- /dev/null +++ b/crates/server/src/session_workflow.rs @@ -0,0 +1,307 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Resume the sealed Session path from the durable provider frontier. +use crate::{ + grpc::Gateway, + grpc_provider::{StreamSettings, WorkflowAdmission}, +}; +use std::{collections::BTreeSet, sync::Arc}; +use tokio_stream::StreamExt; +use weaver_contracts::{Error, ProviderPlan, ProviderState, Result}; +use weaver_ledger::{Ledger, WorkflowObservation}; + +struct SessionStep { + admission: WorkflowAdmission, + next: ProviderPlan, + catalog: String, +} + +enum SessionWork { + Linear(SessionStep), + Graph(Box), +} + +struct SessionGraph { + plans: Vec, + cut: WorkflowObservation, + catalog: String, + edges: Vec<(String, String)>, +} + +impl Gateway { + pub(crate) async fn run_session_workflow(&self) { + let Some(wakeup) = self.runtime.session_wakeup() else { + return; + }; + let mut running = BTreeSet::new(); + let mut deferred = BTreeSet::new(); + let mut streams = tokio::task::JoinSet::new(); + loop { + tokio::select! { + biased; + _ = self.runtime.cancellation() => return, + result = streams.join_next(), if !streams.is_empty() => { + let Some(Ok(node)) = result else { return }; + running.remove(&node); + if deferred.remove(&node) { + wakeup.notify_one(); + } + continue; + } + _ = wakeup.notified() => {} + } + let Some(slot) = self.session_slot().await else { + return; + }; + let gateway = self.clone(); + let Ok(job) = self + .runtime + .spawn_blocking(slot, move |_| gateway.session_observation()) + else { + return; + }; + let Ok(Ok(Some(batch))) = job.await else { + continue; + }; + let steps = match batch { + SessionWork::Linear(step) => vec![step], + SessionWork::Graph(graph) => match self.derive_session_steps(*graph).await { + Ok(steps) => steps, + Err(_) => continue, + }, + }; + for step in steps { + let node = step.next.node.clone(); + if running.contains(&node) { + deferred.insert(node); + continue; + } + let Some(slot) = self.session_slot().await else { + break; + }; + let Ok(mut response) = self.start_provider_stream( + slot, + step.next, + step.admission, + None, + StreamSettings { + arrow: false, + batch_rows: 1, + catalog: step.catalog, + }, + ) else { + continue; + }; + running.insert(node.clone()); + streams.spawn(async move { + // Poll the existing guarded receiver. The release stays + // local to the Session; durable receipts remain inspectable. + while let Some(Ok(_)) = response.next().await {} + node + }); + } + } + } + + async fn session_slot(&self) -> Option> { + tokio::select! { + biased; + _ = self.runtime.cancellation() => None, + slot = self.admission.session_execution() => slot, + } + } + + async fn derive_session_steps(&self, graph: SessionGraph) -> Result> { + let SessionGraph { + plans, + cut, + edges, + catalog, + } = graph; + let nodes = plans.iter().map(|plan| plan.node.clone()).collect(); + let ready = self + .runtime + .governor()? + .derive(weaver_governance::GovernorCut { + nodes, + edges: edges.clone(), + complete: cut.complete.clone(), + available: cut.available.clone(), + pending: cut.pending.clone(), + nested_selectors: cut + .nested + .as_ref() + .map(|n| n.selectors.clone()) + .unwrap_or_default(), + nested_results: cut + .nested + .as_ref() + .map(|n| n.results.clone()) + .unwrap_or_default(), + nested_decisions: cut + .nested + .as_ref() + .map(|n| n.decisions.clone()) + .unwrap_or_default(), + choice_arms: cut + .choice + .as_ref() + .map(|choice| choice.arms.to_vec()) + .unwrap_or_default(), + choice_join: cut + .choice + .iter() + .map(|choice| choice.join.clone()) + .collect(), + choice_result: cut + .choice + .iter() + .filter_map(|choice| choice.route.map(|route| route.as_str().to_owned())) + .collect(), + choice_decided: cut + .choice + .iter() + .filter_map(|choice| choice.decided.clone()) + .collect(), + }) + .await + .map_err(|_| Error::Conflict("Scheme Governor derivation unavailable"))?; + let mut ready = std::collections::BTreeSet::from_iter(ready); + let cut = Arc::new(cut); + let mut steps = Vec::new(); + for next in &plans { + if !ready.remove(&next.node) { + continue; + } + let predecessors = edges + .iter() + .filter(|(child, parent)| { + child == &next.node + && cut.nested.as_ref().is_none_or(|nested| { + nested + .predecessors + .get(child) + .is_some_and(|parents| parents.contains(parent)) + }) + && cut.choice.as_ref().is_none_or(|choice| { + child != &choice.join || choice.decided.as_ref() == Some(parent) + }) + }) + .map(|(_, parent)| { + plans + .iter() + .find(|plan| &plan.node == parent) + .cloned() + .ok_or(Error::Conflict("Session predecessor missing")) + }) + .collect::>>()?; + if predecessors.is_empty() || !cut.pending.contains(&next.node) { + return Err(Error::Conflict("invalid Scheme Governor candidate")); + } + steps.push(SessionStep { + admission: WorkflowAdmission { + predecessors, + observed: Some(cut.clone()), + }, + next: next.clone(), + catalog: catalog.clone(), + }); + } + if !ready.is_empty() { + return Err(Error::Conflict("foreign Scheme Governor candidate")); + } + Ok(steps) + } + + fn session_observation(&self) -> Result> { + let Some(feed) = self.runtime.fact_feed() else { + return Ok(None); + }; + let Some(source) = self + .runtime + .single_provider() + .filter(|lifecycle| lifecycle.activated()) + .and_then(|lifecycle| lifecycle.ready.get()) + .map(crate::single_provider::Prepared::source) + else { + return Ok(None); + }; + let mut ledger = Ledger::open(&self.config.database)?; + // Activation and fact-resolution wakes can arrive during the root + // stream. Only a complete root can produce a DAG successor. Avoid + // taking the family authority cut while its first response is live. + // Durable completion emits another wake; admission still rechecks it. + if feed.workflow_dag + && ledger + .provider_receipt(&feed.family, &feed.root)? + .is_none_or(|receipt| receipt.state != ProviderState::Complete) + { + return Ok(None); + } + let plans = feed + .workflow_path + .iter() + .map(|node| { + source + .plans() + .iter() + .find(|plan| plan.family == feed.family && plan.node == *node) + .cloned() + .ok_or(Error::Conflict("compiled Session plan missing")) + }) + .collect::>>()?; + let catalog = ledger + .provider_catalog()? + .map(|(version, _)| version) + .unwrap_or_default(); + if feed.workflow_dag { + static TIMING: std::sync::OnceLock = std::sync::OnceLock::new(); + let started = TIMING + .get_or_init(|| std::env::var_os("WEAVER_TEST_GOVERNOR_TIMING").is_some()) + .then(std::time::Instant::now); + let cut = ledger.observe_workflow(&plans)?; + if let Some(started) = started { + eprintln!( + "weaver-governor-observe ledger_ns={}", + started.elapsed().as_nanos() + ); + } + return Ok(Some(SessionWork::Graph(Box::new(SessionGraph { + plans, + cut, + catalog, + edges: feed.dependencies.clone(), + })))); + } + let mut previous = None; + for current in plans { + let receipt = ledger.provider_receipt(¤t.family, ¤t.node)?; + match receipt { + Some(receipt) if receipt.digest != current.digest()? => { + return Err(Error::Conflict( + "Session claim differs from compiled original", + )); + } + Some(receipt) if receipt.state == ProviderState::Complete => { + previous = Some(current) + } + Some(receipt) if receipt.state == ProviderState::Unknown => return Ok(None), + _ => { + return Ok(previous.map(|previous| { + SessionWork::Linear(SessionStep { + admission: WorkflowAdmission { + predecessors: vec![previous], + observed: None, + }, + next: current, + catalog, + }) + })); + } + } + } + Ok(None) + } +} diff --git a/crates/server/src/shutdown.rs b/crates/server/src/shutdown.rs index e539fb8b..240f10ae 100644 --- a/crates/server/src/shutdown.rs +++ b/crates/server/src/shutdown.rs @@ -5,6 +5,14 @@ //! Install process signals before admission, then enter the ordinary tracked drain path. use weaver_contracts::Result; +pub(crate) fn trace(stage: &str) { + use std::time::{SystemTime, UNIX_EPOCH}; + let wall = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default(); + eprintln!("weaver shutdown stage={stage} wall_ns={}", wall.as_nanos()); +} + #[cfg(unix)] pub(crate) fn signal() -> Result + Send> { use tokio::signal::unix::{SignalKind, signal}; diff --git a/crates/server/src/single_provider.rs b/crates/server/src/single_provider.rs index 296a3bcb..4f8c793e 100644 --- a/crates/server/src/single_provider.rs +++ b/crates/server/src/single_provider.rs @@ -8,10 +8,8 @@ use std::sync::OnceLock; use tokio::sync::Mutex; use tokio_util::sync::CancellationToken; use tonic::Status; -use weaver_contracts::{ - ProviderPlan, PublicationOutcome, PublicationReceipt, SourceAuthority, SourceIdentity, -}; -use weaver_governance::BoundSource; +use weaver_contracts::{PublicationOutcome, PublicationReceipt, SourceAuthority, SourceIdentity}; +use weaver_governance::{BoundSource, OwnedSource}; #[derive(Default)] pub(crate) struct SingleProvider { @@ -62,6 +60,10 @@ impl Prepared { }) } + pub(crate) fn source(&self) -> &OwnedSource { + self.bound.source() + } + pub(crate) fn reply(&self) -> pb::CompiledSource { pb::CompiledSource { producer: self.producer.clone(), @@ -95,79 +97,42 @@ impl SingleProvider { pub(crate) async fn retired(&self) { self.retired.cancelled().await; } -} + pub(crate) fn activate_governor(&self) { + self.live.cancel(); + } -impl Gateway { - pub(crate) fn workflow_predecessor( - &self, - successor: &ProviderPlan, - ) -> Result, Status> { - let Some((feed, edge)) = self - .runtime - .fact_feed() - .filter(|feed| feed.family == successor.family) - .and_then(|feed| feed.workflow.as_ref().map(|edge| (feed, edge))) - .filter(|(_, edge)| edge.successor == successor.node) - else { - return Ok(None); - }; - let source = self - .runtime - .single_provider() - .filter(|lifecycle| lifecycle.live.is_cancelled()) - .and_then(|lifecycle| lifecycle.ready.get()) - .map(|prepared| prepared.bound.source()) - .ok_or(Status::failed_precondition( - "compiled workflow has not activated", - ))?; - let selection = &source.data().governance; - if selection.family != feed.family - || !selection.open_nodes.contains(&edge.predecessor) - || !selection.open_nodes.contains(&successor.node) - { - return Err(Status::failed_precondition( - "Governor workflow selection changed", - )); - } - let admitted = |node: &str| { - source - .plans() - .iter() - .find(|plan| plan.family == selection.family && plan.node == node) - .ok_or(Status::failed_precondition( - "compiled workflow plan missing", - )) - }; - if admitted(&successor.node)? != successor { - return Err(Status::failed_precondition( - "successor differs from compiled original", - )); - } - Ok(Some(admitted(&edge.predecessor)?.clone())) + pub(crate) fn activated(&self) -> bool { + self.live.is_cancelled() || self.retirement_completed() } + pub(crate) fn retirement_completed(&self) -> bool { + self.retired.is_cancelled() + } +} + +impl Gateway { pub(super) async fn retire_prepared_provider( &self, source: &SourceOwner, caller: SourceIdentity, receipt: &PublicationReceipt, ) -> Result<(), Status> { - let Some(lifecycle) = self.runtime.single_provider() else { - return Ok(()); - }; - let Some(prepared) = lifecycle.ready.get() else { + let Some(prepared) = self + .runtime + .single_provider() + .and_then(|lifecycle| lifecycle.ready.get()) + else { return Ok(()); }; if prepared.matches_commit(receipt) && prepared.authority.identity == caller && prepared.authority == source.authority(caller).await? { - if self - .runtime - .fact_feed() - .is_some_and(|feed| feed.workflow.is_some()) - { - lifecycle.live.cancel(); + if self.runtime.fact_feed().is_some() { + if let Some(lifecycle) = self.runtime.single_provider() { + lifecycle.activate_governor(); + self.runtime.wake_session(); + } return Ok(()); } self.runtime diff --git a/crates/server/src/source_owner.rs b/crates/server/src/source_owner.rs index edb58a64..002d0ac0 100644 --- a/crates/server/src/source_owner.rs +++ b/crates/server/src/source_owner.rs @@ -32,6 +32,7 @@ struct SourceDeployment { metering: Option, oauth: Option, fact_feed: Option, + session_wakeup: Option>, } enum Command { @@ -351,6 +352,7 @@ impl SourceOwner { ) -> Result { authority.validate()?; let fact_feed = runtime.fact_feed().cloned(); + let session_wakeup = runtime.session_wakeup().cloned(); Self::start_inner( runtime, slot, @@ -360,6 +362,7 @@ impl SourceOwner { metering, oauth, fact_feed, + session_wakeup, }, ) .await @@ -379,6 +382,7 @@ impl SourceOwner { metering: None, oauth: None, fact_feed: None, + session_wakeup: None, }, ) .await @@ -609,7 +613,13 @@ fn run( let result = if ready.send(Ok(())).is_err() { Err(Error::Conflict("source startup abandoned")) } else { - process(&mut ledger, receiver, handle, cancel) + process( + &mut ledger, + receiver, + handle, + cancel, + deployment.session_wakeup, + ) }; result.and(ledger.close()) } @@ -618,6 +628,7 @@ fn process( mut receiver: mpsc::Receiver, handle: Handle, cancel: CancellationToken, + session_wakeup: Option>, ) -> Result<()> { loop { let command = handle.block_on(async { @@ -661,6 +672,11 @@ fn process( let result = ledger.with_authenticated_source(&caller, |ledger| { ledger.resolve_fact_projection(&work, affected) }); + if result.is_ok() + && let Some(wakeup) = &session_wakeup + { + wakeup.notify_one(); + } answer(ledger, reply, result, slot)?; } Command::ChangeProviderOAuth { @@ -708,6 +724,11 @@ fn process( let result = ledger.with_authenticated_source(&caller, |ledger| { ledger.publish_provider_catalog(&catalog) }); + if result.is_ok() + && let Some(wakeup) = &session_wakeup + { + wakeup.notify_one(); + } answer(ledger, reply, result, slot)?; } Command::ApplyMetering { diff --git a/crates/server/tests/unit/governance_owner.rs b/crates/server/tests/unit/governance_owner.rs index e0462c90..e55b7cfd 100644 --- a/crates/server/tests/unit/governance_owner.rs +++ b/crates/server/tests/unit/governance_owner.rs @@ -46,6 +46,7 @@ fn original() -> OwnedSource { }) .expect("original source") } + #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn single_provider_retirement_joins_cleanup_without_closing_ingress() { let runtime = ServiceRuntime::new(); diff --git a/dev/sysml/ControlActivation.sysml b/dev/sysml/ControlActivation.sysml index 35b5e8be..d52bf17a 100644 --- a/dev/sysml/ControlActivation.sysml +++ b/dev/sysml/ControlActivation.sysml @@ -27,6 +27,9 @@ package ControlActivation { Stable caller memory and native copy fidelity remain host premises. Scheme assessment, source-authority reobservation, stage/register/ final publication CAS and Rust current-use checks remain separate. + The Rust preparation owner retains the original-bound typed source + for Session observation. An RPC replay projects that same source + onto the wire after the caller and source authority checks. No cached approval replaces claim, budget, history or fence. Runtime evidence separates source activation and actual streaming; builds and fixture startup are excluded, and replay is never a fresh @@ -77,6 +80,12 @@ package ControlActivation { release. Preserve failed deadlines and distinguish unavailable process inventory from an absent process. No source/credential payload or path belongs in producer-created phase attributes. */ + doc /* Release qualification observes linked VM readiness, source-module + view loading, semantic preparation, artifact delivery and authority + reconciliation as separate stages. The source RPC's 10-second + limit is distinct from the 15-second control readiness observation. + A failed trial still records Scheme cancellation, Rust owner cleanup + and the natural process exit outcome. */ } requirement def GovernorSourceHandoff { doc /* Allocate original semantics and derivation constraints to diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index 96797d80..73c46d3d 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -303,6 +303,7 @@ {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem provider_and_connection_composition"}]}, {"id":"SourceIngressBinding","witnesses":[ {"file":"go/dev/provider_source_test.go","pattern":"func TestProviderSourceIngressBindsCertificateCredentialAndMethod"}, + {"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledCatalogRequiresExactSourceEpoch"}, {"file":"go/dev/provider_capacity_test.go","pattern":"full operation ingress blocked new source session"}, {"file":"crates/server/tests/unit/grpc_ingress.rs","pattern":"async fn aliased_or_empty_source_identity_is_rejected_before_serving"}, {"file":"dev/proofs/quint/SourceIngress.qnt","pattern":"run forwardedCredentialCounterexampleTest"}, @@ -338,6 +339,7 @@ {"file":"dev/proofs/quint/ReleaseBinding.qnt","pattern":"run crossPlanCounterexampleTest"}, {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem release_binding_and_execution_composition"}]}, {"id":"SpecificSourceContracts","witnesses":[ + {"file":"crates/server/src/single_provider.rs","pattern":"bound: BoundSource"}, {"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"}, {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run governanceCannotReplaceGovernorTest"}, {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run missingGovernorCounterexampleTest"}, @@ -485,6 +487,8 @@ {"file":"crates/governance/src/host/client.rs","pattern":"pub fn source_lane"}, {"file":"crates/governance/src/host/owner.rs","pattern":"pub fn run"}, {"file":"crates/governance/tests/unit/host.rs","pattern":"cancelled_running_work_keeps_its_slot_until_natural_return"}, + {"file":"crates/governance/tests/unit/host.rs","pattern":"active_compiler_observes_both_request_and_owner_cancellation"}, + {"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSourceCancellationDrainsSchemeOwner"}, {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"checkThenSendCloseRaceCounterexampleTest"}, {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_host_delivery_requires_open_gate"}, {"file":"crates/governance/src/binding.rs","pattern":"pub struct SourceExpectation"}, @@ -521,6 +525,7 @@ {"file":"t/integration/governed-control-test.ss","pattern":"def governed-control-test"}, {"file":"go/internal/config/bundle_test.go","pattern":"func TestBundleRejectsSelectionAndCommitmentSubstitution"}]}, {"id":"SourceStartupObservation","witnesses":[ + {"file":"scheme/gateway/provider-program.ss","pattern":"call-with-module-source-operation-measurement"}, {"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeVerificationUsesOnlyPublicPackageEntries"}, {"file":"crates/governance-build/src/program.rs","pattern":"build_program_archive_with_contract"}, {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run releaseTagCannotRebaseCapturedSourceCounterexampleTest"}, @@ -531,6 +536,12 @@ {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run stalePreparationReceiptCounterexampleTest"}, {"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"}, {"file":"go/internal/controlplane/deployment.go","pattern":"trace\\(\"authority-reconciled\"\\)"}, + {"file":"scheme/gateway/func.ss","pattern":"source-selection-loaded"}, + {"file":"scheme/gateway/func.ss","pattern":"source-module-view-loaded"}, + {"file":"scheme/gateway/func.ss","pattern":"source-contracts-checked"}, + {"file":"scheme/gateway/func.ss","pattern":"source-advisory-derived"}, + {"file":"go/dev/provider_governor_performance_test.go","pattern":"status=failed drain_ns"}, + {"file":"crates/governance/src/host/owner.rs","pattern":"scheme-owner-drop-begin"}, {"file":"t/fixtures/governed-control.ss","pattern":"fixture-module-ready"}, {"file":"go/dev/provider_control_test.go","pattern":"These unauthenticated diagnostics never replace readiness or exit checks"}, {"file":"crates/governance-build/src/tooling.rs","pattern":"fn bind_package_sources"}, @@ -577,10 +588,21 @@ {"id":"SessionWorkflowFrontier","witnesses":[ {"file":"scheme/gateway/program.ss","pattern":"def \\(hard-fact-affected"}, {"file":"go/dev/provider_hard_fact_test.go","pattern":"func TestProviderControlHardFactWithdrawalRestartAndABA"}, + {"file":"scheme/gateway/func.ss","pattern":"def \\(session-workflow-path"}, + {"file":"crates/server/src/governance_deployment.rs","pattern":"admits_session_workflow"}, {"file":"crates/ledger/src/provider_workflow.rs","pattern":"fn bind_winner"}, {"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn provider_workflow_rechecks_prepared_floor_and_frontier_before_one_reservation"}, + {"file":"crates/server/src/session_workflow.rs","pattern":"async fn run_session_workflow"}, + {"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionWorkflowAutomaticallyResumes"}, + {"file":"scheme/gateway/func.ss","pattern":"def \\(governor-ready-steps"}, {"file":"crates/ledger/src/provider_workflow.rs","pattern":"pub fn observe_workflow"}, + {"file":"crates/governance/src/host/owner.rs","pattern":"cut_sha256=.*ready_sha256="}, + {"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched inner-join cut_sha256="}, + {"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched outer-join cut_sha256="}, + {"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionDAGConcurrentJoinAndRecovery"}, {"file":"crates/ledger/src/provider_workflow_choice.rs","pattern":"fn record_result"}, + {"file":"go/dev/provider_workflow_choice_test.go","pattern":"func TestProviderControlSessionChoiceFromReleasedResult"}, {"file":"crates/ledger/src/provider_workflow_nested.rs","pattern":"fn load"}, - {"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn nested_workflow_rejects_stale_decision_and_keeps_winner_after_reopen"}]} + {"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn nested_workflow_rejects_stale_decision_and_keeps_winner_after_reopen"}, + {"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSessionNestedChoiceAndParallelRecovery"}]} ] diff --git a/go/dev/provider_control_test.go b/go/dev/provider_control_test.go index 2cb65f78..f61e21f3 100644 --- a/go/dev/provider_control_test.go +++ b/go/dev/provider_control_test.go @@ -124,9 +124,14 @@ func (c *controlProcess) start(t testing.TB) { c.child = child c.exited = make(chan error, 1) exited := c.exited - go func() { err := child.Wait(); log.Close(); exited <- err }() ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() + go func() { + err := child.Wait() + log.Close() + exited <- err + cancel() + }() caller := c.fixture.pki.client if c.ingress != nil { caller = c.ingress.client diff --git a/go/dev/provider_fixture_test.go b/go/dev/provider_fixture_test.go index c6307518..6a257a50 100644 --- a/go/dev/provider_fixture_test.go +++ b/go/dev/provider_fixture_test.go @@ -437,6 +437,10 @@ func (f *fixture) start(t testing.TB) { } } func (f *fixture) stop(t testing.TB) { + f.stopObserved(t, nil) +} + +func (f *fixture) stopObserved(t testing.TB, observe func(string, time.Time)) { t.Helper() if f.child == nil { return @@ -447,17 +451,35 @@ func (f *fixture) stop(t testing.TB) { if f.admin != nil { f.admin.Connection.Close() } + if observe != nil { + observe("connections-closed", time.Now()) + } f.child.Process.Signal(syscall.SIGTERM) + if observe != nil { + observe("signal-sent", time.Now()) + } select { case err := <-f.exited: + if observe != nil { + observe("exit-observed", time.Now()) + } if err != nil { data, _ := os.ReadFile(filepath.Join(f.directory, "server.log")) t.Errorf("server natural exit: %v: %s", err, data) } case <-time.After(15 * time.Second): + data, _ := os.ReadFile(filepath.Join(f.directory, "server.log")) f.child.Process.Kill() <-f.exited - t.Error("server did not exit naturally; cleanup kill is a failure") + t.Errorf("server did not exit naturally; cleanup kill is a failure: %s", data) + } + if os.Getenv("WEAVER_TEST_SOURCE_MEASURE") != "" { + data, _ := os.ReadFile(filepath.Join(f.directory, "server.log")) + for _, line := range strings.Split(string(data), "\n") { + if strings.HasPrefix(line, "weaver source metric=") { + t.Log(line) + } + } } f.child = nil } diff --git a/go/dev/provider_governor_performance_test.go b/go/dev/provider_governor_performance_test.go new file mode 100644 index 00000000..2ed8a160 --- /dev/null +++ b/go/dev/provider_governor_performance_test.go @@ -0,0 +1,215 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build integration && schemeintegration && !windows + +package dev + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "os" + "path/filepath" + "strconv" + "strings" + "testing" + "time" +) + +type governorTrial struct { + arm string + replay bool + retained bool + innerJoinCut string + outerJoinCut string +} + +func (trial governorTrial) offerReplay(ctx context.Context, f *fixture, producer string) <-chan error { + if !trial.replay { + return nil + } + offered := make(chan struct{}) + result := make(chan error, 1) + go func() { + close(offered) + _, err := f.admin.CompileSource(ctx, producer) + result <- err + }() + <-offered + return result +} + +func (trial *governorTrial) finish(t *testing.T, f *fixture, c *controlProcess) { + t.Helper() + c.stop(t) + start := time.Now() + type shutdownObservation struct { + stage string + at time.Time + } + var observations [3]shutdownObservation + count := 0 + f.stopObserved(t, func(stage string, at time.Time) { + observations[count] = shutdownObservation{stage, at} + count++ + }) + drain := time.Since(start) + for _, observation := range observations[:count] { + t.Logf("governor shutdown stage=%s wall_ns=%d elapsed_ns=%d", + observation.stage, observation.at.UnixNano(), observation.at.Sub(start).Nanoseconds()) + } + log, err := os.ReadFile(filepath.Join(f.directory, "server.log")) + if err != nil { + t.Fatal(err) + } + type boundary struct { + mono, wall uint64 + } + commits := make(map[string]boundary) + var begin, end uint64 + mode := "fresh" + if trial.retained { + mode = "retained" + } + var modeObserved bool + var derivations int + var ownerDecisions int + var innerJoinCut, outerJoinCut string + readyDigest := func(result string) string { + digest := sha256.Sum256([]byte(result)) + return hex.EncodeToString(digest[:]) + } + innerReady := readyDigest(`["inner-finish"]`) + outerReady := readyDigest(`["finish"]`) + matchJoin := func(target *string, cut, predecessor, successor string) { + if commits["release/"+predecessor].wall == 0 || commits["reserve/"+successor].wall != 0 { + return + } + if *target != "" && *target != cut { + t.Fatal("join had multiple distinct Governor inputs", successor, *target, cut) + } + *target = cut + } + readDigest := func(field, prefix string) string { + digest, found := strings.CutPrefix(field, prefix) + decoded, err := hex.DecodeString(digest) + if !found || err != nil || len(decoded) != sha256.Size { + t.Fatal("invalid Governor decision digest", field) + } + return digest + } + parse := func(field string) uint64 { + value, err := strconv.ParseUint(field, 10, 64) + if err != nil { + t.Fatal("malformed Governor trace", field, err) + } + return value + } + lines := strings.Split(string(log), "\n") + for _, line := range lines { + if strings.HasPrefix(line, "weaver shutdown stage=") || + strings.HasPrefix(line, "weaver scheme phase=") || + strings.HasPrefix(line, "weaver-governor-") { + t.Log(line) + } + } + if t.Failed() { + t.Logf("governor trial arm=%s replay=%t status=failed drain_ns=%d", trial.arm, trial.replay, drain.Nanoseconds()) + return + } + for _, line := range lines { + if !strings.HasPrefix(line, "weaver-governor-") { + continue + } + fields := strings.Fields(line) + switch fields[0] { + case "weaver-governor-mode": + if len(fields) != 2 || fields[1] != mode { + t.Fatal("unexpected Scheme Governor mode", line) + } + modeObserved = true + case "weaver-governor-ascent": + expected := "fresh" + if trial.retained { + // The scenario keeps its topology fixed while release facts change. + expected = "open" + if derivations > 0 { + expected = "replace" + } + } + if len(fields) != 4 || fields[3] != "mode="+expected { + t.Fatalf("Governor decision %d expected %s: %s", derivations+1, expected, line) + } + derivations++ + case "weaver-governor-owner": + if len(fields) != 6 || fields[3] != "ok=true" { + t.Fatal("invalid or failed Governor owner decision", line) + } + ownerDecisions++ + cut := readDigest(fields[4], "cut_sha256=") + ready := readDigest(fields[5], "ready_sha256=") + switch ready { + case innerReady: + matchJoin(&innerJoinCut, cut, "fork-b", "inner-finish") + case outerReady: + matchJoin(&outerJoinCut, cut, "inner-finish", "finish") + } + case "weaver-governor-commit": + if len(fields) != 7 { + t.Fatal("invalid commit trace", line) + } + key := fields[1] + "/" + fields[3] + if _, duplicate := commits[key]; duplicate { + t.Fatal("duplicate committed boundary", key) + } + commits[key] = boundary{mono: parse(fields[4]), wall: parse(fields[5])} + case "weaver-governor-compile": + if len(fields) != 3 { + t.Fatal("invalid compile trace", line) + } + at := parse(fields[2]) + if at == 0 { + t.Fatal("zero native compile timestamp", line) + } + switch fields[1] { + case "begin": + if begin != 0 { + t.Fatal("duplicate native compile entry", line) + } + begin = at + case "end": + if end != 0 { + t.Fatal("duplicate native compile exit", line) + } + end = at + default: + t.Fatal("unknown native compile boundary", line) + } + } + } + if !modeObserved { + t.Fatal("missing Scheme Governor mode observation") + } + if derivations < 2 || ownerDecisions != derivations || innerJoinCut == "" || outerJoinCut == "" { + t.Fatalf("incomplete Governor decision trace: ASCENT=%d owner=%d inner cut=%q outer cut=%q", derivations, ownerDecisions, innerJoinCut, outerJoinCut) + } + a, b := commits["release/fork-a"], commits["release/fork-b"] + innerRelease, innerReserve := commits["release/inner-finish"], commits["reserve/inner-finish"] + outer := commits["reserve/finish"] + if a.wall == 0 || b.mono <= a.mono || innerReserve.mono <= b.mono || + innerRelease.mono <= innerReserve.mono || outer.mono <= innerRelease.mono { + t.Fatal("missing or out-of-order fork and join evidence", commits) + } + overlap := a.wall < begin && begin < b.wall && b.wall < end + if begin == 0 || end <= begin || end >= a.wall { + t.Fatalf("unexpected native compile entry: replay=%t fork-a=%d begin=%d fork-b=%d end=%d", trial.replay, a.wall, begin, b.wall, end) + } + trial.innerJoinCut = innerJoinCut + trial.outerJoinCut = outerJoinCut + t.Logf("governor inner-join cut_sha256=%s ready_sha256=%s", innerJoinCut, innerReady) + t.Logf("governor outer-join cut_sha256=%s ready_sha256=%s", outerJoinCut, outerReady) + t.Logf("governor trial arm=%s replay=%t status=complete inner_ns=%d outer_ns=%d drain_ns=%d overlap=%t", + trial.arm, trial.replay, innerReserve.mono-b.mono, outer.mono-innerRelease.mono, drain.Nanoseconds(), overlap) +} diff --git a/go/dev/provider_program_deployment_test.go b/go/dev/provider_program_deployment_test.go index 6ef6be80..1ca39b61 100644 --- a/go/dev/provider_program_deployment_test.go +++ b/go/dev/provider_program_deployment_test.go @@ -12,16 +12,21 @@ import ( "crypto/x509" "encoding/hex" "encoding/json" + "io" + "net/http" "os" "os/exec" "path/filepath" + "strconv" "strings" + "sync" "testing" "time" pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" v1 "github.com/HardenedLinux/weaver/go/api/v1" "github.com/HardenedLinux/weaver/go/internal/config" + "github.com/HardenedLinux/weaver/go/internal/gatewayclient" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" @@ -58,6 +63,7 @@ func configuredCatalogPath(t testing.TB, f *fixture, bundle config.Bundle) strin if err := os.WriteFile(path, data, 0600); err != nil { t.Fatal(err) } + t.Logf("developer fixture catalog sha256=%x", sha256.Sum256(data)) return path } @@ -165,6 +171,439 @@ func TestProviderControlCompiledGovernorSuccessorUsesCompleteRelease(t *testing. } } +func TestProviderControlSessionWorkflowAutomaticallyResumes(t *testing.T) { + t.Run("restart", func(t *testing.T) { exerciseAutomaticSession(t, false) }) + t.Run("withdrawal", func(t *testing.T) { exerciseAutomaticSession(t, true) }) +} + +func exerciseAutomaticSession(t *testing.T, withdraw bool) { + t.Helper() + rootEntered := make(chan struct{}, 1) + releaseRoot := make(chan struct{}) + var release sync.Once + unblock := func() { release.Do(func() { close(releaseRoot) }) } + defer unblock() + f := newFixture(t, func(w http.ResponseWriter, r *http.Request) { + body, err := io.ReadAll(r.Body) + if err != nil { + t.Error(err) + return + } + if !strings.Contains(string(body), `"content":"finish"`) { + select { + case rootEntered <- struct{}{}: + default: + t.Error("extra root send") + } + select { + case <-releaseRoot: + case <-r.Context().Done(): + return + } + } + completeSSE(w, r) + }, false) + bundle := controlBundle(t, f) + bundle.Governance.Schema = config.SessionWorkflowSchema + bundle.Governance.OpenNodes = append(bundle.Governance.OpenNodes, "finish") + task := &bundle.Tasks[0] + task.Nodes = append(task.Nodes, "finish") + task.Budget = 12 + finish := bundle.Plans[0] + finish.Node = "finish" + bundle.Plans = append(bundle.Plans, finish) + for _, route := range bundle.Plans[1].Routes { + if route.Target == "backup" { + bundle.Plans[1].Routes = []v1.ProviderRoute{route} + break + } + } + for i := 1; i < len(bundle.Plans); i++ { + step := &bundle.Plans[i] + step.Body = strings.Replace(step.Body, `"hello"`, `"`+step.Node+`"`, 1) + digest, err := step.Digest() + if err != nil { + t.Fatal(err) + } + body := sha256.Sum256([]byte(step.Body)) + task.BodyDigests[step.Node] = hex.EncodeToString(body[:]) + task.StreamContracts[step.Node] = digest + task.NodeCostBounds[step.Node] = step.Ceiling + } + bundle.Publication.Policy = strings.Replace(bundle.Publication.Policy, `["infer", "next"]`, `["infer", "next", "finish"]`, 1) + root, next, finish := bundle.Plans[0], bundle.Plans[1], bundle.Plans[2] + f.env = append(f.env, `WEAVER_PROVIDER_CREDENTIAL_ENVS={"primary":"WEAVER_TEST_KEY"}`, + "WEAVER_GOVERNANCE_RETIRE_ON_ACTIVATION=1", + hardFactFeedSetting(t, f, root.Family, root.Node, [][2]string{{next.Node, root.Node}, {finish.Node, next.Node}}, + nil, config.SessionWorkflowSchema, nil, bundle.Governance.OpenNodes...)) + policy := compiledControlSources(false) + policy.configure(t, f, bundle) + c := newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")) + c.useProducer(policy.producer) + c.start(t) + ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second) + defer cancel() + prepared, err := f.admin.CompileSource(ctx, policy.producer) + if err != nil || prepared.GetArtifact().GetGovernance().GetSchema() != config.SessionWorkflowSchema || + strings.Join(prepared.GetArtifact().GetGovernance().GetOpenNodes(), ",") != "infer,next,finish" { + t.Fatalf("native Session Workflow handoff: %v", err) + } + stage := func(revision uint64, previous *pb.HardFactBarrier, available bool) *pb.HardFactBarrier { + t.Helper() + snapshot := strings.Repeat("0", 64) + if previous != nil { + snapshot = previous.Snapshot + } + intent := &pb.HardFactIntent{OperationId: "session-fact-" + strconv.FormatUint(revision, 10), + Domain: "availability", Revision: revision, PreviousSnapshot: snapshot, ExpectedFloor: previous.GetFloor(), + Available: proto.Bool(available)} + barrier, err := f.admin.RPC.StageHardFact(f.admin.Context(ctx), intent) + if err != nil || barrier.GetFloor() != revision { + t.Fatalf("stage fact %d: %v %v", revision, barrier, err) + } + return barrier + } + resolve := func(barrier *pb.HardFactBarrier) { + t.Helper() + result, err := f.admin.RPC.ResolveHardFact(f.admin.Context(ctx), barrier) + if err != nil || !proto.Equal(barrier, result.GetBarrier()) || + strings.Join(result.GetAffected(), ",") != "finish,infer,next" { + t.Fatalf("native ASCENT workflow closure: %v %v", result, err) + } + } + attempt := func(step v1.ProviderPlan) error { + _, err := c.client.Execute(ctx, step, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }) + return err + } + receipt := func(step v1.ProviderPlan) (*pb.ProviderReceipt, error) { + return c.client.RPC.Inspect(c.client.Context(ctx), &pb.OperationKey{Family: step.Family, Node: step.Node}) + } + wait := func(step v1.ProviderPlan, state string, held uint64) *pb.ProviderReceipt { + t.Helper() + tick := time.NewTicker(20 * time.Millisecond) + defer tick.Stop() + digest, err := step.Digest() + if err != nil { + t.Fatal(err) + } + for { + r, err := receipt(step) + if err == nil && r.GetState() == state { + if r.GetDigest() != digest || r.GetHeld() != held || r.GetReserved() != 4 || + (state == "complete" && r.GetEvents() == 0) { + t.Fatalf("unexpected durable %s receipt: %v", step.Node, r) + } + return r + } + select { + case <-tick.C: + case <-ctx.Done(): + t.Fatalf("expected %s state %s: %v %v", step.Node, state, r, err) + } + } + } + assertSends := func(primary, backup int64) { + t.Helper() + if f.primary.Load() != primary || f.backup.Load() != backup || f.denied.Load() != 0 { + t.Fatalf("upstream sends %d/%d/%d, want %d/%d/0", f.primary.Load(), f.backup.Load(), f.denied.Load(), primary, backup) + } + } + waitFailed := func(expected uint64) { + t.Helper() + tick := time.NewTicker(20 * time.Millisecond) + defer tick.Stop() + for { + m, err := f.admin.RPC.InspectTelemetry(f.admin.Context(ctx), &pb.Empty{}) + if err == nil && m.GetProviderFailed() >= expected { + return + } + select { + case <-tick.C: + case <-ctx.Done(): + t.Fatalf("Session did not reconcile against withdrawal: %v %v", m, err) + } + } + } + duplicateRoot := func() { + t.Helper() + results := make(chan error, 2) + for range 2 { + go func() { results <- attempt(root) }() + } + for range 2 { + if err := <-results; status.Code(err) != codes.FailedPrecondition { + t.Fatalf("duplicate root unexpectedly executed: %v", err) + } + } + } + + a := stage(1, nil, true) + resolve(a) + result := make(chan error, 1) + go func() { result <- attempt(root) }() + select { + case <-rootEntered: + case err := <-result: + t.Fatalf("root did not reach upstream: %v", err) + case <-ctx.Done(): + t.Fatal("root did not reach upstream") + } + if _, err := receipt(next); status.Code(err) != codes.FailedPrecondition { + t.Fatalf("successor claimed before root release: %v", err) + } + assertSends(1, 0) + unblock() + if err := <-result; err != nil { + t.Fatal(err) + } + + queued := wait(next, "queued", 8) + if err := attempt(next); status.Code(err) != codes.FailedPrecondition { + t.Fatalf("operation caller took over Session successor: %v", err) + } + duplicateRoot() + if retry := wait(next, "queued", 8); !proto.Equal(queued, retry) { + t.Fatal("duplicate trigger changed the successor claim") + } + assertSends(1, 0) + t.Log("complete release queued next automatically; duplicate triggers preserved its claim and held=8") + var b *pb.HardFactBarrier + if withdraw { + b = stage(2, a, false) + } + c.stop(t) + f.stop(t) + f.env = append(f.env, `WEAVER_PROVIDER_CREDENTIAL_ENVS={"primary":"WEAVER_TEST_KEY","backup":"WEAVER_TEST_KEY"}`) + f.start(t) + c.start(t) + if withdraw { + if replay := stage(2, a, false); !proto.Equal(replay, b) { + t.Fatal("restart changed the pending withdrawal") + } + waitFailed(1) + wait(next, "queued", 8) + assertSends(1, 0) + resolve(b) + waitFailed(2) + duplicateRoot() + wait(next, "queued", 8) + assertSends(1, 0) + t.Log("pending and resolved withdrawal fenced the already reserved successor after restart") + resolve(stage(3, b, true)) + } + // No Execute calls for either successor after restart. A late completion + // or duplicate wake must continue under the original reservations. + wait(finish, "complete", 12) + wait(next, "complete", 12) + duplicateRoot() + assertSends(2, 1) + t.Log("Session completed after restart; infer/finish primary=2 next backup=1 held=12") +} + +func graphSessionBundle(t *testing.T, f *fixture, schema, backupNode string, budget uint64) config.Bundle { + t.Helper() + return sessionGraphBundle(t, f, config.Governance{ + Schema: schema, OpenNodes: []string{"infer", "next", "side", "finish"}, + WorkflowEdges: [][2]string{{"finish", "next"}, {"finish", "side"}, {"next", "infer"}, {"side", "infer"}}, + }, backupNode, budget) +} + +func sessionGraphBundle(t *testing.T, f *fixture, governance config.Governance, backupNode string, budget uint64) config.Bundle { + t.Helper() + bundle := controlBundle(t, f) + governance.Family = bundle.Governance.Family + bundle.Governance = governance + nodes := governance.OpenNodes + task := &bundle.Tasks[0] + task.Nodes = nodes + task.Budget = budget + root := bundle.Plans[0] + bundle.Plans = []v1.ProviderPlan{root} + for _, node := range nodes[1:] { + step := root + step.Node = node + step.Body = strings.Replace(step.Body, `"hello"`, `"`+node+`"`, 1) + if node == backupNode { + for _, route := range step.Routes { + if route.Target == "backup" { + step.Routes = []v1.ProviderRoute{route} + break + } + } + } + digest, err := step.Digest() + if err != nil { + t.Fatal(err) + } + body := sha256.Sum256([]byte(step.Body)) + task.BodyDigests[node] = hex.EncodeToString(body[:]) + task.StreamContracts[node] = digest + task.NodeCostBounds[node] = step.Ceiling + bundle.Plans = append(bundle.Plans, step) + } + nodeList, err := json.Marshal(nodes) + if err != nil { + t.Fatal(err) + } + bundle.Publication.Policy = strings.Replace(bundle.Publication.Policy, `["infer", "next"]`, string(nodeList), 1) + return bundle +} + +func TestProviderControlSessionDAGConcurrentJoinAndRecovery(t *testing.T) { + arrived := make(chan string, 2) + nextRelease, sideRelease := make(chan struct{}), make(chan struct{}) + var nextOnce, sideOnce sync.Once + releaseNext := func() { nextOnce.Do(func() { close(nextRelease) }) } + releaseSide := func() { sideOnce.Do(func() { close(sideRelease) }) } + defer releaseNext() + defer releaseSide() + f := newFixture(t, func(w http.ResponseWriter, r *http.Request) { + body, err := io.ReadAll(r.Body) + if err != nil { + t.Error(err) + return + } + for node, release := range map[string]chan struct{}{"next": nextRelease, "side": sideRelease} { + if strings.Contains(string(body), `"content":"`+node+`"`) { + select { + case arrived <- node: + default: + t.Error("duplicate branch send") + } + select { + case <-release: + case <-r.Context().Done(): + return + } + break + } + } + completeSSE(w, r) + }, false) + bundle := graphSessionBundle(t, f, config.SessionDAGSchema, "finish", 16) + root := bundle.Plans[0] + nodes, edges := bundle.Governance.OpenNodes, bundle.Governance.WorkflowEdges + f.env = append(f.env, `WEAVER_PROVIDER_CREDENTIAL_ENVS={"primary":"WEAVER_TEST_KEY"}`, + hardFactFeedSetting(t, f, root.Family, root.Node, edges, nil, config.SessionDAGSchema, nil, nodes...)) + policy := compiledControlSources(false) + policy.configure(t, f, bundle) + c := newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")) + c.useProducer(policy.producer) + c.start(t) + ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second) + defer cancel() + prepared, err := f.admin.CompileSource(ctx, policy.producer) + if err != nil || len(prepared.GetArtifact().GetGovernance().GetWorkflowEdges()) != 4 { + t.Fatalf("compiled Funflow topology: %v %v", prepared, err) + } + stage := func(revision uint64, prior *pb.HardFactBarrier, available bool) *pb.HardFactBarrier { + t.Helper() + snapshot := strings.Repeat("0", 64) + if prior != nil { + snapshot = prior.GetSnapshot() + } + r, err := f.admin.RPC.StageHardFact(f.admin.Context(ctx), &pb.HardFactIntent{ + OperationId: "dag-fact-" + strconv.FormatUint(revision, 10), Domain: "availability", + Revision: revision, PreviousSnapshot: snapshot, ExpectedFloor: prior.GetFloor(), Available: proto.Bool(available), + }) + if err != nil || r.GetFloor() != revision { + t.Fatalf("stage DAG hard fact: %v %v", r, err) + } + return r + } + resolve := func(barrier *pb.HardFactBarrier) { + t.Helper() + r, err := f.admin.RPC.ResolveHardFact(f.admin.Context(ctx), barrier) + if err != nil || !proto.Equal(r.GetBarrier(), barrier) || strings.Join(r.GetAffected(), ",") != "finish,infer,next,side" { + t.Fatalf("resolve DAG hard fact: %v %v", r, err) + } + } + inspect := func(node string) (*pb.ProviderReceipt, error) { + return c.client.RPC.Inspect(c.client.Context(ctx), &pb.OperationKey{Family: root.Family, Node: node}) + } + wait := func(node, state string, held uint64) *pb.ProviderReceipt { + t.Helper() + tick := time.NewTicker(20 * time.Millisecond) + defer tick.Stop() + for { + r, err := inspect(node) + if err == nil && r.GetState() == state && r.GetHeld() == held { + return r + } + select { + case <-tick.C: + case <-ctx.Done(): + t.Fatalf("DAG %s expected %s, held %d: %v %v", node, state, held, r, err) + } + } + } + attemptRoot := func() error { + _, err := c.client.Execute(ctx, root, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }) + return err + } + a := stage(1, nil, true) + resolve(a) + if err := attemptRoot(); err != nil { + t.Fatal(err) + } + seen := map[string]bool{} + for range 2 { + select { + case node := <-arrived: + seen[node] = true + case <-ctx.Done(): + t.Fatal("both branches must dispatch before either releases") + } + } + if !seen["next"] || !seen["side"] { + t.Fatalf("duplicate branch dispatch: %v", seen) + } + releaseNext() + wait("next", "complete", 12) + if _, err := inspect("finish"); status.Code(err) != codes.FailedPrecondition || f.backup.Load() != 0 { + t.Fatalf("join admitted with just one release: %v", err) + } + releaseSide() + queued := wait("finish", "queued", 16) + for range 2 { + if err := attemptRoot(); status.Code(err) != codes.FailedPrecondition { + t.Fatalf("root replay: %v", err) + } + } + if replay := wait("finish", "queued", 16); !proto.Equal(replay, queued) { + t.Fatal("duplicate reconciliation replaced join claim") + } + t.Log("both branches dispatched concurrently; one release did not admit join; two releases reserved join once") + b := stage(2, a, false) + c.stop(t) + f.stop(t) + f.env = append(f.env, `WEAVER_PROVIDER_CREDENTIAL_ENVS={"primary":"WEAVER_TEST_KEY","backup":"WEAVER_TEST_KEY"}`) + f.start(t) + c.start(t) + if replay := stage(2, a, false); !proto.Equal(replay, b) { + t.Fatal("restart changed the withdrawal barrier") + } + wait("finish", "queued", 16) + resolve(b) + if err := attemptRoot(); status.Code(err) != codes.FailedPrecondition { + t.Fatalf("root replay crossed withdrawal: %v", err) + } + wait("finish", "queued", 16) + if f.primary.Load() != 3 || f.backup.Load() != 0 { + t.Fatal("join sent under withdrawal or a predecessor repeated") + } + resolve(stage(3, b, true)) + finished := wait("finish", "complete", 16) + if finished.GetDigest() != queued.GetDigest() || finished.GetReserved() != 4 || + finished.GetEvents() == 0 || f.primary.Load() != 3 || f.backup.Load() != 1 || f.denied.Load() != 0 { + t.Fatalf("recovered join receipt and sends: %v %d/%d/%d", finished, f.primary.Load(), f.backup.Load(), f.denied.Load()) + } + if err := attemptRoot(); status.Code(err) != codes.FailedPrecondition || f.backup.Load() != 1 { + t.Fatalf("completed join replay: %v", err) + } + t.Log("restart and withdrawal retained join; restored facts released it once; primary=3 backup=1 held=16") +} + func TestProviderControlCompiledProgramSharedBudgetRejectsConcurrentSendAndSDKRetry(t *testing.T) { exerciseControlSharedBudgetPolicies(t, nil, compiledControlSources(false)) } @@ -207,6 +646,26 @@ func compiledControlSources(assets bool) controlPolicySources { f.env = append(f.env, "WEAVER_TEST_GOVERNANCE_ASSET_ROOT="+assetRoot) } f.start(t) + // CompileSource returns the frozen source artifact, never the reviewer's + // approval. Register the existing independent issuer's exact review + // before the real control process stages and finalizes that original. + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + reviewer, ok := f.admin.RPC.(*fixtureReviewer) + if !ok { + t.Fatal("independent fixture reviewer missing") + } + approved, err := reviewer.review(f.admin.Context(ctx), bundle.Publication) + if err != nil || approved == nil { + t.Fatalf("compiled source bootstrap review: %v", err) + } + wire, err := gatewayclient.ReviewMessage(*approved) + if err != nil { + t.Fatal(err) + } + if _, err := f.admin.RPC.RegisterPublicationReview(f.admin.Context(ctx), wire); err != nil { + t.Fatal(err) + } }} } @@ -254,16 +713,21 @@ func TestProviderControlCompiledAssetsPartialRequestAndRestart(t *testing.T) { } func TestProviderControlCompiledProgramRequiresRealInstallation(t *testing.T) { + if _, approvedApplication := os.LookupEnv("WEAVER_GOVERNANCE_APPLICATION"); approvedApplication { + t.Skip("the skip-install control is supplied by the debug Scheme fixture") + } f := newFixture(t, completeSSE, false) path := configuredCatalogPath(t, f, controlBundle(t, f)) f.stop(t) // The application is linked and initialized, but deliberately does not // register its producer. No mock readiness response or forced exit is used. - cmd := exec.Command(serverBinary) + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + cmd := exec.CommandContext(ctx, serverBinary) cmd.Env = append(append(os.Environ(), f.env...), "WEAVER_GOVERNANCE_CATALOG="+path, "WEAVER_TEST_SKIP_PROGRAM_INSTALL=1") started := time.Now() output, err := cmd.CombinedOutput() - if err == nil || time.Since(started) > 3*time.Second { + if ctx.Err() != nil || err == nil || time.Since(started) > 3*time.Second { t.Fatalf("missing installation did not refuse naturally within startup gate: %v %s", err, output) } if !strings.Contains(string(output), "governance initialization failed") || strings.Contains(string(output), "stage=listeners-bound") { @@ -273,3 +737,72 @@ func TestProviderControlCompiledProgramRequiresRealInstallation(t *testing.T) { t.Fatal("initialization refusal sent provider traffic") } } + +func TestProviderControlCompiledCatalogRequiresExactSourceEpoch(t *testing.T) { + f := newFixture(t, completeSSE, false) + path := configuredCatalogPath(t, f, controlBundle(t, f)) + good, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + var catalog configuredCatalog + if err := json.Unmarshal(good, &catalog); err != nil { + t.Fatal(err) + } + catalog.Producers[0].Authority.Epoch = 1 + wrongEpoch, err := json.Marshal(catalog) + if err != nil { + t.Fatal(err) + } + f.stop(t) + if err := os.WriteFile(path, wrongEpoch, 0600); err != nil { + t.Fatal(err) + } + f.env = append(f.env, "WEAVER_GOVERNANCE_CATALOG="+path, "WEAVER_TEST_GOVERNOR_TIMING=1") + f.start(t) + ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second) + defer cancel() + authority, err := f.admin.SourceAuthority(ctx) + if err != nil || authority.GetEpoch() != 0 { + t.Fatalf("expected authoritative epoch zero: %v %v", authority, err) + } + if reply, err := f.admin.CompileSource(ctx, "approved-control"); reply != nil || status.Code(err) != codes.PermissionDenied { + t.Fatalf("catalog epoch mismatch crossed source admission: %v %v", reply, err) + } + f.stop(t) + negative, err := os.ReadFile(filepath.Join(f.directory, "server.log")) + if err != nil { + t.Fatal(err) + } + if strings.Contains(string(negative), "weaver scheme phase=compile-begin") || + strings.Contains(string(negative), "weaver scheme phase=source-captured") { + t.Fatal("catalog epoch mismatch entered Scheme capture") + } + t.Log("authenticated source epoch mismatch rejected before Scheme capture and naturally drained") + if err := os.WriteFile(path, good, 0600); err != nil { + t.Fatal(err) + } + f.start(t) + exact, stop := context.WithTimeout(context.Background(), 12*time.Second) + defer stop() + if reply, err := f.admin.CompileSource(exact, "unapproved-control"); reply != nil || status.Code(err) != codes.PermissionDenied { + t.Fatalf("unknown producer crossed source admission: %v %v", reply, err) + } + reply, err := f.admin.CompileSource(exact, "approved-control") + if err != nil || reply.GetArtifact() == nil || reply.GetAuthority().GetEpoch() != 0 || + reply.GetAuthority().GetIdentityDigest() != authority.GetIdentityDigest() { + t.Fatalf("exact catalog epoch and identity did not compile: %v %v", reply, err) + } + if f.primary.Load() != 0 || f.backup.Load() != 0 { + t.Fatal("compile-only source RPC sent provider traffic") + } + f.stop(t) + positive, err := os.ReadFile(filepath.Join(f.directory, "server.log")) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(string(positive), "weaver scheme phase=source-captured") { + t.Fatal("matching source epoch did not execute Scheme capture") + } + t.Log("exact epoch and producer compiled after restart, with zero provider sends") +} diff --git a/go/dev/provider_workflow_choice_test.go b/go/dev/provider_workflow_choice_test.go new file mode 100644 index 00000000..ef168882 --- /dev/null +++ b/go/dev/provider_workflow_choice_test.go @@ -0,0 +1,226 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build integration && schemeintegration && !windows + +package dev + +import ( + "context" + "fmt" + "io" + "net/http" + "strconv" + "strings" + "sync" + "testing" + "time" + + pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" + "github.com/HardenedLinux/weaver/go/internal/config" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +func TestProviderControlSessionChoiceFromReleasedResult(t *testing.T) { + for _, tc := range []struct{ name, result, selected, skipped string }{ + {"left", `{"route":"left"}`, "next", "side"}, + {"right-restart-withdrawal", `{"route":"right"}`, "side", "next"}, + {"duplicate-result-field", `{"route":"left","route":"right"}`, "", ""}, + } { + t.Run(tc.name, func(t *testing.T) { + checkSessionChoice(t, tc.result, tc.selected, tc.skipped) + }) + } +} + +func checkSessionChoice(t *testing.T, document, selected, skipped string) { + t.Helper() + restart := selected == "side" + entered, release := make(chan struct{}, 1), make(chan struct{}) + var once sync.Once + unblock := func() { once.Do(func() { close(release) }) } + defer unblock() + f := newFixture(t, func(w http.ResponseWriter, r *http.Request) { + body, err := io.ReadAll(r.Body) + if err != nil { + t.Error(err) + return + } + if !strings.Contains(string(body), `"content":"hello"`) { + completeSSE(w, r) + return + } + w.Header().Set("Content-Type", "text/event-stream") + emitChunk(w, document[:8], false) + select { + case entered <- struct{}{}: + default: + t.Error("duplicate selector send") + } + select { + case <-release: + case <-r.Context().Done(): + return + } + if selected == "next" { + emitChunk(w, document[8:], true) + } else { + emitChunk(w, document[8:], false) + emitChunk(w, "", true) + } + fmt.Fprint(w, "data: [DONE]\n\n") + }, false) + backup := "" + if restart { + backup = selected + } + bundle := graphSessionBundle(t, f, config.SessionChoiceSchema, backup, 12) + root := bundle.Plans[0] + f.env = append(f.env, `WEAVER_PROVIDER_CREDENTIAL_ENVS={"primary":"WEAVER_TEST_KEY"}`, + hardFactFeedSetting(t, f, root.Family, root.Node, bundle.Governance.WorkflowEdges, nil, config.SessionChoiceSchema, nil, bundle.Governance.OpenNodes...)) + policy := compiledControlSources(false) + policy.configure(t, f, bundle) + c := newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")) + c.useProducer(policy.producer) + c.start(t) + ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second) + defer cancel() + + stage := func(revision uint64, prior *pb.HardFactBarrier, available bool) *pb.HardFactBarrier { + t.Helper() + snapshot := strings.Repeat("0", 64) + if prior != nil { + snapshot = prior.GetSnapshot() + } + barrier, err := f.admin.RPC.StageHardFact(f.admin.Context(ctx), &pb.HardFactIntent{ + OperationId: "choice-fact-" + strconv.FormatUint(revision, 10), Domain: "availability", + Revision: revision, PreviousSnapshot: snapshot, ExpectedFloor: prior.GetFloor(), Available: proto.Bool(available), + }) + if err != nil || barrier.GetFloor() != revision { + t.Fatalf("stage choice facts: %v %v", barrier, err) + } + return barrier + } + resolve := func(barrier *pb.HardFactBarrier) { + t.Helper() + result, err := f.admin.RPC.ResolveHardFact(f.admin.Context(ctx), barrier) + if err != nil || !proto.Equal(result.GetBarrier(), barrier) || strings.Join(result.GetAffected(), ",") != "finish,infer,next,side" { + t.Fatalf("resolve choice facts: %v %v", result, err) + } + } + inspect := func(node string) (*pb.ProviderReceipt, error) { + return c.client.RPC.Inspect(c.client.Context(ctx), &pb.OperationKey{Family: root.Family, Node: node}) + } + missing := func(nodes ...string) { + t.Helper() + for _, node := range nodes { + if receipt, err := inspect(node); status.Code(err) != codes.FailedPrecondition { + t.Fatalf("unexpected claim for %s: %v %v", node, receipt, err) + } + } + } + wait := func(node, state string, held uint64) *pb.ProviderReceipt { + t.Helper() + tick := time.NewTicker(20 * time.Millisecond) + defer tick.Stop() + for { + r, err := inspect(node) + if err == nil && r.GetState() == state && r.GetHeld() == held { + return r + } + select { + case <-tick.C: + case <-ctx.Done(): + t.Fatalf("%s expected %s with hold %d: %v %v", node, state, held, r, err) + } + } + } + execute := func() error { + _, err := c.client.Execute(ctx, root, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }) + return err + } + replay := func() { + t.Helper() + if err := execute(); status.Code(err) != codes.FailedPrecondition { + t.Fatalf("selector replay: %v", err) + } + } + + a := stage(1, nil, true) + resolve(a) + result := make(chan error, 1) + go func() { result <- execute() }() + select { + case <-entered: + case err := <-result: + t.Fatalf("selector did not emit: %v", err) + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + missing("next", "side", "finish") + unblock() + if err := <-result; err != nil { + t.Fatal(err) + } + if selected == "" { + replay() + until := time.Now().Add(150 * time.Millisecond) + for time.Now().Before(until) { + missing("next", "side", "finish") + time.Sleep(10 * time.Millisecond) + } + wait("infer", "complete", 4) + if f.primary.Load() != 1 || f.backup.Load() != 0 { + t.Fatal("ambiguous structured result dispatched a branch") + } + t.Log("ambiguous structured result left the frontier unadvanced") + return + } + if restart { + queued := wait(selected, "queued", 8) + replay() + replay() + if replayed := wait(selected, "queued", 8); !proto.Equal(queued, replayed) { + t.Fatal("duplicate wake changed the selected claim") + } + missing(skipped, "finish") + b := stage(2, a, false) + c.stop(t) + f.stop(t) + f.env = append(f.env, `WEAVER_PROVIDER_CREDENTIAL_ENVS={"primary":"WEAVER_TEST_KEY","backup":"WEAVER_TEST_KEY"}`) + f.start(t) + c.start(t) + if replayed := stage(2, a, false); !proto.Equal(b, replayed) { + t.Fatal("restart changed withdrawal intent") + } + wait(selected, "queued", 8) + resolve(b) + replay() + if replayed := wait(selected, "queued", 8); !proto.Equal(queued, replayed) { + t.Fatal("withdrawal changed the selected claim") + } + missing(skipped, "finish") + if f.primary.Load() != 1 || f.backup.Load() != 0 { + t.Fatal("pending or resolved withdrawal released a branch") + } + resolve(stage(3, b, true)) + if complete := wait(selected, "complete", 12); complete.GetDigest() != queued.GetDigest() { + t.Fatal("restart replaced selected branch") + } + } + wait("finish", "complete", 12) + wait(selected, "complete", 12) + missing(skipped) + replay() + primary, secondary := int64(3), int64(0) + if restart { + primary, secondary = 2, 1 + } + if f.primary.Load() != primary || f.backup.Load() != secondary || f.denied.Load() != 0 { + t.Fatalf("conditional sends = %d/%d/%d, want %d/%d/0", f.primary.Load(), f.backup.Load(), f.denied.Load(), primary, secondary) + } + t.Logf("selected %s, skipped %s, one join, held=12, restart=%v", selected, skipped, restart) +} diff --git a/go/dev/provider_workflow_nested_test.go b/go/dev/provider_workflow_nested_test.go new file mode 100644 index 00000000..7e710c09 --- /dev/null +++ b/go/dev/provider_workflow_nested_test.go @@ -0,0 +1,436 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build integration && schemeintegration && !windows + +package dev + +import ( + "context" + "flag" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "strconv" + "strings" + "sync" + "testing" + "time" + + pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" + "github.com/HardenedLinux/weaver/go/internal/config" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +func TestProviderControlSessionNestedChoiceAndParallelRecovery(t *testing.T) { + t.Run("nested-right-after-restart", func(t *testing.T) { checkNestedSession(t, false) }) + t.Run("outer-right-skips-entire-nested-arm", func(t *testing.T) { checkNestedSession(t, true) }) +} + +func TestProviderControlGovernorPerformance(t *testing.T) { + cohort := os.Getenv("WEAVER_TEST_GOVERNOR_COHORT") + switch cohort { + case "": + t.Skip("select the preregistered aa, replay, or retained cohort") + case "aa", "replay", "retained": + default: + t.Fatal("unknown Governor performance cohort", cohort) + } + arms := [4]string{"A", "B", "B", "A"} + parallel, err := strconv.Atoi(flag.Lookup("test.parallel").Value.String()) + if err != nil || parallel != len(arms) { + t.Fatalf("Governor performance requires -parallel=%d", len(arms)) + } + var trials [4]governorTrial + if !t.Run("wave-0", func(t *testing.T) { + for i, arm := range arms { + t.Run(fmt.Sprintf("%d-%s", i, arm), func(t *testing.T) { + t.Parallel() + trials[i] = governorTrial{ + arm: arm, replay: cohort == "replay" && arm == "B", + retained: cohort == "retained" && arm == "B", + } + runNestedSession(t, false, &trials[i]) + }) + } + }) { + return + } + for _, trial := range trials { + if trial.innerJoinCut == "" { + t.Log("partial Governor wave is diagnostic only") + return + } + } + for i, trial := range trials { + if trial.innerJoinCut != trials[0].innerJoinCut { + t.Fatalf("Governor arm %d-%s observed a different inner-join input: %s, expected %s", i, trial.arm, trial.innerJoinCut, trials[0].innerJoinCut) + } + if trial.outerJoinCut != trials[0].outerJoinCut { + t.Fatalf("Governor arm %d-%s observed a different outer-join input: %s, expected %s", i, trial.arm, trial.outerJoinCut, trials[0].outerJoinCut) + } + } + t.Logf("governor wave matched inner-join cut_sha256=%s trials=%d", trials[0].innerJoinCut, len(trials)) + t.Logf("governor wave matched outer-join cut_sha256=%s trials=%d", trials[0].outerJoinCut, len(trials)) +} + +func TestProviderControlSourceCancellationDrainsSchemeOwner(t *testing.T) { + f := newFixture(t, completeSSE, false) + f.env = append(f.env, "WEAVER_TEST_GOVERNOR_TIMING=1") + bundle := controlBundle(t, f) + policy := compiledControlSources(false) + policy.configure(t, f, bundle) + ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second) + defer cancel() + result := make(chan error, 1) + go func() { + _, err := f.admin.CompileSource(ctx, policy.producer) + result <- err + }() + path := filepath.Join(f.directory, "server.log") + ticker := time.NewTicker(10 * time.Millisecond) + defer ticker.Stop() + for { + log, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + if strings.Contains(string(log), "weaver scheme phase=compile-begin ") { + break + } + select { + case err := <-result: + t.Fatalf("source preparation exited before entering Scheme: %v", err) + case <-ctx.Done(): + t.Fatal(ctx.Err()) + case <-ticker.C: + } + } + f.stop(t) + if err := <-result; err == nil { + t.Fatal("cancelled source preparation delivered an artifact") + } + log, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + _, active, found := strings.Cut(string(log), "weaver scheme phase=compile-begin ") + if !found || !strings.Contains(active, "phase=source-preparation-cancelled ") || + !strings.Contains(active, "stage=scheme-owner-cleaned") || + !strings.Contains(active, "stage=tracked-owners-drained") || + strings.Contains(active, "phase=source-captured ") { + t.Fatalf("cancelled preparation did not unwind and drain: %s", active) + } + t.Log("active Scheme source preparation cancelled, VM cleaned, tracked owners naturally drained") +} + +func checkNestedSession(t *testing.T, outerRight bool) { + t.Helper() + runNestedSession(t, outerRight, nil) +} + +func runNestedSession(t *testing.T, outerRight bool, trial *governorTrial) { + t.Helper() + arrived := make(chan string, 2) + aRelease, bRelease := make(chan struct{}), make(chan struct{}) + rootRelease := make(chan struct{}) + var aOnce, bOnce, rootOnce sync.Once + releaseA := func() { aOnce.Do(func() { close(aRelease) }) } + releaseB := func() { bOnce.Do(func() { close(bRelease) }) } + releaseRoot := func() { rootOnce.Do(func() { close(rootRelease) }) } + defer releaseA() + defer releaseB() + defer releaseRoot() + f := newFixture(t, func(w http.ResponseWriter, r *http.Request) { + body, err := io.ReadAll(r.Body) + if err != nil { + t.Error(err) + return + } + content := func(node string) bool { return strings.Contains(string(body), `"content":"`+node+`"`) } + if content("hello") || content("gate") { + route := "right" + if content("hello") && !outerRight { + route = "left" + } + w.Header().Set("Content-Type", "text/event-stream") + emitChunk(w, `{"route":"`+route+`"}`, false) + if outerRight && content("hello") { + select { + case <-rootRelease: + case <-r.Context().Done(): + return + } + } + emitChunk(w, "", true) + fmt.Fprint(w, "data: [DONE]\n\n") + return + } + for node, release := range map[string]chan struct{}{"fork-a": aRelease, "fork-b": bRelease} { + if content(node) { + select { + case arrived <- node: + default: + t.Error("duplicate parallel dispatch") + } + select { + case <-release: + case <-r.Context().Done(): + return + } + break + } + } + completeSSE(w, r) + }, false) + graph := config.Governance{ + Schema: config.SessionNestedSchema, + OpenNodes: []string{"infer", "gate", "next", "side", "fork-a", "fork-b", "inner-finish", "outer-skip", "finish"}, + WorkflowEdges: [][2]string{ + {"finish", "inner-finish"}, {"finish", "outer-skip"}, {"fork-a", "side"}, {"fork-b", "side"}, + {"gate", "infer"}, {"inner-finish", "fork-a"}, {"inner-finish", "fork-b"}, {"inner-finish", "next"}, + {"next", "gate"}, {"outer-skip", "infer"}, {"side", "gate"}, + }, + WorkflowSelectors: [][3]string{{"gate", "next", "side"}, {"infer", "gate", "outer-skip"}}, + } + bundle := sessionGraphBundle(t, f, graph, "side", 28) + root := bundle.Plans[0] + credentials := `WEAVER_PROVIDER_CREDENTIAL_ENVS={"primary":"WEAVER_TEST_KEY"}` + if trial != nil { + credentials = `WEAVER_PROVIDER_CREDENTIAL_ENVS={"primary":"WEAVER_TEST_KEY","backup":"WEAVER_TEST_KEY"}` + f.env = append(f.env, "WEAVER_TEST_GOVERNOR_TIMING=1") + if trial.retained { + f.env = append(f.env, "WEAVER_TEST_GOVERNOR_RETAINED=1") + } else { + f.env = append(f.env, "WEAVER_TEST_GOVERNOR_RETAINED=0") + } + } + f.env = append(f.env, credentials, + hardFactFeedSetting(t, f, root.Family, root.Node, graph.WorkflowEdges, nil, graph.Schema, graph.WorkflowSelectors, graph.OpenNodes...)) + policy := compiledControlSources(false) + policy.configure(t, f, bundle) + c := newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")) + c.useProducer(policy.producer) + if trial != nil { + defer trial.finish(t, f, c) + } + c.start(t) + ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second) + defer cancel() + started := time.Now() + phase := func(name string) { + deadline, _ := ctx.Deadline() + t.Logf("nested Session phase=%s elapsed=%s remaining=%s", name, time.Since(started), time.Until(deadline)) + } + defer phase("scenario-exit") + + stage := func(revision uint64, prior *pb.HardFactBarrier, available bool) *pb.HardFactBarrier { + t.Helper() + snapshot := strings.Repeat("0", 64) + if prior != nil { + snapshot = prior.GetSnapshot() + } + barrier, err := f.admin.RPC.StageHardFact(f.admin.Context(ctx), &pb.HardFactIntent{ + OperationId: "nested-fact-" + strconv.FormatUint(revision, 10), Domain: "availability", + Revision: revision, PreviousSnapshot: snapshot, ExpectedFloor: prior.GetFloor(), Available: proto.Bool(available), + }) + if err != nil || barrier.GetFloor() != revision { + t.Fatalf("stage nested facts: %v %v", barrier, err) + } + return barrier + } + resolve := func(barrier *pb.HardFactBarrier) { + t.Helper() + result, err := f.admin.RPC.ResolveHardFact(f.admin.Context(ctx), barrier) + if err != nil || !proto.Equal(result.GetBarrier(), barrier) || len(result.GetAffected()) != len(graph.OpenNodes) { + t.Fatalf("resolve nested facts: %v %v", result, err) + } + } + inspect := func(node string) (*pb.ProviderReceipt, error) { + return c.client.RPC.Inspect(c.client.Context(ctx), &pb.OperationKey{Family: root.Family, Node: node}) + } + missing := func(nodes ...string) { + t.Helper() + for _, node := range nodes { + if receipt, err := inspect(node); status.Code(err) != codes.FailedPrecondition { + t.Fatalf("unexpected claim for %s: %v %v", node, receipt, err) + } + } + } + wait := func(node, state string, held uint64) *pb.ProviderReceipt { + t.Helper() + tick := time.NewTicker(20 * time.Millisecond) + defer tick.Stop() + for { + r, err := inspect(node) + if err == nil && r.GetState() == state && r.GetHeld() == held { + return r + } + select { + case <-tick.C: + case <-ctx.Done(): + t.Fatalf("%s expected %s with hold %d: %v %v", node, state, held, r, err) + } + } + } + execute := func() error { + _, err := c.client.Execute(ctx, root, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }) + return err + } + replay := func() { + t.Helper() + if err := execute(); status.Code(err) != codes.FailedPrecondition { + t.Fatalf("root replay: %v", err) + } + } + first := stage(1, nil, true) + resolve(first) + if outerRight { + result := make(chan error, 1) + partial := make(chan struct{}, 1) + go func() { + _, err := c.client.Execute(ctx, root, pb.Encoding_PROTOBUF, 1, func(event *pb.Event) error { + if event.GetKind() == "delta" && event.GetText() == `{"route":"right"}` { + select { + case partial <- struct{}{}: + default: + return fmt.Errorf("outer selector result repeated before release") + } + } + return nil + }) + result <- err + }() + select { + case <-partial: + case err := <-result: + t.Fatalf("outer selector ended before the gated release: %v", err) + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + missing("gate", "outer-skip", "finish") + phase("selector-result-without-terminal-release") + releaseRoot() + if err := <-result; err != nil { + t.Fatal(err) + } + wait("finish", "complete", 12) + wait("outer-skip", "complete", 12) + missing("gate", "next", "side", "fork-a", "fork-b", "inner-finish") + replay() + if f.primary.Load() != 3 || f.backup.Load() != 0 || f.denied.Load() != 0 { + t.Fatal("inactive nested arm dispatched or join repeated") + } + t.Log("outer right skipped the whole undecided nested subtree; one outer join; held=12") + return + } + if trial != nil { + if err := execute(); err != nil { + t.Fatal(err) + } + seen := map[string]bool{} + for range 2 { + select { + case node := <-arrived: + seen[node] = true + case <-ctx.Done(): + t.Fatal("both performance forks must arrive", ctx.Err()) + } + } + if !seen["fork-a"] || !seen["fork-b"] { + t.Fatal("missing independent performance forks", seen) + } + releaseA() + wait("fork-a", "complete", 20) + missing("next", "outer-skip", "inner-finish", "finish") + replayResult := trial.offerReplay(ctx, f, policy.producer) + releaseB() + wait("finish", "complete", 28) + wait("inner-finish", "complete", 28) + missing("next", "outer-skip") + if replayResult != nil { + select { + case err := <-replayResult: + if err != nil { + t.Fatal("concurrent prepared-source replay", err) + } + case <-ctx.Done(): + t.Fatal("concurrent prepared-source replay deadline", ctx.Err()) + } + } + replay() + if f.primary.Load() != 6 || f.backup.Load() != 1 || f.denied.Load() != 0 { + t.Fatalf("unexpected performance sends: %d/%d/%d", f.primary.Load(), f.backup.Load(), f.denied.Load()) + } + phase("joins-completed") + return + } + if err := execute(); err != nil { + t.Fatal(err) + } + queued := wait("side", "queued", 12) + wait("gate", "complete", 12) + missing("next", "outer-skip", "fork-a", "fork-b", "inner-finish", "finish") + replay() + replay() + if other := wait("side", "queued", 12); !proto.Equal(queued, other) { + t.Fatal("duplicate trigger replaced nested decision claim") + } + withdrawn := stage(2, first, false) + phase("withdrawal-staged") + c.stop(t) + phase("control-stopped") + f.stop(t) + phase("rust-stopped") + f.env = append(f.env, `WEAVER_PROVIDER_CREDENTIAL_ENVS={"primary":"WEAVER_TEST_KEY","backup":"WEAVER_TEST_KEY"}`) + f.start(t) + phase("rust-restarted") + c.start(t) + phase("control-restarted") + if other := stage(2, first, false); !proto.Equal(withdrawn, other) { + t.Fatal("restart changed pending withdrawal") + } + wait("side", "queued", 12) + resolve(withdrawn) + replay() + if other := wait("side", "queued", 12); !proto.Equal(queued, other) || f.primary.Load() != 2 || f.backup.Load() != 0 { + t.Fatal("withdrawal advanced or replaced nested claim") + } + missing("next", "outer-skip", "fork-a", "fork-b", "inner-finish", "finish") + resolve(stage(3, withdrawn, true)) + phase("availability-restored") + seen := map[string]bool{} + for range 2 { + select { + case node := <-arrived: + seen[node] = true + case <-ctx.Done(): + t.Fatal("parallel children of restored inner right arm did not both dispatch") + } + } + if !seen["fork-a"] || !seen["fork-b"] { + t.Fatalf("duplicate parallel children: %v", seen) + } + phase("parallel-dispatched") + if complete := wait("side", "complete", 20); complete.GetDigest() != queued.GetDigest() { + t.Fatal("restored branch changed identity") + } + releaseA() + wait("fork-a", "complete", 20) + missing("next", "outer-skip", "inner-finish", "finish") + releaseB() + wait("finish", "complete", 28) + phase("joins-completed") + wait("inner-finish", "complete", 28) + missing("next", "outer-skip") + replay() + if f.primary.Load() != 6 || f.backup.Load() != 1 || f.denied.Load() != 0 { + t.Fatalf("unexpected nested sends: %d/%d/%d", f.primary.Load(), f.backup.Load(), f.denied.Load()) + } + t.Log("outer left and inner right survived restart and withdrawal; both parallel releases required; two joins once each; held=28") +} diff --git a/t/fixtures/governance-program.ss b/t/fixtures/governance-program.ss index 22131443..8b75ccc3 100644 --- a/t/fixtures/governance-program.ss +++ b/t/fixtures/governance-program.ss @@ -16,22 +16,34 @@ (def measure-source? (getenv "WEAVER_TEST_SOURCE_MEASURE" #f)) (def (produce bundle) (let ((init (path-expand "../../init.ss" (path-directory (this-source-file))))) - (capture-control-fixture init (if source-asset-root "assets-only" "policy-only") + (capture-control-fixture init + (cond ((equal? (.ref (.ref bundle 'governance) 'schema) "weaver.session-nested.v1") "session-nested") + ((equal? (.ref (.ref bundle 'governance) 'schema) "weaver.session-choice.v1") "session-choice") + ((equal? (.ref (.ref bundle 'governance) 'schema) "weaver.session-dag.v1") "session-dag") + ((equal? (.ref (.ref bundle 'governance) 'schema) "weaver.session-workflow.v1") "session-workflow") + (source-asset-root "assets-only") + (else "policy-only")) (.ref bundle 'tasks) (.ref bundle 'plans) (.ref bundle 'publication) (or source-asset-root ".")))) (def (produce-measured bundle) ;; Upstream owns operation accounting. Emit only fixed metric keys/scalars; ;; profiling never supplies an approval, source cache or replacement result. (call-with-values - (lambda () (call-with-module-source-operation-measurement (lambda () (produce bundle)))) - (lambda (result metrics) + (lambda () + (call-with-module-source-operation-measurement + (lambda () + (with-catch + (lambda (failure) (lambda () (raise failure))) + (lambda () (let ((result (produce bundle))) (lambda () result))))) + accounting?: 'stages)) + (lambda (result-or-raise metrics) (hash-for-each (lambda (key value) (let ((port (current-error-port))) (display "weaver source metric=" port) (write key port) (display " value=" port) (write value port) (newline port))) metrics) (force-output (current-error-port)) - result))) + (result-or-raise)))) (unless (getenv "WEAVER_TEST_SKIP_PROGRAM_INSTALL" #f) (install-gateway-producer! (lambda (bundle) (if measure-source? (produce-measured bundle) (produce bundle))))) From b9bfc3c2c94802ab612f7faf71a8bd2437a21784 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 00:45:54 +0800 Subject: [PATCH 052/105] Reuse an admitted Yuanxu view across Scheme semantic cases --- scheme/gateway/func.ss | 27 ++++++++++++++------------ t/integration/governed-control-test.ss | 17 ++++++++-------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/scheme/gateway/func.ss b/scheme/gateway/func.ss index 2efe9ed2..e4e6b5dc 100644 --- a/scheme/gateway/func.ss +++ b/scheme/gateway/func.ss @@ -381,17 +381,20 @@ (def (emit-gateway bundle) (deliver-gateway-source bundle)) -;;; Both delivery modes use one admitted module view and one semantic producer. -(def (with-current-gateway init operation) +;;; Accept a source path or a retained Yuanxu view from a Scheme caller. +;;; Every use still checks the view's source generation before and after delivery. +(def (with-current-gateway source operation) (require-source-open!) - (let* ((view (if (gateway-source-cancelled?) - (yuanxu-load-modules init module-view: + (let* ((view (cond + ((not (string? source)) source) + ((gateway-source-cancelled?) + (yuanxu-load-modules source module-view: (lambda (_ resolve) (require-source-open!) (let ((scope (resolve))) (require-source-open!) - scope))) - (apply yuanxu-load-modules (list init)))) + scope)))) + (else (apply yuanxu-load-modules (list source))))) (gateway (begin (source-phase! "source-selection-loaded") (.get view modules Weaver gateway))) @@ -416,13 +419,13 @@ ((.get gateway emit) bundle))) ;;; Scheme source-generation guards qualify compilation, not final execution. -(def (emit-governed-gateway init governor profile context states tasks plans publication) - (with-current-gateway init +(def (emit-governed-gateway source governor profile context states tasks plans publication) + (with-current-gateway source (lambda (gateway admit-current) (produce-governed-source gateway admit-current governor profile context states tasks plans publication)))) -(def (capture-governed-gateway init governor profile context states tasks plans publication) - (with-current-gateway init +(def (capture-governed-gateway source governor profile context states tasks plans publication) + (with-current-gateway source (lambda (gateway admit-current) ((.get gateway capture) (lambda () @@ -430,7 +433,7 @@ ;;; Rich preparation remains inside the same admitted Yuanxu view. The caller ;;; may inspect advisory evidence; existing emit/capture still accept only source. -(def (prepare-governed-gateway init governor profile context states tasks plans publication) - (with-current-gateway init +(def (prepare-governed-gateway source governor profile context states tasks plans publication) + (with-current-gateway source (lambda (gateway admit-current) ((.get gateway prepare) governor profile context states tasks plans publication)))) diff --git a/t/integration/governed-control-test.ss b/t/integration/governed-control-test.ss index b50ecdd4..bb46e00e 100644 --- a/t/integration/governed-control-test.ss +++ b/t/integration/governed-control-test.ss @@ -48,7 +48,8 @@ (def init (path-expand "../../init.ss" (path-directory (this-source-file)))) (call-with-temporary-directory "weaver-control-" (lambda (directory) - (def (invoke mode) + (def view (yuanxu-load-modules init)) + (def (invoke mode (source view)) (def original-task (car (.get input tasks))) (def original-publication (.get input publication)) (def task (if (equal? mode "task-type") @@ -63,11 +64,9 @@ (lambda (port) (display (if (equal? mode "asset-mismatch") "forbid(principal,action,resource);" (.get publication policy)) port))) - (capture-control-fixture init mode (list task) plans publication directory)) - ;; Only framework Scheme sources are fixed within this inert batch. - ;; Profile data and Policy assets still vary and are read per case. - ;; Independent currentness guards bracket the upstream read window. - (def view (yuanxu-load-modules init)) + (capture-control-fixture source mode (list task) plans publication directory)) + ;; Reuse the Yuanxu scope for fixed framework sources. Profile data + ;; and Policy assets still vary, and every capture admits the view. ((.get view admit-current)) (dynamic-wind void @@ -84,13 +83,13 @@ (list (car row) #t))) refusal-cases) (check-exception (invoke "task-type") TypeError?) - ;; Refusal must not poison a subsequent legitimate capture on this VM. + ;; Refusal must not poison a subsequent legitimate capture. (def valid (invoke "valid")) (check-equal? (.get valid governance open_nodes) '("infer" "next")) (check-equal? (.get (car (.get input tasks)) budget) 8) ;; Preparation and source capture use the same declared ;; semantic producer, while evidence stays outside wire data. - (def prepared (prepare-control-fixture init "valid" (.get input tasks) (.get input plans) + (def prepared (prepare-control-fixture view "valid" (.get input tasks) (.get input plans) (.get input publication) directory)) (check-equal? (.get prepared source governance open_nodes) '("infer" "next")) (check-equal? (.get prepared derivation complete) #t) @@ -104,6 +103,8 @@ (def retained ((.get owner derive) query)) (check-equal? ((.get owner matches?) query retained) #t) ((.get owner close)) + ;; The production path also opens and admits its own view. + (check-equal? (.get (invoke "valid" init) governance open_nodes) '("infer" "next")) #t))) (lambda () ((.get view admit-current)))) directory))))) From 03307473998cf19575b7f4347a33a6497f40dee1 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 01:04:23 +0800 Subject: [PATCH 053/105] Honor the selected ASCENT native compiler policy --- .github/workflows/verify-suite.yml | 5 +++++ build.ss | 22 ++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index dcd61055..8f0fec39 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -93,6 +93,7 @@ jobs: command -v timeout export scheme_sources="$RUNNER_TEMP/weaver-scheme-sources" if timeout --verbose --kill-after=5s 12m bash -se -o pipefail <<'SOURCE_CLOSURE'; then + printf 'phase=resolve-pins\n' >> "$GITHUB_OUTPUT" fetch_source() { local package=$1 pin=$2 destination=$3 revision=${2##*@} [[ "$pin" == "$package@$revision" && "$revision" =~ ^[0-9a-f]{40}$ ]] @@ -115,10 +116,13 @@ jobs: # Core supplies the compiler and POO. Lab and ASCENT supply the # source selected by Weaver; their unrelated build products stay out. + printf 'phase=core-and-poo\n' >> "$GITHUB_OUTPUT" gerbil pkg install "$core_pin" + printf 'phase=link-source-packages\n' >> "$GITHUB_OUTPUT" gerbil pkg link "$lab" "$lab_source" gerbil pkg link "$ascent" "$ascent_source" export GERBIL_LOADPATH="$GERBIL_PATH/lib:$scheme_sources/imports" + printf 'phase=ascent-program\n' >> "$GITHUB_OUTPUT" ./build.ss prepare-governor-library SOURCE_CLOSURE dependency_exit_code=0 @@ -165,6 +169,7 @@ jobs: "os": ${{ toJSON(runner.os) }}, "arch": ${{ toJSON(runner.arch) }}, "status": ${{ toJSON(job.status) }}, + "schemeDependencyPhase": ${{ toJSON(steps.scheme_dependencies.outputs.phase || null) }}, "schemeDependencyExitCode": ${{ steps.scheme_dependencies.outputs.exit_code || 'null' }}, "phases": { "checkout": ${{ toJSON(steps.checkout.outcome || 'skipped') }}, diff --git a/build.ss b/build.ss index fcd2a745..22fc54b6 100755 --- a/build.ss +++ b/build.ss @@ -17,22 +17,29 @@ (only-in :gerbil/compiler compile-module) (only-in :yuanxu/module-system/building/interface call-with-init-build-spec) (only-in :yuanxu/module-system/building/products build-output-directory - current-build-module-roots current-build-source-directory) + current-build-compiler-options current-build-module-roots current-build-source-directory) (only-in :yuanxu/module-system/building/source-package register-module-build-source!) (only-in :yuanxu/module-system/source/observations current-module-source-observer) (only-in "./init.ss" hardenedlinux/weaver.init.exports)) (export main) -(def (run-build args entry prepare) +(def (run-build args entry prepare (target-options '())) (def output (build-output-directory)) (def (dispatch spec native-args (prefix #f)) (def (this-source-file) (let (directory (current-build-source-directory)) (if directory (path-expand (path-strip-directory entry) directory) entry))) - (defbuild-script spec libdir: output prefix: prefix) + (def targets + (if (null? target-options) spec + (map (lambda (target) + (append (if (string? target) (list gxc: target) target) target-options)) + spec))) + (defbuild-script targets libdir: output prefix: prefix) (apply main native-args)) - (call-with-init-build-spec prepare dispatch args output entry)) + (parameterize ((current-build-compiler-options + (append (current-build-compiler-options) target-options))) + (call-with-init-build-spec prepare dispatch args output entry))) (def (compile-package args) (run-build args (this-source-file) @@ -43,10 +50,13 @@ (def source (path-normalize (path-expand "github.com/tao3k/gerbil-ascent/" (pkg-root-dir)))) (register-module-build-source! source 'gerbil-ascent) (parameterize ((current-directory source) (current-build-module-roots '(program))) + (def entry (path-expand "build.ss" source)) (eval-syntax `(import (only-in ,(path-expand "init.ss" source) gerbil-ascent.init.exports))) + (eval-syntax `(import (only-in ,entry gerbil-ascent-compiler-options))) (def exports (eval 'gerbil-ascent.init.exports)) - (run-build '("compile") (path-expand "build.ss" source) - (lambda () ((.get exports std-make-spec) '()))))) + (run-build '("compile") entry + (lambda () ((.get exports std-make-spec) '())) + (eval 'gerbil-ascent-compiler-options)))) ;; Cargo needs the inputs already read by the package owner to invalidate its ;; build script. Files created under OUT_DIR are products of the same build. From 6a9c695b013e4be64cbb62d641a345f45a6e1a7c Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 01:04:23 +0800 Subject: [PATCH 054/105] Publish the two SysML-mapped architecture figures --- .../10.14-object-lifecycle.d2 | 159 ++++++++++++++ .../10.14-object-lifecycle.svg | 28 +++ .../10.15-architecture-evolution.d2 | 194 ++++++++++++++++++ .../10.15-architecture-evolution.svg | 28 +++ 4 files changed, 409 insertions(+) create mode 100644 docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.d2 create mode 100644 docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.svg create mode 100644 docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.d2 create mode 100644 docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.svg diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.d2 b/docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.d2 new file mode 100644 index 00000000..dbf8f559 --- /dev/null +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.d2 @@ -0,0 +1,159 @@ +# SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +# +# SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +...@../../../dev/d2/themes/routing +# Generated by Go from SysML and Lean references. Edit source contracts, not D2 semantic copy. +vars: { d2-config: { data: { figure: |json +{ + "design": { + "audience": "Controller and execution contributors", + "medium": "Linked English Org and source-derived SVG", + "message": "Keep existing owners; complete the lifecycle joins.", + "questionRefs": [ + "q1" + ], + "requiredSubjects": [ + "n0", + "n1", + "n2", + "n3", + "n4" + ], + "requiredRelations": [], + "focalSubjects": [ + "n0", + "n4" + ] + }, + "icons": [ + "engineering", + "weaver", + "components" + ], + "title": "Object lifecycle: existing mechanisms and missing joins", + "purpose": "workflow", + "kind": "routing", + "language": "en", + "width": 1120, + "primary": "q1", + "questions": [ + { + "ref": "q1", + "text": "Where does inherited ASCENT join the existing lifecycle?", + "focusRefs": [ + "model" + ], + "subjectRefs": [ + "n0", + "n4" + ] + } + ], + "references": { + "model": "dev/sysml/ControllerObjectLifecycle.sysml", + "model0": "Project.sysml", + "model1": "dev/sysml/AdmissionReaderViews.sysml", + "model10": "dev/sysml/CorrespondenceReaderView.sysml", + "model11": "dev/sysml/ExecutionReaderViews.sysml", + "model12": "dev/sysml/FloorReaderViews.sysml", + "model13": "dev/sysml/GatewayArchitecture.sysml", + "model14": "dev/sysml/PolicyEvidenceDesign.sysml", + "model15": "dev/sysml/ProviderRpc.sysml", + "model16": "dev/sysml/ReaderDesigns.sysml", + "model17": "dev/sysml/ResearchReaderViews.sysml", + "model18": "dev/sysml/StoragePersistence.sysml", + "model19": "dev/sysml/StreamingExecution.sysml", + "model2": "dev/sysml/ArchitectureEvolution.sysml", + "model20": "dev/sysml/WeaverExecution.sysml", + "model21": "dev/sysml/ZeroTrustRefinement.sysml", + "model3": "dev/sysml/ArchitectureReaderViews.sysml", + "model4": "dev/sysml/ArchitectureViews.sysml", + "model5": "dev/sysml/AssuranceReaderViews.sysml", + "model6": "dev/sysml/AttemptReaderViews.sysml", + "model7": "dev/sysml/AuthorityReaderViews.sysml", + "model8": "dev/sysml/ControlActivation.sysml", + "model9": "dev/sysml/ControllerObjectLifecycle.sysml", + "proof0": "dev/proofs/cedar/WeaverPolicyBridge.lean", + "sdkCapture": "dev/sysml/captures/ControllerObjectLifecycle-lifecycle.json" + }, + "copy": {}, + "basis": { + "captureRef": "docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.d2#design-view", + "modelRefs": [ + "Project.sysml", + "dev/sysml/AdmissionReaderViews.sysml", + "dev/sysml/ArchitectureEvolution.sysml", + "dev/sysml/ArchitectureReaderViews.sysml", + "dev/sysml/ArchitectureViews.sysml", + "dev/sysml/AssuranceReaderViews.sysml", + "dev/sysml/AttemptReaderViews.sysml", + "dev/sysml/AuthorityReaderViews.sysml", + "dev/sysml/ControlActivation.sysml", + "dev/sysml/ControllerObjectLifecycle.sysml", + "dev/sysml/CorrespondenceReaderView.sysml", + "dev/sysml/ExecutionReaderViews.sysml", + "dev/sysml/FloorReaderViews.sysml", + "dev/sysml/GatewayArchitecture.sysml", + "dev/sysml/PolicyEvidenceDesign.sysml", + "dev/sysml/ProviderRpc.sysml", + "dev/sysml/ReaderDesigns.sysml", + "dev/sysml/ResearchReaderViews.sysml", + "dev/sysml/StoragePersistence.sysml", + "dev/sysml/StreamingExecution.sysml", + "dev/sysml/WeaverExecution.sysml", + "dev/sysml/ZeroTrustRefinement.sysml" + ], + "obligationRefs": [ + "proof0" + ], + "evidenceRefs": [] + }, + "themes": [ + "sketchbook", + "field-notes", + "comfortable", + "reading" + ], + "layout": "model-view", + "variants": [], + "presentation": { + "options": { + "elk.algorithm": "layered", + "elk.direction": "DOWN", + "elk.edgeRouting": "ORTHOGONAL", + "elk.layered.spacing.nodeNodeBetweenLayers": "27", + "elk.spacing.nodeNode": "16" + }, + "icons": { + "n0": "document", + "n1": "document", + "n2": "document", + "n3": "document", + "n4": "document" + }, + "roles": { + "n0": "semantic", + "n1": "semantic", + "n2": "semantic", + "n3": "semantic", + "n4": "semantic" + }, + "edgeLabels": true + }, + "modelSource": { + "ref": "sdkCapture", + "view": "ControllerObjectLifecycle::lifecycle", + "modelHash": "a9b04d7faf514747966879dfeeb0e0eb0c0817ebb56b7b124448204bb6b6f993", + "portProjection": "owner", + "labels": { + "n0": "Prepare\nExists: advisory derive\nMissing: object warmup", + "n1": "Publish\nExists: durable CAS\nMissing: fact projection", + "n2": "Replace\nExists: source fencing\nMissing: owner handover", + "n3": "Reuse\nExists: retained advice\nMissing: fact authority", + "n4": "Invalidate\nExists: current guard\nMissing: impact loop" + } + } +} +| +} } } diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.svg b/docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.svg new file mode 100644 index 00000000..ca0ab609 --- /dev/null +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.svg @@ -0,0 +1,28 @@ + +{"renderer":{"package":"@deterministic-engineering/render","version":"1.0.0","icons":{"agent":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","agent-request":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","authentication":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","authorization":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","bounded-write":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","budget":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","budget-ledger":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","capture":"a647d42aa11f4e5e85d0bbf66f483f57f3c4ba3a9536362ed0eaaaae10a89cee","catalog":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","claim":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","decision":"3535642a5b613372c3fd374151ec90aafa19b64b2d33d10b19162cad07a35c7a","document":"0bf9674a401262da8a646305cab00006954721c07765b9962e0dee1c31d560f7","evidence":"0a91b169aaa644829a054cbb94194efffaf4298f2b6f8fa8c6ec2b7b413a1766","go":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","history":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","kubernetes":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","ledger":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","library":"df474fa36a74016b79236fff58a980a8c18c682d1866211776e349a0eb4b2979","message":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","model":"0cfd1f9ed3873f556ace725a7b6a251ebe75d7d976567699276f34df36b2443b","model-catalog":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","model-provider":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","obligation":"e76f4d34a7190400446c89e4e7d187762b885808a64a00c99455599d902570c5","pending":"cca7589bc3b1dcdebacb867c6836c6fc166257f05823555a268354ff9bfac00c","permission-check":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","policy":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","provider":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","publication":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","question":"dbf231e1568dc37189d5674d73c4bfc58a17eb8ada579b3f03bf2813d33c56f4","recovery":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","reference":"3814c570f79ab294252c36530de464c9364814b797afb862d9c62e728a8660fc","route-choice":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","routine":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","routing":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","rust":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","selection":"82b4ab6faf195fea0a891c35268e61c186e93e7c6a9d7967a4f6a73dbf25ae7f","stream":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","task-contract":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","telemetry":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","unknown":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","unknown-hold":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","writer":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e"}},"design":{"audience":"Controller and execution contributors","medium":"Linked English Org and source-derived SVG","message":"Keep existing owners; complete the lifecycle joins.","questionRefs":["q1"],"requiredSubjects":["n0","n1","n2","n3","n4"],"requiredRelations":[],"focalSubjects":["n0","n4"]},"evidence":[],"layout":"model-view","presentation":{"options":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.layered.spacing.nodeNodeBetweenLayers":"27","elk.spacing.nodeNode":"16"},"icons":{"n0":"document","n1":"document","n2":"document","n3":"document","n4":"document"},"roles":{"n0":"semantic","n1":"semantic","n2":"semantic","n3":"semantic","n4":"semantic"},"edgeLabels":true,"textColumns":22},"drawing":{"mode":"sketch","options":{"seed":29,"roughness":1.3,"strokeWidth":1.2,"fillStyle":"hachure","hachureGap":9,"fillWeight":0.6}},"fonts":[{"family":"Kalam","weight":400,"source":"@fontsource/kalam/files/kalam-latin-400-normal.woff2"},{"family":"Kalam","weight":700,"source":"@fontsource/kalam/files/kalam-latin-700-normal.woff2"}],"palette":{"background":"#F4F0E7","surface":"#FFFEF9","ink":"#39382F","muted":"#797365","border":"#E0D8C5","accent":"#8D6738","secondary":"#546D5B","tint":"#F4EAD7","secondaryTint":"#EAF0E5","onAccent":"#FFFFFF","supported":"#3B785A","pending":"#A67127","conflict":"#A04F4B"},"inputSHA256":"99b4d1d85907c70798282295e6836fc77b895ef292a0b6a89715f0571fd96200","model":{"subjects":[{"id":"n0","type":"part","sourceName":"ControllerObjectLifecycle::assessment::prepare","label":"Prepare\nExists: advisory derive\nMissing: object warmup"},{"id":"n1","type":"part","sourceName":"ControllerObjectLifecycle::assessment::publish","label":"Publish\nExists: durable CAS\nMissing: fact projection"},{"id":"n2","type":"part","sourceName":"ControllerObjectLifecycle::assessment::replace","label":"Replace\nExists: source fencing\nMissing: owner handover"},{"id":"n3","type":"part","sourceName":"ControllerObjectLifecycle::assessment::reuse","label":"Reuse\nExists: retained advice\nMissing: fact authority"},{"id":"n4","type":"part","sourceName":"ControllerObjectLifecycle::assessment::invalidate","label":"Invalidate\nExists: current guard\nMissing: impact loop"}],"relations":[{"id":"edge:0","src":"n0","dst":"n1","label":"prepared","kind":"connection","fromPort":"n0.1","toPort":"n1.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:1","src":"n1","dst":"n3","label":"current","kind":"connection","fromPort":"n1.1","toPort":"n3.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:2","src":"n1","dst":"n2","label":"predecessor","kind":"connection","fromPort":"n1.1","toPort":"n2.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:3","src":"n2","dst":"n1","label":"successor","kind":"connection","fromPort":"n2.1","toPort":"n1.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:4","src":"n4","dst":"n0","label":"rebuild","kind":"connection","fromPort":"n4.1","toPort":"n0.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:5","src":"n4","dst":"n3","label":"recheck","kind":"connection","fromPort":"n4.1","toPort":"n3.0","srcArrow":"none","dstArrow":"none"}]},"modelSource":{"ref":"sdkCapture","modelHash":"a9b04d7faf514747966879dfeeb0e0eb0c0817ebb56b7b124448204bb6b6f993","view":"ControllerObjectLifecycle::lifecycle","portProjection":"owner","labels":{"n0":"Prepare\nExists: advisory derive\nMissing: object warmup","n1":"Publish\nExists: durable CAS\nMissing: fact projection","n2":"Replace\nExists: source fencing\nMissing: owner handover","n3":"Reuse\nExists: retained advice\nMissing: fact authority","n4":"Invalidate\nExists: current guard\nMissing: impact loop"}},"modelTrace":{"modelHash":"a9b04d7faf514747966879dfeeb0e0eb0c0817ebb56b7b124448204bb6b6f993","requestedView":"ControllerObjectLifecycle::lifecycle","resolvedView":"ControllerObjectLifecycle::lifecycle","renderingSHA256":"f903be891bb4b7161c5637176a235ccf2a377dde522246bd2d9df6b0e6c75c62","capturedRenderingJSON":"{\"modelHash\":\"a9b04d7faf514747966879dfeeb0e0eb0c0817ebb56b7b124448204bb6b6f993\",\"requestedView\":\"ControllerObjectLifecycle::lifecycle\",\"rendering\":{\"view\":\"ControllerObjectLifecycle::lifecycle\",\"kind\":\"interconnection\",\"stated\":\"render asInterconnectionDiagram\",\"nodes\":[{\"id\":\"n0\",\"kind\":\"part\",\"name\":\"ControllerObjectLifecycle::assessment::prepare\",\"nameSynthesized\":false,\"type\":\"Preparation\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n0.0\",\"name\":\"incoming\",\"type\":\"~ReviewDependencyPort\",\"direction\":\"\"},{\"id\":\"n0.1\",\"name\":\"outgoing\",\"type\":\"ReviewDependencyPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ControllerObjectLifecycle.sysml\",\"startLine\":193,\"startCol\":9,\"endLine\":193,\"endCol\":36}},{\"id\":\"n1\",\"kind\":\"part\",\"name\":\"ControllerObjectLifecycle::assessment::publish\",\"nameSynthesized\":false,\"type\":\"Publication\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n1.0\",\"name\":\"incoming\",\"type\":\"~ReviewDependencyPort\",\"direction\":\"\"},{\"id\":\"n1.1\",\"name\":\"outgoing\",\"type\":\"ReviewDependencyPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ControllerObjectLifecycle.sysml\",\"startLine\":194,\"startCol\":9,\"endLine\":194,\"endCol\":36}},{\"id\":\"n2\",\"kind\":\"part\",\"name\":\"ControllerObjectLifecycle::assessment::replace\",\"nameSynthesized\":false,\"type\":\"Replacement\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n2.0\",\"name\":\"incoming\",\"type\":\"~ReviewDependencyPort\",\"direction\":\"\"},{\"id\":\"n2.1\",\"name\":\"outgoing\",\"type\":\"ReviewDependencyPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ControllerObjectLifecycle.sysml\",\"startLine\":195,\"startCol\":9,\"endLine\":195,\"endCol\":36}},{\"id\":\"n3\",\"kind\":\"part\",\"name\":\"ControllerObjectLifecycle::assessment::reuse\",\"nameSynthesized\":false,\"type\":\"Reuse\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n3.0\",\"name\":\"incoming\",\"type\":\"~ReviewDependencyPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ControllerObjectLifecycle.sysml\",\"startLine\":196,\"startCol\":9,\"endLine\":196,\"endCol\":28}},{\"id\":\"n4\",\"kind\":\"part\",\"name\":\"ControllerObjectLifecycle::assessment::invalidate\",\"nameSynthesized\":false,\"type\":\"Invalidation\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n4.1\",\"name\":\"outgoing\",\"type\":\"ReviewDependencyPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ControllerObjectLifecycle.sysml\",\"startLine\":197,\"startCol\":9,\"endLine\":197,\"endCol\":40}}],\"edges\":[{\"from\":\"n0\",\"to\":\"n1\",\"fromPort\":\"n0.1\",\"toPort\":\"n1.0\",\"label\":\"prepared\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ControllerObjectLifecycle.sysml\",\"startLine\":198,\"startCol\":9,\"endLine\":198,\"endCol\":74}},{\"from\":\"n1\",\"to\":\"n3\",\"fromPort\":\"n1.1\",\"toPort\":\"n3.0\",\"label\":\"current\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ControllerObjectLifecycle.sysml\",\"startLine\":199,\"startCol\":9,\"endLine\":199,\"endCol\":71}},{\"from\":\"n1\",\"to\":\"n2\",\"fromPort\":\"n1.1\",\"toPort\":\"n2.0\",\"label\":\"predecessor\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ControllerObjectLifecycle.sysml\",\"startLine\":200,\"startCol\":9,\"endLine\":200,\"endCol\":77}},{\"from\":\"n2\",\"to\":\"n1\",\"fromPort\":\"n2.1\",\"toPort\":\"n1.0\",\"label\":\"successor\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ControllerObjectLifecycle.sysml\",\"startLine\":201,\"startCol\":9,\"endLine\":201,\"endCol\":75}},{\"from\":\"n4\",\"to\":\"n0\",\"fromPort\":\"n4.1\",\"toPort\":\"n0.0\",\"label\":\"rebuild\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ControllerObjectLifecycle.sysml\",\"startLine\":202,\"startCol\":9,\"endLine\":202,\"endCol\":76}},{\"from\":\"n4\",\"to\":\"n3\",\"fromPort\":\"n4.1\",\"toPort\":\"n3.0\",\"label\":\"recheck\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ControllerObjectLifecycle.sysml\",\"startLine\":203,\"startCol\":9,\"endLine\":203,\"endCol\":74}}],\"columns\":[],\"rows\":[],\"notes\":[],\"notices\":[],\"shown\":[]}}","portProjection":"owner","nodes":[{"id":"n0","parent":"","origin":{"file":"dev/sysml/ControllerObjectLifecycle.sysml","startLine":193,"startCol":9,"endLine":193,"endCol":36}},{"id":"n1","parent":"","origin":{"file":"dev/sysml/ControllerObjectLifecycle.sysml","startLine":194,"startCol":9,"endLine":194,"endCol":36}},{"id":"n2","parent":"","origin":{"file":"dev/sysml/ControllerObjectLifecycle.sysml","startLine":195,"startCol":9,"endLine":195,"endCol":36}},{"id":"n3","parent":"","origin":{"file":"dev/sysml/ControllerObjectLifecycle.sysml","startLine":196,"startCol":9,"endLine":196,"endCol":28}},{"id":"n4","parent":"","origin":{"file":"dev/sysml/ControllerObjectLifecycle.sysml","startLine":197,"startCol":9,"endLine":197,"endCol":40}}],"edges":[{"id":"edge:0","index":0,"from":"n0","to":"n1","fromPort":"n0.1","toPort":"n1.0","kind":"connection","origin":{"file":"dev/sysml/ControllerObjectLifecycle.sysml","startLine":198,"startCol":9,"endLine":198,"endCol":74}},{"id":"edge:1","index":1,"from":"n1","to":"n3","fromPort":"n1.1","toPort":"n3.0","kind":"connection","origin":{"file":"dev/sysml/ControllerObjectLifecycle.sysml","startLine":199,"startCol":9,"endLine":199,"endCol":71}},{"id":"edge:2","index":2,"from":"n1","to":"n2","fromPort":"n1.1","toPort":"n2.0","kind":"connection","origin":{"file":"dev/sysml/ControllerObjectLifecycle.sysml","startLine":200,"startCol":9,"endLine":200,"endCol":77}},{"id":"edge:3","index":3,"from":"n2","to":"n1","fromPort":"n2.1","toPort":"n1.0","kind":"connection","origin":{"file":"dev/sysml/ControllerObjectLifecycle.sysml","startLine":201,"startCol":9,"endLine":201,"endCol":75}},{"id":"edge:4","index":4,"from":"n4","to":"n0","fromPort":"n4.1","toPort":"n0.0","kind":"connection","origin":{"file":"dev/sysml/ControllerObjectLifecycle.sysml","startLine":202,"startCol":9,"endLine":202,"endCol":76}},{"id":"edge:5","index":5,"from":"n4","to":"n3","fromPort":"n4.1","toPort":"n3.0","kind":"connection","origin":{"file":"dev/sysml/ControllerObjectLifecycle.sysml","startLine":203,"startCol":9,"endLine":203,"endCol":74}}]},"view":{"source":"docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.d2","title":"Object lifecycle: existing mechanisms and missing joins","purpose":"workflow","kind":"routing","question":{"subjectRefs":["n0","n4"],"ref":"q1","text":"Where does inherited ASCENT join the existing lifecycle?","focusRefs":["model"]},"basis":{"captureRef":"docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.d2#design-view","modelRefs":["Project.sysml","dev/sysml/AdmissionReaderViews.sysml","dev/sysml/ArchitectureEvolution.sysml","dev/sysml/ArchitectureReaderViews.sysml","dev/sysml/ArchitectureViews.sysml","dev/sysml/AssuranceReaderViews.sysml","dev/sysml/AttemptReaderViews.sysml","dev/sysml/AuthorityReaderViews.sysml","dev/sysml/ControlActivation.sysml","dev/sysml/ControllerObjectLifecycle.sysml","dev/sysml/CorrespondenceReaderView.sysml","dev/sysml/ExecutionReaderViews.sysml","dev/sysml/FloorReaderViews.sysml","dev/sysml/GatewayArchitecture.sysml","dev/sysml/PolicyEvidenceDesign.sysml","dev/sysml/ProviderRpc.sysml","dev/sysml/ReaderDesigns.sysml","dev/sysml/ResearchReaderViews.sysml","dev/sysml/StoragePersistence.sysml","dev/sysml/StreamingExecution.sysml","dev/sysml/WeaverExecution.sysml","dev/sysml/ZeroTrustRefinement.sysml"],"obligationRefs":["proof0"],"evidenceRefs":[]}},"questions":[{"subjectRefs":["n0","n4"],"ref":"q1","text":"Where does inherited ASCENT join the existing lifecycle?","focusRefs":["model"]}],"references":{"model":"dev/sysml/ControllerObjectLifecycle.sysml","model0":"Project.sysml","model1":"dev/sysml/AdmissionReaderViews.sysml","model10":"dev/sysml/CorrespondenceReaderView.sysml","model11":"dev/sysml/ExecutionReaderViews.sysml","model12":"dev/sysml/FloorReaderViews.sysml","model13":"dev/sysml/GatewayArchitecture.sysml","model14":"dev/sysml/PolicyEvidenceDesign.sysml","model15":"dev/sysml/ProviderRpc.sysml","model16":"dev/sysml/ReaderDesigns.sysml","model17":"dev/sysml/ResearchReaderViews.sysml","model18":"dev/sysml/StoragePersistence.sysml","model19":"dev/sysml/StreamingExecution.sysml","model2":"dev/sysml/ArchitectureEvolution.sysml","model20":"dev/sysml/WeaverExecution.sysml","model21":"dev/sysml/ZeroTrustRefinement.sysml","model3":"dev/sysml/ArchitectureReaderViews.sysml","model4":"dev/sysml/ArchitectureViews.sysml","model5":"dev/sysml/AssuranceReaderViews.sysml","model6":"dev/sysml/AttemptReaderViews.sysml","model7":"dev/sysml/AuthorityReaderViews.sysml","model8":"dev/sysml/ControlActivation.sysml","model9":"dev/sysml/ControllerObjectLifecycle.sysml","proof0":"dev/proofs/cedar/WeaverPolicyBridge.lean","sdkCapture":"dev/sysml/captures/ControllerObjectLifecycle-lifecycle.json"},"sourceSHA256":{"dev/d2/themes/assurance.d2":"f7723f53e005a68c803a38ce5c04cd733f46f4a2688fa4b17c66f9d5b308fe24","dev/d2/themes/data.d2":"19fceb46186892da02b763217963cc3ca2a35021219c0d353fdeec84604ddaee","dev/d2/themes/flow.d2":"1f13588619d0c8087c08d8afd023c4c0efe12726711c311e623eea3872726c1f","dev/d2/themes/routing.d2":"f185df198e7435d12b17b7b57b62dfc5795597d95eb926159ee13b448727bcce","dev/d2/themes/sequence.d2":"6e39472720dccc717f984c95b79570494b6ce3828b86227629841649e6c956e6","dev/d2/themes/state.d2":"f1a35cbca0f9cbb055ea9f793ba3dfb86e5fee4e462038ef3e72b94baa61d781","dev/d2/themes/system.d2":"b2a32ec6959ca5df9103c16454c4e34b758e061f850f7de6b619bcbc5fcf17a6","dev/d2/themes/vocabulary.d2":"add21e9b87eab485e5daabf6316fea44eb56b1007b70123f24b0e32e3357f744","dev/proofs/cedar/DomainMigrationComposition.lean":"97c2564f79b3ad81b538d763e70727d4505995019d8a96d401bb738486b190e9","dev/proofs/cedar/QualifiedReview.lean":"1ae16e06ad03a2906fa8c21dbeea1e3eb7700aa1e9359e64848dec65ccfd079f","dev/proofs/cedar/WeaverPolicyBridge.lean":"a9628a8123d504a34f64bf986feb4471325aa2b0ddc603d76b62632481eab67b","dev/proofs/cedar/ZeroTrustEnrichment.lean":"0c4b138843cc176c27d42d4a31177a3c12486b2d8ff124a6453e3d0922170884","dev/proofs/lean/ProviderAdmissionTurn.lean":"9b30418066f14197ad601d0f439a7326c7940a5f67785353c37f2ac044801bf4","dev/proofs/lean/ProviderEgressWindow.lean":"c4a15b4ccd3a6474290b71374499087dba7dac7a1fda53f3a870100ec2e768a9","dev/proofs/lean/ProviderLifecycleFootprint.lean":"4786544c8a8193c5221bda2f7cd5cf20531bd1856d88b10ae29b280f223e307c","dev/proofs/lean/ProviderReadCustody.lean":"67e83773a1a063852e2303512d4b75b73cd3b9a90117972aafda9ee7348e6b77","dev/proofs/lean/ProviderRpc.lean":"e79d7639ac11220585e59e85dc5bec12b6717f7b51fb28fdcd62dc96d8fae38e","dev/proofs/lean/ProviderSemanticProgress.lean":"d32e010145a7dfcd646daeeeb4b08c0e852b9006bca404681af7e7fe10d0eaa0","dev/proofs/lean/ProviderSnapshotPublication.lean":"312c0380e334fbc5380815d882c6b5b0007747100f818becbee9c6784eeb5716","dev/proofs/lean/RuntimeAdmission.lean":"6111d4b9e93ebaa9f7cc44a55ed504c88c20c8d9de81e947a2e13b3f4a13b13c","dev/proofs/lean/SharedDomains.lean":"10eef67918986264689b09f0a6c0d53b314d7bf43b42f4b9652b403570beb58d","dev/proofs/lean/StreamingExecution.lean":"3fba798a7887a0b2ae29a7e3f0aaa3d7e2fb191e5f1f28109a4a73d28e27b776","dev/sysml/AdmissionReaderViews.sysml":"27ebc6c98ec3a1f7f9081e77a130953c3b646a1fdf6f1d6fc1fa6ed6376e9623","dev/sysml/ArchitectureEvolution.sysml":"95708e0c53ce6b5c245a78e0fe911eb4ceb2a199c6ba7cef93f09aff68cb7ece","dev/sysml/ArchitectureReaderViews.sysml":"52ffbccbb17bd257e8ad9f4aa9f727c8ce0c00149e7d6738b82042ba06fdd0e3","dev/sysml/ArchitectureViews.sysml":"e5b5dbbd27acfba0bd5d5b52e45990b99471d88da0e814ec13fb7ab23d752d4b","dev/sysml/AssuranceReaderViews.sysml":"cd99fb7e9b23e08beac265bc832a8debee0dc1e1d318b0f64d5263519270e390","dev/sysml/AttemptReaderViews.sysml":"0d87cf71e15c26566422a6ddb5945fdb8add8af0484d9d024c32b97597675e21","dev/sysml/AuthorityReaderViews.sysml":"6fa25bd3a64e7f89987caec8e4773928be2cbea0a3c943299e536ca81978316d","dev/sysml/captures/ArchitectureEvolution-reinforcingCapabilities.json":"edbe988ddb9c287864911d4405199a9e58667b9389b00cb267d754e3edda6fa4","dev/sysml/captures/ControllerObjectLifecycle-lifecycle.json":"f903be891bb4b7161c5637176a235ccf2a377dde522246bd2d9df6b0e6c75c62","dev/sysml/captures/WeaverAdmissionReaderViews-beneficiaryRegistration.json":"432b9379f69f40ecd41a8727595ecdae540b107d997d9b9981ec87ff35bd4f3b","dev/sysml/captures/WeaverAdmissionReaderViews-bootstrapInvitation.json":"55be61f983346e3d126edbfbc7f12a057642dd9d691c16204d56e51c71a282f3","dev/sysml/captures/WeaverAdmissionReaderViews-callerCustody.json":"1ab1bfd17b15d3545523aba839ee27d93e1ab11cd83f002ad703efea841b147f","dev/sysml/captures/WeaverAdmissionReaderViews-custodyPublication.json":"7a2f14c093c89418ebac9670070d342df6ee996e29142eb30f9404bbdcc52457","dev/sysml/captures/WeaverAdmissionReaderViews-enrollmentCredential.json":"80a525fba14c68429895652c4944c847a452a5be432cb1f1f5015a7c4cee2ddc","dev/sysml/captures/WeaverAdmissionReaderViews-incarnationIssuance.json":"ea35c502ff46d5707442a527171bcef7d717f83ab036b402ce86d9688ceb629b","dev/sysml/captures/WeaverAdmissionReaderViews-routineRouting.json":"a484553c144eb52370857196edb291b10390a5ceae2dbc19cab7fa850bde7bdb","dev/sysml/captures/WeaverAdmissionReaderViews-sourceCustody.json":"e6b7c197e8fa7b26444c8324fe75bb05dbf2c5ec1fb59b36670b90ad937216ba","dev/sysml/captures/WeaverAdmissionReaderViews-sourceJoin.json":"1bad3d182a6b1238eab2f661a4e608ac015c63106df0836b6ce2e7c7e46f2618","dev/sysml/captures/WeaverAdmissionReaderViews-subjectAuthority.json":"c0c4ebb0c5eeb4d698732d9accb9ef7e307d3cd62a1769bf52682a12a5887e5e","dev/sysml/captures/WeaverArchitectureReaderViews-adapterBroker.json":"68803012fa23c614decfc9c1af28810ba852df038973a4c2d6862d89e8c0fa3f","dev/sysml/captures/WeaverArchitectureReaderViews-anchorBroker.json":"53dfd6a7c5e8a2732b4d156cee45654132df66c45c5a52e648902d75d0555754","dev/sysml/captures/WeaverArchitectureReaderViews-anchorEgress.json":"14a6bddbc480101ab660dd95488b18ee21762d70019f3151f809a8cd0409a654","dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json":"3851beebafd9d86dc6682ee98f2399be7058a8f6b76d30957dc9c5b226f00c65","dev/sysml/captures/WeaverArchitectureReaderViews-codePolicy.json":"f4ed13f93377948fd86b212ba70c7a2353ffee081c4590b414d00a4e0df81aa9","dev/sysml/captures/WeaverArchitectureReaderViews-configPrefix.json":"f96e5188af05dfc522bb1eb154367fd5681b36b31952ab9833645ce79d90ff39","dev/sysml/captures/WeaverArchitectureReaderViews-driverCompletion.json":"ae41657d0e830a6a96755ba0a7b548a0e33deb5562ca4362f7fee780005d1905","dev/sysml/captures/WeaverArchitectureReaderViews-fencing.json":"cd23acea8403195e33f12225881a006b1120aa9334abd488855633fb0e7688fd","dev/sysml/captures/WeaverArchitectureReaderViews-gatePersistence.json":"5537a7bf61060246c121f7157d2b5ec659c916f3e595fcfaa5f6dbb2342b9eb0","dev/sysml/captures/WeaverArchitectureReaderViews-journalLifecycle.json":"367aa48a3237deae8b61be69414523a1c8bc8b928aceedb424914aed909f78ba","dev/sysml/captures/WeaverArchitectureReaderViews-logicalObservation.json":"5ef7eb4071414434763382bbd935e8c178b61980d8424ff675e5aec78a101932","dev/sysml/captures/WeaverArchitectureReaderViews-manifest.json":"aec0cad85842570184dcb94d108a24fc1be4ac1ba55db2e785d0ac71011c6af3","dev/sysml/captures/WeaverArchitectureReaderViews-migration.json":"52c75b3bc7b2f6a889d18d94dae879509090945eea428075279fe818adb3c799","dev/sysml/captures/WeaverArchitectureReaderViews-policyExecution.json":"62d6cf3e99538c202a4dd8c6d516f5150dedd3556c5607c4f61b32e893b2cf21","dev/sysml/captures/WeaverArchitectureReaderViews-quorumPromises.json":"1d0f0e3e9b2dbd124afa028344bbf01802b114d81929cd26a2d3fad8af84f8e1","dev/sysml/captures/WeaverArchitectureReaderViews-relationships.json":"782ec97d1c8b9419ad050e08c8ad5e87c4876eb2526aa399de7e24db5010b6fc","dev/sysml/captures/WeaverArchitectureReaderViews-settlementAnchor.json":"cb59d079f570aac873831b41e52ac43c02e41249e5d78dba4c5ff900fa4ea9ad","dev/sysml/captures/WeaverArchitectureReaderViews-sharedBudget.json":"ff1af8fbb913d9c45b11d929b4f36e3b810f436368bf79c8629f1a288583709c","dev/sysml/captures/WeaverArchitectureReaderViews-sharedExposure.json":"586c790fa221785dc41e5e1204a0b2acd5ff1dc126dbf142acbfa18cf81ab77b","dev/sysml/captures/WeaverArchitectureReaderViews-spentState.json":"bd1a42300c7a1a9c07e3281e7bbd32060e51f28ed0b9bf36ab2fb54e4e851ca5","dev/sysml/captures/WeaverArchitectureReaderViews-writerSettlement.json":"169bc56560a16b1601922d8f2ad2f4ed75ac540431971bbf930e3542c140bcfe","dev/sysml/captures/WeaverArchitectureReaderViews-zeroAssurance.json":"2059214421a178bf14cb0a2c0085d7a3718b39c4379e9af7828e1feef67164e8","dev/sysml/captures/WeaverAssuranceReaderViews-brokerQueue.json":"15745e4f9cec33f7bfdada37b0eacaf92de69eb07bb6bdbee515fb9512ebf2df","dev/sysml/captures/WeaverAssuranceReaderViews-continuation.json":"11f392fab1acd0caf8186eb54d20cc8e9d19bf292108c4e00b01440420b6aeb6","dev/sysml/captures/WeaverAssuranceReaderViews-deviceEvidence.json":"3bac7aa69802aeb5c32b78ffc88e7e5f17f8968bf7a03fc85402f1b36f0cb57b","dev/sysml/captures/WeaverAssuranceReaderViews-gatewayHead.json":"0f49c092feeb1d8c5d8216048321e3d98abb8a15af2e65aad8fce12d3cedaa4f","dev/sysml/captures/WeaverAssuranceReaderViews-keySession.json":"2e2494f8879e191867956d1b3e62b9d7a0243e00733d913e7a96ce0b9e1e5a33","dev/sysml/captures/WeaverAssuranceReaderViews-rangeRecovery.json":"37ab951ab4cdc2115ddd572024c5dda218e3490baeecd66c1622bccd2b88262a","dev/sysml/captures/WeaverAssuranceReaderViews-signer.json":"83f37ecb3d74214752e1872f8c51e6e6ba98a0d95b491a9bc417b5d9abd47a1e","dev/sysml/captures/WeaverAttemptReaderViews-admission.json":"4eeb4662458b8bdf0dd19a6a22639d70abdd95c41fb7534536be2216c1ad966a","dev/sysml/captures/WeaverAttemptReaderViews-outcome.json":"1b3f2a8ddc54bf6612476af88a8e4cec0b0c06080f12461db91a27927adc2af0","dev/sysml/captures/WeaverAuthorityReaderViews-attemptLedger.json":"f921aa38afa58615be7794518099bc626c9b3b640c9a2a65f49eaf097da4a530","dev/sysml/captures/WeaverAuthorityReaderViews-canonical.json":"be06876b8a2f5a9c46dea301bb0a3a96a100f6da8100cf95dc90756a99710bb5","dev/sysml/captures/WeaverAuthorityReaderViews-multiKey.json":"5d4143cc5ac238f51180f951cdf84e1487d5ef8f131e0ee18ab6289fa14885a9","dev/sysml/captures/WeaverAuthorityReaderViews-publication.json":"3b73428f7168ee48e5be05e9db82a34c00429bb235015b667d2c23e9295fcbf9","dev/sysml/captures/WeaverAuthorityReaderViews-recoveryCAS.json":"03e89b63939aee3e5accede80f2f021762e58b1da4cd36e1dd8cdf1fe421a607","dev/sysml/captures/WeaverAuthorityReaderViews-scope.json":"8d2a0fd2cc246231bbb38370e0b4480262f91477014b9e4985e54678eef40f14","dev/sysml/captures/WeaverCorrespondenceReaderView-correspondence.json":"e2299aee079f5842e7eac1d90025f0b7cd11d463e5c6eee280ecda483824b6ce","dev/sysml/captures/WeaverExecutionReaderViews-accountCommit.json":"a89cf5cf9b52e6387fe8fce939484346503a55a1d38d527ac7be66c4c892635d","dev/sysml/captures/WeaverExecutionReaderViews-admissionFloor.json":"29aa9654abf6b61636a3a5350a00f0d4270a0b9cb2d6cea08480395359dfc05b","dev/sysml/captures/WeaverExecutionReaderViews-appendHandoff.json":"bac680e1f4dd0a906585b1ca58620b104643c2467b8e4aa27e0b70732cd7c1af","dev/sysml/captures/WeaverExecutionReaderViews-checkpoint.json":"78e33402e07ddeed6b1b56fdb4a9e0a487e12b2cd8c38fc25c12c76fc11cf623","dev/sysml/captures/WeaverExecutionReaderViews-executionEvidence.json":"a3a53712803542868a18f45fe8cf438301d5bf2328e612ddee2e6ec325791791","dev/sysml/captures/WeaverExecutionReaderViews-executorOffer.json":"65e8c494c684cd7d5ca653f6b246fc86a5845d836376aaa08e0ae62f87404b11","dev/sysml/captures/WeaverExecutionReaderViews-joinEnqueue.json":"937322f451a92f812b2bd440780934e6a8c71cfac830e4b98665f190cea780a3","dev/sysml/captures/WeaverExecutionReaderViews-manifestSwitch.json":"1f8e2bc0faf38b88dd34c024c005cfe6d38b487c85fb875c6fa9cc6e025cfdc2","dev/sysml/captures/WeaverExecutionReaderViews-resultProjection.json":"2c33a5616409509c0524cd974b301ce7ae56acbe4fac6f5d7b684c9ae5bd80f9","dev/sysml/captures/WeaverExecutionReaderViews-walActivation.json":"a359e8294f24db0679f36b70f8aaee2da0937edf4c8d7f2bb73a7d3e87c68005","dev/sysml/captures/WeaverFloorReaderViews-floorOrdering.json":"67d2a58c8ce4bc1071165602e0065d479e62b01035032f1108f8ebc266e67cf9","dev/sysml/captures/WeaverFloorReaderViews-floorRecovery.json":"d656eba4d6f6b09f07ff11dcd82bf70a1ceb6f2d284a987ecbb9c8967048b117","dev/sysml/captures/WeaverResearchReaderViews-embeddedTooling.json":"8c60871a93a2f3a1906e14b6ea81dab55492d58acc9ec123e8a5f45884634398","dev/sysml/captures/WeaverResearchReaderViews-floorTransport.json":"1dfc5dce990a0eaf8fcc1342f7e3318f9b405725e8621dd8b1cada2f8f66fe64","dev/sysml/captures/WeaverResearchReaderViews-gerbilLifecycle.json":"77da614bbefc6b5b628349343692301e61d19971c2e15ab465811bec34062aac","dev/sysml/captures/WeaverResearchReaderViews-gxiLifecycle.json":"22373d2a7dd4324b14f02920c1fe066edcfc3f93930897cceb01cdd5c35bfb44","dev/sysml/captures/WeaverResearchReaderViews-parentReplay.json":"9e061e30a41f79c34e63ce3ea0dfee2d250aaa97ccdf726b2b78d0f6f21d9451","dev/sysml/captures/WeaverResearchReaderViews-profileBinding.json":"71a89b539ee9aa7174f1981fe753251641bf8df2cc085f1bb73e84aba6cd9a8a","dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json":"8d17c69f7a55337797917b251f91e0e480b1b41347d90a545fab1ceae19e839d","dev/sysml/captures/WeaverResearchReaderViews-runtimeAssets.json":"eb59b55ff93e58a03e6a8f9a4123f2e57c9dd9d979b6f554454b828a6b1567cf","dev/sysml/captures/WeaverResearchReaderViews-semanticSlice.json":"6ef38a0ce6b5f0ff16d085af8cb6342c3603e638e84805c0d572accad2404728","dev/sysml/captures/WeaverViews-architecture.json":"82982f844fb59ca130a82ec8e8493a3d87600d089835565c8b932b2f2cbca73f","dev/sysml/captures/WeaverViews-assurance.json":"deed1f1eb9f5cf10beeee368fded527f470bd78d1fca0264bce2b1e42d4337c6","dev/sysml/captures/WeaverViews-contractRefinement.json":"7f9ae3f31d8c23aa22cf582acc135feb0d8373871b8c17395e33570e3c2d857b","dev/sysml/captures/WeaverViews-execution.json":"95b448394f8503a04f26d2f485ea1267ade1a6ce3fead6f28390ce3873fea101","dev/sysml/captures/WeaverViews-gateway.json":"7b90100dadb412dd7f282875afb975e7b5bd8b061ea6929ef620b2581ce0a006","dev/sysml/captures/WeaverViews-providerDeliveryJoin.json":"15b4f7f038afd47b409184ca90ec1f8b97d42bef8c9fbfa489d180fb245f284a","dev/sysml/captures/WeaverViews-providerEgressWindow.json":"02056950ae8774fae8cae76f4f0ff1fdb558790289cce235ebe842d8d2c0e20d","dev/sysml/captures/WeaverViews-rangeRecovery.json":"067e46a50745b6f5cafe50f07a723a19bc64ea715c6637a1689f3001d78f9ea5","dev/sysml/captures/WeaverViews-routeExecution.json":"ad6b20e13cf5621830e13deab4a35c350bb461db7ae6e56b492b43920a67eb19","dev/sysml/captures/WeaverViews-routeSelection.json":"ea0f930692982260f5bc8681405a2b21def87d67c90b8852eb89bb92e4f50c0c","dev/sysml/captures/WeaverViews-storage.json":"a3a98328e2c3ae5e64e44a5f2516b4fd810b367c23af2d462db0ef438edf3b62","dev/sysml/captures/WeaverViews-streamAdmission.json":"4c2ab7cc35bc57ef525b48ec503449aa24e113c97e51aa7ea0aef3fed7f3c694","dev/sysml/captures/WeaverViews-zeroTrust.json":"54f44d30936aaf278a59bf2530bfe59184b83514953a3c2bf2753b8013330e2a","dev/sysml/ControlActivation.sysml":"f9f0d8e8746c041a22de2933fe4728fe4f96e33030a0d62ae38404a14edd79e6","dev/sysml/ControllerObjectLifecycle.sysml":"306655b388578daaad139d4e3bebc111744293f62657173588aff48b129c1124","dev/sysml/CorrespondenceReaderView.sysml":"24b811c00528feaab3547d5db3b7fada290ff89478ac2be0a1d252d8ea1e5828","dev/sysml/ExecutionReaderViews.sysml":"88f690ed1fed91f63f7571d14bf5d7c1c8d14ee3b8d1d17ae333dfd7a6176df3","dev/sysml/FloorReaderViews.sysml":"93401ba5b2009dd54614f7e5aff81d91a20085efbb77b3a143726ffdea16592c","dev/sysml/GatewayArchitecture.sysml":"dbec3964b7873ed0633964b05d1ba1ee828050aed35a3066858d0c38893f2642","dev/sysml/PolicyEvidenceDesign.sysml":"2476fbebe5f299283eca4e0e0f77b114893717c09d839b1f4a7ffad6ea4428ae","dev/sysml/ProviderRpc.sysml":"dc5712dc57b4901a563df8c77c1fdb9001c93f56349a599a44f40fecc32019fc","dev/sysml/ReaderDesigns.sysml":"4df8352980f9727b85a26533dc5ebfd67730540359d553a17d562574f3ea2529","dev/sysml/ResearchReaderViews.sysml":"cb10ed4ab79e911197834a8102e8a84986c567a358098e36d234d15b9c5acaec","dev/sysml/StoragePersistence.sysml":"b6b58b8802a557a7f3af787c2e7875be64865169ca3fd7e9973b13f6c3dc792d","dev/sysml/StreamingExecution.sysml":"d0d4d92300fba2b908ace30d9065cb2bac1d86f3b7c98219c1853a30f3110e85","dev/sysml/WeaverExecution.sysml":"0224c33a6eb9cecdfe69bcf0747eaf7d9168422c2ed0b8ce39c345e041277d42","dev/sysml/ZeroTrustRefinement.sysml":"7cbec57110f03ed68469a1f49cb2046769516b09a6eb1b9433d866161bba6a82","docs/10-19-llm-gateway/10-routing-and-inference/10.02-llm-routing.d2":"513cad143cde846a9393bb5020dc4843caa1bb844204d3d0c13d1b5ada5efc70","docs/10-19-llm-gateway/10-routing-and-inference/10.05-route-execution.d2":"7c3ff8609c24983d0b27511756d8c5c04d0dc2cf5c973fc7012eaa0acda421e2","docs/10-19-llm-gateway/10-routing-and-inference/10.07-provider-egress-window.d2":"3c9c7c67296700d3b08cea62dddd5bdd011e7bafd61c2b4ecf1e38c32a94d6e7","docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2":"80b85a1f845c440259a93a52b33fae42f5373f985b6dd24d1fcef2c798e5ccf4","docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.d2":"69eb501f2425805d13ad56442db851e4d165198854df3ba6994d0f39e1946767","docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.d2":"d1d5ebe1aeacd18a1f295bf479edb64b2f6f231c4beaf1fe39611bf34c70252f","docs/10-19-llm-gateway/11-attempts-and-failover/11.02-attempt-ledger.d2":"5438329d7af60e9596b5fe4519b04a27a7c36ce1d1dc1aa5442db6df7167cd8e","docs/10-19-llm-gateway/12-semantic-contracts/12.02-semantic-contract.d2":"8560ac03652d2dfb8aeb7797c0e3b61031e49f9a3276d3207c8758a32037c530","docs/10-19-llm-gateway/13-authoritative-scope/13.02-authoritative-scope.d2":"e5950b420b85e30891bdb2264c7fad7ccd9ec9934b6175906d592d683b3a844c","docs/10-19-llm-gateway/14-registry-publication/14.02-registry-publication.d2":"9153743fc734fb044f94a4d22175fbe963f0f15f02598143dfbd7a06cd880177","docs/10-19-llm-gateway/15-recovery-cas/15.02-recovery-cas.d2":"c5de2f6cb52b0450361b2ed0523f647bdcad1fc43d410231f91ae86aee450859","docs/10-19-llm-gateway/16-policy-publication/16.02-policy-publication.d2":"4be00575666b7ada7185a30e553b42b9c36fe9109ce89df3d0dbb4b30ac10cab","docs/10-19-llm-gateway/17-policy-continuation/17.02-policy-continuation.d2":"4108a821aba5a2de1ffebc59b9e0d9180130bb3f598ac2130d59a83e8eca571f","docs/10-19-llm-gateway/18-canonical-registry/18.02-canonical-registry.d2":"f3b44cf54b006df34b528075bbc54742963a53e2afd4cbee435f81095b59b800","docs/10-19-llm-gateway/19-multi-key-registry/19.02-multi-key-registry.d2":"c44a2569dec8ae1fab46acb1ddd58f8b468e7ea7b11136c120a6bf2b042cf8b7","docs/20-29-execution-authority/20-result-projection/20.02-result-projection.d2":"696df32a9d705c6915bcc43a33616126cdce61ce5af0ae198c0dca5bc898d645","docs/20-29-execution-authority/21-join-enqueue/21.02-join-enqueue.d2":"430f46389111827b9f0ad5c9c3193366729fffe917ef18a5bfa0ec8238f6ab02","docs/20-29-execution-authority/22-executor-offer/22.02-executor-offer.d2":"0d93c13abcc1bd79afb32e6ae8a965cc5ec3b0c30fc1958f2f212e12b5e4b65a","docs/20-29-execution-authority/23-execution-reconciliation/23.02-execution-reconciliation.d2":"14c698ad47a243d46d788ab3494b1ad22ae7f14a163140eb6b4f5e8e071c6269","docs/20-29-execution-authority/24-account-commit/24.02-account-commit.d2":"10d6a5116d2c8be77ce7f27312d9d49ad832645c6748bb7bd68bb6942055990e","docs/20-29-execution-authority/25-wal-activation/25.02-wal-activation.d2":"9ebcd14701116e583157282a1678a6f1e0fe70e1ee4b9b7e038b520d4392ce05","docs/20-29-execution-authority/26-checkpoint-truncation/26.02-checkpoint-truncation.d2":"c5c1a35a16fe9b33029169b16d4c0af113f49e665eed0074ce524fc7a15bdb77","docs/20-29-execution-authority/27-manifest-switch/27.02-manifest-switch.d2":"c4de2ef519af25b2c41194df561860ad0236b0309b3178b388204c29cebf9f41","docs/20-29-execution-authority/28-append-handoff/28.02-append-handoff.d2":"f7646793e8540ec5f1e587d5e13deaf16d166180f80107ac8f9c904ea5c9372c","docs/20-29-execution-authority/29-admission-floor/29.02-admission-floor.d2":"0b9794f3d5fdfc7dcdbb519426eecf7e6ec6cb707de5017387c9aa47208ea385","docs/30-39-assurance/31-protected-signer/31.02-protected-signer.d2":"bc787086ae26a1a6cd56e51a2b4182c86e476f13e28ed1f5d80363b1d827e013","docs/30-39-assurance/32-key-boundary/32.02-key-boundary.d2":"1b616363aa68166988cc1d09404d637da406f048b9647676ec5f42d15f1762ca","docs/30-39-assurance/33-device-isolation/33.02-device-isolation.d2":"f4b086efce29484b70d4d4b2c04dad3887976d69187c25234e734e90260a6c7c","docs/30-39-assurance/34-floor-decision/34.02-floor-decision.d2":"78e2de9f044edb41944a56c1c8c8251a9cacd3470cf73c16b87f5ba100139a04","docs/30-39-assurance/34-floor-decision/34.04-floor-recovery.d2":"296d821eae11d4b77a552ae21d91eadcddcf032a15989dd35490128397044203","docs/30-39-assurance/35-intent-continuation/35.02-intent-continuation.d2":"08475ba17d7c98911a7db912041b669d049c75315c861322f72a5b50a471df55","docs/30-39-assurance/36-gateway-head-cas/36.02-gateway-head-cas.d2":"51669df10ec208197e690f656b962b259959af5f225243b62e5ff6bbea5637a5","docs/30-39-assurance/37-broker-consumption-queue/37.02-broker-consumption-queue.d2":"1ad636df3ba980d5f25b1a330c00c8b21f152958fe7c86617736e1b1f85a1ed8","docs/30-39-assurance/38-logical-range-recovery/38.02-logical-range-recovery.d2":"8ed5e1adc741da6852d027828993a83816cadb0c7bc1732bfaf121b2a64878d3","docs/40-49-admission-coordination/40-source-join/40.02-source-join.d2":"b8815cf59a1be49a4657b6ec3857d39e6d7d39ab4bb3ed44521c71ffe0ec5cee","docs/40-49-admission-coordination/41-source-custody/41.02-source-custody.d2":"feef18f62d537d4eb0659c0f1d719218df1a3eda506c9468b59423b151550bd7","docs/40-49-admission-coordination/42-custody-publication/42.02-custody-publication.d2":"24f019e8633cc816f7488e3f65384d2dea96ac8a3685714665a47bc6144b1e5c","docs/40-49-admission-coordination/43-caller-custody/43.02-caller-custody.d2":"6352167e4d3427fd9a66befb74fb3eebf91a127c5e82ecff8312b24178d5117f","docs/40-49-admission-coordination/44-incarnation-issuance/44.02-incarnation-issuance.d2":"215f52c84c9f41c36352f8b6da8b4670f1b375672cfc9efdf6a8bd1df95c946e","docs/40-49-admission-coordination/45-bootstrap-invitation/45.02-bootstrap-invitation.d2":"9e019de8289428a97580fe66ccefc6b9d0a43c1bac07433d2f29596f4d407401","docs/40-49-admission-coordination/46-beneficiary-registration/46.02-beneficiary-registration.d2":"322b848fdd67ea88c99b509cb5d913d7a5023e327edea51f16f44816356d81ce","docs/40-49-admission-coordination/47-enrollment-credential/47.02-enrollment-credential.d2":"ea0aa0bed915bea42d3d65c8f6572f799eb63d0aee1018b75803e61ef034d303","docs/40-49-admission-coordination/48-subject-authority/48.02-subject-authority.d2":"9f707fbc6e5ba8933a0e4d9d057f013c5764afc503f819288f628d3f9709f88d","docs/40-49-admission-coordination/49-routine-routing-config/49.02-routine-routing-config.d2":"7fa18b652ba97e8fe66f402a9a85d65740db9d3ffadff7890db7d72826c498b6","docs/50-59-research-program/51-qualified-semantic-slice/51.06-semantic-gateway-slice.d2":"d63df655a635fccac3c92eded92c039a3f079c24fa2b7a2fd0dc1f3fabd3c0f5","docs/50-59-research-program/52-committed-profile-binding/52.04-committed-profile.d2":"3ea30976830c607bf8cec62cbabc4291c384bd5f368049a45777f6f981d87d6e","docs/50-59-research-program/53-gerbil-exit/53.04-gerbil-lifecycle.d2":"b7b623664edc6e86efe62eeee7f5977dc207f0cb12e40cb6f0e77e38160695de","docs/50-59-research-program/54-dynamic-gxi-exit/54.04-dynamic-lifecycle.d2":"d4d410dd8cb10de6d3526b54ac7f96731d2f2a94dd9763aad96a0926608e251c","docs/50-59-research-program/55-dynamic-gxi-paired/55.04-runtime-boundary.d2":"573b248a6b7ce2d7eee1e70a469c54e4f195c4894ec7b0f61c8406fae843eccc","docs/50-59-research-program/56-gambit-image-closure/56.04-locator-boundary.d2":"0c45ee11d269b0cab8998c7fc3432ec851b9390b7530486225134b261d8d7de8","docs/50-59-research-program/57-runtime-implementation/57.03-runtime-boundary.d2":"193d22a5bd9e4b23260334d085df8aa5ec19c349f13cd9f56eaa26fe54f7e3ac","docs/50-59-research-program/58-streaming-execution/58.03-streaming-runtime.d2":"76ea49c83b4b36af1e775f80475d40747640b80a330434bf86635e255e84ef14","docs/50-59-research-program/58-streaming-execution/58.05-range-progress-recovery.d2":"aef20c8ad7d7420a65422add6d9fb635bdbe32e42e49427d3179bf20499ae4cd","docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2":"6f4e8218ea262e35efaebaf8cc2f96345b2ef1e7e9c1a6b12b68290dd99c683d","docs/50-59-research-program/59-provider-rpc/59.21-verification-ownership.d2":"e035ae7e56ee5e6498f131ed62f4792547c1e716aa5ed29865b333f54665e8f1","docs/50-59-research-program/59-provider-rpc/59.26-semantic-execution-ecosystem.d2":"50c091b094125693e2debe73599a63405849f1f55ab3658030674692c9334e14","docs/50-59-research-program/59-provider-rpc/59.30-governance-adapter-acceptance.d2":"88cbbd45e63358bb45a58fb27f85e275b9cc9fb3d3aee6af19eabed0912545d2","docs/50-59-research-program/59-provider-rpc/59.43-floor-transport-owner.d2":"36c4d6b561332ab30deb464a92bb4c2f02ceed5c8a1ca66617f72b6086b2c555","docs/50-59-research-program/59-provider-rpc/59.44-cloud-rpc-arrow-boundaries.d2":"fe0ac2220e04f6ccea851247ecf8ae1cab4ec8c8ba8744010c478992c233ebed","docs/50-59-research-program/59-provider-rpc/59.45-slow-consumer-zero-trust.d2":"e36cf58a239a2d9f0c99789bb7484de4e26180a8f941970540f72b530a79d813","docs/50-59-research-program/59-provider-rpc/59.46-functional-security-frameworks.d2":"e541b969352e8149e71e5b539988f9955b525e5e5ba3e7e7270bd4a98fbe19f5","docs/50-59-research-program/59-provider-rpc/59.47-property-testing-framework.d2":"f66ed065dcf955a233968ca295517c642be30dad9b24e23a781fe34e4bed45d9","docs/50-59-research-program/59-provider-rpc/59.49-policy-proposal-barrier.d2":"3a8559bb22f812075d9d7de4a397978995d06c32ed22e9415f990413551aebb6","docs/50-59-research-program/59-provider-rpc/59.50-parent-contract-and-replay.d2":"2db3983f56e938c927b68077551573c8e86362da892f47890459ab7b3f929c64","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-architecture.d2":"10e92e79b69f4b0813551dd2ddadc5ad225b7b0fa8374ed7015b7f2fe66bb6e1","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-contract-refinement.d2":"204c9e20d9027b7a38bf2a964da9a7cadb92744561fa9f1eb3fa29d00f4fa386","docs/50-59-research-program/59-provider-rpc/59.52-reviewed-publication-cas.d2":"4e0998e61717d5441e242cde0dfc52198312b67b63f0ce8b0425a423d1b88a24","docs/50-59-research-program/59-provider-rpc/59.53-artifact-registry-recovery.d2":"f7083a48413d41ad99e7191281bd6e74a92b33c7cc1f4f2f9ae322bb1405088a","docs/50-59-research-program/59-provider-rpc/59.54-source-incarnation-authority.d2":"1e55c0487f01d70462e8df6b46eff9e799b0dc592c0e780c759fa602e3d84444","docs/50-59-research-program/59-provider-rpc/59.55-evidence-reviewed-publication.d2":"c66435372642f7a93ca7fc6f78c2abcbc364a4dde447d10dcc4b2b21ccc06456","docs/50-59-research-program/59-provider-rpc/59.56-runtime-assets-and-authority-floor.d2":"c675469701bb6994fed1976d1e90d01dc1cc4e416a6788f865494fa3243d32c1","docs/50-59-research-program/59-provider-rpc/59.57-schema-bound-candidate-replay.d2":"5ca15af556e0a4ba5bdf1742cf81182ad72e7f51b2eb63352b839e068a7ad7d2","docs/50-59-research-program/59-provider-rpc/59.58-independent-source-recovery.d2":"4b21999b3554be15374448f36ffbccf517b32784a65cadde0f4c1eb8308da377","docs/50-59-research-program/59-provider-rpc/59.59-retained-root-and-recovery-coverage.d2":"37fdf1d3dd01f087434a6108b43a5657d7aecf79a2b9e60638d70eb0b1a4984b","docs/50-59-research-program/59-provider-rpc/59.60-persistent-source-key-custody.d2":"d27df3a14df5d57ad725c1455c82a4ab5bad45b78acea8cd1a76e59958b710eb","docs/50-59-research-program/59-provider-rpc/59.61-authority-bound-replay-pair.d2":"bd4962775564848a90ec49439301cf0cdfbaa4018956344e809f5b318bea6ccd","docs/50-59-research-program/59-provider-rpc/59.62-burn-exposure-recovery.d2":"fab4ea6d0981d75dd4c704f302268f3c5af0898e299e8e0fb38b34d07200b22c","docs/50-59-research-program/59-provider-rpc/59.63-mrr-admission-contract.d2":"ed3c604e0d350049f00528c7117675a7db751b3d6683719b03be116bcf49d5c5","docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.d2":"7164874fdbeec99f2185e1091f759466a68a3b7d9b239db6a503f16383fce50e","docs/50-59-research-program/59-provider-rpc/59.65-turso-concurrent-admission.d2":"0ade3ea326e2066ce908129e383b7e0f371a429710ed0a0bad30ddcfd61f034e","docs/50-59-research-program/59-provider-rpc/59.66-bounded-writer-reuse.d2":"9390a3c12f06c2f33e3df99088dc39de92d3bccc971ddf5a632910515a67623e","docs/50-59-research-program/59-provider-rpc/59.67-writer-owner-lifecycle.d2":"c28559ccf38b2f3320d84bbc0ffc6133e2708081e95bff39d5ed75d064287bde","docs/50-59-research-program/59-provider-rpc/59.69-hot-path-cost-boundaries.d2":"e5789625590fab63bc3635627b7e20ac41f64b8f40cbeee84d51a85f27ab31f1","docs/50-59-research-program/59-provider-rpc/59.75-complete-entry-and-output-contract.d2":"d667501bc15d6c31d986994f641d8d38f63c1d910784e6852e596c24c4e4c7c7","docs/50-59-research-program/59-provider-rpc/59.75-package-linkage.d2":"bc655ae71cc46e0d5b7f42637b78530f262c3142394485e2a9ba31f6516a0a10","docs/50-59-research-program/59-provider-rpc/59.76-embedded-tooling-and-darwin-io.d2":"87655d7c6d81c1ab203f886930f1630003e006c0edb71f90ac3ca23a0cb91845","docs/50-59-research-program/59-provider-rpc/59.77-mrr-turso-storage.d2":"72a4dceeb20cca337276f64537d47dbbd2ac0ce359a7a63997090e6476a40c96","docs/50-59-research-program/59-provider-rpc/59.84-quint-preparation-and-completion.d2":"17f485d7c541506c42003ebba887705ea61972f00c9498aa3c0d153a33b02922","docs/architecture/08-diagram-catalog.org":"353a4296584381207513468ef291e7e1aefdcd6f9f2b854c92be90aab47577ea","docs/architecture/diagrams/00a-readme-overview.d2":"1e6119c9d5b2d8a40d3bec0c8add35e8c078dd739e46fcf45c589b8125c7c46f","docs/architecture/diagrams/00c-gateway-runtime.d2":"c1d93cc1f635803872e3349c89b5127145bdcdd2b85e9a48f83d63f0bda439da","docs/architecture/diagrams/00d-zero-trust-overview.d2":"0d3d1a5de0967db2331b9be81468cee1b7cb1d1d98966c5e541e4fc24023f2e6","docs/architecture/diagrams/01-system-boundaries.d2":"69b4622c26b18a8518d46f79db8ce281c756a16f7f1a46977272086bf4dc38e0","docs/architecture/diagrams/01-system-relationships.d2":"dde40fac8667b79a070fda14ebd892f1f1e7c1217726595179b541c855f80c2c","docs/architecture/diagrams/02-admission-sequence.d2":"97077cb16cd4457fe14092caeb4bc8cf2912d434763a08fcf350cd6a4c2b2c74","docs/architecture/diagrams/03-attempt-state.d2":"e696fc0f1d63f58100405852e88e8a7dfb1a625e43be398f3bb54bbc1d90e13a","docs/architecture/diagrams/03a-attempt-observation.d2":"6b387ec7fbcff7d5e3e129bad7ea9590afe0324800a5a13bf7a89377ad86c387","docs/architecture/diagrams/04-consume-timeout.d2":"2ccfe8d033069e0d891531f3b5afef4febf21b2722209a612454d14321cac940","docs/architecture/diagrams/05-fencing-boundaries.d2":"1103ed75ac615b1a2f8239c0321d046a5a87acfa235d5042d8a529e23acd7483","docs/architecture/diagrams/06-source-admission.d2":"4d20817291c5de93b7f97366e6cb1b4af954f22de1ebcb3012c139a4b9dbd82c","docs/architecture/diagrams/07-post-claim-outcomes.d2":"63258620c15c2f52963dcdba33b4ac82cd12aadd1c2de005cd029655493493c1","docs/architecture/diagrams/08-code-as-policy.d2":"fc2263ff1ae000055e6054b89beee60f53b9621707510354c34ef45057889676","docs/architecture/diagrams/09-claim-wins-race.d2":"9eff775ddac29c47acd2c0b69fb1ff98ba9a20943da970c2804e270979555c41","docs/architecture/diagrams/10-commit-dispatch-sequence.d2":"fa5d56c49bc3f590c88cf7c3b63e180afd2d2a39fca878d1515917077ff1687a","docs/architecture/diagrams/11-zero-trust-assurance.d2":"ea93840da2ff4bdac59349f5ad7a56cee5506600283d0c364c53275dde0b5b48","docs/architecture/diagrams/12-execution-correspondence.d2":"1dd66ee8c517fd9c6f2f4b1700aeec3e620d699fbe9eeee20df8e05a7f1decb0","docs/architecture/diagrams/13-policy-to-execution.d2":"4bb05b74c3bc0ca997c5e5035ddc949fa374db3ff49bf2104a6c9753e12be3ef","docs/architecture/diagrams/14-adapter-broker-boundary.d2":"b855fa0482a5524226354b26bc8d7ecef0daf2ab1cab54c1783eba0ff29fab01","docs/architecture/diagrams/15-stream-message-authorization.d2":"cedf1c545a853ec2a9ae51bea928b04376d192f1a4c2af117fa54f475ad541e0","docs/architecture/diagrams/16-authoritative-spent-state.d2":"201bd9fe5eb6101543d939e3d83aca646e2b07c13ff1e3c56779571a0cd1172e","docs/architecture/diagrams/17-logical-message-observation.d2":"2333ad147295ead60ed6a92dc824cf6f5769f3828eff1e0cdf58e50aace7b1e1","docs/architecture/diagrams/18-shared-identity-budget.d2":"5ab4992fd8b6a6abf518fb0bbc8c2c8ad8b920d0be74a6e734d846319252ffa7","docs/architecture/diagrams/19-finite-domains-and-migration.d2":"b72b451d0bb97de46831e4b266d8fdd22d59e7d54db99446d53549f081a008e2","docs/architecture/diagrams/20-anchor-recovery-and-egress.d2":"9479271410f1bb57f92106a1d91ec73c73872568d9fcda55cac5aa64b89e5c9f","docs/architecture/diagrams/21-composed-journal-transport-lifecycle.d2":"0fffe555ee4c2c1222c97eebd24ca9b0df91a4d3ec118300ae3b88240004c3c8","docs/architecture/diagrams/22-finite-stream-manifest.d2":"60b33eb6d06aeaa1027546a1fc9d6c07069c3cd3c7d23df8ff8d63a341afe2ea","docs/architecture/diagrams/23-driver-completion-recovery.d2":"271963db2cd881bb82e164bb1544c7bcf311e1781f20170d858ccb65a596d8f5","docs/architecture/diagrams/24-writer-settlement-closure.d2":"ea1930326b0073e7fabd8b64ef3ffea781f1aef60db0d942f9ab14f1150296e9","docs/architecture/diagrams/25-settlement-anchor-recovery.d2":"8904bfcda525de21b48ea8f2db8d12aaa27e85818ccde43fb545851dc522ba3b","docs/architecture/diagrams/26-gate-consumption-persistence.d2":"42e676634ecb40cfb2dee06db1f5497d0e58c05f30097618c3852eb946992f0d","docs/architecture/diagrams/27-anchor-commit-broker-fencing.d2":"5c2ae36987b00655bbcdba36352e03b61765739ad2f3fc80a561ff0d325a9461","docs/architecture/diagrams/28-anchor-configuration-prefix.d2":"1ac0eeb3c76f5ae0ce3565d4469e50210786c3bc53c703a1a61d519dfa075512","docs/architecture/diagrams/29-quorum-durable-promises.d2":"2e4a24c3fae49e710d5afc31d4681a9efc8c2e8af3fa58a0957ede05fe7c0255","docs/architecture/diagrams/39-shared-execution-exposure.d2":"2c08f5b3d4531a7be2aadec8f1ff9d4476495418e94e84c1ff643583ac991ce4","docs/architecture/diagrams/assets/agent-request.svg":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","docs/architecture/diagrams/assets/bounded-write.svg":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","docs/architecture/diagrams/assets/budget-ledger.svg":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","docs/architecture/diagrams/assets/components/activity.svg":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","docs/architecture/diagrams/assets/components/book-open.svg":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","docs/architecture/diagrams/assets/components/bot.svg":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","docs/architecture/diagrams/assets/components/brain.svg":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","docs/architecture/diagrams/assets/components/circle-question-mark.svg":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","docs/architecture/diagrams/assets/components/clipboard-check.svg":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","docs/architecture/diagrams/assets/components/coins.svg":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","docs/architecture/diagrams/assets/components/database.svg":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","docs/architecture/diagrams/assets/components/file-check.svg":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","docs/architecture/diagrams/assets/components/fingerprint-pattern.svg":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","docs/architecture/diagrams/assets/components/message-square.svg":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","docs/architecture/diagrams/assets/components/rotate-ccw-clock.svg":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","docs/architecture/diagrams/assets/components/rotate-ccw.svg":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","docs/architecture/diagrams/assets/components/route.svg":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","docs/architecture/diagrams/assets/components/send.svg":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e","docs/architecture/diagrams/assets/components/shield-check.svg":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","docs/architecture/diagrams/assets/components/ticket-check.svg":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","docs/architecture/diagrams/assets/components/waves-horizontal.svg":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","docs/architecture/diagrams/assets/components/workflow.svg":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","docs/architecture/diagrams/assets/go.svg":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","docs/architecture/diagrams/assets/kubernetes.svg":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","docs/architecture/diagrams/assets/model-catalog.svg":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","docs/architecture/diagrams/assets/model-provider.svg":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","docs/architecture/diagrams/assets/permission-check.svg":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","docs/architecture/diagrams/assets/route-choice.svg":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","docs/architecture/diagrams/assets/rust.svg":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","docs/architecture/diagrams/assets/task-contract.svg":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","docs/architecture/diagrams/assets/unknown-hold.svg":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","Project.sysml":"7dd1fbea3abe3e3f2f4fe23dbfd746533d5ee4c4789aacc01627b4ebadd99f12"},"rendered":{"observation":{"canvas":{"x":0,"y":0,"width":1120,"height":1678},"subjects":[{"id":"n0","role":"semantic","x":613.3243408203125,"y":517.1906127929688,"width":358.493408203125,"height":276.60968017578125},{"id":"n1","role":"semantic","x":558.5,"y":905.9114379882812,"width":311.813232421875,"height":273.96148681640625},{"id":"n2","role":"semantic","x":265.4620361328125,"y":521,"width":333.292724609375,"height":270.0634765625},{"id":"n3","role":"semantic","x":530.104736328125,"y":1288,"width":273.58203125,"height":330.3145751953125},{"id":"n4","role":"semantic","x":575.5,"y":192.62644958496094,"width":321.31201171875,"height":214.56483459472656}],"relations":["edge:0","edge:1","edge:2","edge:3","edge:4","edge:5"],"headings":[{"role":"title","x":32,"y":32,"width":1056,"height":63},{"role":"question","x":32,"y":95,"width":1056,"height":56}]},"readability":{"minimumTextSize":26,"samples":29},"bounds":{"model":{"x":32,"y":165,"width":1056,"height":1481}}}}Object lifecycle: existing mechanisms and missing joins?Where does inherited ASCENT join the existing lifecycle?{"graph":{"id":"model-root","children":[{"id":"n0"},{"id":"n1"},{"id":"n2"},{"id":"n3"},{"id":"n4"}],"layoutOptions":{"elk.spacing.nodeNode":"16","elk.layered.spacing.nodeNodeBetweenLayers":"27","elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL"},"edges":[{"id":"edge:0","sources":["n0"],"targets":["n1"]},{"id":"edge:1","sources":["n1"],"targets":["n3"]},{"id":"edge:2","sources":["n1"],"targets":["n2"]},{"id":"edge:3","sources":["n2"],"targets":["n1"]},{"id":"edge:4","sources":["n4"],"targets":["n0"]},{"id":"edge:5","sources":["n4"],"targets":["n3"]}]},"marker":"arrow-9d1260538d13"}preparedcurrentpredecessorsuccessorrebuildrecheckPrepareExists: advisory deriveMissing: object warmupPublishExists: durable CASMissing: fact projectionReplaceExists: source fencingMissing: owner handoverReuseExists: retained adviceMissing: fact authorityInvalidateExists: current guardMissing: impact loop \ No newline at end of file diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.d2 b/docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.d2 new file mode 100644 index 00000000..20d20d03 --- /dev/null +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.d2 @@ -0,0 +1,194 @@ +# SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +# +# SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +...@../../../dev/d2/themes/routing +# Generated by Go from SysML and Lean references. Edit source contracts, not D2 semantic copy. +vars: { d2-config: { data: { figure: |json +{ + "design": { + "audience": "Architecture and execution contributors", + "medium": "GitHub at 830 CSS pixels", + "message": "Compose, prepare, enforce and observe through existing owners.", + "questionRefs": [ + "q1" + ], + "requiredSubjects": [ + "n0", + "n1", + "n2", + "n3" + ], + "requiredRelations": [], + "focalSubjects": [ + "n0", + "n2" + ] + }, + "icons": [ + "engineering", + "weaver", + "components" + ], + "title": "Make architecture capabilities reinforce each other", + "purpose": "workflow", + "kind": "routing", + "language": "en", + "width": 980, + "primary": "q1", + "questions": [ + { + "ref": "q1", + "text": "How do our existing strengths compound?", + "focusRefs": [ + "model" + ], + "subjectRefs": [ + "n0", + "n2" + ] + } + ], + "references": { + "model": "dev/sysml/ArchitectureEvolution.sysml", + "model0": "Project.sysml", + "model1": "dev/sysml/AdmissionReaderViews.sysml", + "model10": "dev/sysml/CorrespondenceReaderView.sysml", + "model11": "dev/sysml/ExecutionReaderViews.sysml", + "model12": "dev/sysml/FloorReaderViews.sysml", + "model13": "dev/sysml/GatewayArchitecture.sysml", + "model14": "dev/sysml/PolicyEvidenceDesign.sysml", + "model15": "dev/sysml/ProviderRpc.sysml", + "model16": "dev/sysml/ReaderDesigns.sysml", + "model17": "dev/sysml/ResearchReaderViews.sysml", + "model18": "dev/sysml/StoragePersistence.sysml", + "model19": "dev/sysml/StreamingExecution.sysml", + "model2": "dev/sysml/ArchitectureEvolution.sysml", + "model20": "dev/sysml/WeaverExecution.sysml", + "model21": "dev/sysml/ZeroTrustRefinement.sysml", + "model3": "dev/sysml/ArchitectureReaderViews.sysml", + "model4": "dev/sysml/ArchitectureViews.sysml", + "model5": "dev/sysml/AssuranceReaderViews.sysml", + "model6": "dev/sysml/AttemptReaderViews.sysml", + "model7": "dev/sysml/AuthorityReaderViews.sysml", + "model8": "dev/sysml/ControlActivation.sysml", + "model9": "dev/sysml/ControllerObjectLifecycle.sysml", + "proof0": "dev/proofs/lean/RuntimeAdmission.lean", + "proof1": "dev/proofs/lean/SharedDomains.lean", + "sdkCapture": "dev/sysml/captures/ArchitectureEvolution-reinforcingCapabilities.json" + }, + "copy": {}, + "basis": { + "captureRef": "docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.d2#design-view", + "modelRefs": [ + "Project.sysml", + "dev/sysml/AdmissionReaderViews.sysml", + "dev/sysml/ArchitectureEvolution.sysml", + "dev/sysml/ArchitectureReaderViews.sysml", + "dev/sysml/ArchitectureViews.sysml", + "dev/sysml/AssuranceReaderViews.sysml", + "dev/sysml/AttemptReaderViews.sysml", + "dev/sysml/AuthorityReaderViews.sysml", + "dev/sysml/ControlActivation.sysml", + "dev/sysml/ControllerObjectLifecycle.sysml", + "dev/sysml/CorrespondenceReaderView.sysml", + "dev/sysml/ExecutionReaderViews.sysml", + "dev/sysml/FloorReaderViews.sysml", + "dev/sysml/GatewayArchitecture.sysml", + "dev/sysml/PolicyEvidenceDesign.sysml", + "dev/sysml/ProviderRpc.sysml", + "dev/sysml/ReaderDesigns.sysml", + "dev/sysml/ResearchReaderViews.sysml", + "dev/sysml/StoragePersistence.sysml", + "dev/sysml/StreamingExecution.sysml", + "dev/sysml/WeaverExecution.sysml", + "dev/sysml/ZeroTrustRefinement.sysml" + ], + "obligationRefs": [ + "proof0", + "proof1" + ], + "evidenceRefs": [] + }, + "themes": [ + "sketchbook", + "field-notes", + "comfortable", + "reading" + ], + "layout": "model-view", + "variants": [], + "presentation": { + "options": { + "elk.algorithm": "layered", + "elk.direction": "DOWN", + "elk.edgeRouting": "ORTHOGONAL", + "elk.layered.spacing.nodeNodeBetweenLayers": "27", + "elk.spacing.nodeNode": "16" + }, + "icons": { + "n0": "model", + "n1": "model", + "n2": "model", + "n3": "model" + }, + "roles": { + "n0": "semantic", + "n1": "semantic", + "n2": "semantic", + "n3": "semantic" + }, + "edgeLabels": true, + "graph": { + "id": "declared-reading-order", + "children": [ + { + "id": "n0", + "layoutOptions": { + "elk.partitioning.partition": "0" + } + }, + { + "id": "n1", + "layoutOptions": { + "elk.partitioning.partition": "1" + } + }, + { + "id": "n2", + "layoutOptions": { + "elk.partitioning.partition": "2" + } + }, + { + "id": "n3", + "layoutOptions": { + "elk.partitioning.partition": "3" + } + } + ], + "layoutOptions": { + "elk.algorithm": "layered", + "elk.direction": "DOWN", + "elk.edgeRouting": "ORTHOGONAL", + "elk.layered.spacing.nodeNodeBetweenLayers": "27", + "elk.partitioning.activate": "true", + "elk.spacing.nodeNode": "16" + } + } + }, + "modelSource": { + "ref": "sdkCapture", + "view": "ArchitectureEvolution::reinforcingCapabilities", + "modelHash": "a9b04d7faf514747966879dfeeb0e0eb0c0817ebb56b7b124448204bb6b6f993", + "portProjection": "owner", + "labels": { + "n0": "Compose\nPOO + Scheme\nASCENT relations", + "n1": "Prepare\nDependency cut\nBounded owners", + "n2": "Enforce\nCedar + SPEC\nRust final effects", + "n3": "Observe\nAuthentic outcomes\nScoped explanation" + } + } +} +| +} } } diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.svg b/docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.svg new file mode 100644 index 00000000..f35d9e16 --- /dev/null +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.svg @@ -0,0 +1,28 @@ + +{"renderer":{"package":"@deterministic-engineering/render","version":"1.0.0","icons":{"agent":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","agent-request":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","authentication":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","authorization":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","bounded-write":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","budget":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","budget-ledger":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","capture":"a647d42aa11f4e5e85d0bbf66f483f57f3c4ba3a9536362ed0eaaaae10a89cee","catalog":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","claim":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","decision":"3535642a5b613372c3fd374151ec90aafa19b64b2d33d10b19162cad07a35c7a","document":"0bf9674a401262da8a646305cab00006954721c07765b9962e0dee1c31d560f7","evidence":"0a91b169aaa644829a054cbb94194efffaf4298f2b6f8fa8c6ec2b7b413a1766","go":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","history":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","kubernetes":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","ledger":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","library":"df474fa36a74016b79236fff58a980a8c18c682d1866211776e349a0eb4b2979","message":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","model":"0cfd1f9ed3873f556ace725a7b6a251ebe75d7d976567699276f34df36b2443b","model-catalog":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","model-provider":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","obligation":"e76f4d34a7190400446c89e4e7d187762b885808a64a00c99455599d902570c5","pending":"cca7589bc3b1dcdebacb867c6836c6fc166257f05823555a268354ff9bfac00c","permission-check":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","policy":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","provider":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","publication":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","question":"dbf231e1568dc37189d5674d73c4bfc58a17eb8ada579b3f03bf2813d33c56f4","recovery":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","reference":"3814c570f79ab294252c36530de464c9364814b797afb862d9c62e728a8660fc","route-choice":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","routine":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","routing":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","rust":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","selection":"82b4ab6faf195fea0a891c35268e61c186e93e7c6a9d7967a4f6a73dbf25ae7f","stream":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","task-contract":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","telemetry":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","unknown":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","unknown-hold":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","writer":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e"}},"design":{"audience":"Architecture and execution contributors","medium":"GitHub at 830 CSS pixels","message":"Compose, prepare, enforce and observe through existing owners.","questionRefs":["q1"],"requiredSubjects":["n0","n1","n2","n3"],"requiredRelations":[],"focalSubjects":["n0","n2"]},"evidence":[],"layout":"model-view","presentation":{"options":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.layered.spacing.nodeNodeBetweenLayers":"27","elk.spacing.nodeNode":"16"},"icons":{"n0":"model","n1":"model","n2":"model","n3":"model"},"roles":{"n0":"semantic","n1":"semantic","n2":"semantic","n3":"semantic"},"edgeLabels":true,"graph":{"id":"declared-reading-order","children":[{"id":"n0","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n1","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n2","layoutOptions":{"elk.partitioning.partition":"2"}},{"id":"n3","layoutOptions":{"elk.partitioning.partition":"3"}}],"layoutOptions":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.layered.spacing.nodeNodeBetweenLayers":"27","elk.partitioning.activate":"true","elk.spacing.nodeNode":"16"}},"textColumns":22},"drawing":{"mode":"sketch","options":{"seed":29,"roughness":1.3,"strokeWidth":1.2,"fillStyle":"hachure","hachureGap":9,"fillWeight":0.6}},"fonts":[{"family":"Kalam","weight":400,"source":"@fontsource/kalam/files/kalam-latin-400-normal.woff2"},{"family":"Kalam","weight":700,"source":"@fontsource/kalam/files/kalam-latin-700-normal.woff2"}],"palette":{"background":"#F4F0E7","surface":"#FFFEF9","ink":"#39382F","muted":"#797365","border":"#E0D8C5","accent":"#8D6738","secondary":"#546D5B","tint":"#F4EAD7","secondaryTint":"#EAF0E5","onAccent":"#FFFFFF","supported":"#3B785A","pending":"#A67127","conflict":"#A04F4B"},"inputSHA256":"0e05159f3af12b0746ec95f4859764b473bbf59762a47815c16e78656942f1f6","model":{"subjects":[{"id":"n0","type":"part","sourceName":"ArchitectureEvolution::reinforcement::compose","label":"Compose\nPOO + Scheme\nASCENT relations"},{"id":"n1","type":"part","sourceName":"ArchitectureEvolution::reinforcement::prepare","label":"Prepare\nDependency cut\nBounded owners"},{"id":"n2","type":"part","sourceName":"ArchitectureEvolution::reinforcement::enforce","label":"Enforce\nCedar + SPEC\nRust final effects"},{"id":"n3","type":"part","sourceName":"ArchitectureEvolution::reinforcement::observe","label":"Observe\nAuthentic outcomes\nScoped explanation"}],"relations":[{"id":"edge:0","src":"n0","dst":"n1","label":"derive","kind":"connection","fromPort":"n0.1","toPort":"n1.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:1","src":"n1","dst":"n2","label":"propose","kind":"connection","fromPort":"n1.1","toPort":"n2.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:2","src":"n2","dst":"n3","label":"report","kind":"connection","fromPort":"n2.1","toPort":"n3.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:3","src":"n3","dst":"n0","label":"reconcile","kind":"connection","fromPort":"n3.1","toPort":"n0.0","srcArrow":"none","dstArrow":"none"}]},"modelSource":{"ref":"sdkCapture","modelHash":"a9b04d7faf514747966879dfeeb0e0eb0c0817ebb56b7b124448204bb6b6f993","view":"ArchitectureEvolution::reinforcingCapabilities","portProjection":"owner","labels":{"n0":"Compose\nPOO + Scheme\nASCENT relations","n1":"Prepare\nDependency cut\nBounded owners","n2":"Enforce\nCedar + SPEC\nRust final effects","n3":"Observe\nAuthentic outcomes\nScoped explanation"}},"modelTrace":{"modelHash":"a9b04d7faf514747966879dfeeb0e0eb0c0817ebb56b7b124448204bb6b6f993","requestedView":"ArchitectureEvolution::reinforcingCapabilities","resolvedView":"ArchitectureEvolution::reinforcingCapabilities","renderingSHA256":"edbe988ddb9c287864911d4405199a9e58667b9389b00cb267d754e3edda6fa4","capturedRenderingJSON":"{\"modelHash\":\"a9b04d7faf514747966879dfeeb0e0eb0c0817ebb56b7b124448204bb6b6f993\",\"requestedView\":\"ArchitectureEvolution::reinforcingCapabilities\",\"rendering\":{\"view\":\"ArchitectureEvolution::reinforcingCapabilities\",\"kind\":\"interconnection\",\"stated\":\"render asInterconnectionDiagram\",\"nodes\":[{\"id\":\"n0\",\"kind\":\"part\",\"name\":\"ArchitectureEvolution::reinforcement::compose\",\"nameSynthesized\":false,\"type\":\"Compose\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n0.0\",\"name\":\"incoming\",\"type\":\"~CapabilityDependency\",\"direction\":\"\"},{\"id\":\"n0.1\",\"name\":\"outgoing\",\"type\":\"CapabilityDependency\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ArchitectureEvolution.sysml\",\"startLine\":317,\"startCol\":9,\"endLine\":317,\"endCol\":32}},{\"id\":\"n1\",\"kind\":\"part\",\"name\":\"ArchitectureEvolution::reinforcement::prepare\",\"nameSynthesized\":false,\"type\":\"Prepare\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n1.0\",\"name\":\"incoming\",\"type\":\"~CapabilityDependency\",\"direction\":\"\"},{\"id\":\"n1.1\",\"name\":\"outgoing\",\"type\":\"CapabilityDependency\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ArchitectureEvolution.sysml\",\"startLine\":318,\"startCol\":9,\"endLine\":318,\"endCol\":32}},{\"id\":\"n2\",\"kind\":\"part\",\"name\":\"ArchitectureEvolution::reinforcement::enforce\",\"nameSynthesized\":false,\"type\":\"Enforce\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n2.0\",\"name\":\"incoming\",\"type\":\"~CapabilityDependency\",\"direction\":\"\"},{\"id\":\"n2.1\",\"name\":\"outgoing\",\"type\":\"CapabilityDependency\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ArchitectureEvolution.sysml\",\"startLine\":319,\"startCol\":9,\"endLine\":319,\"endCol\":32}},{\"id\":\"n3\",\"kind\":\"part\",\"name\":\"ArchitectureEvolution::reinforcement::observe\",\"nameSynthesized\":false,\"type\":\"Observe\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n3.0\",\"name\":\"incoming\",\"type\":\"~CapabilityDependency\",\"direction\":\"\"},{\"id\":\"n3.1\",\"name\":\"outgoing\",\"type\":\"CapabilityDependency\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ArchitectureEvolution.sysml\",\"startLine\":320,\"startCol\":9,\"endLine\":320,\"endCol\":32}}],\"edges\":[{\"from\":\"n0\",\"to\":\"n1\",\"fromPort\":\"n0.1\",\"toPort\":\"n1.0\",\"label\":\"derive\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ArchitectureEvolution.sysml\",\"startLine\":321,\"startCol\":9,\"endLine\":321,\"endCol\":72}},{\"from\":\"n1\",\"to\":\"n2\",\"fromPort\":\"n1.1\",\"toPort\":\"n2.0\",\"label\":\"propose\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ArchitectureEvolution.sysml\",\"startLine\":322,\"startCol\":9,\"endLine\":322,\"endCol\":73}},{\"from\":\"n2\",\"to\":\"n3\",\"fromPort\":\"n2.1\",\"toPort\":\"n3.0\",\"label\":\"report\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ArchitectureEvolution.sysml\",\"startLine\":323,\"startCol\":9,\"endLine\":323,\"endCol\":72}},{\"from\":\"n3\",\"to\":\"n0\",\"fromPort\":\"n3.1\",\"toPort\":\"n0.0\",\"label\":\"reconcile\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ArchitectureEvolution.sysml\",\"startLine\":324,\"startCol\":9,\"endLine\":324,\"endCol\":75}}],\"columns\":[],\"rows\":[],\"notes\":[],\"notices\":[],\"shown\":[]}}","portProjection":"owner","nodes":[{"id":"n0","parent":"","origin":{"file":"dev/sysml/ArchitectureEvolution.sysml","startLine":317,"startCol":9,"endLine":317,"endCol":32}},{"id":"n1","parent":"","origin":{"file":"dev/sysml/ArchitectureEvolution.sysml","startLine":318,"startCol":9,"endLine":318,"endCol":32}},{"id":"n2","parent":"","origin":{"file":"dev/sysml/ArchitectureEvolution.sysml","startLine":319,"startCol":9,"endLine":319,"endCol":32}},{"id":"n3","parent":"","origin":{"file":"dev/sysml/ArchitectureEvolution.sysml","startLine":320,"startCol":9,"endLine":320,"endCol":32}}],"edges":[{"id":"edge:0","index":0,"from":"n0","to":"n1","fromPort":"n0.1","toPort":"n1.0","kind":"connection","origin":{"file":"dev/sysml/ArchitectureEvolution.sysml","startLine":321,"startCol":9,"endLine":321,"endCol":72}},{"id":"edge:1","index":1,"from":"n1","to":"n2","fromPort":"n1.1","toPort":"n2.0","kind":"connection","origin":{"file":"dev/sysml/ArchitectureEvolution.sysml","startLine":322,"startCol":9,"endLine":322,"endCol":73}},{"id":"edge:2","index":2,"from":"n2","to":"n3","fromPort":"n2.1","toPort":"n3.0","kind":"connection","origin":{"file":"dev/sysml/ArchitectureEvolution.sysml","startLine":323,"startCol":9,"endLine":323,"endCol":72}},{"id":"edge:3","index":3,"from":"n3","to":"n0","fromPort":"n3.1","toPort":"n0.0","kind":"connection","origin":{"file":"dev/sysml/ArchitectureEvolution.sysml","startLine":324,"startCol":9,"endLine":324,"endCol":75}}]},"view":{"source":"docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.d2","title":"Make architecture capabilities reinforce each other","purpose":"workflow","kind":"routing","question":{"subjectRefs":["n0","n2"],"ref":"q1","text":"How do our existing strengths compound?","focusRefs":["model"]},"basis":{"captureRef":"docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.d2#design-view","modelRefs":["Project.sysml","dev/sysml/AdmissionReaderViews.sysml","dev/sysml/ArchitectureEvolution.sysml","dev/sysml/ArchitectureReaderViews.sysml","dev/sysml/ArchitectureViews.sysml","dev/sysml/AssuranceReaderViews.sysml","dev/sysml/AttemptReaderViews.sysml","dev/sysml/AuthorityReaderViews.sysml","dev/sysml/ControlActivation.sysml","dev/sysml/ControllerObjectLifecycle.sysml","dev/sysml/CorrespondenceReaderView.sysml","dev/sysml/ExecutionReaderViews.sysml","dev/sysml/FloorReaderViews.sysml","dev/sysml/GatewayArchitecture.sysml","dev/sysml/PolicyEvidenceDesign.sysml","dev/sysml/ProviderRpc.sysml","dev/sysml/ReaderDesigns.sysml","dev/sysml/ResearchReaderViews.sysml","dev/sysml/StoragePersistence.sysml","dev/sysml/StreamingExecution.sysml","dev/sysml/WeaverExecution.sysml","dev/sysml/ZeroTrustRefinement.sysml"],"obligationRefs":["proof0","proof1"],"evidenceRefs":[]}},"questions":[{"subjectRefs":["n0","n2"],"ref":"q1","text":"How do our existing strengths compound?","focusRefs":["model"]}],"references":{"model":"dev/sysml/ArchitectureEvolution.sysml","model0":"Project.sysml","model1":"dev/sysml/AdmissionReaderViews.sysml","model10":"dev/sysml/CorrespondenceReaderView.sysml","model11":"dev/sysml/ExecutionReaderViews.sysml","model12":"dev/sysml/FloorReaderViews.sysml","model13":"dev/sysml/GatewayArchitecture.sysml","model14":"dev/sysml/PolicyEvidenceDesign.sysml","model15":"dev/sysml/ProviderRpc.sysml","model16":"dev/sysml/ReaderDesigns.sysml","model17":"dev/sysml/ResearchReaderViews.sysml","model18":"dev/sysml/StoragePersistence.sysml","model19":"dev/sysml/StreamingExecution.sysml","model2":"dev/sysml/ArchitectureEvolution.sysml","model20":"dev/sysml/WeaverExecution.sysml","model21":"dev/sysml/ZeroTrustRefinement.sysml","model3":"dev/sysml/ArchitectureReaderViews.sysml","model4":"dev/sysml/ArchitectureViews.sysml","model5":"dev/sysml/AssuranceReaderViews.sysml","model6":"dev/sysml/AttemptReaderViews.sysml","model7":"dev/sysml/AuthorityReaderViews.sysml","model8":"dev/sysml/ControlActivation.sysml","model9":"dev/sysml/ControllerObjectLifecycle.sysml","proof0":"dev/proofs/lean/RuntimeAdmission.lean","proof1":"dev/proofs/lean/SharedDomains.lean","sdkCapture":"dev/sysml/captures/ArchitectureEvolution-reinforcingCapabilities.json"},"sourceSHA256":{"dev/d2/themes/assurance.d2":"f7723f53e005a68c803a38ce5c04cd733f46f4a2688fa4b17c66f9d5b308fe24","dev/d2/themes/data.d2":"19fceb46186892da02b763217963cc3ca2a35021219c0d353fdeec84604ddaee","dev/d2/themes/flow.d2":"1f13588619d0c8087c08d8afd023c4c0efe12726711c311e623eea3872726c1f","dev/d2/themes/routing.d2":"f185df198e7435d12b17b7b57b62dfc5795597d95eb926159ee13b448727bcce","dev/d2/themes/sequence.d2":"6e39472720dccc717f984c95b79570494b6ce3828b86227629841649e6c956e6","dev/d2/themes/state.d2":"f1a35cbca0f9cbb055ea9f793ba3dfb86e5fee4e462038ef3e72b94baa61d781","dev/d2/themes/system.d2":"b2a32ec6959ca5df9103c16454c4e34b758e061f850f7de6b619bcbc5fcf17a6","dev/d2/themes/vocabulary.d2":"add21e9b87eab485e5daabf6316fea44eb56b1007b70123f24b0e32e3357f744","dev/proofs/cedar/DomainMigrationComposition.lean":"97c2564f79b3ad81b538d763e70727d4505995019d8a96d401bb738486b190e9","dev/proofs/cedar/QualifiedReview.lean":"1ae16e06ad03a2906fa8c21dbeea1e3eb7700aa1e9359e64848dec65ccfd079f","dev/proofs/cedar/WeaverPolicyBridge.lean":"a9628a8123d504a34f64bf986feb4471325aa2b0ddc603d76b62632481eab67b","dev/proofs/cedar/ZeroTrustEnrichment.lean":"0c4b138843cc176c27d42d4a31177a3c12486b2d8ff124a6453e3d0922170884","dev/proofs/lean/ProviderAdmissionTurn.lean":"9b30418066f14197ad601d0f439a7326c7940a5f67785353c37f2ac044801bf4","dev/proofs/lean/ProviderEgressWindow.lean":"c4a15b4ccd3a6474290b71374499087dba7dac7a1fda53f3a870100ec2e768a9","dev/proofs/lean/ProviderLifecycleFootprint.lean":"4786544c8a8193c5221bda2f7cd5cf20531bd1856d88b10ae29b280f223e307c","dev/proofs/lean/ProviderReadCustody.lean":"67e83773a1a063852e2303512d4b75b73cd3b9a90117972aafda9ee7348e6b77","dev/proofs/lean/ProviderRpc.lean":"e79d7639ac11220585e59e85dc5bec12b6717f7b51fb28fdcd62dc96d8fae38e","dev/proofs/lean/ProviderSemanticProgress.lean":"d32e010145a7dfcd646daeeeb4b08c0e852b9006bca404681af7e7fe10d0eaa0","dev/proofs/lean/ProviderSnapshotPublication.lean":"312c0380e334fbc5380815d882c6b5b0007747100f818becbee9c6784eeb5716","dev/proofs/lean/RuntimeAdmission.lean":"6111d4b9e93ebaa9f7cc44a55ed504c88c20c8d9de81e947a2e13b3f4a13b13c","dev/proofs/lean/SharedDomains.lean":"10eef67918986264689b09f0a6c0d53b314d7bf43b42f4b9652b403570beb58d","dev/proofs/lean/StreamingExecution.lean":"3fba798a7887a0b2ae29a7e3f0aaa3d7e2fb191e5f1f28109a4a73d28e27b776","dev/sysml/AdmissionReaderViews.sysml":"27ebc6c98ec3a1f7f9081e77a130953c3b646a1fdf6f1d6fc1fa6ed6376e9623","dev/sysml/ArchitectureEvolution.sysml":"95708e0c53ce6b5c245a78e0fe911eb4ceb2a199c6ba7cef93f09aff68cb7ece","dev/sysml/ArchitectureReaderViews.sysml":"52ffbccbb17bd257e8ad9f4aa9f727c8ce0c00149e7d6738b82042ba06fdd0e3","dev/sysml/ArchitectureViews.sysml":"e5b5dbbd27acfba0bd5d5b52e45990b99471d88da0e814ec13fb7ab23d752d4b","dev/sysml/AssuranceReaderViews.sysml":"cd99fb7e9b23e08beac265bc832a8debee0dc1e1d318b0f64d5263519270e390","dev/sysml/AttemptReaderViews.sysml":"0d87cf71e15c26566422a6ddb5945fdb8add8af0484d9d024c32b97597675e21","dev/sysml/AuthorityReaderViews.sysml":"6fa25bd3a64e7f89987caec8e4773928be2cbea0a3c943299e536ca81978316d","dev/sysml/captures/ArchitectureEvolution-reinforcingCapabilities.json":"edbe988ddb9c287864911d4405199a9e58667b9389b00cb267d754e3edda6fa4","dev/sysml/captures/ControllerObjectLifecycle-lifecycle.json":"f903be891bb4b7161c5637176a235ccf2a377dde522246bd2d9df6b0e6c75c62","dev/sysml/captures/WeaverAdmissionReaderViews-beneficiaryRegistration.json":"432b9379f69f40ecd41a8727595ecdae540b107d997d9b9981ec87ff35bd4f3b","dev/sysml/captures/WeaverAdmissionReaderViews-bootstrapInvitation.json":"55be61f983346e3d126edbfbc7f12a057642dd9d691c16204d56e51c71a282f3","dev/sysml/captures/WeaverAdmissionReaderViews-callerCustody.json":"1ab1bfd17b15d3545523aba839ee27d93e1ab11cd83f002ad703efea841b147f","dev/sysml/captures/WeaverAdmissionReaderViews-custodyPublication.json":"7a2f14c093c89418ebac9670070d342df6ee996e29142eb30f9404bbdcc52457","dev/sysml/captures/WeaverAdmissionReaderViews-enrollmentCredential.json":"80a525fba14c68429895652c4944c847a452a5be432cb1f1f5015a7c4cee2ddc","dev/sysml/captures/WeaverAdmissionReaderViews-incarnationIssuance.json":"ea35c502ff46d5707442a527171bcef7d717f83ab036b402ce86d9688ceb629b","dev/sysml/captures/WeaverAdmissionReaderViews-routineRouting.json":"a484553c144eb52370857196edb291b10390a5ceae2dbc19cab7fa850bde7bdb","dev/sysml/captures/WeaverAdmissionReaderViews-sourceCustody.json":"e6b7c197e8fa7b26444c8324fe75bb05dbf2c5ec1fb59b36670b90ad937216ba","dev/sysml/captures/WeaverAdmissionReaderViews-sourceJoin.json":"1bad3d182a6b1238eab2f661a4e608ac015c63106df0836b6ce2e7c7e46f2618","dev/sysml/captures/WeaverAdmissionReaderViews-subjectAuthority.json":"c0c4ebb0c5eeb4d698732d9accb9ef7e307d3cd62a1769bf52682a12a5887e5e","dev/sysml/captures/WeaverArchitectureReaderViews-adapterBroker.json":"68803012fa23c614decfc9c1af28810ba852df038973a4c2d6862d89e8c0fa3f","dev/sysml/captures/WeaverArchitectureReaderViews-anchorBroker.json":"53dfd6a7c5e8a2732b4d156cee45654132df66c45c5a52e648902d75d0555754","dev/sysml/captures/WeaverArchitectureReaderViews-anchorEgress.json":"14a6bddbc480101ab660dd95488b18ee21762d70019f3151f809a8cd0409a654","dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json":"3851beebafd9d86dc6682ee98f2399be7058a8f6b76d30957dc9c5b226f00c65","dev/sysml/captures/WeaverArchitectureReaderViews-codePolicy.json":"f4ed13f93377948fd86b212ba70c7a2353ffee081c4590b414d00a4e0df81aa9","dev/sysml/captures/WeaverArchitectureReaderViews-configPrefix.json":"f96e5188af05dfc522bb1eb154367fd5681b36b31952ab9833645ce79d90ff39","dev/sysml/captures/WeaverArchitectureReaderViews-driverCompletion.json":"ae41657d0e830a6a96755ba0a7b548a0e33deb5562ca4362f7fee780005d1905","dev/sysml/captures/WeaverArchitectureReaderViews-fencing.json":"cd23acea8403195e33f12225881a006b1120aa9334abd488855633fb0e7688fd","dev/sysml/captures/WeaverArchitectureReaderViews-gatePersistence.json":"5537a7bf61060246c121f7157d2b5ec659c916f3e595fcfaa5f6dbb2342b9eb0","dev/sysml/captures/WeaverArchitectureReaderViews-journalLifecycle.json":"367aa48a3237deae8b61be69414523a1c8bc8b928aceedb424914aed909f78ba","dev/sysml/captures/WeaverArchitectureReaderViews-logicalObservation.json":"5ef7eb4071414434763382bbd935e8c178b61980d8424ff675e5aec78a101932","dev/sysml/captures/WeaverArchitectureReaderViews-manifest.json":"aec0cad85842570184dcb94d108a24fc1be4ac1ba55db2e785d0ac71011c6af3","dev/sysml/captures/WeaverArchitectureReaderViews-migration.json":"52c75b3bc7b2f6a889d18d94dae879509090945eea428075279fe818adb3c799","dev/sysml/captures/WeaverArchitectureReaderViews-policyExecution.json":"62d6cf3e99538c202a4dd8c6d516f5150dedd3556c5607c4f61b32e893b2cf21","dev/sysml/captures/WeaverArchitectureReaderViews-quorumPromises.json":"1d0f0e3e9b2dbd124afa028344bbf01802b114d81929cd26a2d3fad8af84f8e1","dev/sysml/captures/WeaverArchitectureReaderViews-relationships.json":"782ec97d1c8b9419ad050e08c8ad5e87c4876eb2526aa399de7e24db5010b6fc","dev/sysml/captures/WeaverArchitectureReaderViews-settlementAnchor.json":"cb59d079f570aac873831b41e52ac43c02e41249e5d78dba4c5ff900fa4ea9ad","dev/sysml/captures/WeaverArchitectureReaderViews-sharedBudget.json":"ff1af8fbb913d9c45b11d929b4f36e3b810f436368bf79c8629f1a288583709c","dev/sysml/captures/WeaverArchitectureReaderViews-sharedExposure.json":"586c790fa221785dc41e5e1204a0b2acd5ff1dc126dbf142acbfa18cf81ab77b","dev/sysml/captures/WeaverArchitectureReaderViews-spentState.json":"bd1a42300c7a1a9c07e3281e7bbd32060e51f28ed0b9bf36ab2fb54e4e851ca5","dev/sysml/captures/WeaverArchitectureReaderViews-writerSettlement.json":"169bc56560a16b1601922d8f2ad2f4ed75ac540431971bbf930e3542c140bcfe","dev/sysml/captures/WeaverArchitectureReaderViews-zeroAssurance.json":"2059214421a178bf14cb0a2c0085d7a3718b39c4379e9af7828e1feef67164e8","dev/sysml/captures/WeaverAssuranceReaderViews-brokerQueue.json":"15745e4f9cec33f7bfdada37b0eacaf92de69eb07bb6bdbee515fb9512ebf2df","dev/sysml/captures/WeaverAssuranceReaderViews-continuation.json":"11f392fab1acd0caf8186eb54d20cc8e9d19bf292108c4e00b01440420b6aeb6","dev/sysml/captures/WeaverAssuranceReaderViews-deviceEvidence.json":"3bac7aa69802aeb5c32b78ffc88e7e5f17f8968bf7a03fc85402f1b36f0cb57b","dev/sysml/captures/WeaverAssuranceReaderViews-gatewayHead.json":"0f49c092feeb1d8c5d8216048321e3d98abb8a15af2e65aad8fce12d3cedaa4f","dev/sysml/captures/WeaverAssuranceReaderViews-keySession.json":"2e2494f8879e191867956d1b3e62b9d7a0243e00733d913e7a96ce0b9e1e5a33","dev/sysml/captures/WeaverAssuranceReaderViews-rangeRecovery.json":"37ab951ab4cdc2115ddd572024c5dda218e3490baeecd66c1622bccd2b88262a","dev/sysml/captures/WeaverAssuranceReaderViews-signer.json":"83f37ecb3d74214752e1872f8c51e6e6ba98a0d95b491a9bc417b5d9abd47a1e","dev/sysml/captures/WeaverAttemptReaderViews-admission.json":"4eeb4662458b8bdf0dd19a6a22639d70abdd95c41fb7534536be2216c1ad966a","dev/sysml/captures/WeaverAttemptReaderViews-outcome.json":"1b3f2a8ddc54bf6612476af88a8e4cec0b0c06080f12461db91a27927adc2af0","dev/sysml/captures/WeaverAuthorityReaderViews-attemptLedger.json":"f921aa38afa58615be7794518099bc626c9b3b640c9a2a65f49eaf097da4a530","dev/sysml/captures/WeaverAuthorityReaderViews-canonical.json":"be06876b8a2f5a9c46dea301bb0a3a96a100f6da8100cf95dc90756a99710bb5","dev/sysml/captures/WeaverAuthorityReaderViews-multiKey.json":"5d4143cc5ac238f51180f951cdf84e1487d5ef8f131e0ee18ab6289fa14885a9","dev/sysml/captures/WeaverAuthorityReaderViews-publication.json":"3b73428f7168ee48e5be05e9db82a34c00429bb235015b667d2c23e9295fcbf9","dev/sysml/captures/WeaverAuthorityReaderViews-recoveryCAS.json":"03e89b63939aee3e5accede80f2f021762e58b1da4cd36e1dd8cdf1fe421a607","dev/sysml/captures/WeaverAuthorityReaderViews-scope.json":"8d2a0fd2cc246231bbb38370e0b4480262f91477014b9e4985e54678eef40f14","dev/sysml/captures/WeaverCorrespondenceReaderView-correspondence.json":"e2299aee079f5842e7eac1d90025f0b7cd11d463e5c6eee280ecda483824b6ce","dev/sysml/captures/WeaverExecutionReaderViews-accountCommit.json":"a89cf5cf9b52e6387fe8fce939484346503a55a1d38d527ac7be66c4c892635d","dev/sysml/captures/WeaverExecutionReaderViews-admissionFloor.json":"29aa9654abf6b61636a3a5350a00f0d4270a0b9cb2d6cea08480395359dfc05b","dev/sysml/captures/WeaverExecutionReaderViews-appendHandoff.json":"bac680e1f4dd0a906585b1ca58620b104643c2467b8e4aa27e0b70732cd7c1af","dev/sysml/captures/WeaverExecutionReaderViews-checkpoint.json":"78e33402e07ddeed6b1b56fdb4a9e0a487e12b2cd8c38fc25c12c76fc11cf623","dev/sysml/captures/WeaverExecutionReaderViews-executionEvidence.json":"a3a53712803542868a18f45fe8cf438301d5bf2328e612ddee2e6ec325791791","dev/sysml/captures/WeaverExecutionReaderViews-executorOffer.json":"65e8c494c684cd7d5ca653f6b246fc86a5845d836376aaa08e0ae62f87404b11","dev/sysml/captures/WeaverExecutionReaderViews-joinEnqueue.json":"937322f451a92f812b2bd440780934e6a8c71cfac830e4b98665f190cea780a3","dev/sysml/captures/WeaverExecutionReaderViews-manifestSwitch.json":"1f8e2bc0faf38b88dd34c024c005cfe6d38b487c85fb875c6fa9cc6e025cfdc2","dev/sysml/captures/WeaverExecutionReaderViews-resultProjection.json":"2c33a5616409509c0524cd974b301ce7ae56acbe4fac6f5d7b684c9ae5bd80f9","dev/sysml/captures/WeaverExecutionReaderViews-walActivation.json":"a359e8294f24db0679f36b70f8aaee2da0937edf4c8d7f2bb73a7d3e87c68005","dev/sysml/captures/WeaverFloorReaderViews-floorOrdering.json":"67d2a58c8ce4bc1071165602e0065d479e62b01035032f1108f8ebc266e67cf9","dev/sysml/captures/WeaverFloorReaderViews-floorRecovery.json":"d656eba4d6f6b09f07ff11dcd82bf70a1ceb6f2d284a987ecbb9c8967048b117","dev/sysml/captures/WeaverResearchReaderViews-embeddedTooling.json":"8c60871a93a2f3a1906e14b6ea81dab55492d58acc9ec123e8a5f45884634398","dev/sysml/captures/WeaverResearchReaderViews-floorTransport.json":"1dfc5dce990a0eaf8fcc1342f7e3318f9b405725e8621dd8b1cada2f8f66fe64","dev/sysml/captures/WeaverResearchReaderViews-gerbilLifecycle.json":"77da614bbefc6b5b628349343692301e61d19971c2e15ab465811bec34062aac","dev/sysml/captures/WeaverResearchReaderViews-gxiLifecycle.json":"22373d2a7dd4324b14f02920c1fe066edcfc3f93930897cceb01cdd5c35bfb44","dev/sysml/captures/WeaverResearchReaderViews-parentReplay.json":"9e061e30a41f79c34e63ce3ea0dfee2d250aaa97ccdf726b2b78d0f6f21d9451","dev/sysml/captures/WeaverResearchReaderViews-profileBinding.json":"71a89b539ee9aa7174f1981fe753251641bf8df2cc085f1bb73e84aba6cd9a8a","dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json":"8d17c69f7a55337797917b251f91e0e480b1b41347d90a545fab1ceae19e839d","dev/sysml/captures/WeaverResearchReaderViews-runtimeAssets.json":"eb59b55ff93e58a03e6a8f9a4123f2e57c9dd9d979b6f554454b828a6b1567cf","dev/sysml/captures/WeaverResearchReaderViews-semanticSlice.json":"6ef38a0ce6b5f0ff16d085af8cb6342c3603e638e84805c0d572accad2404728","dev/sysml/captures/WeaverViews-architecture.json":"82982f844fb59ca130a82ec8e8493a3d87600d089835565c8b932b2f2cbca73f","dev/sysml/captures/WeaverViews-assurance.json":"deed1f1eb9f5cf10beeee368fded527f470bd78d1fca0264bce2b1e42d4337c6","dev/sysml/captures/WeaverViews-contractRefinement.json":"7f9ae3f31d8c23aa22cf582acc135feb0d8373871b8c17395e33570e3c2d857b","dev/sysml/captures/WeaverViews-execution.json":"95b448394f8503a04f26d2f485ea1267ade1a6ce3fead6f28390ce3873fea101","dev/sysml/captures/WeaverViews-gateway.json":"7b90100dadb412dd7f282875afb975e7b5bd8b061ea6929ef620b2581ce0a006","dev/sysml/captures/WeaverViews-providerDeliveryJoin.json":"15b4f7f038afd47b409184ca90ec1f8b97d42bef8c9fbfa489d180fb245f284a","dev/sysml/captures/WeaverViews-providerEgressWindow.json":"02056950ae8774fae8cae76f4f0ff1fdb558790289cce235ebe842d8d2c0e20d","dev/sysml/captures/WeaverViews-rangeRecovery.json":"067e46a50745b6f5cafe50f07a723a19bc64ea715c6637a1689f3001d78f9ea5","dev/sysml/captures/WeaverViews-routeExecution.json":"ad6b20e13cf5621830e13deab4a35c350bb461db7ae6e56b492b43920a67eb19","dev/sysml/captures/WeaverViews-routeSelection.json":"ea0f930692982260f5bc8681405a2b21def87d67c90b8852eb89bb92e4f50c0c","dev/sysml/captures/WeaverViews-storage.json":"a3a98328e2c3ae5e64e44a5f2516b4fd810b367c23af2d462db0ef438edf3b62","dev/sysml/captures/WeaverViews-streamAdmission.json":"4c2ab7cc35bc57ef525b48ec503449aa24e113c97e51aa7ea0aef3fed7f3c694","dev/sysml/captures/WeaverViews-zeroTrust.json":"54f44d30936aaf278a59bf2530bfe59184b83514953a3c2bf2753b8013330e2a","dev/sysml/ControlActivation.sysml":"f9f0d8e8746c041a22de2933fe4728fe4f96e33030a0d62ae38404a14edd79e6","dev/sysml/ControllerObjectLifecycle.sysml":"306655b388578daaad139d4e3bebc111744293f62657173588aff48b129c1124","dev/sysml/CorrespondenceReaderView.sysml":"24b811c00528feaab3547d5db3b7fada290ff89478ac2be0a1d252d8ea1e5828","dev/sysml/ExecutionReaderViews.sysml":"88f690ed1fed91f63f7571d14bf5d7c1c8d14ee3b8d1d17ae333dfd7a6176df3","dev/sysml/FloorReaderViews.sysml":"93401ba5b2009dd54614f7e5aff81d91a20085efbb77b3a143726ffdea16592c","dev/sysml/GatewayArchitecture.sysml":"dbec3964b7873ed0633964b05d1ba1ee828050aed35a3066858d0c38893f2642","dev/sysml/PolicyEvidenceDesign.sysml":"2476fbebe5f299283eca4e0e0f77b114893717c09d839b1f4a7ffad6ea4428ae","dev/sysml/ProviderRpc.sysml":"dc5712dc57b4901a563df8c77c1fdb9001c93f56349a599a44f40fecc32019fc","dev/sysml/ReaderDesigns.sysml":"4df8352980f9727b85a26533dc5ebfd67730540359d553a17d562574f3ea2529","dev/sysml/ResearchReaderViews.sysml":"cb10ed4ab79e911197834a8102e8a84986c567a358098e36d234d15b9c5acaec","dev/sysml/StoragePersistence.sysml":"b6b58b8802a557a7f3af787c2e7875be64865169ca3fd7e9973b13f6c3dc792d","dev/sysml/StreamingExecution.sysml":"d0d4d92300fba2b908ace30d9065cb2bac1d86f3b7c98219c1853a30f3110e85","dev/sysml/WeaverExecution.sysml":"0224c33a6eb9cecdfe69bcf0747eaf7d9168422c2ed0b8ce39c345e041277d42","dev/sysml/ZeroTrustRefinement.sysml":"7cbec57110f03ed68469a1f49cb2046769516b09a6eb1b9433d866161bba6a82","docs/10-19-llm-gateway/10-routing-and-inference/10.02-llm-routing.d2":"513cad143cde846a9393bb5020dc4843caa1bb844204d3d0c13d1b5ada5efc70","docs/10-19-llm-gateway/10-routing-and-inference/10.05-route-execution.d2":"7c3ff8609c24983d0b27511756d8c5c04d0dc2cf5c973fc7012eaa0acda421e2","docs/10-19-llm-gateway/10-routing-and-inference/10.07-provider-egress-window.d2":"3c9c7c67296700d3b08cea62dddd5bdd011e7bafd61c2b4ecf1e38c32a94d6e7","docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2":"80b85a1f845c440259a93a52b33fae42f5373f985b6dd24d1fcef2c798e5ccf4","docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.d2":"69eb501f2425805d13ad56442db851e4d165198854df3ba6994d0f39e1946767","docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.d2":"fbdd875bcb9814de5d73556daaf6f8e7f131bee18d177bf20b8d1fad6407eaeb","docs/10-19-llm-gateway/11-attempts-and-failover/11.02-attempt-ledger.d2":"5438329d7af60e9596b5fe4519b04a27a7c36ce1d1dc1aa5442db6df7167cd8e","docs/10-19-llm-gateway/12-semantic-contracts/12.02-semantic-contract.d2":"8560ac03652d2dfb8aeb7797c0e3b61031e49f9a3276d3207c8758a32037c530","docs/10-19-llm-gateway/13-authoritative-scope/13.02-authoritative-scope.d2":"e5950b420b85e30891bdb2264c7fad7ccd9ec9934b6175906d592d683b3a844c","docs/10-19-llm-gateway/14-registry-publication/14.02-registry-publication.d2":"9153743fc734fb044f94a4d22175fbe963f0f15f02598143dfbd7a06cd880177","docs/10-19-llm-gateway/15-recovery-cas/15.02-recovery-cas.d2":"c5de2f6cb52b0450361b2ed0523f647bdcad1fc43d410231f91ae86aee450859","docs/10-19-llm-gateway/16-policy-publication/16.02-policy-publication.d2":"4be00575666b7ada7185a30e553b42b9c36fe9109ce89df3d0dbb4b30ac10cab","docs/10-19-llm-gateway/17-policy-continuation/17.02-policy-continuation.d2":"4108a821aba5a2de1ffebc59b9e0d9180130bb3f598ac2130d59a83e8eca571f","docs/10-19-llm-gateway/18-canonical-registry/18.02-canonical-registry.d2":"f3b44cf54b006df34b528075bbc54742963a53e2afd4cbee435f81095b59b800","docs/10-19-llm-gateway/19-multi-key-registry/19.02-multi-key-registry.d2":"c44a2569dec8ae1fab46acb1ddd58f8b468e7ea7b11136c120a6bf2b042cf8b7","docs/20-29-execution-authority/20-result-projection/20.02-result-projection.d2":"696df32a9d705c6915bcc43a33616126cdce61ce5af0ae198c0dca5bc898d645","docs/20-29-execution-authority/21-join-enqueue/21.02-join-enqueue.d2":"430f46389111827b9f0ad5c9c3193366729fffe917ef18a5bfa0ec8238f6ab02","docs/20-29-execution-authority/22-executor-offer/22.02-executor-offer.d2":"0d93c13abcc1bd79afb32e6ae8a965cc5ec3b0c30fc1958f2f212e12b5e4b65a","docs/20-29-execution-authority/23-execution-reconciliation/23.02-execution-reconciliation.d2":"14c698ad47a243d46d788ab3494b1ad22ae7f14a163140eb6b4f5e8e071c6269","docs/20-29-execution-authority/24-account-commit/24.02-account-commit.d2":"10d6a5116d2c8be77ce7f27312d9d49ad832645c6748bb7bd68bb6942055990e","docs/20-29-execution-authority/25-wal-activation/25.02-wal-activation.d2":"9ebcd14701116e583157282a1678a6f1e0fe70e1ee4b9b7e038b520d4392ce05","docs/20-29-execution-authority/26-checkpoint-truncation/26.02-checkpoint-truncation.d2":"c5c1a35a16fe9b33029169b16d4c0af113f49e665eed0074ce524fc7a15bdb77","docs/20-29-execution-authority/27-manifest-switch/27.02-manifest-switch.d2":"c4de2ef519af25b2c41194df561860ad0236b0309b3178b388204c29cebf9f41","docs/20-29-execution-authority/28-append-handoff/28.02-append-handoff.d2":"f7646793e8540ec5f1e587d5e13deaf16d166180f80107ac8f9c904ea5c9372c","docs/20-29-execution-authority/29-admission-floor/29.02-admission-floor.d2":"0b9794f3d5fdfc7dcdbb519426eecf7e6ec6cb707de5017387c9aa47208ea385","docs/30-39-assurance/31-protected-signer/31.02-protected-signer.d2":"bc787086ae26a1a6cd56e51a2b4182c86e476f13e28ed1f5d80363b1d827e013","docs/30-39-assurance/32-key-boundary/32.02-key-boundary.d2":"1b616363aa68166988cc1d09404d637da406f048b9647676ec5f42d15f1762ca","docs/30-39-assurance/33-device-isolation/33.02-device-isolation.d2":"f4b086efce29484b70d4d4b2c04dad3887976d69187c25234e734e90260a6c7c","docs/30-39-assurance/34-floor-decision/34.02-floor-decision.d2":"78e2de9f044edb41944a56c1c8c8251a9cacd3470cf73c16b87f5ba100139a04","docs/30-39-assurance/34-floor-decision/34.04-floor-recovery.d2":"296d821eae11d4b77a552ae21d91eadcddcf032a15989dd35490128397044203","docs/30-39-assurance/35-intent-continuation/35.02-intent-continuation.d2":"08475ba17d7c98911a7db912041b669d049c75315c861322f72a5b50a471df55","docs/30-39-assurance/36-gateway-head-cas/36.02-gateway-head-cas.d2":"51669df10ec208197e690f656b962b259959af5f225243b62e5ff6bbea5637a5","docs/30-39-assurance/37-broker-consumption-queue/37.02-broker-consumption-queue.d2":"1ad636df3ba980d5f25b1a330c00c8b21f152958fe7c86617736e1b1f85a1ed8","docs/30-39-assurance/38-logical-range-recovery/38.02-logical-range-recovery.d2":"8ed5e1adc741da6852d027828993a83816cadb0c7bc1732bfaf121b2a64878d3","docs/40-49-admission-coordination/40-source-join/40.02-source-join.d2":"b8815cf59a1be49a4657b6ec3857d39e6d7d39ab4bb3ed44521c71ffe0ec5cee","docs/40-49-admission-coordination/41-source-custody/41.02-source-custody.d2":"feef18f62d537d4eb0659c0f1d719218df1a3eda506c9468b59423b151550bd7","docs/40-49-admission-coordination/42-custody-publication/42.02-custody-publication.d2":"24f019e8633cc816f7488e3f65384d2dea96ac8a3685714665a47bc6144b1e5c","docs/40-49-admission-coordination/43-caller-custody/43.02-caller-custody.d2":"6352167e4d3427fd9a66befb74fb3eebf91a127c5e82ecff8312b24178d5117f","docs/40-49-admission-coordination/44-incarnation-issuance/44.02-incarnation-issuance.d2":"215f52c84c9f41c36352f8b6da8b4670f1b375672cfc9efdf6a8bd1df95c946e","docs/40-49-admission-coordination/45-bootstrap-invitation/45.02-bootstrap-invitation.d2":"9e019de8289428a97580fe66ccefc6b9d0a43c1bac07433d2f29596f4d407401","docs/40-49-admission-coordination/46-beneficiary-registration/46.02-beneficiary-registration.d2":"322b848fdd67ea88c99b509cb5d913d7a5023e327edea51f16f44816356d81ce","docs/40-49-admission-coordination/47-enrollment-credential/47.02-enrollment-credential.d2":"ea0aa0bed915bea42d3d65c8f6572f799eb63d0aee1018b75803e61ef034d303","docs/40-49-admission-coordination/48-subject-authority/48.02-subject-authority.d2":"9f707fbc6e5ba8933a0e4d9d057f013c5764afc503f819288f628d3f9709f88d","docs/40-49-admission-coordination/49-routine-routing-config/49.02-routine-routing-config.d2":"7fa18b652ba97e8fe66f402a9a85d65740db9d3ffadff7890db7d72826c498b6","docs/50-59-research-program/51-qualified-semantic-slice/51.06-semantic-gateway-slice.d2":"d63df655a635fccac3c92eded92c039a3f079c24fa2b7a2fd0dc1f3fabd3c0f5","docs/50-59-research-program/52-committed-profile-binding/52.04-committed-profile.d2":"3ea30976830c607bf8cec62cbabc4291c384bd5f368049a45777f6f981d87d6e","docs/50-59-research-program/53-gerbil-exit/53.04-gerbil-lifecycle.d2":"b7b623664edc6e86efe62eeee7f5977dc207f0cb12e40cb6f0e77e38160695de","docs/50-59-research-program/54-dynamic-gxi-exit/54.04-dynamic-lifecycle.d2":"d4d410dd8cb10de6d3526b54ac7f96731d2f2a94dd9763aad96a0926608e251c","docs/50-59-research-program/55-dynamic-gxi-paired/55.04-runtime-boundary.d2":"573b248a6b7ce2d7eee1e70a469c54e4f195c4894ec7b0f61c8406fae843eccc","docs/50-59-research-program/56-gambit-image-closure/56.04-locator-boundary.d2":"0c45ee11d269b0cab8998c7fc3432ec851b9390b7530486225134b261d8d7de8","docs/50-59-research-program/57-runtime-implementation/57.03-runtime-boundary.d2":"193d22a5bd9e4b23260334d085df8aa5ec19c349f13cd9f56eaa26fe54f7e3ac","docs/50-59-research-program/58-streaming-execution/58.03-streaming-runtime.d2":"76ea49c83b4b36af1e775f80475d40747640b80a330434bf86635e255e84ef14","docs/50-59-research-program/58-streaming-execution/58.05-range-progress-recovery.d2":"aef20c8ad7d7420a65422add6d9fb635bdbe32e42e49427d3179bf20499ae4cd","docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2":"6f4e8218ea262e35efaebaf8cc2f96345b2ef1e7e9c1a6b12b68290dd99c683d","docs/50-59-research-program/59-provider-rpc/59.21-verification-ownership.d2":"e035ae7e56ee5e6498f131ed62f4792547c1e716aa5ed29865b333f54665e8f1","docs/50-59-research-program/59-provider-rpc/59.26-semantic-execution-ecosystem.d2":"50c091b094125693e2debe73599a63405849f1f55ab3658030674692c9334e14","docs/50-59-research-program/59-provider-rpc/59.30-governance-adapter-acceptance.d2":"88cbbd45e63358bb45a58fb27f85e275b9cc9fb3d3aee6af19eabed0912545d2","docs/50-59-research-program/59-provider-rpc/59.43-floor-transport-owner.d2":"36c4d6b561332ab30deb464a92bb4c2f02ceed5c8a1ca66617f72b6086b2c555","docs/50-59-research-program/59-provider-rpc/59.44-cloud-rpc-arrow-boundaries.d2":"fe0ac2220e04f6ccea851247ecf8ae1cab4ec8c8ba8744010c478992c233ebed","docs/50-59-research-program/59-provider-rpc/59.45-slow-consumer-zero-trust.d2":"e36cf58a239a2d9f0c99789bb7484de4e26180a8f941970540f72b530a79d813","docs/50-59-research-program/59-provider-rpc/59.46-functional-security-frameworks.d2":"e541b969352e8149e71e5b539988f9955b525e5e5ba3e7e7270bd4a98fbe19f5","docs/50-59-research-program/59-provider-rpc/59.47-property-testing-framework.d2":"f66ed065dcf955a233968ca295517c642be30dad9b24e23a781fe34e4bed45d9","docs/50-59-research-program/59-provider-rpc/59.49-policy-proposal-barrier.d2":"3a8559bb22f812075d9d7de4a397978995d06c32ed22e9415f990413551aebb6","docs/50-59-research-program/59-provider-rpc/59.50-parent-contract-and-replay.d2":"2db3983f56e938c927b68077551573c8e86362da892f47890459ab7b3f929c64","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-architecture.d2":"10e92e79b69f4b0813551dd2ddadc5ad225b7b0fa8374ed7015b7f2fe66bb6e1","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-contract-refinement.d2":"204c9e20d9027b7a38bf2a964da9a7cadb92744561fa9f1eb3fa29d00f4fa386","docs/50-59-research-program/59-provider-rpc/59.52-reviewed-publication-cas.d2":"4e0998e61717d5441e242cde0dfc52198312b67b63f0ce8b0425a423d1b88a24","docs/50-59-research-program/59-provider-rpc/59.53-artifact-registry-recovery.d2":"f7083a48413d41ad99e7191281bd6e74a92b33c7cc1f4f2f9ae322bb1405088a","docs/50-59-research-program/59-provider-rpc/59.54-source-incarnation-authority.d2":"1e55c0487f01d70462e8df6b46eff9e799b0dc592c0e780c759fa602e3d84444","docs/50-59-research-program/59-provider-rpc/59.55-evidence-reviewed-publication.d2":"c66435372642f7a93ca7fc6f78c2abcbc364a4dde447d10dcc4b2b21ccc06456","docs/50-59-research-program/59-provider-rpc/59.56-runtime-assets-and-authority-floor.d2":"c675469701bb6994fed1976d1e90d01dc1cc4e416a6788f865494fa3243d32c1","docs/50-59-research-program/59-provider-rpc/59.57-schema-bound-candidate-replay.d2":"5ca15af556e0a4ba5bdf1742cf81182ad72e7f51b2eb63352b839e068a7ad7d2","docs/50-59-research-program/59-provider-rpc/59.58-independent-source-recovery.d2":"4b21999b3554be15374448f36ffbccf517b32784a65cadde0f4c1eb8308da377","docs/50-59-research-program/59-provider-rpc/59.59-retained-root-and-recovery-coverage.d2":"37fdf1d3dd01f087434a6108b43a5657d7aecf79a2b9e60638d70eb0b1a4984b","docs/50-59-research-program/59-provider-rpc/59.60-persistent-source-key-custody.d2":"d27df3a14df5d57ad725c1455c82a4ab5bad45b78acea8cd1a76e59958b710eb","docs/50-59-research-program/59-provider-rpc/59.61-authority-bound-replay-pair.d2":"bd4962775564848a90ec49439301cf0cdfbaa4018956344e809f5b318bea6ccd","docs/50-59-research-program/59-provider-rpc/59.62-burn-exposure-recovery.d2":"fab4ea6d0981d75dd4c704f302268f3c5af0898e299e8e0fb38b34d07200b22c","docs/50-59-research-program/59-provider-rpc/59.63-mrr-admission-contract.d2":"ed3c604e0d350049f00528c7117675a7db751b3d6683719b03be116bcf49d5c5","docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.d2":"7164874fdbeec99f2185e1091f759466a68a3b7d9b239db6a503f16383fce50e","docs/50-59-research-program/59-provider-rpc/59.65-turso-concurrent-admission.d2":"0ade3ea326e2066ce908129e383b7e0f371a429710ed0a0bad30ddcfd61f034e","docs/50-59-research-program/59-provider-rpc/59.66-bounded-writer-reuse.d2":"9390a3c12f06c2f33e3df99088dc39de92d3bccc971ddf5a632910515a67623e","docs/50-59-research-program/59-provider-rpc/59.67-writer-owner-lifecycle.d2":"c28559ccf38b2f3320d84bbc0ffc6133e2708081e95bff39d5ed75d064287bde","docs/50-59-research-program/59-provider-rpc/59.69-hot-path-cost-boundaries.d2":"e5789625590fab63bc3635627b7e20ac41f64b8f40cbeee84d51a85f27ab31f1","docs/50-59-research-program/59-provider-rpc/59.75-complete-entry-and-output-contract.d2":"d667501bc15d6c31d986994f641d8d38f63c1d910784e6852e596c24c4e4c7c7","docs/50-59-research-program/59-provider-rpc/59.75-package-linkage.d2":"bc655ae71cc46e0d5b7f42637b78530f262c3142394485e2a9ba31f6516a0a10","docs/50-59-research-program/59-provider-rpc/59.76-embedded-tooling-and-darwin-io.d2":"87655d7c6d81c1ab203f886930f1630003e006c0edb71f90ac3ca23a0cb91845","docs/50-59-research-program/59-provider-rpc/59.77-mrr-turso-storage.d2":"72a4dceeb20cca337276f64537d47dbbd2ac0ce359a7a63997090e6476a40c96","docs/50-59-research-program/59-provider-rpc/59.84-quint-preparation-and-completion.d2":"17f485d7c541506c42003ebba887705ea61972f00c9498aa3c0d153a33b02922","docs/architecture/08-diagram-catalog.org":"353a4296584381207513468ef291e7e1aefdcd6f9f2b854c92be90aab47577ea","docs/architecture/diagrams/00a-readme-overview.d2":"1e6119c9d5b2d8a40d3bec0c8add35e8c078dd739e46fcf45c589b8125c7c46f","docs/architecture/diagrams/00c-gateway-runtime.d2":"c1d93cc1f635803872e3349c89b5127145bdcdd2b85e9a48f83d63f0bda439da","docs/architecture/diagrams/00d-zero-trust-overview.d2":"0d3d1a5de0967db2331b9be81468cee1b7cb1d1d98966c5e541e4fc24023f2e6","docs/architecture/diagrams/01-system-boundaries.d2":"69b4622c26b18a8518d46f79db8ce281c756a16f7f1a46977272086bf4dc38e0","docs/architecture/diagrams/01-system-relationships.d2":"dde40fac8667b79a070fda14ebd892f1f1e7c1217726595179b541c855f80c2c","docs/architecture/diagrams/02-admission-sequence.d2":"97077cb16cd4457fe14092caeb4bc8cf2912d434763a08fcf350cd6a4c2b2c74","docs/architecture/diagrams/03-attempt-state.d2":"e696fc0f1d63f58100405852e88e8a7dfb1a625e43be398f3bb54bbc1d90e13a","docs/architecture/diagrams/03a-attempt-observation.d2":"6b387ec7fbcff7d5e3e129bad7ea9590afe0324800a5a13bf7a89377ad86c387","docs/architecture/diagrams/04-consume-timeout.d2":"2ccfe8d033069e0d891531f3b5afef4febf21b2722209a612454d14321cac940","docs/architecture/diagrams/05-fencing-boundaries.d2":"1103ed75ac615b1a2f8239c0321d046a5a87acfa235d5042d8a529e23acd7483","docs/architecture/diagrams/06-source-admission.d2":"4d20817291c5de93b7f97366e6cb1b4af954f22de1ebcb3012c139a4b9dbd82c","docs/architecture/diagrams/07-post-claim-outcomes.d2":"63258620c15c2f52963dcdba33b4ac82cd12aadd1c2de005cd029655493493c1","docs/architecture/diagrams/08-code-as-policy.d2":"fc2263ff1ae000055e6054b89beee60f53b9621707510354c34ef45057889676","docs/architecture/diagrams/09-claim-wins-race.d2":"9eff775ddac29c47acd2c0b69fb1ff98ba9a20943da970c2804e270979555c41","docs/architecture/diagrams/10-commit-dispatch-sequence.d2":"fa5d56c49bc3f590c88cf7c3b63e180afd2d2a39fca878d1515917077ff1687a","docs/architecture/diagrams/11-zero-trust-assurance.d2":"ea93840da2ff4bdac59349f5ad7a56cee5506600283d0c364c53275dde0b5b48","docs/architecture/diagrams/12-execution-correspondence.d2":"1dd66ee8c517fd9c6f2f4b1700aeec3e620d699fbe9eeee20df8e05a7f1decb0","docs/architecture/diagrams/13-policy-to-execution.d2":"4bb05b74c3bc0ca997c5e5035ddc949fa374db3ff49bf2104a6c9753e12be3ef","docs/architecture/diagrams/14-adapter-broker-boundary.d2":"b855fa0482a5524226354b26bc8d7ecef0daf2ab1cab54c1783eba0ff29fab01","docs/architecture/diagrams/15-stream-message-authorization.d2":"cedf1c545a853ec2a9ae51bea928b04376d192f1a4c2af117fa54f475ad541e0","docs/architecture/diagrams/16-authoritative-spent-state.d2":"201bd9fe5eb6101543d939e3d83aca646e2b07c13ff1e3c56779571a0cd1172e","docs/architecture/diagrams/17-logical-message-observation.d2":"2333ad147295ead60ed6a92dc824cf6f5769f3828eff1e0cdf58e50aace7b1e1","docs/architecture/diagrams/18-shared-identity-budget.d2":"5ab4992fd8b6a6abf518fb0bbc8c2c8ad8b920d0be74a6e734d846319252ffa7","docs/architecture/diagrams/19-finite-domains-and-migration.d2":"b72b451d0bb97de46831e4b266d8fdd22d59e7d54db99446d53549f081a008e2","docs/architecture/diagrams/20-anchor-recovery-and-egress.d2":"9479271410f1bb57f92106a1d91ec73c73872568d9fcda55cac5aa64b89e5c9f","docs/architecture/diagrams/21-composed-journal-transport-lifecycle.d2":"0fffe555ee4c2c1222c97eebd24ca9b0df91a4d3ec118300ae3b88240004c3c8","docs/architecture/diagrams/22-finite-stream-manifest.d2":"60b33eb6d06aeaa1027546a1fc9d6c07069c3cd3c7d23df8ff8d63a341afe2ea","docs/architecture/diagrams/23-driver-completion-recovery.d2":"271963db2cd881bb82e164bb1544c7bcf311e1781f20170d858ccb65a596d8f5","docs/architecture/diagrams/24-writer-settlement-closure.d2":"ea1930326b0073e7fabd8b64ef3ffea781f1aef60db0d942f9ab14f1150296e9","docs/architecture/diagrams/25-settlement-anchor-recovery.d2":"8904bfcda525de21b48ea8f2db8d12aaa27e85818ccde43fb545851dc522ba3b","docs/architecture/diagrams/26-gate-consumption-persistence.d2":"42e676634ecb40cfb2dee06db1f5497d0e58c05f30097618c3852eb946992f0d","docs/architecture/diagrams/27-anchor-commit-broker-fencing.d2":"5c2ae36987b00655bbcdba36352e03b61765739ad2f3fc80a561ff0d325a9461","docs/architecture/diagrams/28-anchor-configuration-prefix.d2":"1ac0eeb3c76f5ae0ce3565d4469e50210786c3bc53c703a1a61d519dfa075512","docs/architecture/diagrams/29-quorum-durable-promises.d2":"2e4a24c3fae49e710d5afc31d4681a9efc8c2e8af3fa58a0957ede05fe7c0255","docs/architecture/diagrams/39-shared-execution-exposure.d2":"2c08f5b3d4531a7be2aadec8f1ff9d4476495418e94e84c1ff643583ac991ce4","docs/architecture/diagrams/assets/agent-request.svg":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","docs/architecture/diagrams/assets/bounded-write.svg":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","docs/architecture/diagrams/assets/budget-ledger.svg":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","docs/architecture/diagrams/assets/components/activity.svg":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","docs/architecture/diagrams/assets/components/book-open.svg":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","docs/architecture/diagrams/assets/components/bot.svg":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","docs/architecture/diagrams/assets/components/brain.svg":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","docs/architecture/diagrams/assets/components/circle-question-mark.svg":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","docs/architecture/diagrams/assets/components/clipboard-check.svg":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","docs/architecture/diagrams/assets/components/coins.svg":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","docs/architecture/diagrams/assets/components/database.svg":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","docs/architecture/diagrams/assets/components/file-check.svg":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","docs/architecture/diagrams/assets/components/fingerprint-pattern.svg":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","docs/architecture/diagrams/assets/components/message-square.svg":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","docs/architecture/diagrams/assets/components/rotate-ccw-clock.svg":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","docs/architecture/diagrams/assets/components/rotate-ccw.svg":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","docs/architecture/diagrams/assets/components/route.svg":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","docs/architecture/diagrams/assets/components/send.svg":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e","docs/architecture/diagrams/assets/components/shield-check.svg":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","docs/architecture/diagrams/assets/components/ticket-check.svg":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","docs/architecture/diagrams/assets/components/waves-horizontal.svg":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","docs/architecture/diagrams/assets/components/workflow.svg":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","docs/architecture/diagrams/assets/go.svg":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","docs/architecture/diagrams/assets/kubernetes.svg":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","docs/architecture/diagrams/assets/model-catalog.svg":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","docs/architecture/diagrams/assets/model-provider.svg":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","docs/architecture/diagrams/assets/permission-check.svg":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","docs/architecture/diagrams/assets/route-choice.svg":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","docs/architecture/diagrams/assets/rust.svg":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","docs/architecture/diagrams/assets/task-contract.svg":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","docs/architecture/diagrams/assets/unknown-hold.svg":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","Project.sysml":"7dd1fbea3abe3e3f2f4fe23dbfd746533d5ee4c4789aacc01627b4ebadd99f12"},"rendered":{"observation":{"canvas":{"x":0,"y":0,"width":980,"height":1435},"subjects":[{"id":"n0","role":"semantic","x":301.6576843261719,"y":192.19061279296875,"width":289.7815856933594,"height":218.66900634765625},{"id":"n1","role":"semantic","x":416,"y":517.9114379882812,"width":275.2169189453125,"height":215.848876953125},{"id":"n2","role":"semantic","x":408.4620361328125,"y":840,"width":286.257080078125,"height":213.85107421875},{"id":"n3","role":"semantic","x":293.93804931640625,"y":1164.70703125,"width":311.41827392578125,"height":211.508056640625}],"relations":["edge:0","edge:1","edge:2","edge:3"],"headings":[{"role":"title","x":32,"y":32,"width":916,"height":63},{"role":"question","x":32,"y":95,"width":916,"height":56}]},"readability":{"minimumTextSize":26,"samples":19},"bounds":{"model":{"x":32,"y":165,"width":916,"height":1238}}}}Make architecture capabilities reinforce each other?How do our existing strengths compound?{"graph":{"id":"declared-reading-order","children":[{"id":"n0","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n1","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n2","layoutOptions":{"elk.partitioning.partition":"2"}},{"id":"n3","layoutOptions":{"elk.partitioning.partition":"3"}}],"layoutOptions":{"elk.spacing.nodeNode":"16","elk.layered.spacing.nodeNodeBetweenLayers":"27","elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.partitioning.activate":"true"},"edges":[{"id":"edge:0","sources":["n0"],"targets":["n1"]},{"id":"edge:1","sources":["n1"],"targets":["n2"]},{"id":"edge:2","sources":["n2"],"targets":["n3"]},{"id":"edge:3","sources":["n3"],"targets":["n0"]}]},"marker":"arrow-3841b4e6e411"}deriveproposereportreconcileComposePOO + SchemeASCENT relationsPrepareDependency cutBounded ownersEnforceCedar + SPECRust final effectsObserveAuthentic outcomesScoped explanation \ No newline at end of file From 2d26e67ce38d9d2b4fd4b299f1a02c19dffb998a Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 01:15:09 +0800 Subject: [PATCH 055/105] Qualify source rotation with independent review signatures --- crates/ledger/tests/unit/review_fixture.rs | 10 +++- .../tests/integration/governance_owner.rs | 58 ++++++++++++++++--- 2 files changed, 59 insertions(+), 9 deletions(-) diff --git a/crates/ledger/tests/unit/review_fixture.rs b/crates/ledger/tests/unit/review_fixture.rs index 68f16b4b..3d3475b3 100644 --- a/crates/ledger/tests/unit/review_fixture.rs +++ b/crates/ledger/tests/unit/review_fixture.rs @@ -34,8 +34,16 @@ pub fn change(id: &str, parent: Option) -> Publication { } } pub fn evidence(ledger: &mut weaver_ledger::Ledger, p: &Publication) -> DeltaReview { + evidence_for_source(ledger, p, &source()) +} +/// Reuse the same synthetic issuer with an independently authenticated fixture source. +pub fn evidence_for_source( + ledger: &mut weaver_ledger::Ledger, + p: &Publication, + authenticated_source: &SourceIdentity, +) -> DeltaReview { let ctx = ledger - .with_authenticated_source(&source(), |l| { + .with_authenticated_source(authenticated_source, |l| { let key = l.stage_reviewed_authority(p)?; l.publication_review_context(&key) }) diff --git a/crates/server/tests/integration/governance_owner.rs b/crates/server/tests/integration/governance_owner.rs index 95f6e934..b693cbfd 100644 --- a/crates/server/tests/integration/governance_owner.rs +++ b/crates/server/tests/integration/governance_owner.rs @@ -9,6 +9,9 @@ use weaver_governance::{OwnedSource, SchemeCompiler, SourceError}; use weaver_server::ServiceRuntime; #[path = "../../../governance/tests/unit/fixture.rs"] mod fixture; +#[allow(dead_code, reason = "integration reuses the issuer only")] +#[path = "../../../ledger/tests/unit/review_fixture.rs"] +mod review_fixture; mod rpc_fixture; struct Compiler { @@ -45,7 +48,7 @@ impl Drop for Compiler { } } } -#[tokio::test] +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain() { use sha2::{Digest, Sha256}; use tonic::transport::{Certificate, Identity, ServerTlsConfig}; @@ -111,6 +114,26 @@ async fn actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain() { let client = runtime.producers().expect("installed producer set"); let directory = tempfile::tempdir().expect("database directory"); let database = directory.path().join("state.db"); + // Keep the existing no-expansion deployment profile. The independent test + // issuer approves the exact bootstrap; compilation is never that approval. + // This is signature/binding fixture evidence, not a SPEC semantic proof. + let mut review_authority = review_fixture::issuer(0); + review_authority.allow_expansion = false; + let mut preparation = weaver_ledger::Ledger::open(&database).expect("review preparation"); + preparation + .install_review_authority(&review_authority) + .expect("initial review deployment"); + let bootstrap = review_fixture::evidence_for_source( + &mut preparation, + &original.publication, + &source_identity, + ); + preparation + .with_authenticated_source(&source_identity, |ledger| { + ledger.register_delta_review(&bootstrap) + }) + .expect("independent exact bootstrap review"); + preparation.close().expect("review preparation closes"); let listeners = GrpcListeners { operation: tokio::net::TcpListener::bind("127.0.0.1:0") .await @@ -124,13 +147,7 @@ async fn actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain() { let settings = GrpcConfig { metering: None, provider_oauth: None, - review_authority: weaver_contracts::ReviewAuthority { - audience: "test-gateway".into(), - epoch: 0, - public_key: "4".repeat(64), - allow_expansion: false, - qualified_catalog: None, - }, + review_authority, owner: ServerConfig { database: database.clone(), principal: "alice".into(), @@ -302,8 +319,33 @@ async fn actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain() { policy: include_str!("../../../../prod/policies/provider/provider.cedar").into(), schema: original.publication.schema.clone(), }; + assert!( + ledger + .with_authenticated_source(&next, |ledger| { + ledger.stage_authority(&allow)?; + ledger.publish_authority(&allow) + }) + .is_err(), + "the source alone cannot publish an unreviewed Permit" + ); + let forbidden_approval = review_fixture::evidence_for_source(&mut ledger, &allow, &next); + assert!( + ledger + .with_authenticated_source(&next, |ledger| { + ledger.register_delta_review(&forbidden_approval) + }) + .is_err(), + "the initial no-expansion deployment must reject an explicit grant" + ); + // Only the native deployment owner can advance this review profile. A + // source RPC and a completed Scheme derivation cannot perform this step. + ledger + .install_review_authority(&review_fixture::issuer(1)) + .expect("explicit deployment authorization for the Permit control"); + let approved = review_fixture::evidence_for_source(&mut ledger, &allow, &next); ledger .with_authenticated_source(&next, |ledger| { + ledger.register_delta_review(&approved)?; ledger.stage_authority(&allow)?; let receipt = ledger.publish_authority(&allow)?; assert_eq!( From faa9cb5c1be9a6b881b8a90ccc81246adea0d7f3 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 01:22:38 +0800 Subject: [PATCH 056/105] Enforce native qualification worker and drain limits --- .../tests/integration/governance_owner.rs | 31 ++++++++++++------- go/internal/devrunner/plan.go | 2 +- go/internal/devrunner/scheme_tools_test.go | 2 +- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/crates/server/tests/integration/governance_owner.rs b/crates/server/tests/integration/governance_owner.rs index b693cbfd..624b435d 100644 --- a/crates/server/tests/integration/governance_owner.rs +++ b/crates/server/tests/integration/governance_owner.rs @@ -210,6 +210,9 @@ async fn actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain() { .current_dir(std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../../go")) .args([ "test", + "-p", + "4", + "-parallel=4", "-count=1", "-race", "./internal/controlplane", @@ -276,19 +279,23 @@ async fn actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain() { tonic::Code::PermissionDenied ); let _ = stop.send(()); - server - .await - .expect("service task") - .expect("natural shared drain"); - runtime.drain().await; - assert_eq!( - cleaned + tokio::time::timeout(std::time::Duration::from_secs(15), async { + server .await - .expect("natural VM cleanup before acknowledgment"), - 3 - ); - assert_eq!(permits.available_permits(), capacity.get()); - worker.finish().await.expect("tracked worker joined"); + .expect("service task") + .expect("natural shared drain"); + runtime.drain().await; + assert_eq!( + cleaned + .await + .expect("natural VM cleanup before acknowledgment"), + 3 + ); + assert_eq!(permits.available_permits(), capacity.get()); + worker.finish().await.expect("tracked worker joined"); + }) + .await + .expect("owner and service did not drain within 15 seconds"); let mut ledger = weaver_ledger::Ledger::open(database).expect("recovered ledger"); let next = weaver_server::source_certificate_identity( &pki.next.der, diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index 3cfe9d65..c1b210d7 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -250,7 +250,7 @@ func stagesForMode(mode, goBinary string) ([]Stage, error) { {"scheme-module-selection-integration", schemeTool(), []string{"test", "-g", "-v", "5", "t/qualification/module-selection"}}, {"scheme-source-integration-tests", schemeTool(), []string{"test", "-g", "-v", "5", "t/integration"}}, {"scheme-provider-server-build", "cargo", append(SchemeQualificationCargoArgs(), "--no-run")}, - {"scheme-rooted-sdk-integration", "cargo", SchemeQualificationCargoArgs()}, + {"scheme-rooted-sdk-integration", "cargo", append(SchemeQualificationCargoArgs(), "--", "--test-threads=4")}, {"scheme-grpc-stream-integration", goBinary, []string{"-C", "go", "test", "-json", "-count=1", "-race", "-tags=integration,schemeintegration", "-timeout=10m", "./dev", "-run", "^TestProviderControl", "-skip", "^TestProviderControlGovernorPerformance$"}}, }, nil case "bench-execution": diff --git a/go/internal/devrunner/scheme_tools_test.go b/go/internal/devrunner/scheme_tools_test.go index 5295f530..1c366489 100644 --- a/go/internal/devrunner/scheme_tools_test.go +++ b/go/internal/devrunner/scheme_tools_test.go @@ -94,7 +94,7 @@ func TestSchemeQualificationStaysWithPreparedSchemeOwner(t *testing.T) { for _, stage := range stages { if stage.Name == "scheme-rooted-sdk-integration" { args := strings.Join(stage.Args, " ") - found = imagePrepared && slices.Equal(stage.Args, SchemeQualificationCargoArgs()) && + found = imagePrepared && slices.Equal(stage.Args, append(SchemeQualificationCargoArgs(), "--", "--test-threads=4")) && strings.Contains(args, "weaver-governance/scheme-qualification") && strings.Contains(args, "weaver-server/governance-qualification") } if stage.Name == "scheme-provider-server-build" { From 64e892a1a68cce37079758a032423b9a5af68473 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 01:28:26 +0800 Subject: [PATCH 057/105] Keep Session admission within Rust architecture gates --- crates/ledger/src/provider.rs | 69 ------------------ crates/ledger/src/provider_admission.rs | 96 +++++++++++++++++++++++-- crates/server/src/grpc_provider.rs | 9 ++- crates/server/src/session_workflow.rs | 8 +-- 4 files changed, 99 insertions(+), 83 deletions(-) diff --git a/crates/ledger/src/provider.rs b/crates/ledger/src/provider.rs index f3a2411b..1fd11cf8 100644 --- a/crates/ledger/src/provider.rs +++ b/crates/ledger/src/provider.rs @@ -11,7 +11,6 @@ pub use release_group::{MAX_PROVIDER_PREPARATION_RANGES, MAX_PROVIDER_PREPARATIO use crate::persistence::{ProviderScopePhase, WriteScope}; use crate::{Ledger, db, integer}; -use admission::{admissible_receipt, store_authorized_provider_plan}; use std::collections::BTreeSet; use std::{ sync::OnceLock, @@ -219,74 +218,6 @@ impl Ledger { pub fn finish_provider_scope_trace(&mut self) { self.connection.finish_provider_scope_trace(); } - pub fn enqueue_provider(&mut self, plan: &ProviderPlan) -> Result { - self.enqueue_catalog_provider(plan, "") - } - - pub fn enqueue_catalog_provider( - &mut self, - plan: &ProviderPlan, - catalog: &str, - ) -> Result { - self.enqueue_provider_with_oauth(plan, catalog, None) - } - - /// Bind the request observation before exposing any reservation or prior outcome. - pub fn enqueue_provider_with_oauth( - &mut self, - plan: &ProviderPlan, - catalog: &str, - oauth: Option<&ProviderOAuthUse>, - ) -> Result { - self.enqueue_provider_progression(plan, catalog, oauth, None) - } - - /// Commit the prepared successor frontier with the existing claim and hold. - pub fn enqueue_provider_progression( - &mut self, - plan: &ProviderPlan, - catalog: &str, - oauth: Option<&ProviderOAuthUse>, - progression: Option<&crate::ProviderProgression>, - ) -> Result { - let digest = plan.digest()?; - let encoded = serde_json::to_string(plan)?; - let prepared = self - .connection - .prepare_provider_oauth(oauth, "provider:execute")?; - let publication = self.connection.prepare_provider_publication(&plan.family); - let original = self.connection.prepare_provider_original(&plan.family); - self.connection.prepare_provider_domain(); - let transaction = (progression.is_some() && governor_timing()).then(Instant::now); - let tx = crate::persistence::begin_provider_admission( - &mut self.connection, - &plan.family, - &AdmissionRequest { _sealed: () }, - ) - .map_err(db)?; - let new_claim = - match admissible_receipt(&tx, plan, &digest, prepared.as_ref(), progression)? { - Some(old) if old.state != ProviderState::Queued => return Ok(old), - Some(_) => false, - None => true, - }; - store_authorized_provider_plan( - &tx, - plan, - (&digest, encoded), - catalog, - new_claim, - &publication?, - original.as_ref(), - )?; - crate::provider_workflow::record_admission(&tx, plan, &digest, progression, new_claim)?; - tx.commit_provider_admission().map_err(db)?; - if new_claim && progression.is_some() { - governor_commit_trace("reserve", plan, transaction); - } - self.provider_receipt(&plan.family, &plan.node)? - .ok_or(Error::Conflict("provider receipt missing")) - } /// Eligibility is a local Rust credential/configuration observation, never a provider call. pub fn consume_provider( &mut self, diff --git a/crates/ledger/src/provider_admission.rs b/crates/ledger/src/provider_admission.rs index 8ec50cea..1321d028 100644 --- a/crates/ledger/src/provider_admission.rs +++ b/crates/ledger/src/provider_admission.rs @@ -3,11 +3,97 @@ // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 //! Bind an admissible provider plan and its reservation to the existing writer. -use super::{any_authorized, receipt}; -use crate::{db, persistence::WriteScope}; -use weaver_contracts::{DomainView, Error, ProviderPlan, ProviderReceipt, Result}; +use super::{AdmissionRequest, any_authorized, governor_commit_trace, governor_timing, receipt}; +use crate::{Ledger, db, persistence::WriteScope}; +use std::time::Instant; +use weaver_contracts::{ + DomainView, Error, ProviderOAuthUse, ProviderPlan, ProviderReceipt, ProviderState, Result, +}; -pub(super) fn admissible_receipt( +impl Ledger { + pub fn enqueue_provider(&mut self, plan: &ProviderPlan) -> Result { + self.enqueue_catalog_provider(plan, "") + } + + pub fn enqueue_catalog_provider( + &mut self, + plan: &ProviderPlan, + catalog: &str, + ) -> Result { + self.enqueue_provider_with_oauth(plan, catalog, None) + } + + /// Bind the request observation before exposing any reservation or prior outcome. + pub fn enqueue_provider_with_oauth( + &mut self, + plan: &ProviderPlan, + catalog: &str, + oauth: Option<&ProviderOAuthUse>, + ) -> Result { + self.enqueue_provider_progression(plan, catalog, oauth, None) + } + + /// Commit the prepared successor frontier with the existing claim and hold. + pub fn enqueue_provider_progression( + &mut self, + plan: &ProviderPlan, + catalog: &str, + oauth: Option<&ProviderOAuthUse>, + progression: Option<&crate::ProviderProgression>, + ) -> Result { + let digest = plan.digest()?; + let encoded = serde_json::to_string(plan)?; + let prepared = self + .connection + .prepare_provider_oauth(oauth, "provider:execute")?; + let publication = self.connection.prepare_provider_publication(&plan.family); + let original = self.connection.prepare_provider_original(&plan.family); + self.connection.prepare_provider_domain(); + let transaction = (progression.is_some() && governor_timing()).then(Instant::now); + let tx = crate::persistence::begin_provider_admission( + &mut self.connection, + &plan.family, + &AdmissionRequest { _sealed: () }, + ) + .map_err(db)?; + let new_claim = + match admissible_receipt(&tx, plan, &digest, prepared.as_ref(), progression)? { + Some(old) if old.state != ProviderState::Queued => return Ok(old), + Some(_) => false, + None => true, + }; + store_authorized_provider_plan( + &tx, + plan, + (&digest, encoded), + catalog, + new_claim, + &publication?, + original.as_ref(), + )?; + commit_provider_progression(tx, plan, &digest, progression, new_claim, transaction)?; + self.provider_receipt(&plan.family, &plan.node)? + .ok_or(Error::Conflict("provider receipt missing")) + } +} + +fn commit_provider_progression( + tx: WriteScope<'_>, + plan: &ProviderPlan, + digest: &str, + progression: Option<&crate::ProviderProgression>, + new_claim: bool, + transaction: Option, +) -> Result<()> { + crate::provider_workflow::record_admission(&tx, plan, digest, progression, new_claim)?; + tx.commit_provider_admission().map_err(db)?; + if new_claim && progression.is_some() { + governor_commit_trace("reserve", plan, transaction); + } + Ok(()) +} + +fn admissible_receipt( tx: &WriteScope<'_>, plan: &ProviderPlan, digest: &str, @@ -23,7 +109,7 @@ pub(super) fn admissible_receipt( Ok(previous) } -pub(super) fn store_authorized_provider_plan( +fn store_authorized_provider_plan( tx: &WriteScope<'_>, plan: &ProviderPlan, (digest, encoded): (&str, String), diff --git a/crates/server/src/grpc_provider.rs b/crates/server/src/grpc_provider.rs index 9b2aad4a..57a5e458 100644 --- a/crates/server/src/grpc_provider.rs +++ b/crates/server/src/grpc_provider.rs @@ -122,12 +122,11 @@ impl Gateway { .runtime .fact_feed() .is_some_and(|feed| !feed.workflow_path.is_empty() && feed.family == plan.family) + && !predecessors.is_empty() { - if !predecessors.is_empty() { - return Err(Status::failed_precondition( - "Session owns successor execution", - )); - } + return Err(Status::failed_precondition( + "Session owns successor execution", + )); } self.start_provider_stream( slot, diff --git a/crates/server/src/session_workflow.rs b/crates/server/src/session_workflow.rs index 7a86769e..6648c027 100644 --- a/crates/server/src/session_workflow.rs +++ b/crates/server/src/session_workflow.rs @@ -19,7 +19,7 @@ struct SessionStep { } enum SessionWork { - Linear(SessionStep), + Linear(Vec), Graph(Box), } @@ -66,7 +66,7 @@ impl Gateway { continue; }; let steps = match batch { - SessionWork::Linear(step) => vec![step], + SessionWork::Linear(steps) => steps, SessionWork::Graph(graph) => match self.derive_session_steps(*graph).await { Ok(steps) => steps, Err(_) => continue, @@ -290,14 +290,14 @@ impl Gateway { Some(receipt) if receipt.state == ProviderState::Unknown => return Ok(None), _ => { return Ok(previous.map(|previous| { - SessionWork::Linear(SessionStep { + SessionWork::Linear(vec![SessionStep { admission: WorkflowAdmission { predecessors: vec![previous], observed: None, }, next: current, catalog, - }) + }]) })); } } From 53e925d4c4e09a94151ed04e4b89d44503f148a8 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 01:34:38 +0800 Subject: [PATCH 058/105] Bound provider ownership fuzzing by executed samples --- go/internal/devrunner/plan.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index c1b210d7..2fce59cc 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -102,7 +102,7 @@ func Plan(goBinary string) []Stage { {"turso-atomicity-safety", "quint", []string{"run", "dev/proofs/quint/TursoAdmission.qnt", "--main", "TursoAdmission", "--invariant", "safety", "--max-samples", "1000", "--max-steps", "60", "--seed", "293"}}, {"provider-routing-pbt", goBinary, []string{"-C", "go", "test", "./internal/routing", "-run", "^$", "-fuzz", "FuzzProviderPlanCannotExpandAuthority", "-fuzztime=3s"}}, {"provider-routing-ownership-pbt", goBinary, []string{"-C", "go", "test", "./internal/routing", "-run", "^$", "-fuzz", "FuzzCompiledProviderOwnsRouteOrder", "-fuzztime=3s"}}, - {"provider-stream-ownership-pbt", goBinary, []string{"-C", "go", "test", "./internal/gatewayclient", "-run", "^$", "-fuzz", "FuzzProviderExecutionOwnsRouteObservation", "-fuzztime=3s"}}, + {"provider-stream-ownership-pbt", goBinary, []string{"-C", "go", "test", "./internal/gatewayclient", "-run", "^$", "-fuzz", "FuzzProviderExecutionOwnsRouteObservation", "-fuzztime=24000x", "-timeout=15s"}}, {"source-task-ownership-pbt", goBinary, []string{"-C", "go", "test", "./internal/gatewayclient", "-run", "^$", "-fuzz", "FuzzTaskRequestOwnsMutableFields", "-fuzztime=3s"}}, {"publication-snapshot-pbt", goBinary, []string{"-C", "go", "test", "./internal/gatewayclient", "-run", "^$", "-fuzz", "FuzzPublicationStagesRetainOriginalParent", "-fuzztime=3s"}}, {"llm-routing-quint-tests", "quint", []string{"test", "dev/proofs/quint/LlmRouting.qnt", "--main", "LlmRouting", "--seed", "293"}}, From d4c5589ec915a52f1a2adc59737dbeeae713c6e4 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 01:43:16 +0800 Subject: [PATCH 059/105] Use one optimized Cargo development profile --- Cargo.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d1b8d859..561771a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,10 +83,6 @@ unimplemented = "deny" opt-level = 1 incremental = true -# Keep cold development builds bounded while optimizing workspace code. -[profile.dev.package."*"] -opt-level = 0 - [profile.release] opt-level = 3 incremental = true From 0710cbad10b1a86fb7c34b7eda6de7526aa9b426 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 02:02:40 +0800 Subject: [PATCH 060/105] Reuse the prepared Scheme build owner for isolation cleanup --- .../module-selection/module-selection-test.ss | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/t/qualification/module-selection/module-selection-test.ss b/t/qualification/module-selection/module-selection-test.ss index e6679a4e..b75e0e65 100644 --- a/t/qualification/module-selection/module-selection-test.ss +++ b/t/qualification/module-selection/module-selection-test.ss @@ -111,16 +111,17 @@ '("*** ERROR" "ERROR CASE" "ERROR CHECK" "ERROR HARNESS" "Heap overflow" "Stack overflow")) (error "Weaver action reported failure" command)) output) - (def (cold-from-source-plan state) - ;; Use the guarded init plan already measured above for an empty - ;; native output. B's hot build and business use remain independent. + (def (build-in-state state command) + ;; Use the guarded init plan already measured above for B's cold + ;; build and A's clean. B's hot build and business use remain + ;; independent processes. (def output (call-with-output-string (lambda (port) (parameterize ((current-build-output-directory (path-expand "lib" state)) (current-output-port port) (current-directory root)) - (weaver-build-main "compile"))))) + (weaver-build-main command))))) (display output) (force-output) output) @@ -131,13 +132,13 @@ (check-equal? (interfaces library) '()) (check-equal? (compile-events (if (equal? state a) (action state '("gxi" "build.ss" "compile")) - (cold-from-source-plan state))) targets) + (build-in-state state "compile"))) targets) (check-equal? (interfaces library) targets)) (list a b)) (def b-lib (path-expand "lib" b)) (def b-products (digests (artifact-files identities b-lib))) (def sentinel (path-expand "lib/unrelated.ssi" a)) (call-with-output-file sentinel (lambda (port) (display "unrelated" port))) - (action a '("gxi" "build.ss" "clean")) + (build-in-state a "clean") (check-equal? (interfaces (path-expand "lib" a)) '("unrelated")) (check-equal? (digests (artifact-files identities b-lib)) b-products) (check-equal? (compile-events (action b '("gxi" "build.ss" "compile"))) '()) From 088cb9fb0631e83b312958d36fc756e52f201da2 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 02:11:49 +0800 Subject: [PATCH 061/105] Bound the linked Scheme qualification build separately --- Project.sysml | 5 +++-- go/internal/devrunner/runner.go | 9 ++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Project.sysml b/Project.sysml index 79873c09..2d0b0ea4 100644 --- a/Project.sysml +++ b/Project.sysml @@ -246,8 +246,9 @@ package WeaverProject { part 'check-scheme' : VerificationMode; doc /* Compile the qualification executable and Rust tests in one Cargo graph before running the Rust or Go tests. The Go fixture - uses the normal executable reported by that graph. Bound the - native build, Rust tests and Go suite separately. + uses the normal executable reported by that graph. Give the + cold native build eight minutes for Rust and the linked Scheme + archive. Bound the Rust tests and Go suite separately. Resolve Lab and ASCENT sources from native package declarations. Gerbil prepares the pinned Core and POO compiler dependencies. ASCENT's selected Program build supplies native linker inputs. diff --git a/go/internal/devrunner/runner.go b/go/internal/devrunner/runner.go index 76e66057..46d4e9e1 100644 --- a/go/internal/devrunner/runner.go +++ b/go/internal/devrunner/runner.go @@ -269,15 +269,21 @@ const ( schemeModuleBuildTimeout = 2 * time.Minute schemePackageTestTimeout = time.Minute schemeModuleSelectionTimeout = 2 * time.Minute + schemeProviderBuildTimeout = 8 * time.Minute ) func runStageObserved(ctx context.Context, root, directory string, environment []string, stage Stage, streamSchemeOutput bool, onStart func(int)) Result { tests := "" testTimeout := schemePackageTestTimeout deadline := time.Duration(0) + if stage.providerBuild() { + deadline = 5 * time.Minute + } switch stage.Name { case "scheme-module-build": deadline = schemeModuleBuildTimeout + case "scheme-provider-server-build": + deadline = schemeProviderBuildTimeout case "scheme-rooted-sdk-integration": deadline = 5 * time.Minute case "scheme-unit-tests": @@ -291,9 +297,6 @@ func runStageObserved(ctx context.Context, root, directory string, environment [ if tests != "" { deadline = testTimeout } - if stage.providerBuild() { - deadline = 5 * time.Minute - } if deadline != 0 { var cancel context.CancelFunc ctx, cancel = context.WithTimeout(ctx, deadline) From c9e5c732dddbaad1f6aa5b4620daf6e4835bfe4a Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 02:29:46 +0800 Subject: [PATCH 062/105] Budget macOS Scheme source preparation by platform --- .github/workflows/verify-suite.yml | 10 ++++++---- Project.sysml | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 8f0fec39..b78429e1 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -82,17 +82,18 @@ jobs: - name: Prepare the Weaver Scheme source closure id: scheme_dependencies if: inputs.suite == 'check-scheme' - # The native watchdog owns the existing 12-minute limit. Leave time - # for GitHub to retain its exit status before the outer cutoff. - timeout-minutes: 13 + # Leave time after either native watchdog for its exit receipt. + timeout-minutes: 19 env: # The SDK setup exports the host core count via GITHUB_ENV. GERBIL_BUILD_CORES: '4' GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil + SOURCE_PREPARE_MINUTES: ${{ runner.os == 'macOS' && 18 || 12 }} run: | + printf 'budget_minutes=%s\n' "$SOURCE_PREPARE_MINUTES" >> "$GITHUB_OUTPUT" command -v timeout export scheme_sources="$RUNNER_TEMP/weaver-scheme-sources" - if timeout --verbose --kill-after=5s 12m bash -se -o pipefail <<'SOURCE_CLOSURE'; then + if timeout --verbose --kill-after=5s "${SOURCE_PREPARE_MINUTES}m" bash -se -o pipefail <<'SOURCE_CLOSURE'; then printf 'phase=resolve-pins\n' >> "$GITHUB_OUTPUT" fetch_source() { local package=$1 pin=$2 destination=$3 revision=${2##*@} @@ -170,6 +171,7 @@ jobs: "arch": ${{ toJSON(runner.arch) }}, "status": ${{ toJSON(job.status) }}, "schemeDependencyPhase": ${{ toJSON(steps.scheme_dependencies.outputs.phase || null) }}, + "schemeDependencyBudgetMinutes": ${{ steps.scheme_dependencies.outputs.budget_minutes || 'null' }}, "schemeDependencyExitCode": ${{ steps.scheme_dependencies.outputs.exit_code || 'null' }}, "phases": { "checkout": ${{ toJSON(steps.checkout.outcome || 'skipped') }}, diff --git a/Project.sysml b/Project.sysml index 2d0b0ea4..3fd266c8 100644 --- a/Project.sysml +++ b/Project.sysml @@ -252,8 +252,9 @@ package WeaverProject { Resolve Lab and ASCENT sources from native package declarations. Gerbil prepares the pinned Core and POO compiler dependencies. ASCENT's selected Program build supplies native linker inputs. - Dependency preparation defaults to four workers and has a - twelve-minute watchdog with its exit code in the job receipt. + Dependency preparation defaults to four workers, with a + twelve-minute watchdog on Linux and eighteen minutes on macOS. + Record the selected watchdog and its exit code in the job receipt. Run the selected package Build with a separate two-minute bound. Retain native Go failure events with the stage receipt. The provider recovery and natural-exit deadlines govern runtime. From 0ecf042fe0f6306591c8b96e26d0740b183f6830 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 02:35:32 +0800 Subject: [PATCH 063/105] Keep cold Cargo dependency builds within their budget --- Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 561771a5..acfce37e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,6 +83,10 @@ unimplemented = "deny" opt-level = 1 incremental = true +# Keep locked dependency compilation within the cold development build budget. +[profile.dev.package."*"] +opt-level = 0 + [profile.release] opt-level = 3 incremental = true From 5d5dfd3870f1b283af82f9d0a9c1f4742a8a614e Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 03:18:39 +0800 Subject: [PATCH 064/105] Retain SDK archive milestones in Scheme build receipts --- Project.sysml | 5 ++-- go/internal/devrunner/plan.go | 2 +- go/internal/devrunner/runner.go | 2 +- go/internal/devrunner/scheme_observation.go | 27 +++++++++++++++---- .../devrunner/scheme_observation_test.go | 24 +++++++++++++++++ go/internal/devrunner/scheme_tools_test.go | 2 +- 6 files changed, 52 insertions(+), 10 deletions(-) diff --git a/Project.sysml b/Project.sysml index 3fd266c8..cac2b845 100644 --- a/Project.sysml +++ b/Project.sysml @@ -256,8 +256,9 @@ package WeaverProject { twelve-minute watchdog on Linux and eighteen minutes on macOS. Record the selected watchdog and its exit code in the job receipt. Run the selected package Build with a separate two-minute bound. - Retain native Go failure events with the stage receipt. The - provider recovery and natural-exit deadlines govern runtime. + Retain SDK archive milestones and native Go failure events + with their stage receipts. The provider recovery and natural-exit + deadlines govern runtime. Unrelated producer products stay outside this source closure. */ } part architecture : VerificationSuite { part 'check-architecture' : VerificationMode; } diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index 2fce59cc..04de1b8b 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -249,7 +249,7 @@ func stagesForMode(mode, goBinary string) ([]Stage, error) { {"scheme-unit-tests", schemeTool(), []string{"test", "-g", "-v", "5", "t"}}, {"scheme-module-selection-integration", schemeTool(), []string{"test", "-g", "-v", "5", "t/qualification/module-selection"}}, {"scheme-source-integration-tests", schemeTool(), []string{"test", "-g", "-v", "5", "t/integration"}}, - {"scheme-provider-server-build", "cargo", append(SchemeQualificationCargoArgs(), "--no-run")}, + {"scheme-provider-server-build", "cargo", append(SchemeQualificationCargoArgs(), "--no-run", "-vv")}, {"scheme-rooted-sdk-integration", "cargo", append(SchemeQualificationCargoArgs(), "--", "--test-threads=4")}, {"scheme-grpc-stream-integration", goBinary, []string{"-C", "go", "test", "-json", "-count=1", "-race", "-tags=integration,schemeintegration", "-timeout=10m", "./dev", "-run", "^TestProviderControl", "-skip", "^TestProviderControlGovernorPerformance$"}}, }, nil diff --git a/go/internal/devrunner/runner.go b/go/internal/devrunner/runner.go index 46d4e9e1..f1868303 100644 --- a/go/internal/devrunner/runner.go +++ b/go/internal/devrunner/runner.go @@ -320,7 +320,7 @@ func runStageObserved(ctx context.Context, root, directory string, environment [ cmd.Env = environment var output io.Writer = log var observation *schemeOutput - if tests != "" && streamSchemeOutput { + if streamSchemeOutput && (tests != "" || stage.Name == "scheme-provider-server-build") { observation = &schemeOutput{destination: log, started: started} output = observation } diff --git a/go/internal/devrunner/scheme_observation.go b/go/internal/devrunner/scheme_observation.go index d02941b6..db7c304e 100644 --- a/go/internal/devrunner/scheme_observation.go +++ b/go/internal/devrunner/scheme_observation.go @@ -15,11 +15,18 @@ import ( // cleanup or deadline. PreHarness includes discovery/loading; these timestamps // cannot distinguish boundaries the SDK does not expose. type SchemeTiming struct { - PreHarness string `json:"preHarness,omitempty"` - FirstCase string `json:"firstCase,omitempty"` - HarnessDone string `json:"harnessDone,omitempty"` - Terminal string `json:"terminal,omitempty"` - AfterTerminal string `json:"afterTerminal,omitempty"` + PreHarness string `json:"preHarness,omitempty"` + FirstCase string `json:"firstCase,omitempty"` + HarnessDone string `json:"harnessDone,omitempty"` + Terminal string `json:"terminal,omitempty"` + AfterTerminal string `json:"afterTerminal,omitempty"` + Archive []schemeArchiveEvent `json:"archive,omitempty"` +} + +type schemeArchiveEvent struct { + Phase string `json:"phase"` + State string `json:"state"` + At string `json:"at"` } type schemeOutput struct { @@ -60,6 +67,16 @@ func (s *schemeOutput) observe(line string, now time.Time) { case line == "OK" && s.terminal.IsZero(): s.observed.Terminal = elapsed s.terminal = now + case strings.HasPrefix(line, "[weaver-governance "): + _, event, ok := strings.Cut(line, "] governance-program: phase=") + phase, state, framed := strings.Cut(event, " state=") + state, _, _ = strings.Cut(state, " ") + if ok && framed { + switch phase { + case "program-plan", "native-link-inputs", "module-c-batch", "gsc-link", "native-object-batch", "static-archive": + s.observed.Archive = append(s.observed.Archive, schemeArchiveEvent{Phase: phase, State: state, At: elapsed}) + } + } } } diff --git a/go/internal/devrunner/scheme_observation_test.go b/go/internal/devrunner/scheme_observation_test.go index 544ffa1c..e5796588 100644 --- a/go/internal/devrunner/scheme_observation_test.go +++ b/go/internal/devrunner/scheme_observation_test.go @@ -38,3 +38,27 @@ func TestSchemeObservationPreservesChunkedOutputAndExitBoundary(t *testing.T) { t.Fatal("fabricated a terminal marker or shutdown interval") } } + +func TestSchemeObservationRetainsUnfinishedNativeArchivePhase(t *testing.T) { + var log bytes.Buffer + started := time.Now() + output := &schemeOutput{destination: &log, started: started} + chunks := []string{ + "[other 0.1.0] governance-program: phase=static-archive state=complete\n", + "[weaver-governance 0.1.0] governance-program: phase=module-c-batch state=complete operation=generate C elapsedMs=1\n", + "[weaver-governance 0.1.0] governance-program: phase=native-object state=complete operation=compile module\n", + "[weaver-governance 0.1.0] governance-program: phase=native-object-batch state=st", + "art operation=compile program module objects\n", + } + for _, chunk := range chunks { + if _, err := output.Write([]byte(chunk)); err != nil { + t.Fatal(err) + } + } + report := output.timing(started.Add(time.Second)) + if len(report.Archive) != 2 || report.Archive[0].Phase != "module-c-batch" || + report.Archive[0].State != "complete" || report.Archive[1].Phase != "native-object-batch" || + report.Archive[1].State != "start" || report.Archive[1].At == "" { + t.Fatalf("unexpected native archive milestones: %+v", report.Archive) + } +} diff --git a/go/internal/devrunner/scheme_tools_test.go b/go/internal/devrunner/scheme_tools_test.go index 1c366489..d7de2e48 100644 --- a/go/internal/devrunner/scheme_tools_test.go +++ b/go/internal/devrunner/scheme_tools_test.go @@ -98,7 +98,7 @@ func TestSchemeQualificationStaysWithPreparedSchemeOwner(t *testing.T) { strings.Contains(args, "weaver-governance/scheme-qualification") && strings.Contains(args, "weaver-server/governance-qualification") } if stage.Name == "scheme-provider-server-build" { - imagePrepared = stage.providerBuild() && slices.Equal(stage.Args, append(SchemeQualificationCargoArgs(), "--no-run")) + imagePrepared = stage.providerBuild() && slices.Equal(stage.Args, append(SchemeQualificationCargoArgs(), "--no-run", "-vv")) } if stage.Name == "scheme-grpc-stream-integration" && !imagePrepared { t.Fatal("Scheme Go integration has no preceding qualification image build") From d9dd6d36a08e18f71725ed707d37395299271e8f Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 03:21:20 +0800 Subject: [PATCH 065/105] Keep the Scheme suite watchdog outside the native stage budgets --- .github/workflows/verify-suite.yml | 6 ++++-- Project.sysml | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index b78429e1..97d75898 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -140,11 +140,13 @@ jobs: - name: Verify Scheme modules, Cedar FFI and streaming recovery id: verify_scheme if: inputs.suite == 'check-scheme' - timeout-minutes: 20 + # The source-closure watchdog is separate. Give the suite room for + # its prelude and all three independently bounded native stages. + timeout-minutes: 37 env: GERBIL_GXI: ${{ env.GERBIL_PREFIX }}/bin/gxi GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil - run: go -C go run ./cmd/weaver-dev -clean-source -timeout 18m check-scheme + run: go -C go run ./cmd/weaver-dev -clean-source -timeout 35m check-scheme - name: Require successful phase receipts id: receipt_check timeout-minutes: 1 diff --git a/Project.sysml b/Project.sysml index cac2b845..f9fc47fe 100644 --- a/Project.sysml +++ b/Project.sysml @@ -248,7 +248,9 @@ package WeaverProject { Cargo graph before running the Rust or Go tests. The Go fixture uses the normal executable reported by that graph. Give the cold native build eight minutes for Rust and the linked Scheme - archive. Bound the Rust tests and Go suite separately. + archive. Bound the Rust tests and Go suite separately. The + whole-suite watchdog leaves time for these stages and the + preceding package checks to retain independent results. Resolve Lab and ASCENT sources from native package declarations. Gerbil prepares the pinned Core and POO compiler dependencies. ASCENT's selected Program build supplies native linker inputs. From 1f9b3a863bdf4bccc32627d6513f613d2e7cf76e Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 03:25:43 +0800 Subject: [PATCH 066/105] Reuse the prepared Scheme owner for the hot B check --- .../module-selection/module-selection-test.ss | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/t/qualification/module-selection/module-selection-test.ss b/t/qualification/module-selection/module-selection-test.ss index b75e0e65..70a09cbc 100644 --- a/t/qualification/module-selection/module-selection-test.ss +++ b/t/qualification/module-selection/module-selection-test.ss @@ -50,6 +50,7 @@ (check-equal? (hash-ref counts '(calls scope-factory) 0) 0) (check-equal? (hash-ref counts '(calls candidate-read) 0) 4) (def targets (list-sort string Date: Sun, 8 Nov 2026 09:18:37 +0800 Subject: [PATCH 067/105] Build Weaver with the SDK program prerequisites --- .github/workflows/verify-suite.yml | 2 +- Cargo.lock | 10 +++++----- Cargo.toml | 6 +++--- crates/governance-build/src/tooling.rs | 11 ++++++++--- crates/governance/build.rs | 1 + 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 97d75898..2c6a6d6a 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -67,7 +67,7 @@ jobs: id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-policy", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 - uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e + uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@cfd58c634d932c5f8576f18e7b98f16442745d0e with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog diff --git a/Cargo.lock b/Cargo.lock index b258b958..b8e8ef70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "gerbil-scheme" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e#380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=cfd58c634d932c5f8576f18e7b98f16442745d0e#cfd58c634d932c5f8576f18e7b98f16442745d0e" dependencies = [ "gerbil-scheme-rust-project-harness-policy", "gerbil-scheme-sys", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-aot-build" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e#380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=cfd58c634d932c5f8576f18e7b98f16442745d0e#cfd58c634d932c5f8576f18e7b98f16442745d0e" dependencies = [ "cbindgen", "cc", @@ -1822,7 +1822,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness" version = "0.1.2" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e#380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=cfd58c634d932c5f8576f18e7b98f16442745d0e#cfd58c634d932c5f8576f18e7b98f16442745d0e" dependencies = [ "cargo-lock", "cargo_toml", @@ -1840,7 +1840,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness-policy" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e#380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=cfd58c634d932c5f8576f18e7b98f16442745d0e#cfd58c634d932c5f8576f18e7b98f16442745d0e" dependencies = [ "gerbil-scheme-rust-project-harness", ] @@ -1848,7 +1848,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-sys" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e#380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=cfd58c634d932c5f8576f18e7b98f16442745d0e#cfd58c634d932c5f8576f18e7b98f16442745d0e" dependencies = [ "gerbil-scheme-aot-build", "gerbil-scheme-rust-project-harness-policy", diff --git a/Cargo.toml b/Cargo.toml index acfce37e..5b3d6868 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,9 @@ arrow-array = "58.4.0" arrow-schema = "58.4.0" arrow-ipc = "58.4.0" criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } -gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e" } -gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e" } -gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "380f8ba5f87b2f9ba3924302b35b3eea1e3f2a8e", features = ["external-program"] } +gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "cfd58c634d932c5f8576f18e7b98f16442745d0e" } +gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "cfd58c634d932c5f8576f18e7b98f16442745d0e" } +gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "cfd58c634d932c5f8576f18e7b98f16442745d0e", features = ["external-program"] } asp-rust = { git = "https://github.com/tao3k/asp-rust", rev = "1ca41124b846dec947f3d05119cafa07eaa57924", default-features = false } diff --git a/crates/governance-build/src/tooling.rs b/crates/governance-build/src/tooling.rs index addddf1f..c9dcef06 100644 --- a/crates/governance-build/src/tooling.rs +++ b/crates/governance-build/src/tooling.rs @@ -12,6 +12,7 @@ pub struct PackageTooling { pub initialize: fn() -> Result, pub configure_paths: fn(&Runtime, &str, &str) -> Result, pub build_package: fn(&Runtime, &str) -> Result, + pub build_package_spec: fn(&Runtime, &str, &str) -> Result, pub run_package_main: fn(&Runtime, &str, &[&str]) -> Result, pub stage_package_program: fn(&Runtime, &str, &str, &[&str]) -> Result, } @@ -39,14 +40,18 @@ impl PackageTooling { runtime } fn prepare_sdk(&self, runtime: &Runtime) { - // The selected SDK's standard package entry owns its complete module graph. + // The SDK's Build Packages specification owns the program prerequisites. // All outputs use Cargo's prefix; the SDK source checkout is read-only. let sdk = gerbil_scheme_aot_build::source_workspace() .canonicalize() .expect("Cargo SDK source"); assert_eq!( - (self.build_package)(runtime, sdk.to_str().expect("SDK source encoding")) - .expect("SDK package build"), + (self.build_package_spec)( + runtime, + sdk.to_str().expect("SDK source encoding"), + "gerbil-scheme-rust-program-build-spec", + ) + .expect("SDK program prerequisites"), 0 ); } diff --git a/crates/governance/build.rs b/crates/governance/build.rs index 731a08a1..12cf087f 100644 --- a/crates/governance/build.rs +++ b/crates/governance/build.rs @@ -11,6 +11,7 @@ fn main() { initialize: gerbil_scheme::GerbilRuntime::initialize, configure_paths: gerbil_scheme::GerbilRuntime::configure_package_paths, build_package: gerbil_scheme::GerbilRuntime::build_package, + build_package_spec: gerbil_scheme::GerbilRuntime::build_package_spec, run_package_main: gerbil_scheme::GerbilRuntime::run_package_main, stage_package_program: gerbil_scheme::GerbilRuntime::stage_package_program, }, From f066e91fdbc383286eaa3c6bcc537ba363ae5a91 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 11:21:48 +0800 Subject: [PATCH 068/105] Select upstream Go fuzz deadline fix in CI --- .github/actions/prepare-toolchain/action.yml | 2 +- .../59-provider-rpc/59.14-go-fuzz-coordinator.org | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/actions/prepare-toolchain/action.yml b/.github/actions/prepare-toolchain/action.yml index 6d0cae70..a415a3f8 100644 --- a/.github/actions/prepare-toolchain/action.yml +++ b/.github/actions/prepare-toolchain/action.yml @@ -10,7 +10,7 @@ runs: - name: Select standard Go uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6 with: - go-version: '1.26.1' + go-version: '1.27.3' cache: false - name: Select Node for Quint if: env.WEAVER_VERIFY_SUITE == 'check-policy' diff --git a/docs/50-59-research-program/59-provider-rpc/59.14-go-fuzz-coordinator.org b/docs/50-59-research-program/59-provider-rpc/59.14-go-fuzz-coordinator.org index 4194387e..7862a8d7 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.14-go-fuzz-coordinator.org +++ b/docs/50-59-research-program/59-provider-rpc/59.14-go-fuzz-coordinator.org @@ -15,12 +15,11 @@ watchdog. Coordinator errors remain failures; no text-based suppression or retry is introduced. The compiler-source substring assertion that required this exact backport has been retired. -The locked standard Go 1.26.1 lacks the upstream race fix described below. A -passing paired control does not prove that the race is absent. A recurrence -must retain its failed receipt; moving to a fixed upstream release is a separate -toolchain-version decision. Existing dependency and language-version pins are -unchanged. The following package-build receipts describe the historical -backport experiment, not the currently selected toolchain. +GitHub CI selects the official Go 1.27.3 release, which includes the upstream +coordinator fix described below. The locked development Go 1.26.1 still lacks +that fix. The package-build receipts below describe the historical backport +experiment. Both toolchains retain the native controls and their original +workloads. * Failure mechanism and source repair From c1d190ab94a6c04515ff789e873193c8378d1f4c Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 15:56:46 +0800 Subject: [PATCH 069/105] Select Go 1.27 in the standard Nix environment --- devenv.lock | 12 ++++++------ devenv.nix | 2 +- .../59-provider-rpc/59.14-go-fuzz-coordinator.org | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/devenv.lock b/devenv.lock index 5db0df13..43551d8d 100644 --- a/devenv.lock +++ b/devenv.lock @@ -81,11 +81,11 @@ "nixpkgs-src": "nixpkgs-src" }, "locked": { - "lastModified": 1776852779, - "narHash": "sha256-WwO/ITisCXwyiRgtktZgv3iGhAGO+IB5Av4kKCwezR0=", + "lastModified": 1793043970, + "narHash": "sha256-m14odYTdkBUEkJOiEYs2zjGjn8fcjvdCJsm45+k084U=", "owner": "cachix", "repo": "devenv-nixpkgs", - "rev": "ec3063523dcd911aeadb50faa589f237cdab5853", + "rev": "d97234e58d4e90e3bf77c082fc3b546e51200938", "type": "github" }, "original": { @@ -98,11 +98,11 @@ "nixpkgs-src": { "flake": false, "locked": { - "lastModified": 1776329215, - "narHash": "sha256-a8BYi3mzoJ/AcJP8UldOx8emoPRLeWqALZWu4ZvjPXw=", + "lastModified": 1792812153, + "narHash": "sha256-T2+XBfNbf9pecLUWS4+RtuVNZ3W8K5taG5QdV71mWlk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b86751bc4085f48661017fa226dee99fab6c651b", + "rev": "674a2028661e550a97400c1cc992b9cca9a668a1", "type": "github" }, "original": { diff --git a/devenv.nix b/devenv.nix index 12793802..09299fa0 100644 --- a/devenv.nix +++ b/devenv.nix @@ -48,7 +48,7 @@ in languages.go = { enable = true; - package = pkgs.go; + package = pkgs.go_1_27; }; profiles.ci.module = { diff --git a/docs/50-59-research-program/59-provider-rpc/59.14-go-fuzz-coordinator.org b/docs/50-59-research-program/59-provider-rpc/59.14-go-fuzz-coordinator.org index 7862a8d7..3d1189bc 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.14-go-fuzz-coordinator.org +++ b/docs/50-59-research-program/59-provider-rpc/59.14-go-fuzz-coordinator.org @@ -7,7 +7,7 @@ * Current standard toolchain decision -The project now selects the unchanged locked upstream =pkgs.go= package, +The project selects the locked upstream =pkgs.go_1_27= package, without a local Go override or patch. Gateway production behavior does not require a custom fuzz engine. The native no-op and real-failure controls remain mandatory with the original three-second workload, one worker and thirty-second @@ -15,11 +15,11 @@ watchdog. Coordinator errors remain failures; no text-based suppression or retry is introduced. The compiler-source substring assertion that required this exact backport has been retired. -GitHub CI selects the official Go 1.27.3 release, which includes the upstream -coordinator fix described below. The locked development Go 1.26.1 still lacks -that fix. The package-build receipts below describe the historical backport -experiment. Both toolchains retain the native controls and their original -workloads. +GitHub CI and the Nix development environment select Go 1.27.3, which includes +the upstream coordinator fix described below. The standard Nixpkgs input owns +the development package. The package-build receipts below describe the +historical backport experiment. Both toolchains retain the native controls and +their original workloads. * Failure mechanism and source repair From f4e0ba80fe541cfd25c5f8a56bc7b7a443735cfe Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 16:10:58 +0800 Subject: [PATCH 070/105] Declare the existing CodeQL package in the Nix allowlist --- devenv.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/devenv.yaml b/devenv.yaml index cb8a977d..903e59fe 100644 --- a/devenv.yaml +++ b/devenv.yaml @@ -2,6 +2,10 @@ # # SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later +nixpkgs: + permitted_unfree_packages: + - codeql + inputs: git-hooks: url: github:cachix/git-hooks.nix From 6fb6a3951c9d234b06979d51ce2994027d5dcdb4 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 16:10:58 +0800 Subject: [PATCH 071/105] Optimize native source and ABI hashing in development builds --- Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 5b3d6868..c08790f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,6 +87,10 @@ incremental = true [profile.dev.package."*"] opt-level = 0 +# The native build verifies generated sources and ABI headers with SHA-256. +[profile.dev.package.sha2] +opt-level = 3 + [profile.release] opt-level = 3 incremental = true From f2ca52b4ceb299e7bdd48c2a4d02fe6bcffd772b Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 16:16:51 +0800 Subject: [PATCH 072/105] Pin the SDK lazy metadata compilation layout --- .github/workflows/verify-suite.yml | 2 +- Cargo.lock | 10 +++++----- Cargo.toml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 2c6a6d6a..ffc87ea8 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -67,7 +67,7 @@ jobs: id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-policy", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 - uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@cfd58c634d932c5f8576f18e7b98f16442745d0e + uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@977f4c471a0100e9c840d172dc69d01a6eef9844 with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog diff --git a/Cargo.lock b/Cargo.lock index b8e8ef70..4ea3865b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "gerbil-scheme" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=cfd58c634d932c5f8576f18e7b98f16442745d0e#cfd58c634d932c5f8576f18e7b98f16442745d0e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=977f4c471a0100e9c840d172dc69d01a6eef9844#977f4c471a0100e9c840d172dc69d01a6eef9844" dependencies = [ "gerbil-scheme-rust-project-harness-policy", "gerbil-scheme-sys", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-aot-build" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=cfd58c634d932c5f8576f18e7b98f16442745d0e#cfd58c634d932c5f8576f18e7b98f16442745d0e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=977f4c471a0100e9c840d172dc69d01a6eef9844#977f4c471a0100e9c840d172dc69d01a6eef9844" dependencies = [ "cbindgen", "cc", @@ -1822,7 +1822,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness" version = "0.1.2" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=cfd58c634d932c5f8576f18e7b98f16442745d0e#cfd58c634d932c5f8576f18e7b98f16442745d0e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=977f4c471a0100e9c840d172dc69d01a6eef9844#977f4c471a0100e9c840d172dc69d01a6eef9844" dependencies = [ "cargo-lock", "cargo_toml", @@ -1840,7 +1840,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness-policy" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=cfd58c634d932c5f8576f18e7b98f16442745d0e#cfd58c634d932c5f8576f18e7b98f16442745d0e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=977f4c471a0100e9c840d172dc69d01a6eef9844#977f4c471a0100e9c840d172dc69d01a6eef9844" dependencies = [ "gerbil-scheme-rust-project-harness", ] @@ -1848,7 +1848,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-sys" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=cfd58c634d932c5f8576f18e7b98f16442745d0e#cfd58c634d932c5f8576f18e7b98f16442745d0e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=977f4c471a0100e9c840d172dc69d01a6eef9844#977f4c471a0100e9c840d172dc69d01a6eef9844" dependencies = [ "gerbil-scheme-aot-build", "gerbil-scheme-rust-project-harness-policy", diff --git a/Cargo.toml b/Cargo.toml index c08790f0..6e89d8d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,9 @@ arrow-array = "58.4.0" arrow-schema = "58.4.0" arrow-ipc = "58.4.0" criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } -gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "cfd58c634d932c5f8576f18e7b98f16442745d0e" } -gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "cfd58c634d932c5f8576f18e7b98f16442745d0e" } -gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "cfd58c634d932c5f8576f18e7b98f16442745d0e", features = ["external-program"] } +gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "977f4c471a0100e9c840d172dc69d01a6eef9844" } +gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "977f4c471a0100e9c840d172dc69d01a6eef9844" } +gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "977f4c471a0100e9c840d172dc69d01a6eef9844", features = ["external-program"] } asp-rust = { git = "https://github.com/tao3k/asp-rust", rev = "1ca41124b846dec947f3d05119cafa07eaa57924", default-features = false } From 2eaf10d16743dab295f5fbc7885c15123623c267 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 17:26:11 +0800 Subject: [PATCH 073/105] Retain native batch worker counts in structured receipts --- go/internal/devrunner/scheme_observation.go | 11 +++++++---- go/internal/devrunner/scheme_observation_test.go | 5 +++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/go/internal/devrunner/scheme_observation.go b/go/internal/devrunner/scheme_observation.go index db7c304e..30e5d613 100644 --- a/go/internal/devrunner/scheme_observation.go +++ b/go/internal/devrunner/scheme_observation.go @@ -24,9 +24,10 @@ type SchemeTiming struct { } type schemeArchiveEvent struct { - Phase string `json:"phase"` - State string `json:"state"` - At string `json:"at"` + Phase string `json:"phase"` + State string `json:"state"` + At string `json:"at"` + Subject string `json:"subject,omitempty"` } type schemeOutput struct { @@ -74,7 +75,9 @@ func (s *schemeOutput) observe(line string, now time.Time) { if ok && framed { switch phase { case "program-plan", "native-link-inputs", "module-c-batch", "gsc-link", "native-object-batch", "static-archive": - s.observed.Archive = append(s.observed.Archive, schemeArchiveEvent{Phase: phase, State: state, At: elapsed}) + _, subject, _ := strings.Cut(event, " subject=") + subject, _, _ = strings.Cut(subject, " elapsedMs=") + s.observed.Archive = append(s.observed.Archive, schemeArchiveEvent{Phase: phase, State: state, At: elapsed, Subject: subject}) } } } diff --git a/go/internal/devrunner/scheme_observation_test.go b/go/internal/devrunner/scheme_observation_test.go index e5796588..14cc5970 100644 --- a/go/internal/devrunner/scheme_observation_test.go +++ b/go/internal/devrunner/scheme_observation_test.go @@ -48,7 +48,7 @@ func TestSchemeObservationRetainsUnfinishedNativeArchivePhase(t *testing.T) { "[weaver-governance 0.1.0] governance-program: phase=module-c-batch state=complete operation=generate C elapsedMs=1\n", "[weaver-governance 0.1.0] governance-program: phase=native-object state=complete operation=compile module\n", "[weaver-governance 0.1.0] governance-program: phase=native-object-batch state=st", - "art operation=compile program module objects\n", + "art operation=compile program module objects subject=jobs=459 workers=4\n", } for _, chunk := range chunks { if _, err := output.Write([]byte(chunk)); err != nil { @@ -58,7 +58,8 @@ func TestSchemeObservationRetainsUnfinishedNativeArchivePhase(t *testing.T) { report := output.timing(started.Add(time.Second)) if len(report.Archive) != 2 || report.Archive[0].Phase != "module-c-batch" || report.Archive[0].State != "complete" || report.Archive[1].Phase != "native-object-batch" || - report.Archive[1].State != "start" || report.Archive[1].At == "" { + report.Archive[1].State != "start" || report.Archive[1].At == "" || + report.Archive[1].Subject != "jobs=459 workers=4" { t.Fatalf("unexpected native archive milestones: %+v", report.Archive) } } From 5f60c9586ce232130ec09b60fc5ab034a241d59b Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 17:26:11 +0800 Subject: [PATCH 074/105] Align native program compilation with the Cargo development profile --- .github/workflows/verify-suite.yml | 2 +- Cargo.lock | 10 +++++----- Cargo.toml | 7 ++++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index ffc87ea8..64537685 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -67,7 +67,7 @@ jobs: id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-policy", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 - uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@977f4c471a0100e9c840d172dc69d01a6eef9844 + uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@df8014bc16cde63e16f933dba30c486ba6f0616c with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog diff --git a/Cargo.lock b/Cargo.lock index 4ea3865b..f4159747 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "gerbil-scheme" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=977f4c471a0100e9c840d172dc69d01a6eef9844#977f4c471a0100e9c840d172dc69d01a6eef9844" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=df8014bc16cde63e16f933dba30c486ba6f0616c#df8014bc16cde63e16f933dba30c486ba6f0616c" dependencies = [ "gerbil-scheme-rust-project-harness-policy", "gerbil-scheme-sys", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-aot-build" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=977f4c471a0100e9c840d172dc69d01a6eef9844#977f4c471a0100e9c840d172dc69d01a6eef9844" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=df8014bc16cde63e16f933dba30c486ba6f0616c#df8014bc16cde63e16f933dba30c486ba6f0616c" dependencies = [ "cbindgen", "cc", @@ -1822,7 +1822,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness" version = "0.1.2" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=977f4c471a0100e9c840d172dc69d01a6eef9844#977f4c471a0100e9c840d172dc69d01a6eef9844" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=df8014bc16cde63e16f933dba30c486ba6f0616c#df8014bc16cde63e16f933dba30c486ba6f0616c" dependencies = [ "cargo-lock", "cargo_toml", @@ -1840,7 +1840,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness-policy" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=977f4c471a0100e9c840d172dc69d01a6eef9844#977f4c471a0100e9c840d172dc69d01a6eef9844" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=df8014bc16cde63e16f933dba30c486ba6f0616c#df8014bc16cde63e16f933dba30c486ba6f0616c" dependencies = [ "gerbil-scheme-rust-project-harness", ] @@ -1848,7 +1848,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-sys" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=977f4c471a0100e9c840d172dc69d01a6eef9844#977f4c471a0100e9c840d172dc69d01a6eef9844" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=df8014bc16cde63e16f933dba30c486ba6f0616c#df8014bc16cde63e16f933dba30c486ba6f0616c" dependencies = [ "gerbil-scheme-aot-build", "gerbil-scheme-rust-project-harness-policy", diff --git a/Cargo.toml b/Cargo.toml index 6e89d8d7..3e192654 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,9 @@ arrow-array = "58.4.0" arrow-schema = "58.4.0" arrow-ipc = "58.4.0" criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } -gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "977f4c471a0100e9c840d172dc69d01a6eef9844" } -gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "977f4c471a0100e9c840d172dc69d01a6eef9844" } -gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "977f4c471a0100e9c840d172dc69d01a6eef9844", features = ["external-program"] } +gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "df8014bc16cde63e16f933dba30c486ba6f0616c" } +gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "df8014bc16cde63e16f933dba30c486ba6f0616c" } +gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "df8014bc16cde63e16f933dba30c486ba6f0616c", features = ["external-program"] } asp-rust = { git = "https://github.com/tao3k/asp-rust", rev = "1ca41124b846dec947f3d05119cafa07eaa57924", default-features = false } @@ -86,6 +86,7 @@ incremental = true # Keep locked dependency compilation within the cold development build budget. [profile.dev.package."*"] opt-level = 0 +debug = false # The native build verifies generated sources and ABI headers with SHA-256. [profile.dev.package.sha2] From 1c425a96add58f7d7282cf23f9688e0e82068cf3 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 18:05:05 +0800 Subject: [PATCH 075/105] ci: provision pinned Lean through verified release assets --- .github/actions/prepare-toolchain/action.yml | 4 +++ .../actions/prepare-toolchain/install-lean.sh | 29 +++++++++++++++++++ go/internal/devrunner/ci.go | 6 ++-- go/internal/devrunner/provenance.go | 2 +- go/internal/devrunner/provenance_test.go | 3 ++ 5 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 .github/actions/prepare-toolchain/install-lean.sh diff --git a/.github/actions/prepare-toolchain/action.yml b/.github/actions/prepare-toolchain/action.yml index a415a3f8..cc0dde8f 100644 --- a/.github/actions/prepare-toolchain/action.yml +++ b/.github/actions/prepare-toolchain/action.yml @@ -20,6 +20,10 @@ runs: - name: Install Ubuntu or Darwin packages shell: sh run: go -C go run ./cmd/weaver-dev prepare-ci-tools + - name: Prepare the pinned Lean release + if: env.WEAVER_VERIFY_SUITE == 'check-policy' && runner.os == 'Linux' + shell: bash + run: bash "${{ github.action_path }}/install-lean.sh" - name: Bind the Cedar solver if: env.WEAVER_VERIFY_SUITE == 'check-policy' shell: sh diff --git a/.github/actions/prepare-toolchain/install-lean.sh b/.github/actions/prepare-toolchain/install-lean.sh new file mode 100644 index 00000000..15e0f4e7 --- /dev/null +++ b/.github/actions/prepare-toolchain/install-lean.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +# +# SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +set -euo pipefail + +read -r toolchain < dev/proofs/cedar/lean-toolchain +[[ "$toolchain" == leanprover/lean4:v* ]] +tag="${toolchain#*:}" +asset_name="lean-${tag#v}-linux.tar.zst" +tag_uri="$(jq -nr --arg tag "$tag" '$tag | @uri')" +read -r asset_id sha256 < <( + curl --fail --silent --show-error --location --retry 3 \ + "https://api.github.com/repos/leanprover/lean4/releases/tags/$tag_uri" | + jq -er --arg name "$asset_name" \ + '.assets[] | select(.name == $name) | [.id, (.digest | ltrimstr("sha256:"))] | @tsv' +) +[[ "$asset_id" =~ ^[0-9]+$ && "$sha256" =~ ^[0-9a-f]{64}$ ]] +archive="${RUNNER_TEMP:?}/$asset_name" +release_root="$RUNNER_TEMP/weaver-lean" +curl --fail --location --retry 3 --header 'Accept: application/octet-stream' \ + --output "$archive" \ + "https://api.github.com/repos/leanprover/lean4/releases/assets/$asset_id" +echo "$sha256 $archive" | shasum -a 256 --check +mkdir -p "$release_root" +tar --zstd -xf "$archive" -C "$release_root" --strip-components=1 +elan toolchain link "$toolchain" "$release_root" +elan run "$toolchain" lean --version diff --git a/go/internal/devrunner/ci.go b/go/internal/devrunner/ci.go index 4fc73a23..cabbd5a0 100644 --- a/go/internal/devrunner/ci.go +++ b/go/internal/devrunner/ci.go @@ -27,7 +27,9 @@ func PrepareCITools(ctx context.Context, output io.Writer) error { default: return fmt.Errorf("unsupported CI suite %q", suite) } - if os.Getenv("RUNNER_TEMP") == "" || os.Getenv("GITHUB_PATH") == "" { return fmt.Errorf("missing disposable runner paths") } + if os.Getenv("RUNNER_TEMP") == "" || os.Getenv("GITHUB_PATH") == "" { + return fmt.Errorf("missing disposable runner paths") + } run := func(binary string, args ...string) error { command := exec.CommandContext(ctx, binary, args...) command.Stdout, command.Stderr = output, output @@ -50,7 +52,7 @@ func PrepareCITools(ctx context.Context, output io.Writer) error { } packages := []string{"apt-get", "install", "-y", "--no-install-recommends", "build-essential", "ca-certificates", "pkg-config", "libssl-dev", "zlib1g-dev", "protobuf-compiler"} if suite == "check-policy" { - packages = append(packages, "elan", "cvc5") + packages = append(packages, "elan", "cvc5", "zstd") } if err := run("sudo", packages...); err != nil { return err diff --git a/go/internal/devrunner/provenance.go b/go/internal/devrunner/provenance.go index 575082f2..1985e361 100644 --- a/go/internal/devrunner/provenance.go +++ b/go/internal/devrunner/provenance.go @@ -78,7 +78,7 @@ func SourceInputs(root string) (map[string]string, error) { if directory == "dev/d2" { return add(path) } - case ".license", ".go", ".rs", ".h", ".ss", ".pkg", ".toml", ".json", ".yaml", ".yml", ".proto", ".sysml", ".cedar", ".lean", ".qnt", ".org", ".d2": + case ".license", ".go", ".rs", ".h", ".sh", ".ss", ".pkg", ".toml", ".json", ".yaml", ".yml", ".proto", ".sysml", ".cedar", ".lean", ".qnt", ".org", ".d2": return add(path) case ".svg": if directory == "dev/d2" || strings.Contains(filepath.ToSlash(path), "/diagrams/assets/") { diff --git a/go/internal/devrunner/provenance_test.go b/go/internal/devrunner/provenance_test.go index 2d8e84e7..cc8d3147 100644 --- a/go/internal/devrunner/provenance_test.go +++ b/go/internal/devrunner/provenance_test.go @@ -25,6 +25,9 @@ func TestSourceCurrentnessRejectsDifferentExpectedInput(t *testing.T) { if err != nil { t.Fatal(err) } + if _, ok := inputs[".github/actions/prepare-toolchain/install-lean.sh"]; !ok { + t.Fatal("toolchain installer is absent from source inputs") + } changed := maps.Clone(inputs) changed["Cargo.lock"] = "different-source-hash" if result := sourceCurrentness(root, t.TempDir(), changed); result.Status != "FAIL" { From 4892a5fd94aee4a1b858602fb7bed7c0aa45b0cb Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 18:08:35 +0800 Subject: [PATCH 076/105] build: pin SDK host affinity and verified release download fixes --- .github/workflows/verify-suite.yml | 2 +- Cargo.lock | 10 +++++----- Cargo.toml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 64537685..3ef35f46 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -67,7 +67,7 @@ jobs: id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-policy", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 - uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@df8014bc16cde63e16f933dba30c486ba6f0616c + uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@ddcf5d0959a300d85428e88b0766ff48adba5d2f with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog diff --git a/Cargo.lock b/Cargo.lock index f4159747..389f8078 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "gerbil-scheme" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=df8014bc16cde63e16f933dba30c486ba6f0616c#df8014bc16cde63e16f933dba30c486ba6f0616c" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=ddcf5d0959a300d85428e88b0766ff48adba5d2f#ddcf5d0959a300d85428e88b0766ff48adba5d2f" dependencies = [ "gerbil-scheme-rust-project-harness-policy", "gerbil-scheme-sys", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-aot-build" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=df8014bc16cde63e16f933dba30c486ba6f0616c#df8014bc16cde63e16f933dba30c486ba6f0616c" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=ddcf5d0959a300d85428e88b0766ff48adba5d2f#ddcf5d0959a300d85428e88b0766ff48adba5d2f" dependencies = [ "cbindgen", "cc", @@ -1822,7 +1822,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness" version = "0.1.2" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=df8014bc16cde63e16f933dba30c486ba6f0616c#df8014bc16cde63e16f933dba30c486ba6f0616c" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=ddcf5d0959a300d85428e88b0766ff48adba5d2f#ddcf5d0959a300d85428e88b0766ff48adba5d2f" dependencies = [ "cargo-lock", "cargo_toml", @@ -1840,7 +1840,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness-policy" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=df8014bc16cde63e16f933dba30c486ba6f0616c#df8014bc16cde63e16f933dba30c486ba6f0616c" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=ddcf5d0959a300d85428e88b0766ff48adba5d2f#ddcf5d0959a300d85428e88b0766ff48adba5d2f" dependencies = [ "gerbil-scheme-rust-project-harness", ] @@ -1848,7 +1848,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-sys" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=df8014bc16cde63e16f933dba30c486ba6f0616c#df8014bc16cde63e16f933dba30c486ba6f0616c" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=ddcf5d0959a300d85428e88b0766ff48adba5d2f#ddcf5d0959a300d85428e88b0766ff48adba5d2f" dependencies = [ "gerbil-scheme-aot-build", "gerbil-scheme-rust-project-harness-policy", diff --git a/Cargo.toml b/Cargo.toml index 3e192654..5db6acf0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,9 @@ arrow-array = "58.4.0" arrow-schema = "58.4.0" arrow-ipc = "58.4.0" criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } -gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "df8014bc16cde63e16f933dba30c486ba6f0616c" } -gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "df8014bc16cde63e16f933dba30c486ba6f0616c" } -gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "df8014bc16cde63e16f933dba30c486ba6f0616c", features = ["external-program"] } +gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "ddcf5d0959a300d85428e88b0766ff48adba5d2f" } +gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "ddcf5d0959a300d85428e88b0766ff48adba5d2f" } +gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "ddcf5d0959a300d85428e88b0766ff48adba5d2f", features = ["external-program"] } asp-rust = { git = "https://github.com/tao3k/asp-rust", rev = "1ca41124b846dec947f3d05119cafa07eaa57924", default-features = false } From f12720f75dae0e8cfe14c8856456d5554559ddf4 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 18:59:53 +0800 Subject: [PATCH 077/105] build: pin SDK host SIGPIPE lifecycle repair --- .github/workflows/verify-suite.yml | 2 +- Cargo.lock | 10 +++++----- Cargo.toml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 3ef35f46..8243dcb6 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -67,7 +67,7 @@ jobs: id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-policy", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 - uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@ddcf5d0959a300d85428e88b0766ff48adba5d2f + uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@bd94bb7d1598e3aa013b040dad024fc43758b7c2 with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog diff --git a/Cargo.lock b/Cargo.lock index 389f8078..1b31c4de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "gerbil-scheme" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=ddcf5d0959a300d85428e88b0766ff48adba5d2f#ddcf5d0959a300d85428e88b0766ff48adba5d2f" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bd94bb7d1598e3aa013b040dad024fc43758b7c2#bd94bb7d1598e3aa013b040dad024fc43758b7c2" dependencies = [ "gerbil-scheme-rust-project-harness-policy", "gerbil-scheme-sys", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-aot-build" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=ddcf5d0959a300d85428e88b0766ff48adba5d2f#ddcf5d0959a300d85428e88b0766ff48adba5d2f" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bd94bb7d1598e3aa013b040dad024fc43758b7c2#bd94bb7d1598e3aa013b040dad024fc43758b7c2" dependencies = [ "cbindgen", "cc", @@ -1822,7 +1822,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness" version = "0.1.2" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=ddcf5d0959a300d85428e88b0766ff48adba5d2f#ddcf5d0959a300d85428e88b0766ff48adba5d2f" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bd94bb7d1598e3aa013b040dad024fc43758b7c2#bd94bb7d1598e3aa013b040dad024fc43758b7c2" dependencies = [ "cargo-lock", "cargo_toml", @@ -1840,7 +1840,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness-policy" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=ddcf5d0959a300d85428e88b0766ff48adba5d2f#ddcf5d0959a300d85428e88b0766ff48adba5d2f" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bd94bb7d1598e3aa013b040dad024fc43758b7c2#bd94bb7d1598e3aa013b040dad024fc43758b7c2" dependencies = [ "gerbil-scheme-rust-project-harness", ] @@ -1848,7 +1848,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-sys" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=ddcf5d0959a300d85428e88b0766ff48adba5d2f#ddcf5d0959a300d85428e88b0766ff48adba5d2f" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bd94bb7d1598e3aa013b040dad024fc43758b7c2#bd94bb7d1598e3aa013b040dad024fc43758b7c2" dependencies = [ "gerbil-scheme-aot-build", "gerbil-scheme-rust-project-harness-policy", diff --git a/Cargo.toml b/Cargo.toml index 5db6acf0..d5f764e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,9 @@ arrow-array = "58.4.0" arrow-schema = "58.4.0" arrow-ipc = "58.4.0" criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } -gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "ddcf5d0959a300d85428e88b0766ff48adba5d2f" } -gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "ddcf5d0959a300d85428e88b0766ff48adba5d2f" } -gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "ddcf5d0959a300d85428e88b0766ff48adba5d2f", features = ["external-program"] } +gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "bd94bb7d1598e3aa013b040dad024fc43758b7c2" } +gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "bd94bb7d1598e3aa013b040dad024fc43758b7c2" } +gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "bd94bb7d1598e3aa013b040dad024fc43758b7c2", features = ["external-program"] } asp-rust = { git = "https://github.com/tao3k/asp-rust", rev = "1ca41124b846dec947f3d05119cafa07eaa57924", default-features = false } From dccb3d4c7351c01d22291bf235f2d0a46a7705b8 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 19:03:22 +0800 Subject: [PATCH 078/105] fix(server): retain static causes in provider rejection receipts --- crates/ledger/src/provider_delivery.rs | 34 ++++++++++----- crates/ledger/tests/unit/provider_delivery.rs | 42 +++++++++++++++++++ crates/server/src/grpc_contracts.rs | 13 ++++++ crates/server/src/grpc_delivery.rs | 9 ++-- crates/server/src/grpc_provider.rs | 9 ++-- crates/server/tests/unit/grpc_rejection.rs | 21 ++++++++++ 6 files changed, 109 insertions(+), 19 deletions(-) create mode 100644 crates/server/tests/unit/grpc_rejection.rs diff --git a/crates/ledger/src/provider_delivery.rs b/crates/ledger/src/provider_delivery.rs index 5e9b51c0..284e1053 100644 --- a/crates/ledger/src/provider_delivery.rs +++ b/crates/ledger/src/provider_delivery.rs @@ -258,18 +258,30 @@ impl DeliveryCursor { .owner .as_ref() .is_some_and(|owner| !Arc::ptr_eq(owner, &binding.owner)) - || receipt - .deadline - .is_some_and(|deadline| Instant::now() >= deadline) - || receipt.consumed - || binding.plan != self.plan - || binding.first != self.next - || self - .session - .as_ref() - .is_some_and(|session| session != &binding.session) { - return Err(Error::Conflict("delivery owner, interval or grant expired")); + return Err(Error::Conflict("delivery owner changed")); + } + if receipt + .deadline + .is_some_and(|deadline| Instant::now() >= deadline) + { + return Err(Error::Conflict("delivery grant expired")); + } + if receipt.consumed { + return Err(Error::Conflict("delivery already consumed")); + } + if binding.plan != self.plan { + return Err(Error::Conflict("delivery plan changed")); + } + if binding.first != self.next { + return Err(Error::Conflict("delivery interval changed")); + } + if self + .session + .as_ref() + .is_some_and(|session| session != &binding.session) + { + return Err(Error::Conflict("delivery session changed")); } // Fail closed on a clock error as well as expiration. if let Some(validity) = &binding.validity diff --git a/crates/ledger/tests/unit/provider_delivery.rs b/crates/ledger/tests/unit/provider_delivery.rs index 5e829357..33189b15 100644 --- a/crates/ledger/tests/unit/provider_delivery.rs +++ b/crates/ledger/tests/unit/provider_delivery.rs @@ -24,6 +24,48 @@ impl Wake for DeliveryWake { } } +#[test] +fn expired_delivery_keeps_the_payload_inert() { + let directory = tempfile::tempdir().expect("store"); + let path = directory.path().join("expired.db"); + let _custody = persistence::Session::open_with_journal(&path, persistence::Journal::Wal) + .expect("native owner"); + let (mut ledger, plan) = fixture(&path); + ledger.enqueue_provider(&plan).expect("reserve"); + let permit = ledger + .consume_provider("f", "infer", &BTreeSet::from(["primary".into()])) + .expect("consume"); + ledger + .dispatch_provider(&permit, || Ok(())) + .expect("dispatch burn"); + let release = ledger + .prepare_provider_release(&permit, "expired-frame", "arrow", 1) + .expect("range"); + let mut staged = None; + ledger + .release_provider_for_delivery(&permit, release, "arrow", |_, delivery| { + staged = Some(delivery.split()); + Ok(()) + }) + .expect("native release committed"); + let (producer, frame) = staged.expect("inert frame"); + producer + .acknowledge(Instant::now() - Duration::from_secs(1)) + .expect("acknowledged expired grant"); + let mut cursor = DeliveryCursor::new(&plan).expect("receiver"); + let cx = Context::from_waker(Waker::noop()); + let mut payload = Some(42); + assert!(matches!( + cursor.poll(&frame, &cx, &mut payload), + Poll::Ready(Err(weaver_contracts::Error::Conflict( + "delivery grant expired" + ))) + )); + assert_eq!(payload, Some(42)); + drop((producer, frame, cursor)); + ledger.close().expect("release worker"); +} + proptest! { #![proptest_config(Config::with_cases(24))] #[test] diff --git a/crates/server/src/grpc_contracts.rs b/crates/server/src/grpc_contracts.rs index 06bf3b01..6c10aa64 100644 --- a/crates/server/src/grpc_contracts.rs +++ b/crates/server/src/grpc_contracts.rs @@ -42,6 +42,19 @@ pub(crate) fn publication_receipt( pub(crate) fn status(_: Error) -> Status { Status::failed_precondition("native authority or state rejected") } +/// Only static contract reasons may cross this boundary; storage, policy and +/// codec errors can contain source or request data. +pub(crate) fn rejection_reason(error: &Error) -> &'static str { + match error { + Error::Invalid(reason) | Error::Conflict(reason) => reason, + Error::Denied => "authorization denied", + _ => "native validation failed", + } +} + +#[cfg(test)] +#[path = "../tests/unit/grpc_rejection.rs"] +mod rejection_tests; pub(crate) fn plan(p: pb::ProviderPlan) -> std::result::Result { let body = String::from_utf8(p.body) .map_err(|_| Status::invalid_argument("UTF-8 provider body required"))?; diff --git a/crates/server/src/grpc_delivery.rs b/crates/server/src/grpc_delivery.rs index 0cbe4ad4..0aeadbc0 100644 --- a/crates/server/src/grpc_delivery.rs +++ b/crates/server/src/grpc_delivery.rs @@ -92,14 +92,15 @@ impl Stream for ResponseStream { } Poll::Pending } - _ => { + Poll::Ready(Err(error)) => { this.cancelled.cancel(); this.receiver.close(); this.staged = None; this.ended = true; - Poll::Ready(Some(Err(Status::failed_precondition( - "delivery authority changed; original reservation retained", - )))) + Poll::Ready(Some(Err(Status::failed_precondition(format!( + "delivery authority changed; original reservation retained: {}", + crate::grpc_contracts::rejection_reason(&error), + ))))) } } } diff --git a/crates/server/src/grpc_provider.rs b/crates/server/src/grpc_provider.rs index 57a5e458..0eebaee8 100644 --- a/crates/server/src/grpc_provider.rs +++ b/crates/server/src/grpc_provider.rs @@ -378,10 +378,11 @@ impl Gateway { { wakeup.notify_one(); } - if result.is_err() { - let _ = sender.try_send(Err(Status::failed_precondition( - "provider execution not completed; inspect original operation", - ))); + if let Err(error) = &result { + let _ = sender.try_send(Err(Status::failed_precondition(format!( + "provider execution not completed; inspect original operation: {}", + crate::grpc_contracts::rejection_reason(error), + )))); } result }) diff --git a/crates/server/tests/unit/grpc_rejection.rs b/crates/server/tests/unit/grpc_rejection.rs new file mode 100644 index 00000000..ed1d91ef --- /dev/null +++ b/crates/server/tests/unit/grpc_rejection.rs @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +use super::rejection_reason; +use weaver_contracts::Error; + +#[test] +fn rejection_reasons_keep_static_causes_and_exclude_dynamic_data() { + assert_eq!( + rejection_reason(&Error::Conflict("delivery cancelled or expired")), + "delivery cancelled or expired", + ); + let dynamic = "private source and request contents"; + for error in [ + Error::Storage(dynamic.into()), + Error::Policy(dynamic.into()), + ] { + assert_eq!(rejection_reason(&error), "native validation failed"); + } +} From de95409cdf575b0bea13594a46805b354a23195e Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 19:28:36 +0800 Subject: [PATCH 079/105] build: pin SDK verified release transport fallback --- .github/workflows/verify-suite.yml | 2 +- Cargo.lock | 10 +++++----- Cargo.toml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 8243dcb6..d8a9c299 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -67,7 +67,7 @@ jobs: id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-policy", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 - uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@bd94bb7d1598e3aa013b040dad024fc43758b7c2 + uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@13351077ca6e7b6194638ade9f0115d544edca19 with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog diff --git a/Cargo.lock b/Cargo.lock index 1b31c4de..1ab0dbd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "gerbil-scheme" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bd94bb7d1598e3aa013b040dad024fc43758b7c2#bd94bb7d1598e3aa013b040dad024fc43758b7c2" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=13351077ca6e7b6194638ade9f0115d544edca19#13351077ca6e7b6194638ade9f0115d544edca19" dependencies = [ "gerbil-scheme-rust-project-harness-policy", "gerbil-scheme-sys", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-aot-build" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bd94bb7d1598e3aa013b040dad024fc43758b7c2#bd94bb7d1598e3aa013b040dad024fc43758b7c2" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=13351077ca6e7b6194638ade9f0115d544edca19#13351077ca6e7b6194638ade9f0115d544edca19" dependencies = [ "cbindgen", "cc", @@ -1822,7 +1822,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness" version = "0.1.2" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bd94bb7d1598e3aa013b040dad024fc43758b7c2#bd94bb7d1598e3aa013b040dad024fc43758b7c2" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=13351077ca6e7b6194638ade9f0115d544edca19#13351077ca6e7b6194638ade9f0115d544edca19" dependencies = [ "cargo-lock", "cargo_toml", @@ -1840,7 +1840,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness-policy" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bd94bb7d1598e3aa013b040dad024fc43758b7c2#bd94bb7d1598e3aa013b040dad024fc43758b7c2" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=13351077ca6e7b6194638ade9f0115d544edca19#13351077ca6e7b6194638ade9f0115d544edca19" dependencies = [ "gerbil-scheme-rust-project-harness", ] @@ -1848,7 +1848,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-sys" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bd94bb7d1598e3aa013b040dad024fc43758b7c2#bd94bb7d1598e3aa013b040dad024fc43758b7c2" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=13351077ca6e7b6194638ade9f0115d544edca19#13351077ca6e7b6194638ade9f0115d544edca19" dependencies = [ "gerbil-scheme-aot-build", "gerbil-scheme-rust-project-harness-policy", diff --git a/Cargo.toml b/Cargo.toml index d5f764e4..dce07066 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,9 @@ arrow-array = "58.4.0" arrow-schema = "58.4.0" arrow-ipc = "58.4.0" criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } -gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "bd94bb7d1598e3aa013b040dad024fc43758b7c2" } -gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "bd94bb7d1598e3aa013b040dad024fc43758b7c2" } -gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "bd94bb7d1598e3aa013b040dad024fc43758b7c2", features = ["external-program"] } +gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "13351077ca6e7b6194638ade9f0115d544edca19" } +gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "13351077ca6e7b6194638ade9f0115d544edca19" } +gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "13351077ca6e7b6194638ade9f0115d544edca19", features = ["external-program"] } asp-rust = { git = "https://github.com/tao3k/asp-rust", rev = "1ca41124b846dec947f3d05119cafa07eaa57924", default-features = false } From fc7a41e21d77a91e7567d51a52c62150512f5b17 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 19:28:36 +0800 Subject: [PATCH 080/105] refactor(ledger): separate guarded delivery validation and consumption --- crates/ledger/src/provider_delivery.rs | 128 ++++++++++++++----------- 1 file changed, 73 insertions(+), 55 deletions(-) diff --git a/crates/ledger/src/provider_delivery.rs b/crates/ledger/src/provider_delivery.rs index 284e1053..4fb1bacb 100644 --- a/crates/ledger/src/provider_delivery.rs +++ b/crates/ledger/src/provider_delivery.rs @@ -5,7 +5,11 @@ //! Inert gRPC frames join acknowledged Turso validation at the receiver owner. use crate::{ Ledger, ProviderDispatch, db, - persistence::{authority::Completion, owner::Owner, scheduler::Scope}, + persistence::{ + authority::{Completion, Receipt}, + owner::Owner, + scheduler::Scope, + }, }; use std::{ sync::Arc, @@ -253,60 +257,7 @@ impl DeliveryCursor { &binding.scope, &binding.completion, cx.waker(), - |receipt| { - if self - .owner - .as_ref() - .is_some_and(|owner| !Arc::ptr_eq(owner, &binding.owner)) - { - return Err(Error::Conflict("delivery owner changed")); - } - if receipt - .deadline - .is_some_and(|deadline| Instant::now() >= deadline) - { - return Err(Error::Conflict("delivery grant expired")); - } - if receipt.consumed { - return Err(Error::Conflict("delivery already consumed")); - } - if binding.plan != self.plan { - return Err(Error::Conflict("delivery plan changed")); - } - if binding.first != self.next { - return Err(Error::Conflict("delivery interval changed")); - } - if self - .session - .as_ref() - .is_some_and(|session| session != &binding.session) - { - return Err(Error::Conflict("delivery session changed")); - } - // Fail closed on a clock error as well as expiration. - if let Some(validity) = &binding.validity - && !validity.contains(&crate::provider_oauth::now()?) - { - return Err(Error::Denied); - } - let next = self - .next - .checked_add(binding.rows) - .ok_or(Error::Invalid("delivery interval exhausted"))?; - let value = payload - .take() - .ok_or(Error::Conflict("delivery payload absent"))?; - self.next = next; - self.owner.get_or_insert_with(|| binding.owner.clone()); - self.session.get_or_insert_with(|| binding.session.clone()); - receipt.consumed = true; - #[cfg(feature = "commit-observer")] - { - receipt.accepted_at = Some(std::time::SystemTime::now()); - } - binding.completion.changed.notify_all(); - Ok(value) - }, + |receipt| self.accept_current_frame(binding, receipt, payload), ); match result { Ok(Some(value)) => Poll::Ready(Ok(value)), @@ -314,6 +265,73 @@ impl DeliveryCursor { Err(error) => Poll::Ready(Err(error)), } } + + fn validate_frame(&self, binding: &Binding, receipt: &Receipt) -> Result<()> { + if self + .owner + .as_ref() + .is_some_and(|owner| !Arc::ptr_eq(owner, &binding.owner)) + { + return Err(Error::Conflict("delivery owner changed")); + } + if receipt + .deadline + .is_some_and(|deadline| Instant::now() >= deadline) + { + return Err(Error::Conflict("delivery grant expired")); + } + if receipt.consumed { + return Err(Error::Conflict("delivery already consumed")); + } + if binding.plan != self.plan { + return Err(Error::Conflict("delivery plan changed")); + } + if binding.first != self.next { + return Err(Error::Conflict("delivery interval changed")); + } + if self + .session + .as_ref() + .is_some_and(|session| session != &binding.session) + { + return Err(Error::Conflict("delivery session changed")); + } + // Fail closed on a clock error as well as expiration. + if let Some(validity) = &binding.validity + && !validity.contains(&crate::provider_oauth::now()?) + { + return Err(Error::Denied); + } + Ok(()) + } + + // Authority::current keeps validation and payload transfer in one deciding + // turn under its mutex; this helper must not be called before that turn. + fn accept_current_frame( + &mut self, + binding: &Binding, + receipt: &mut Receipt, + payload: &mut Option, + ) -> Result { + self.validate_frame(binding, receipt)?; + let next = self + .next + .checked_add(binding.rows) + .ok_or(Error::Invalid("delivery interval exhausted"))?; + let value = payload + .take() + .ok_or(Error::Conflict("delivery payload absent"))?; + self.next = next; + self.owner.get_or_insert_with(|| binding.owner.clone()); + self.session.get_or_insert_with(|| binding.session.clone()); + receipt.consumed = true; + #[cfg(feature = "commit-observer")] + { + receipt.accepted_at = Some(std::time::SystemTime::now()); + } + binding.completion.changed.notify_all(); + Ok(value) + } } impl Drop for DeliveryFrame { fn drop(&mut self) { From 184953d918e73963629faee0d0a7da2b63d976f1 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 20:23:55 +0800 Subject: [PATCH 081/105] test(control): activate the staged source before hard fact recovery --- go/dev/provider_hard_fact_test.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/go/dev/provider_hard_fact_test.go b/go/dev/provider_hard_fact_test.go index ad971c00..a60022e2 100644 --- a/go/dev/provider_hard_fact_test.go +++ b/go/dev/provider_hard_fact_test.go @@ -64,14 +64,22 @@ func hardFactFeedSetting(t *testing.T, f *fixture, family, root string, dependen func TestProviderControlHardFactWithdrawalRestartAndABA(t *testing.T) { f := newFixture(t, completeSSE, false) - f.env = append(f.env, hardFactFeedSetting(t, f, f.plan.Family, f.plan.Node, [][2]string{}, nil, "", nil)) - compiledControlSources(false).configure(t, f, controlBundle(t, f)) + bundle := controlBundle(t, f) + plan := bundle.Plans[0] + f.env = append(f.env, hardFactFeedSetting(t, f, plan.Family, plan.Node, [][2]string{}, nil, "", nil)) + sources := compiledControlSources(false) + sources.configure(t, f, bundle) + // configure stages the reviewed publication. Activate that same original + // before testing facts, rather than leaving an unrelated Policy barrier open. + c := newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")) + c.useProducer(sources.producer) + c.start(t) ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second) defer cancel() blocked := func(label string) { t.Helper() - _, err := f.client.Execute(ctx, f.plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { + _, err := f.client.Execute(ctx, plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { t.Errorf("%s emitted a provider event", label) return nil }) @@ -91,7 +99,7 @@ func TestProviderControlHardFactWithdrawalRestartAndABA(t *testing.T) { t.Helper() result, err := f.admin.RPC.ResolveHardFact(f.admin.Context(ctx), barrier) if err != nil || !proto.Equal(barrier, result.GetBarrier()) || - len(result.GetAffected()) != 1 || result.GetAffected()[0] != f.plan.Node { + len(result.GetAffected()) != 1 || result.GetAffected()[0] != plan.Node { t.Fatalf("resolve hard fact: %v %v", result, err) } return result @@ -137,7 +145,7 @@ func TestProviderControlHardFactWithdrawalRestartAndABA(t *testing.T) { resolve(a) blocked("old exact receipt replay cannot clear a newer pending barrier") resolve(aAgain) - _, err := f.client.Execute(ctx, f.plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }) + _, err := f.client.Execute(ctx, plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }) if err != nil || f.primary.Load() != 1 || f.backup.Load() != 0 { t.Fatalf("restored fact did not permit normal guarded provider execution: %v", err) } From a1643e8c87d35984d3a581de54bab60fe2e2e293 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 20:23:55 +0800 Subject: [PATCH 082/105] ci: delegate Scheme source preparation to native package APIs --- .github/workflows/verify-suite.yml | 42 ++------------------ Project.sysml | 11 ++++++ dev/prepare-scheme.ss | 61 ++++++++++++++++++++++++++++++ prepare.ss | 7 ++++ t/source-preparation-test.ss | 20 ++++++++++ 5 files changed, 102 insertions(+), 39 deletions(-) create mode 100644 dev/prepare-scheme.ss create mode 100644 prepare.ss create mode 100644 t/source-preparation-test.ss diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index d8a9c299..c9b4bb4f 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -88,48 +88,12 @@ jobs: # The SDK setup exports the host core count via GITHUB_ENV. GERBIL_BUILD_CORES: '4' GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil + WEAVER_SCHEME_SOURCE_ROOT: ${{ runner.temp }}/weaver-scheme-sources SOURCE_PREPARE_MINUTES: ${{ runner.os == 'macOS' && 18 || 12 }} run: | printf 'budget_minutes=%s\n' "$SOURCE_PREPARE_MINUTES" >> "$GITHUB_OUTPUT" - command -v timeout - export scheme_sources="$RUNNER_TEMP/weaver-scheme-sources" - if timeout --verbose --kill-after=5s "${SOURCE_PREPARE_MINUTES}m" bash -se -o pipefail <<'SOURCE_CLOSURE'; then - printf 'phase=resolve-pins\n' >> "$GITHUB_OUTPUT" - fetch_source() { - local package=$1 pin=$2 destination=$3 revision=${2##*@} - [[ "$pin" == "$package@$revision" && "$revision" =~ ^[0-9a-f]{40}$ ]] - git init --quiet "$destination" - git -C "$destination" fetch --quiet --depth=1 --no-tags "https://$package.git" "$revision" - git -C "$destination" checkout --quiet --detach FETCH_HEAD - test "$(git -C "$destination" rev-parse HEAD)" = "$revision" - } - - lab=github.com/tao3k/agentic-ai-lab - ascent=github.com/tao3k/gerbil-ascent - lab_source="$scheme_sources/lab" - ascent_source="$scheme_sources/imports/gerbil-ascent" - mkdir -p "$scheme_sources/imports" - fetch_source "$lab" "$(gerbil deps)" "$lab_source" - ascent_pin=$(cd "$lab_source" && gerbil deps | grep "^$ascent@") - fetch_source "$ascent" "$ascent_pin" "$ascent_source" - core_pin=$(cd "$ascent_source" && gerbil deps) - [[ "$core_pin" =~ ^github\.com/tao3k/gebril-yuanxu@[0-9a-f]{40}$ ]] - - # Core supplies the compiler and POO. Lab and ASCENT supply the - # source selected by Weaver; their unrelated build products stay out. - printf 'phase=core-and-poo\n' >> "$GITHUB_OUTPUT" - gerbil pkg install "$core_pin" - printf 'phase=link-source-packages\n' >> "$GITHUB_OUTPUT" - gerbil pkg link "$lab" "$lab_source" - gerbil pkg link "$ascent" "$ascent_source" - export GERBIL_LOADPATH="$GERBIL_PATH/lib:$scheme_sources/imports" - printf 'phase=ascent-program\n' >> "$GITHUB_OUTPUT" - ./build.ss prepare-governor-library - SOURCE_CLOSURE - dependency_exit_code=0 - else - dependency_exit_code=$? - fi + dependency_exit_code=0 + timeout --verbose --kill-after=5s "${SOURCE_PREPARE_MINUTES}m" gxi prepare.ss || dependency_exit_code=$? printf 'exit_code=%s\n' "$dependency_exit_code" >> "$GITHUB_OUTPUT" exit "$dependency_exit_code" - name: Verify declared suite diff --git a/Project.sysml b/Project.sysml index f9fc47fe..d1d0f822 100644 --- a/Project.sysml +++ b/Project.sysml @@ -252,6 +252,9 @@ package WeaverProject { whole-suite watchdog leaves time for these stages and the preceding package checks to retain independent results. Resolve Lab and ASCENT sources from native package declarations. + The Scheme prepare.ss bootstrap uses gxpkg metadata and package + installation APIs before the Yuanxu prelude is available. + CI only selects the watchdog and invokes this package entry. Gerbil prepares the pinned Core and POO compiler dependencies. ASCENT's selected Program build supplies native linker inputs. Dependency preparation defaults to four workers, with a @@ -520,6 +523,14 @@ package WeaverProject { part 'go/go.mod' : File; part 'go/go.sum' : File; part 'gerbil.pkg' : File; + part 'prepare.ss' : File; + part 'dev/prepare-scheme.ss' : File { + doc /* Development-only bootstrap before Core's prelude exists. + Read native package declarations, prepare exact source revisions, + install Core/POO through gxpkg and invoke the selected Build. + This is not a runtime configuration or publication authority. */ + } + part 't/source-preparation-test.ss' : File; part 'build.ss' : ExecutableFile; part 'init.ss' : File; part 'proto/gateway/v1/gateway.proto' : File; diff --git a/dev/prepare-scheme.ss b/dev/prepare-scheme.ss new file mode 100644 index 00000000..bfdce959 --- /dev/null +++ b/dev/prepare-scheme.ss @@ -0,0 +1,61 @@ +;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +;;; +;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 +prelude: :gerbil/core + +;;; Bootstrap before Yuanxu's prelude exists. Package metadata and installation +;;; stay with gxpkg; build.ss owns the selected ASCENT Program library. +(import (only-in :gerbil/tools/gxpkg pkg-plist pkg-link pkg-install) + (only-in :gerbil/tools/env setup-local-pkg-env!) + (only-in :std/misc/process run-process run-process/batch) + (only-in :std/text/pregexp pregexp-match)) +(export main dependency-pin) + +(def (dependency-pin properties package) + (def prefix (string-append package "@")) + (def matches + (filter (lambda (pin) (and (string? pin) (string-prefix? prefix pin))) + (pgetq depend: properties '()))) + (unless (and (= (length matches) 1) + (pregexp-match "^[0-9a-f]{40}$" + (substring (car matches) (string-length prefix) + (string-length (car matches))))) + (error "expected one exact source revision in package dependencies" package matches)) + (car matches)) + +(def (phase! name) + (displayln "Scheme preparation: " name) + (when (getenv "GITHUB_OUTPUT" #f) + (call-with-output-file (list path: (getenv "GITHUB_OUTPUT") append: #t) + (lambda (port) + (display (string-append "phase=" name "\n") port))))) + +(def (fetch-source! properties package destination) + (def pin (dependency-pin properties package)) + (def revision (substring pin (+ (string-length package) 1) (string-length pin))) + (run-process/batch ["git" "init" "--quiet" destination]) + (run-process/batch ["git" "-C" destination "fetch" "--quiet" "--depth=1" "--no-tags" + (string-append "https://" package ".git") revision]) + (run-process/batch ["git" "-C" destination "checkout" "--quiet" "--detach" "FETCH_HEAD"]) + (unless (string=? (string-append revision "\n") + (run-process ["git" "-C" destination "rev-parse" "HEAD"])) + (error "source checkout does not match declared revision" package revision)) + (pkg-link package destination)) + +(def (main . args) + (unless (null? args) (error "usage: gxi prepare.ss" args)) + (setup-local-pkg-env! #t) + (def root (path-expand "" (getenv "WEAVER_SCHEME_SOURCE_ROOT" + ".cache/verification/scheme-sources"))) + (def lab "github.com/tao3k/agentic-ai-lab") + (def ascent "github.com/tao3k/gerbil-ascent") + (create-directory* (path-expand "imports" root)) + (phase! "resolve-pins") + (fetch-source! (pkg-plist ".") lab (path-expand "lab" root)) + (fetch-source! (pkg-plist lab) ascent (path-expand "imports/gerbil-ascent" root)) + (phase! "core-and-poo") + (pkg-install (dependency-pin (pkg-plist ascent) "github.com/tao3k/gebril-yuanxu")) + (setenv "GERBIL_LOADPATH" + (string-append (path-expand "lib" (gerbil-path)) ":" (path-expand "imports" root))) + (phase! "ascent-program") + (run-process/batch ["gxi" "build.ss" "prepare-governor-library"])) diff --git a/prepare.ss b/prepare.ss new file mode 100644 index 00000000..4700cd0f --- /dev/null +++ b/prepare.ss @@ -0,0 +1,7 @@ +#!/usr/bin/env gxi +;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +;;; +;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +(import (rename-in (only-in "./dev/prepare-scheme.ss" main) (main prepare-package!))) +(def (main . args) (apply prepare-package! args)) diff --git a/t/source-preparation-test.ss b/t/source-preparation-test.ss new file mode 100644 index 00000000..8cd2081c --- /dev/null +++ b/t/source-preparation-test.ss @@ -0,0 +1,20 @@ +;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +;;; +;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 +prelude: :gerbil/core +(import :std/test (only-in "../dev/prepare-scheme.ss" dependency-pin)) +(export source-preparation-test) + +(def source-preparation-test + (test-suite "Native package source selection" + (def package "github.com/tao3k/source") + (def pin (string-append package "@0123456789abcdef0123456789abcdef01234567")) + (test-case "accept the sole exact declared revision" + (check-equal? (dependency-pin [depend: ["github.com/other/source@main" pin]] package) pin)) + (test-case "reject absent, duplicate, mutable and malformed source revisions" + (for-each + (lambda (dependencies) + (check-exception (dependency-pin [depend: dependencies] package) error?)) + [[] [pin pin] [(string-append package "@main")] + [(string-append package "@0123456789abcdef")] + [(string-append package "@0123456789abcdef0123456789abcdef0123456g")]])))) From bd92d9f74122e9e52c8b4bc497b195fd3fe73e32 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 20:26:06 +0800 Subject: [PATCH 083/105] build: bind the verified native cleanup lifecycle revision --- .github/workflows/verify-suite.yml | 2 +- Cargo.lock | 10 +++++----- Cargo.toml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index c9b4bb4f..59fef346 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -67,7 +67,7 @@ jobs: id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-policy", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 - uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@13351077ca6e7b6194638ade9f0115d544edca19 + uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4 with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog diff --git a/Cargo.lock b/Cargo.lock index 1ab0dbd0..603dd12a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "gerbil-scheme" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=13351077ca6e7b6194638ade9f0115d544edca19#13351077ca6e7b6194638ade9f0115d544edca19" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4#03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4" dependencies = [ "gerbil-scheme-rust-project-harness-policy", "gerbil-scheme-sys", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-aot-build" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=13351077ca6e7b6194638ade9f0115d544edca19#13351077ca6e7b6194638ade9f0115d544edca19" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4#03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4" dependencies = [ "cbindgen", "cc", @@ -1822,7 +1822,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness" version = "0.1.2" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=13351077ca6e7b6194638ade9f0115d544edca19#13351077ca6e7b6194638ade9f0115d544edca19" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4#03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4" dependencies = [ "cargo-lock", "cargo_toml", @@ -1840,7 +1840,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness-policy" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=13351077ca6e7b6194638ade9f0115d544edca19#13351077ca6e7b6194638ade9f0115d544edca19" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4#03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4" dependencies = [ "gerbil-scheme-rust-project-harness", ] @@ -1848,7 +1848,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-sys" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=13351077ca6e7b6194638ade9f0115d544edca19#13351077ca6e7b6194638ade9f0115d544edca19" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4#03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4" dependencies = [ "gerbil-scheme-aot-build", "gerbil-scheme-rust-project-harness-policy", diff --git a/Cargo.toml b/Cargo.toml index dce07066..354ae748 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,9 @@ arrow-array = "58.4.0" arrow-schema = "58.4.0" arrow-ipc = "58.4.0" criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } -gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "13351077ca6e7b6194638ade9f0115d544edca19" } -gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "13351077ca6e7b6194638ade9f0115d544edca19" } -gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "13351077ca6e7b6194638ade9f0115d544edca19", features = ["external-program"] } +gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4" } +gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4" } +gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4", features = ["external-program"] } asp-rust = { git = "https://github.com/tao3k/asp-rust", rev = "1ca41124b846dec947f3d05119cafa07eaa57924", default-features = false } From d7a0cf263f24b4e87c3b6dd3adf243ed492add44 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 20:29:09 +0800 Subject: [PATCH 084/105] build: track SDK native control lint correction --- .github/workflows/verify-suite.yml | 2 +- Cargo.lock | 10 +++++----- Cargo.toml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 59fef346..1193f83c 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -67,7 +67,7 @@ jobs: id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-policy", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 - uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4 + uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@9029ac9d9bb680b13b2976d614965daf8b0d7d50 with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog diff --git a/Cargo.lock b/Cargo.lock index 603dd12a..51938e53 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "gerbil-scheme" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4#03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9029ac9d9bb680b13b2976d614965daf8b0d7d50#9029ac9d9bb680b13b2976d614965daf8b0d7d50" dependencies = [ "gerbil-scheme-rust-project-harness-policy", "gerbil-scheme-sys", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-aot-build" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4#03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9029ac9d9bb680b13b2976d614965daf8b0d7d50#9029ac9d9bb680b13b2976d614965daf8b0d7d50" dependencies = [ "cbindgen", "cc", @@ -1822,7 +1822,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness" version = "0.1.2" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4#03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9029ac9d9bb680b13b2976d614965daf8b0d7d50#9029ac9d9bb680b13b2976d614965daf8b0d7d50" dependencies = [ "cargo-lock", "cargo_toml", @@ -1840,7 +1840,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness-policy" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4#03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9029ac9d9bb680b13b2976d614965daf8b0d7d50#9029ac9d9bb680b13b2976d614965daf8b0d7d50" dependencies = [ "gerbil-scheme-rust-project-harness", ] @@ -1848,7 +1848,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-sys" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4#03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9029ac9d9bb680b13b2976d614965daf8b0d7d50#9029ac9d9bb680b13b2976d614965daf8b0d7d50" dependencies = [ "gerbil-scheme-aot-build", "gerbil-scheme-rust-project-harness-policy", diff --git a/Cargo.toml b/Cargo.toml index 354ae748..d11dc0b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,9 @@ arrow-array = "58.4.0" arrow-schema = "58.4.0" arrow-ipc = "58.4.0" criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } -gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4" } -gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4" } -gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "03d7c2ef32807a6d0f8d55e755c85dbb2a2ac0c4", features = ["external-program"] } +gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "9029ac9d9bb680b13b2976d614965daf8b0d7d50" } +gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "9029ac9d9bb680b13b2976d614965daf8b0d7d50" } +gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "9029ac9d9bb680b13b2976d614965daf8b0d7d50", features = ["external-program"] } asp-rust = { git = "https://github.com/tao3k/asp-rust", rev = "1ca41124b846dec947f3d05119cafa07eaa57924", default-features = false } From bc125f65604c216a265b9ff4fd0abbe1d35bf246 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 20:32:58 +0800 Subject: [PATCH 085/105] ci: use native Gerbil dependency installation directly --- .github/workflows/verify-suite.yml | 6 +-- Project.sysml | 21 +++------- build.ss | 41 ++++---------------- dev/prepare-scheme.ss | 61 ------------------------------ prepare.ss | 7 ---- t/source-preparation-test.ss | 20 ---------- 6 files changed, 15 insertions(+), 141 deletions(-) delete mode 100644 dev/prepare-scheme.ss delete mode 100644 prepare.ss delete mode 100644 t/source-preparation-test.ss diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 1193f83c..df677d06 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -79,7 +79,7 @@ jobs: run: | brew install coreutils echo "$(brew --prefix coreutils)/libexec/gnubin" >> "$GITHUB_PATH" - - name: Prepare the Weaver Scheme source closure + - name: Install declared Scheme dependencies id: scheme_dependencies if: inputs.suite == 'check-scheme' # Leave time after either native watchdog for its exit receipt. @@ -88,12 +88,11 @@ jobs: # The SDK setup exports the host core count via GITHUB_ENV. GERBIL_BUILD_CORES: '4' GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil - WEAVER_SCHEME_SOURCE_ROOT: ${{ runner.temp }}/weaver-scheme-sources SOURCE_PREPARE_MINUTES: ${{ runner.os == 'macOS' && 18 || 12 }} run: | printf 'budget_minutes=%s\n' "$SOURCE_PREPARE_MINUTES" >> "$GITHUB_OUTPUT" dependency_exit_code=0 - timeout --verbose --kill-after=5s "${SOURCE_PREPARE_MINUTES}m" gxi prepare.ss || dependency_exit_code=$? + timeout --verbose --kill-after=5s "${SOURCE_PREPARE_MINUTES}m" gerbil deps --install || dependency_exit_code=$? printf 'exit_code=%s\n' "$dependency_exit_code" >> "$GITHUB_OUTPUT" exit "$dependency_exit_code" - name: Verify declared suite @@ -136,7 +135,6 @@ jobs: "os": ${{ toJSON(runner.os) }}, "arch": ${{ toJSON(runner.arch) }}, "status": ${{ toJSON(job.status) }}, - "schemeDependencyPhase": ${{ toJSON(steps.scheme_dependencies.outputs.phase || null) }}, "schemeDependencyBudgetMinutes": ${{ steps.scheme_dependencies.outputs.budget_minutes || 'null' }}, "schemeDependencyExitCode": ${{ steps.scheme_dependencies.outputs.exit_code || 'null' }}, "phases": { diff --git a/Project.sysml b/Project.sysml index d1d0f822..84963316 100644 --- a/Project.sysml +++ b/Project.sysml @@ -251,20 +251,17 @@ package WeaverProject { archive. Bound the Rust tests and Go suite separately. The whole-suite watchdog leaves time for these stages and the preceding package checks to retain independent results. - Resolve Lab and ASCENT sources from native package declarations. - The Scheme prepare.ss bootstrap uses gxpkg metadata and package - installation APIs before the Yuanxu prelude is available. - CI only selects the watchdog and invokes this package entry. - Gerbil prepares the pinned Core and POO compiler dependencies. - ASCENT's selected Program build supplies native linker inputs. + gerbil deps --install owns dependency resolution, source revisions + and native dependency builds from gerbil.pkg declarations. + Each dependency owns its own Build targets and package tests. + CI only selects the watchdog and invokes the package manager. Dependency preparation defaults to four workers, with a twelve-minute watchdog on Linux and eighteen minutes on macOS. Record the selected watchdog and its exit code in the job receipt. Run the selected package Build with a separate two-minute bound. Retain SDK archive milestones and native Go failure events with their stage receipts. The provider recovery and natural-exit - deadlines govern runtime. - Unrelated producer products stay outside this source closure. */ + deadlines govern runtime. */ } part architecture : VerificationSuite { part 'check-architecture' : VerificationMode; } part policy : VerificationSuite { @@ -523,14 +520,6 @@ package WeaverProject { part 'go/go.mod' : File; part 'go/go.sum' : File; part 'gerbil.pkg' : File; - part 'prepare.ss' : File; - part 'dev/prepare-scheme.ss' : File { - doc /* Development-only bootstrap before Core's prelude exists. - Read native package declarations, prepare exact source revisions, - install Core/POO through gxpkg and invoke the selected Build. - This is not a runtime configuration or publication authority. */ - } - part 't/source-preparation-test.ss' : File; part 'build.ss' : ExecutableFile; part 'init.ss' : File; part 'proto/gateway/v1/gateway.proto' : File; diff --git a/build.ss b/build.ss index 22fc54b6..e1bbfc16 100755 --- a/build.ss +++ b/build.ss @@ -12,51 +12,27 @@ (import (only-in :clan/poo/object .get) (only-in :std/source this-source-file) (only-in :std/build-script defbuild-script) - (only-in :gerbil/tools/gxpkg pkg-root-dir) - (only-in :gerbil/expander eval-syntax import-module expander-context-id) + (only-in :gerbil/expander import-module expander-context-id) (only-in :gerbil/compiler compile-module) (only-in :yuanxu/module-system/building/interface call-with-init-build-spec) - (only-in :yuanxu/module-system/building/products build-output-directory - current-build-compiler-options current-build-module-roots current-build-source-directory) - (only-in :yuanxu/module-system/building/source-package register-module-build-source!) + (only-in :yuanxu/module-system/building/products build-output-directory current-build-source-directory) (only-in :yuanxu/module-system/source/observations current-module-source-observer) (only-in "./init.ss" hardenedlinux/weaver.init.exports)) (export main) -(def (run-build args entry prepare (target-options '())) +(def (compile-package args) (def output (build-output-directory)) + (def entry (this-source-file)) (def (dispatch spec native-args (prefix #f)) (def (this-source-file) (let (directory (current-build-source-directory)) (if directory (path-expand (path-strip-directory entry) directory) entry))) - (def targets - (if (null? target-options) spec - (map (lambda (target) - (append (if (string? target) (list gxc: target) target) target-options)) - spec))) - (defbuild-script targets libdir: output prefix: prefix) + (defbuild-script spec libdir: output prefix: prefix) (apply main native-args)) - (parameterize ((current-build-compiler-options - (append (current-build-compiler-options) target-options))) - (call-with-init-build-spec prepare dispatch args output entry))) - -(def (compile-package args) - (run-build args (this-source-file) - (lambda () ((.get hardenedlinux/weaver.init.exports std-make-spec) '())))) - -;; The pinned producer's Program root owns its Scheme library closure. -(def (prepare-governor-library) - (def source (path-normalize (path-expand "github.com/tao3k/gerbil-ascent/" (pkg-root-dir)))) - (register-module-build-source! source 'gerbil-ascent) - (parameterize ((current-directory source) (current-build-module-roots '(program))) - (def entry (path-expand "build.ss" source)) - (eval-syntax `(import (only-in ,(path-expand "init.ss" source) gerbil-ascent.init.exports))) - (eval-syntax `(import (only-in ,entry gerbil-ascent-compiler-options))) - (def exports (eval 'gerbil-ascent.init.exports)) - (run-build '("compile") entry - (lambda () ((.get exports std-make-spec) '())) - (eval 'gerbil-ascent-compiler-options)))) + (call-with-init-build-spec + (lambda () ((.get hardenedlinux/weaver.init.exports std-make-spec) '())) + dispatch args output entry)) ;; Cargo needs the inputs already read by the package owner to invalidate its ;; build script. Files created under OUT_DIR are products of the same build. @@ -80,7 +56,6 @@ (def (main . args) (match args - (["prepare-governor-library"] (prepare-governor-library)) (["compile-approved-program" source expected-module] ;; An operator can approve a source in a different package. (compile-module source [output-dir: (path-expand "lib" (gerbil-path)) diff --git a/dev/prepare-scheme.ss b/dev/prepare-scheme.ss deleted file mode 100644 index bfdce959..00000000 --- a/dev/prepare-scheme.ss +++ /dev/null @@ -1,61 +0,0 @@ -;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors -;;; -;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 -prelude: :gerbil/core - -;;; Bootstrap before Yuanxu's prelude exists. Package metadata and installation -;;; stay with gxpkg; build.ss owns the selected ASCENT Program library. -(import (only-in :gerbil/tools/gxpkg pkg-plist pkg-link pkg-install) - (only-in :gerbil/tools/env setup-local-pkg-env!) - (only-in :std/misc/process run-process run-process/batch) - (only-in :std/text/pregexp pregexp-match)) -(export main dependency-pin) - -(def (dependency-pin properties package) - (def prefix (string-append package "@")) - (def matches - (filter (lambda (pin) (and (string? pin) (string-prefix? prefix pin))) - (pgetq depend: properties '()))) - (unless (and (= (length matches) 1) - (pregexp-match "^[0-9a-f]{40}$" - (substring (car matches) (string-length prefix) - (string-length (car matches))))) - (error "expected one exact source revision in package dependencies" package matches)) - (car matches)) - -(def (phase! name) - (displayln "Scheme preparation: " name) - (when (getenv "GITHUB_OUTPUT" #f) - (call-with-output-file (list path: (getenv "GITHUB_OUTPUT") append: #t) - (lambda (port) - (display (string-append "phase=" name "\n") port))))) - -(def (fetch-source! properties package destination) - (def pin (dependency-pin properties package)) - (def revision (substring pin (+ (string-length package) 1) (string-length pin))) - (run-process/batch ["git" "init" "--quiet" destination]) - (run-process/batch ["git" "-C" destination "fetch" "--quiet" "--depth=1" "--no-tags" - (string-append "https://" package ".git") revision]) - (run-process/batch ["git" "-C" destination "checkout" "--quiet" "--detach" "FETCH_HEAD"]) - (unless (string=? (string-append revision "\n") - (run-process ["git" "-C" destination "rev-parse" "HEAD"])) - (error "source checkout does not match declared revision" package revision)) - (pkg-link package destination)) - -(def (main . args) - (unless (null? args) (error "usage: gxi prepare.ss" args)) - (setup-local-pkg-env! #t) - (def root (path-expand "" (getenv "WEAVER_SCHEME_SOURCE_ROOT" - ".cache/verification/scheme-sources"))) - (def lab "github.com/tao3k/agentic-ai-lab") - (def ascent "github.com/tao3k/gerbil-ascent") - (create-directory* (path-expand "imports" root)) - (phase! "resolve-pins") - (fetch-source! (pkg-plist ".") lab (path-expand "lab" root)) - (fetch-source! (pkg-plist lab) ascent (path-expand "imports/gerbil-ascent" root)) - (phase! "core-and-poo") - (pkg-install (dependency-pin (pkg-plist ascent) "github.com/tao3k/gebril-yuanxu")) - (setenv "GERBIL_LOADPATH" - (string-append (path-expand "lib" (gerbil-path)) ":" (path-expand "imports" root))) - (phase! "ascent-program") - (run-process/batch ["gxi" "build.ss" "prepare-governor-library"])) diff --git a/prepare.ss b/prepare.ss deleted file mode 100644 index 4700cd0f..00000000 --- a/prepare.ss +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env gxi -;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors -;;; -;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 - -(import (rename-in (only-in "./dev/prepare-scheme.ss" main) (main prepare-package!))) -(def (main . args) (apply prepare-package! args)) diff --git a/t/source-preparation-test.ss b/t/source-preparation-test.ss deleted file mode 100644 index 8cd2081c..00000000 --- a/t/source-preparation-test.ss +++ /dev/null @@ -1,20 +0,0 @@ -;;; SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors -;;; -;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 -prelude: :gerbil/core -(import :std/test (only-in "../dev/prepare-scheme.ss" dependency-pin)) -(export source-preparation-test) - -(def source-preparation-test - (test-suite "Native package source selection" - (def package "github.com/tao3k/source") - (def pin (string-append package "@0123456789abcdef0123456789abcdef01234567")) - (test-case "accept the sole exact declared revision" - (check-equal? (dependency-pin [depend: ["github.com/other/source@main" pin]] package) pin)) - (test-case "reject absent, duplicate, mutable and malformed source revisions" - (for-each - (lambda (dependencies) - (check-exception (dependency-pin [depend: dependencies] package) error?)) - [[] [pin pin] [(string-append package "@main")] - [(string-append package "@0123456789abcdef")] - [(string-append package "@0123456789abcdef0123456789abcdef0123456g")]])))) From b511a5751970f4daf208688e47775282457b950c Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 21:31:20 +0800 Subject: [PATCH 086/105] ci: expose native package phase progress without changing budgets --- .github/workflows/verify-suite.yml | 2 +- Project.sysml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index df677d06..1bbd3148 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -92,7 +92,7 @@ jobs: run: | printf 'budget_minutes=%s\n' "$SOURCE_PREPARE_MINUTES" >> "$GITHUB_OUTPUT" dependency_exit_code=0 - timeout --verbose --kill-after=5s "${SOURCE_PREPARE_MINUTES}m" gerbil deps --install || dependency_exit_code=$? + timeout --verbose --kill-after=5s "${SOURCE_PREPARE_MINUTES}m" gerbil -:1n,2n deps --install || dependency_exit_code=$? printf 'exit_code=%s\n' "$dependency_exit_code" >> "$GITHUB_OUTPUT" exit "$dependency_exit_code" - name: Verify declared suite diff --git a/Project.sysml b/Project.sysml index 84963316..3a172079 100644 --- a/Project.sysml +++ b/Project.sysml @@ -255,6 +255,8 @@ package WeaverProject { and native dependency builds from gerbil.pkg declarations. Each dependency owns its own Build targets and package tests. CI only selects the watchdog and invokes the package manager. + Native stdout/stderr line buffering exposes package boundaries + as they occur; buffered batches do not establish phase durations. Dependency preparation defaults to four workers, with a twelve-minute watchdog on Linux and eighteen minutes on macOS. Record the selected watchdog and its exit code in the job receipt. From 55f7dd7cb54f1c08cb9fdc96f1f38a47c54a156f Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 21:56:32 +0800 Subject: [PATCH 087/105] build: reuse native separate C hosts for package dependencies --- .github/workflows/verify-suite.yml | 3 +++ Project.sysml | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 1bbd3148..f1f848ad 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -88,6 +88,9 @@ jobs: # The SDK setup exports the host core count via GITHUB_ENV. GERBIL_BUILD_CORES: '4' GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil + # Native gambuild-C contract, also used by Parser's compiler profile. + # Preserve tail calls and the release's optimization level. + CORCXXFLAGS_GAMBUILD: '-pipe -foptimize-sibling-calls -Wp,-U___SINGLE_HOST,-D___MULTIPLE_HOSTS -ftrack-macro-expansion=0' SOURCE_PREPARE_MINUTES: ${{ runner.os == 'macOS' && 18 || 12 }} run: | printf 'budget_minutes=%s\n' "$SOURCE_PREPARE_MINUTES" >> "$GITHUB_OUTPUT" diff --git a/Project.sysml b/Project.sysml index 3a172079..be729f01 100644 --- a/Project.sysml +++ b/Project.sysml @@ -257,6 +257,10 @@ package WeaverProject { CI only selects the watchdog and invokes the package manager. Native stdout/stderr line buffering exposes package boundaries as they occur; buffered batches do not establish phase durations. + Dependency compilation uses gambuild-C's native host flags, + matching Parser's separate C procedure policy for both macro + and runtime phases. Retain release optimization and tail calls; + qualify unchanged workloads and limits before accepting it. Dependency preparation defaults to four workers, with a twelve-minute watchdog on Linux and eighteen minutes on macOS. Record the selected watchdog and its exit code in the job receipt. From 6453b674f3f1bfe98a41e2ebc33d2168ef85319d Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 22:33:26 +0800 Subject: [PATCH 088/105] ci: measure native package CPU work and compiler commands --- .github/workflows/verify-suite.yml | 3 ++- Project.sysml | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index f1f848ad..bc7d1f9f 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -91,11 +91,12 @@ jobs: # Native gambuild-C contract, also used by Parser's compiler profile. # Preserve tail calls and the release's optimization level. CORCXXFLAGS_GAMBUILD: '-pipe -foptimize-sibling-calls -Wp,-U___SINGLE_HOST,-D___MULTIPLE_HOSTS -ftrack-macro-expansion=0' + GAMBUILD_VERBOSE: '1' SOURCE_PREPARE_MINUTES: ${{ runner.os == 'macOS' && 18 || 12 }} run: | printf 'budget_minutes=%s\n' "$SOURCE_PREPARE_MINUTES" >> "$GITHUB_OUTPUT" dependency_exit_code=0 - timeout --verbose --kill-after=5s "${SOURCE_PREPARE_MINUTES}m" gerbil -:1n,2n deps --install || dependency_exit_code=$? + /usr/bin/time -p timeout --verbose --kill-after=5s "${SOURCE_PREPARE_MINUTES}m" gerbil -:1n,2n deps --install || dependency_exit_code=$? printf 'exit_code=%s\n' "$dependency_exit_code" >> "$GITHUB_OUTPUT" exit "$dependency_exit_code" - name: Verify declared suite diff --git a/Project.sysml b/Project.sysml index be729f01..d9075ea3 100644 --- a/Project.sysml +++ b/Project.sysml @@ -261,6 +261,8 @@ package WeaverProject { matching Parser's separate C procedure policy for both macro and runtime phases. Retain release optimization and tail calls; qualify unchanged workloads and limits before accepting it. + Native compiler command diagnostics and POSIX real/user/sys + totals distinguish configured flags and CPU work from wall time. Dependency preparation defaults to four workers, with a twelve-minute watchdog on Linux and eighteen minutes on macOS. Record the selected watchdog and its exit code in the job receipt. From 1d85224971b39baf88131a063183eb4b963c81f9 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 23:04:19 +0800 Subject: [PATCH 089/105] fix(ci): consume native parallel Scheme package tooling --- .github/workflows/verify-suite.yml | 2 +- Cargo.lock | 10 +++++----- Cargo.toml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index bc7d1f9f..b43d4fc6 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -67,7 +67,7 @@ jobs: id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-policy", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 - uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@9029ac9d9bb680b13b2976d614965daf8b0d7d50 + uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7 with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog diff --git a/Cargo.lock b/Cargo.lock index 51938e53..cbe53bae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "gerbil-scheme" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9029ac9d9bb680b13b2976d614965daf8b0d7d50#9029ac9d9bb680b13b2976d614965daf8b0d7d50" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7#3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7" dependencies = [ "gerbil-scheme-rust-project-harness-policy", "gerbil-scheme-sys", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-aot-build" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9029ac9d9bb680b13b2976d614965daf8b0d7d50#9029ac9d9bb680b13b2976d614965daf8b0d7d50" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7#3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7" dependencies = [ "cbindgen", "cc", @@ -1822,7 +1822,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness" version = "0.1.2" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9029ac9d9bb680b13b2976d614965daf8b0d7d50#9029ac9d9bb680b13b2976d614965daf8b0d7d50" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7#3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7" dependencies = [ "cargo-lock", "cargo_toml", @@ -1840,7 +1840,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness-policy" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9029ac9d9bb680b13b2976d614965daf8b0d7d50#9029ac9d9bb680b13b2976d614965daf8b0d7d50" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7#3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7" dependencies = [ "gerbil-scheme-rust-project-harness", ] @@ -1848,7 +1848,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-sys" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9029ac9d9bb680b13b2976d614965daf8b0d7d50#9029ac9d9bb680b13b2976d614965daf8b0d7d50" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7#3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7" dependencies = [ "gerbil-scheme-aot-build", "gerbil-scheme-rust-project-harness-policy", diff --git a/Cargo.toml b/Cargo.toml index d11dc0b0..d161cbc6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,9 @@ arrow-array = "58.4.0" arrow-schema = "58.4.0" arrow-ipc = "58.4.0" criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } -gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "9029ac9d9bb680b13b2976d614965daf8b0d7d50" } -gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "9029ac9d9bb680b13b2976d614965daf8b0d7d50" } -gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "9029ac9d9bb680b13b2976d614965daf8b0d7d50", features = ["external-program"] } +gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7" } +gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7" } +gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7", features = ["external-program"] } asp-rust = { git = "https://github.com/tao3k/asp-rust", rev = "1ca41124b846dec947f3d05119cafa07eaa57924", default-features = false } From b8adf195699a287c1a2fa658880ae97558e8c3e4 Mon Sep 17 00:00:00 2001 From: guangtao Date: Sun, 8 Nov 2026 23:37:16 +0800 Subject: [PATCH 090/105] ci: calibrate full Scheme dependencies independently --- .github/workflows/verify-suite.yml | 16 ++++++++++------ Cargo.lock | 10 +++++----- Cargo.toml | 6 +++--- Project.sysml | 10 +++++++--- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index b43d4fc6..17024db5 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -67,7 +67,7 @@ jobs: id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-policy", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 - uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7 + uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@deca3571a46fc66ac76a044a6b173c67cf24029e with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog @@ -83,21 +83,23 @@ jobs: id: scheme_dependencies if: inputs.suite == 'check-scheme' # Leave time after either native watchdog for its exit receipt. - timeout-minutes: 19 + timeout-minutes: 21 env: - # The SDK setup exports the host core count via GITHUB_ENV. + # Fix the dependency worker budget before the package manager starts. GERBIL_BUILD_CORES: '4' GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil # Native gambuild-C contract, also used by Parser's compiler profile. # Preserve tail calls and the release's optimization level. CORCXXFLAGS_GAMBUILD: '-pipe -foptimize-sibling-calls -Wp,-U___SINGLE_HOST,-D___MULTIPLE_HOSTS -ftrack-macro-expansion=0' GAMBUILD_VERBOSE: '1' - SOURCE_PREPARE_MINUTES: ${{ runner.os == 'macOS' && 18 || 12 }} + # Calibrate the full Linux dependency closure separately from runtime. + SOURCE_PREPARE_MINUTES: ${{ runner.os == 'macOS' && 18 || 20 }} run: | - printf 'budget_minutes=%s\n' "$SOURCE_PREPARE_MINUTES" >> "$GITHUB_OUTPUT" + printf 'budget_minutes=%s\nbuild_cores=%s\n' "$SOURCE_PREPARE_MINUTES" "$GERBIL_BUILD_CORES" >> "$GITHUB_OUTPUT" + dependency_started=$SECONDS dependency_exit_code=0 /usr/bin/time -p timeout --verbose --kill-after=5s "${SOURCE_PREPARE_MINUTES}m" gerbil -:1n,2n deps --install || dependency_exit_code=$? - printf 'exit_code=%s\n' "$dependency_exit_code" >> "$GITHUB_OUTPUT" + printf 'exit_code=%s\nelapsed_seconds=%s\n' "$dependency_exit_code" "$((SECONDS - dependency_started))" >> "$GITHUB_OUTPUT" exit "$dependency_exit_code" - name: Verify declared suite id: verify_suite @@ -140,6 +142,8 @@ jobs: "arch": ${{ toJSON(runner.arch) }}, "status": ${{ toJSON(job.status) }}, "schemeDependencyBudgetMinutes": ${{ steps.scheme_dependencies.outputs.budget_minutes || 'null' }}, + "schemeDependencyBuildCores": ${{ steps.scheme_dependencies.outputs.build_cores || 'null' }}, + "schemeDependencyElapsedSeconds": ${{ steps.scheme_dependencies.outputs.elapsed_seconds || 'null' }}, "schemeDependencyExitCode": ${{ steps.scheme_dependencies.outputs.exit_code || 'null' }}, "phases": { "checkout": ${{ toJSON(steps.checkout.outcome || 'skipped') }}, diff --git a/Cargo.lock b/Cargo.lock index cbe53bae..8106217d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "gerbil-scheme" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7#3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=deca3571a46fc66ac76a044a6b173c67cf24029e#deca3571a46fc66ac76a044a6b173c67cf24029e" dependencies = [ "gerbil-scheme-rust-project-harness-policy", "gerbil-scheme-sys", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-aot-build" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7#3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=deca3571a46fc66ac76a044a6b173c67cf24029e#deca3571a46fc66ac76a044a6b173c67cf24029e" dependencies = [ "cbindgen", "cc", @@ -1822,7 +1822,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness" version = "0.1.2" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7#3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=deca3571a46fc66ac76a044a6b173c67cf24029e#deca3571a46fc66ac76a044a6b173c67cf24029e" dependencies = [ "cargo-lock", "cargo_toml", @@ -1840,7 +1840,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness-policy" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7#3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=deca3571a46fc66ac76a044a6b173c67cf24029e#deca3571a46fc66ac76a044a6b173c67cf24029e" dependencies = [ "gerbil-scheme-rust-project-harness", ] @@ -1848,7 +1848,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-sys" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7#3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=deca3571a46fc66ac76a044a6b173c67cf24029e#deca3571a46fc66ac76a044a6b173c67cf24029e" dependencies = [ "gerbil-scheme-aot-build", "gerbil-scheme-rust-project-harness-policy", diff --git a/Cargo.toml b/Cargo.toml index d161cbc6..0bfe1bc7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,9 @@ arrow-array = "58.4.0" arrow-schema = "58.4.0" arrow-ipc = "58.4.0" criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } -gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7" } -gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7" } -gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "3ccd4ccf6db52f1cac8522a96a0dd510fb69afc7", features = ["external-program"] } +gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "deca3571a46fc66ac76a044a6b173c67cf24029e" } +gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "deca3571a46fc66ac76a044a6b173c67cf24029e" } +gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "deca3571a46fc66ac76a044a6b173c67cf24029e", features = ["external-program"] } asp-rust = { git = "https://github.com/tao3k/asp-rust", rev = "1ca41124b846dec947f3d05119cafa07eaa57924", default-features = false } diff --git a/Project.sysml b/Project.sysml index d9075ea3..943c67a8 100644 --- a/Project.sysml +++ b/Project.sysml @@ -263,9 +263,13 @@ package WeaverProject { qualify unchanged workloads and limits before accepting it. Native compiler command diagnostics and POSIX real/user/sys totals distinguish configured flags and CPU work from wall time. - Dependency preparation defaults to four workers, with a - twelve-minute watchdog on Linux and eighteen minutes on macOS. - Record the selected watchdog and its exit code in the job receipt. + Dependency preparation uses four workers. Calibrate the full + Linux dependency cold preparation within a twenty-minute cap; + retain prior twelve-minute timeouts as failed evidence. macOS + keeps its eighteen-minute watchdog. This independent preparation + cap does not relax target selection, the cold linked archive, + recovery or natural-exit gates. Record worker count, elapsed + whole seconds, the selected cap and exit code in the job receipt. Run the selected package Build with a separate two-minute bound. Retain SDK archive milestones and native Go failure events with their stage receipts. The provider recovery and natural-exit From 4d679382d45cba9fb614e554397bebb78823fd22 Mon Sep 17 00:00:00 2001 From: guangtao Date: Mon, 9 Nov 2026 00:10:04 +0800 Subject: [PATCH 091/105] ci: observe full native dependency preparation without a phase cutoff --- .github/workflows/verify-suite.yml | 12 +++++------- Project.sysml | 16 +++++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 17024db5..e5785528 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -82,8 +82,7 @@ jobs: - name: Install declared Scheme dependencies id: scheme_dependencies if: inputs.suite == 'check-scheme' - # Leave time after either native watchdog for its exit receipt. - timeout-minutes: 21 + # Observe complete cold preparation under the whole-job watchdog. env: # Fix the dependency worker budget before the package manager starts. GERBIL_BUILD_CORES: '4' @@ -92,13 +91,12 @@ jobs: # Preserve tail calls and the release's optimization level. CORCXXFLAGS_GAMBUILD: '-pipe -foptimize-sibling-calls -Wp,-U___SINGLE_HOST,-D___MULTIPLE_HOSTS -ftrack-macro-expansion=0' GAMBUILD_VERBOSE: '1' - # Calibrate the full Linux dependency closure separately from runtime. - SOURCE_PREPARE_MINUTES: ${{ runner.os == 'macOS' && 18 || 20 }} run: | - printf 'budget_minutes=%s\nbuild_cores=%s\n' "$SOURCE_PREPARE_MINUTES" "$GERBIL_BUILD_CORES" >> "$GITHUB_OUTPUT" + printf 'build_cores=%s\n' "$GERBIL_BUILD_CORES" >> "$GITHUB_OUTPUT" + export GAMBOPT="${GAMBOPT:+$GAMBOPT,}debug=q5" dependency_started=$SECONDS dependency_exit_code=0 - /usr/bin/time -p timeout --verbose --kill-after=5s "${SOURCE_PREPARE_MINUTES}m" gerbil -:1n,2n deps --install || dependency_exit_code=$? + /usr/bin/time -p gerbil -:1n,2n deps --install || dependency_exit_code=$? printf 'exit_code=%s\nelapsed_seconds=%s\n' "$dependency_exit_code" "$((SECONDS - dependency_started))" >> "$GITHUB_OUTPUT" exit "$dependency_exit_code" - name: Verify declared suite @@ -141,7 +139,7 @@ jobs: "os": ${{ toJSON(runner.os) }}, "arch": ${{ toJSON(runner.arch) }}, "status": ${{ toJSON(job.status) }}, - "schemeDependencyBudgetMinutes": ${{ steps.scheme_dependencies.outputs.budget_minutes || 'null' }}, + "schemeDependencyBudgetMinutes": null, "schemeDependencyBuildCores": ${{ steps.scheme_dependencies.outputs.build_cores || 'null' }}, "schemeDependencyElapsedSeconds": ${{ steps.scheme_dependencies.outputs.elapsed_seconds || 'null' }}, "schemeDependencyExitCode": ${{ steps.scheme_dependencies.outputs.exit_code || 'null' }}, diff --git a/Project.sysml b/Project.sysml index 943c67a8..d7237641 100644 --- a/Project.sysml +++ b/Project.sysml @@ -263,13 +263,15 @@ package WeaverProject { qualify unchanged workloads and limits before accepting it. Native compiler command diagnostics and POSIX real/user/sys totals distinguish configured flags and CPU work from wall time. - Dependency preparation uses four workers. Calibrate the full - Linux dependency cold preparation within a twenty-minute cap; - retain prior twelve-minute timeouts as failed evidence. macOS - keeps its eighteen-minute watchdog. This independent preparation - cap does not relax target selection, the cold linked archive, - recovery or natural-exit gates. Record worker count, elapsed - whole seconds, the selected cap and exit code in the job receipt. + Dependency preparation uses four workers. Observe full dependency + cold preparation under the existing whole-job watchdog, without + an independent installation cutoff. Retain prior installation + timeouts as failed evidence. Native GC reports expose allocation + and heap progress during indexing; completion still requires the + package manager to exit successfully. This observation does not + relax target selection, the cold linked archive, recovery or + natural-exit gates. Record worker count, elapsed whole seconds + and exit code in the job receipt; the independent cap is null. Run the selected package Build with a separate two-minute bound. Retain SDK archive milestones and native Go failure events with their stage receipts. The provider recovery and natural-exit From 7bafd3d708174943e74a817cfdc9fccac9e51ed1 Mon Sep 17 00:00:00 2001 From: guangtao Date: Mon, 9 Nov 2026 01:21:06 +0800 Subject: [PATCH 092/105] Reserve complete Scheme qualification time after dependency preparation --- .github/workflows/verify-suite.yml | 5 +++-- Project.sysml | 7 +++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index e5785528..9452d06a 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -24,8 +24,9 @@ jobs: verify: name: ${{ inputs.label }} runs-on: ${{ inputs.runner }} - # Keep time for the receipt upload after a phase hits its own limit. - timeout-minutes: 65 + # Full dependency preparation has no phase cutoff. Reserve room for the + # unchanged 37-minute Scheme suite and receipt upload after preparation. + timeout-minutes: ${{ inputs.suite == 'check-scheme' && 120 || 65 }} env: GOTOOLCHAIN: local WEAVER_VERIFY_SUITE: ${{ inputs.suite }} diff --git a/Project.sysml b/Project.sysml index d7237641..2bd68d1f 100644 --- a/Project.sysml +++ b/Project.sysml @@ -264,8 +264,11 @@ package WeaverProject { Native compiler command diagnostics and POSIX real/user/sys totals distinguish configured flags and CPU work from wall time. Dependency preparation uses four workers. Observe full dependency - cold preparation under the existing whole-job watchdog, without - an independent installation cutoff. Retain prior installation + cold preparation without an independent installation cutoff. + The Scheme job has a 120-minute infrastructure watchdog so full + preparation does not consume the separate 37-minute suite window; + other verification jobs retain their 65-minute watchdog. + Retain prior installation timeouts as failed evidence. Native GC reports expose allocation and heap progress during indexing; completion still requires the package manager to exit successfully. This observation does not From 5e7b9a5c0eae7090248d9e03f39dc52c0eccb0c1 Mon Sep 17 00:00:00 2001 From: guangtao Date: Mon, 9 Nov 2026 01:49:04 +0800 Subject: [PATCH 093/105] Reduce cold Scheme build serialization and Rust debug data --- .github/workflows/verify-suite.yml | 2 +- Cargo.lock | 10 +++++----- Cargo.toml | 8 +++++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 9452d06a..ad989659 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -68,7 +68,7 @@ jobs: id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-policy", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 - uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@deca3571a46fc66ac76a044a6b173c67cf24029e + uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@56f0d82c061b3d459a0ea15002249654e01853b5 with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog diff --git a/Cargo.lock b/Cargo.lock index 8106217d..ba5f1210 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "gerbil-scheme" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=deca3571a46fc66ac76a044a6b173c67cf24029e#deca3571a46fc66ac76a044a6b173c67cf24029e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=56f0d82c061b3d459a0ea15002249654e01853b5#56f0d82c061b3d459a0ea15002249654e01853b5" dependencies = [ "gerbil-scheme-rust-project-harness-policy", "gerbil-scheme-sys", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-aot-build" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=deca3571a46fc66ac76a044a6b173c67cf24029e#deca3571a46fc66ac76a044a6b173c67cf24029e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=56f0d82c061b3d459a0ea15002249654e01853b5#56f0d82c061b3d459a0ea15002249654e01853b5" dependencies = [ "cbindgen", "cc", @@ -1822,7 +1822,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness" version = "0.1.2" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=deca3571a46fc66ac76a044a6b173c67cf24029e#deca3571a46fc66ac76a044a6b173c67cf24029e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=56f0d82c061b3d459a0ea15002249654e01853b5#56f0d82c061b3d459a0ea15002249654e01853b5" dependencies = [ "cargo-lock", "cargo_toml", @@ -1840,7 +1840,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness-policy" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=deca3571a46fc66ac76a044a6b173c67cf24029e#deca3571a46fc66ac76a044a6b173c67cf24029e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=56f0d82c061b3d459a0ea15002249654e01853b5#56f0d82c061b3d459a0ea15002249654e01853b5" dependencies = [ "gerbil-scheme-rust-project-harness", ] @@ -1848,7 +1848,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-sys" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=deca3571a46fc66ac76a044a6b173c67cf24029e#deca3571a46fc66ac76a044a6b173c67cf24029e" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=56f0d82c061b3d459a0ea15002249654e01853b5#56f0d82c061b3d459a0ea15002249654e01853b5" dependencies = [ "gerbil-scheme-aot-build", "gerbil-scheme-rust-project-harness-policy", diff --git a/Cargo.toml b/Cargo.toml index 0bfe1bc7..f0348263 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,9 @@ arrow-array = "58.4.0" arrow-schema = "58.4.0" arrow-ipc = "58.4.0" criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } -gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "deca3571a46fc66ac76a044a6b173c67cf24029e" } -gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "deca3571a46fc66ac76a044a6b173c67cf24029e" } -gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "deca3571a46fc66ac76a044a6b173c67cf24029e", features = ["external-program"] } +gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "56f0d82c061b3d459a0ea15002249654e01853b5" } +gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "56f0d82c061b3d459a0ea15002249654e01853b5" } +gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "56f0d82c061b3d459a0ea15002249654e01853b5", features = ["external-program"] } asp-rust = { git = "https://github.com/tao3k/asp-rust", rev = "1ca41124b846dec947f3d05119cafa07eaa57924", default-features = false } @@ -82,6 +82,8 @@ unimplemented = "deny" [profile.dev] opt-level = 1 incremental = true +# Keep filename/line backtraces without full type and local-variable debug data. +debug = "line-tables-only" # Keep locked dependency compilation within the cold development build budget. [profile.dev.package."*"] From 5dd8693cee6ae7cfe89446a90b78eebcccafbf6c Mon Sep 17 00:00:00 2001 From: guangtao Date: Mon, 9 Nov 2026 04:06:57 +0800 Subject: [PATCH 094/105] Capture native owner signal stacks after failed qualification --- .../prepare-toolchain/native-owner.gdb | 24 +++++++++++++++++++ .github/workflows/verify-suite.yml | 14 +++++++++++ Project.sysml | 7 +++++- go/internal/devrunner/ci.go | 3 +++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 .github/actions/prepare-toolchain/native-owner.gdb diff --git a/.github/actions/prepare-toolchain/native-owner.gdb b/.github/actions/prepare-toolchain/native-owner.gdb new file mode 100644 index 00000000..5146d286 --- /dev/null +++ b/.github/actions/prepare-toolchain/native-owner.gdb @@ -0,0 +1,24 @@ +# Failure-only observation. Pass every signal through to the unchanged process. +set pagination off +set confirm off +set debuginfod enabled off +set print frame-arguments none +set follow-fork-mode parent +handle all nostop noprint pass +handle SIGPIPE stop print pass +set $weaver_sigpipe_events = 0 +catch signal SIGPIPE +commands + silent + set $weaver_sigpipe_events = $weaver_sigpipe_events + 1 + if $weaver_sigpipe_events <= 16 + printf "WEAVER-NATIVE-SIGPIPE event=%d\n", $weaver_sigpipe_events + thread + bt 24 + if $weaver_sigpipe_events == 1 + thread apply all bt 24 + end + end + continue +end +run diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index ad989659..dbef48a7 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -115,6 +115,19 @@ jobs: GERBIL_GXI: ${{ env.GERBIL_PREFIX }}/bin/gxi GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil run: go -C go run ./cmd/weaver-dev -clean-source -timeout 35m check-scheme + - name: Diagnose failed native Scheme owner without rebuilding + id: scheme_native_diagnostic + if: failure() && inputs.suite == 'check-scheme' && runner.os == 'Linux' && steps.verify_scheme.conclusion == 'failure' + timeout-minutes: 4 + env: + GERBIL_GXI: ${{ env.GERBIL_PREFIX }}/bin/gxi + GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil + CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: gdb --batch --return-child-result -x ${{ github.workspace }}/.github/actions/prepare-toolchain/native-owner.gdb --args + run: | + if ! jq -e 'any(.stages[]; .name == "scheme-rooted-sdk-integration" and .status == "FAIL")' .cache/verification/latest-check-scheme.json > /dev/null; then + exit 0 + fi + cargo test -p weaver-governance -p weaver-governance-build -p weaver-server --features weaver-governance/scheme-qualification,weaver-server/governance-qualification,weaver-server/arrow --locked --offline -j 4 --test governance_owner -- --exact actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain --nocapture --test-threads=4 - name: Require successful phase receipts id: receipt_check timeout-minutes: 1 @@ -155,6 +168,7 @@ jobs: "schemeDependencies": ${{ toJSON(steps.scheme_dependencies.outcome || 'skipped') }}, "verifySuite": ${{ toJSON(steps.verify_suite.outcome || 'skipped') }}, "verifyScheme": ${{ toJSON(steps.verify_scheme.outcome || 'skipped') }}, + "schemeNativeDiagnostic": ${{ toJSON(steps.scheme_native_diagnostic.outcome || 'skipped') }}, "receiptCheck": ${{ toJSON(steps.receipt_check.outcome || 'skipped') }} } } diff --git a/Project.sysml b/Project.sysml index 2bd68d1f..e2fc5f95 100644 --- a/Project.sysml +++ b/Project.sysml @@ -278,7 +278,11 @@ package WeaverProject { Run the selected package Build with a separate two-minute bound. Retain SDK archive milestones and native Go failure events with their stage receipts. The provider recovery and natural-exit - deadlines govern runtime. */ + deadlines govern runtime. After a Linux rooted SDK integration + failure only, observe the already-built owner test once through + Cargo's native GDB runner, bounded to four minutes. Pass signals + through unchanged and bound stack output. This diagnostic cannot + replace the failed suite receipt or qualify recovery deadlines. */ } part architecture : VerificationSuite { part 'check-architecture' : VerificationMode; } part policy : VerificationSuite { @@ -543,6 +547,7 @@ package WeaverProject { part '.github/workflows/ci.yml' : File; part '.github/workflows/verify-suite.yml' : File; part '.github/actions/prepare-toolchain/action.yml' : File; + part '.github/actions/prepare-toolchain/native-owner.gdb' : File; part 'scheme/policy/cedar-ffi.ss' : File; part 'docs/50-59-research-program/59-provider-rpc/59.24-telemetry-service.org' : File; part 'docs/50-59-research-program/59-provider-rpc/59.25-openshell-and-tao3k-ecosystem.org' : File; diff --git a/go/internal/devrunner/ci.go b/go/internal/devrunner/ci.go index cabbd5a0..53ff7053 100644 --- a/go/internal/devrunner/ci.go +++ b/go/internal/devrunner/ci.go @@ -51,6 +51,9 @@ func PrepareCITools(ctx context.Context, output io.Writer) error { return err } packages := []string{"apt-get", "install", "-y", "--no-install-recommends", "build-essential", "ca-certificates", "pkg-config", "libssl-dev", "zlib1g-dev", "protobuf-compiler"} + if suite == "check-scheme" { + packages = append(packages, "gdb", "jq") + } if suite == "check-policy" { packages = append(packages, "elan", "cvc5", "zstd") } From 0de0f3eb1d3cc706192413925ab1f57465e3e8a2 Mon Sep 17 00:00:00 2001 From: guangtao Date: Mon, 9 Nov 2026 04:14:12 +0800 Subject: [PATCH 095/105] Declare licensing for native owner debugger commands --- .github/actions/prepare-toolchain/native-owner.gdb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/actions/prepare-toolchain/native-owner.gdb b/.github/actions/prepare-toolchain/native-owner.gdb index 5146d286..7741664d 100644 --- a/.github/actions/prepare-toolchain/native-owner.gdb +++ b/.github/actions/prepare-toolchain/native-owner.gdb @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +# +# SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + # Failure-only observation. Pass every signal through to the unchanged process. set pagination off set confirm off From 3988eeff56c57e12fbe6ce8d5b19349c8272dc61 Mon Sep 17 00:00:00 2001 From: guangtao Date: Mon, 9 Nov 2026 04:17:05 +0800 Subject: [PATCH 096/105] Diagnose only the existing native owner executable --- .github/workflows/verify-suite.yml | 10 ++++++++-- Project.sysml | 6 ++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index dbef48a7..6e1ce592 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -122,12 +122,18 @@ jobs: env: GERBIL_GXI: ${{ env.GERBIL_PREFIX }}/bin/gxi GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil - CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: gdb --batch --return-child-result -x ${{ github.workspace }}/.github/actions/prepare-toolchain/native-owner.gdb --args + GOCACHE: ${{ github.workspace }}/.cache/go-build-cache + GOMODCACHE: ${{ github.workspace }}/.cache/go-mod-cache run: | if ! jq -e 'any(.stages[]; .name == "scheme-rooted-sdk-integration" and .status == "FAIL")' .cache/verification/latest-check-scheme.json > /dev/null; then exit 0 fi - cargo test -p weaver-governance -p weaver-governance-build -p weaver-server --features weaver-governance/scheme-qualification,weaver-server/governance-qualification,weaver-server/arrow --locked --offline -j 4 --test governance_owner -- --exact actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain --nocapture --test-threads=4 + owners=() + for candidate in target/debug/deps/governance_owner-*; do + if [[ -f "$candidate" && -x "$candidate" ]]; then owners+=("$candidate"); fi + done + test "${#owners[@]}" -eq 1 + gdb --batch --return-child-result -x .github/actions/prepare-toolchain/native-owner.gdb --args "${owners[0]}" --exact actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain --nocapture --test-threads=4 - name: Require successful phase receipts id: receipt_check timeout-minutes: 1 diff --git a/Project.sysml b/Project.sysml index e2fc5f95..99a93d85 100644 --- a/Project.sysml +++ b/Project.sysml @@ -280,8 +280,10 @@ package WeaverProject { with their stage receipts. The provider recovery and natural-exit deadlines govern runtime. After a Linux rooted SDK integration failure only, observe the already-built owner test once through - Cargo's native GDB runner, bounded to four minutes. Pass signals - through unchanged and bound stack output. This diagnostic cannot + native GDB, bounded to four minutes. Require exactly one built + executable for this target; reject missing or ambiguous images. + Do not invoke Cargo after the private build environment retires. + Pass signals through unchanged and bound stack output. This diagnostic cannot replace the failed suite receipt or qualify recovery deadlines. */ } part architecture : VerificationSuite { part 'check-architecture' : VerificationMode; } From 6dbcd4fdc1f15d5b7187445b1b7eff122b793b34 Mon Sep 17 00:00:00 2001 From: guangtao Date: Mon, 9 Nov 2026 07:51:33 +0800 Subject: [PATCH 097/105] Use SDK-owned Gambit cleanup scope for native governance --- .github/workflows/verify-suite.yml | 2 +- Cargo.lock | 11 ++++++----- Cargo.toml | 6 +++--- Project.sysml | 4 ++++ dev/sysml/ControlActivation.sysml | 7 ++++++- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 6e1ce592..8a0052d7 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -68,7 +68,7 @@ jobs: id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-policy", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 - uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@56f0d82c061b3d459a0ea15002249654e01853b5 + uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@9aa4de6adc1f566f78586b046ba9452c1e996d7b with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog diff --git a/Cargo.lock b/Cargo.lock index ba5f1210..1e243b35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "gerbil-scheme" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=56f0d82c061b3d459a0ea15002249654e01853b5#56f0d82c061b3d459a0ea15002249654e01853b5" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9aa4de6adc1f566f78586b046ba9452c1e996d7b#9aa4de6adc1f566f78586b046ba9452c1e996d7b" dependencies = [ "gerbil-scheme-rust-project-harness-policy", "gerbil-scheme-sys", @@ -1808,11 +1808,12 @@ dependencies = [ [[package]] name = "gerbil-scheme-aot-build" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=56f0d82c061b3d459a0ea15002249654e01853b5#56f0d82c061b3d459a0ea15002249654e01853b5" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9aa4de6adc1f566f78586b046ba9452c1e996d7b#9aa4de6adc1f566f78586b046ba9452c1e996d7b" dependencies = [ "cbindgen", "cc", "gerbil-scheme-rust-project-harness-policy", + "object", "serde", "serde_json", "sha2 0.10.9", @@ -1822,7 +1823,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness" version = "0.1.2" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=56f0d82c061b3d459a0ea15002249654e01853b5#56f0d82c061b3d459a0ea15002249654e01853b5" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9aa4de6adc1f566f78586b046ba9452c1e996d7b#9aa4de6adc1f566f78586b046ba9452c1e996d7b" dependencies = [ "cargo-lock", "cargo_toml", @@ -1840,7 +1841,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness-policy" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=56f0d82c061b3d459a0ea15002249654e01853b5#56f0d82c061b3d459a0ea15002249654e01853b5" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9aa4de6adc1f566f78586b046ba9452c1e996d7b#9aa4de6adc1f566f78586b046ba9452c1e996d7b" dependencies = [ "gerbil-scheme-rust-project-harness", ] @@ -1848,7 +1849,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-sys" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=56f0d82c061b3d459a0ea15002249654e01853b5#56f0d82c061b3d459a0ea15002249654e01853b5" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9aa4de6adc1f566f78586b046ba9452c1e996d7b#9aa4de6adc1f566f78586b046ba9452c1e996d7b" dependencies = [ "gerbil-scheme-aot-build", "gerbil-scheme-rust-project-harness-policy", diff --git a/Cargo.toml b/Cargo.toml index f0348263..3d79bce8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,9 @@ arrow-array = "58.4.0" arrow-schema = "58.4.0" arrow-ipc = "58.4.0" criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } -gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "56f0d82c061b3d459a0ea15002249654e01853b5" } -gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "56f0d82c061b3d459a0ea15002249654e01853b5" } -gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "56f0d82c061b3d459a0ea15002249654e01853b5", features = ["external-program"] } +gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "9aa4de6adc1f566f78586b046ba9452c1e996d7b" } +gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "9aa4de6adc1f566f78586b046ba9452c1e996d7b" } +gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "9aa4de6adc1f566f78586b046ba9452c1e996d7b", features = ["external-program"] } asp-rust = { git = "https://github.com/tao3k/asp-rust", rev = "1ca41124b846dec947f3d05119cafa07eaa57924", default-features = false } diff --git a/Project.sysml b/Project.sysml index 99a93d85..1bcb5dd8 100644 --- a/Project.sysml +++ b/Project.sysml @@ -729,6 +729,10 @@ package WeaverProject { Approved compiler factories construct non-Send Scheme VMs on its tracked blocking worker. Terminal shutdown closes source delivery; drain waits for natural factory/call return and VM cleanup. + Compiler teardown may overlap host Tokio/TLS writes. The SDK + cleanup boundary preserves process-wide host SIGPIPE disposition + throughout that overlap; an owner-only signal mask is insufficient. + The SDK archive owns the scoped binding to the paired Gambit ABI. One compiler owner is installed for this runtime incarnation; rejected duplicates cannot retire the current owner. This lifecycle run_from_env may install the compiled program and explicit startup diff --git a/dev/sysml/ControlActivation.sysml b/dev/sysml/ControlActivation.sysml index d52bf17a..bad8c65a 100644 --- a/dev/sysml/ControlActivation.sysml +++ b/dev/sysml/ControlActivation.sysml @@ -118,7 +118,12 @@ package ControlActivation { owner using an explicit host resource permit and source queue budget. The Send factory builds its non-Send compiler on the owner thread. Shared shutdown fences source delivery before returning, and shared - drain waits for natural VM cleanup. Abandoned or late initialization + drain waits for natural VM cleanup. Compiler teardown preserves + process-wide host SIGPIPE disposition while Tokio/TLS writes drain. + The SDK owns scoped SIGPIPE cleanup; host SIGPIPE updates retain + their original semantics. + Owner-local masking alone does not establish that process invariant. + Abandoned or late initialization cannot report activation after close. Embedding gRPC configuration failure still drains attached owners. Neither startup readiness nor resource cleanup is source admission, no-execution or budget evidence. */ From 144923a832c823da3008889199135211e53587bc Mon Sep 17 00:00:00 2001 From: guangtao Date: Mon, 9 Nov 2026 08:54:11 +0800 Subject: [PATCH 098/105] Run Scheme dependency preparation through the verification entrypoint --- .github/workflows/verify-suite.yml | 53 +++--------------------------- Project.sysml | 4 +++ go/cmd/weaver-dev/main.go | 2 +- go/internal/devrunner/ci.go | 3 -- go/internal/devrunner/plan.go | 2 ++ go/internal/devrunner/runner.go | 19 +++++++++-- 6 files changed, 28 insertions(+), 55 deletions(-) diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 8a0052d7..8b60263c 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -83,23 +83,9 @@ jobs: - name: Install declared Scheme dependencies id: scheme_dependencies if: inputs.suite == 'check-scheme' - # Observe complete cold preparation under the whole-job watchdog. env: - # Fix the dependency worker budget before the package manager starts. - GERBIL_BUILD_CORES: '4' GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil - # Native gambuild-C contract, also used by Parser's compiler profile. - # Preserve tail calls and the release's optimization level. - CORCXXFLAGS_GAMBUILD: '-pipe -foptimize-sibling-calls -Wp,-U___SINGLE_HOST,-D___MULTIPLE_HOSTS -ftrack-macro-expansion=0' - GAMBUILD_VERBOSE: '1' - run: | - printf 'build_cores=%s\n' "$GERBIL_BUILD_CORES" >> "$GITHUB_OUTPUT" - export GAMBOPT="${GAMBOPT:+$GAMBOPT,}debug=q5" - dependency_started=$SECONDS - dependency_exit_code=0 - /usr/bin/time -p gerbil -:1n,2n deps --install || dependency_exit_code=$? - printf 'exit_code=%s\nelapsed_seconds=%s\n' "$dependency_exit_code" "$((SECONDS - dependency_started))" >> "$GITHUB_OUTPUT" - exit "$dependency_exit_code" + run: go -C go run ./cmd/weaver-dev -clean-source bootstrap-scheme - name: Verify declared suite id: verify_suite if: inputs.suite != 'check-scheme' @@ -115,34 +101,6 @@ jobs: GERBIL_GXI: ${{ env.GERBIL_PREFIX }}/bin/gxi GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil run: go -C go run ./cmd/weaver-dev -clean-source -timeout 35m check-scheme - - name: Diagnose failed native Scheme owner without rebuilding - id: scheme_native_diagnostic - if: failure() && inputs.suite == 'check-scheme' && runner.os == 'Linux' && steps.verify_scheme.conclusion == 'failure' - timeout-minutes: 4 - env: - GERBIL_GXI: ${{ env.GERBIL_PREFIX }}/bin/gxi - GERBIL_PATH: ${{ runner.temp }}/weaver-gerbil - GOCACHE: ${{ github.workspace }}/.cache/go-build-cache - GOMODCACHE: ${{ github.workspace }}/.cache/go-mod-cache - run: | - if ! jq -e 'any(.stages[]; .name == "scheme-rooted-sdk-integration" and .status == "FAIL")' .cache/verification/latest-check-scheme.json > /dev/null; then - exit 0 - fi - owners=() - for candidate in target/debug/deps/governance_owner-*; do - if [[ -f "$candidate" && -x "$candidate" ]]; then owners+=("$candidate"); fi - done - test "${#owners[@]}" -eq 1 - gdb --batch --return-child-result -x .github/actions/prepare-toolchain/native-owner.gdb --args "${owners[0]}" --exact actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain --nocapture --test-threads=4 - - name: Require successful phase receipts - id: receipt_check - timeout-minutes: 1 - run: | - test -s .cache/verification/latest-bootstrap-build.json - test -s ".cache/verification/latest-$WEAVER_VERIFY_SUITE.json" - if [ "$WEAVER_VERIFY_SUITE" = check-policy ]; then - test -s .cache/verification/latest-bootstrap-proofs.json - fi - name: Write verification job receipt if: always() timeout-minutes: 1 @@ -160,9 +118,7 @@ jobs: "arch": ${{ toJSON(runner.arch) }}, "status": ${{ toJSON(job.status) }}, "schemeDependencyBudgetMinutes": null, - "schemeDependencyBuildCores": ${{ steps.scheme_dependencies.outputs.build_cores || 'null' }}, - "schemeDependencyElapsedSeconds": ${{ steps.scheme_dependencies.outputs.elapsed_seconds || 'null' }}, - "schemeDependencyExitCode": ${{ steps.scheme_dependencies.outputs.exit_code || 'null' }}, + "schemeDependencyBuildCores": ${{ inputs.suite == 'check-scheme' && 4 || 'null' }}, "phases": { "checkout": ${{ toJSON(steps.checkout.outcome || 'skipped') }}, "source": ${{ toJSON(steps.source.outcome || 'skipped') }}, @@ -173,9 +129,7 @@ jobs: "schemeWatchdog": ${{ toJSON(steps.scheme_watchdog.outcome || 'skipped') }}, "schemeDependencies": ${{ toJSON(steps.scheme_dependencies.outcome || 'skipped') }}, "verifySuite": ${{ toJSON(steps.verify_suite.outcome || 'skipped') }}, - "verifyScheme": ${{ toJSON(steps.verify_scheme.outcome || 'skipped') }}, - "schemeNativeDiagnostic": ${{ toJSON(steps.scheme_native_diagnostic.outcome || 'skipped') }}, - "receiptCheck": ${{ toJSON(steps.receipt_check.outcome || 'skipped') }} + "verifyScheme": ${{ toJSON(steps.verify_scheme.outcome || 'skipped') }} } } run: | @@ -191,6 +145,7 @@ jobs: .cache/verification/ci-job.json .cache/verification/latest-bootstrap-build.json .cache/verification/latest-bootstrap-proofs.json + .cache/verification/latest-bootstrap-scheme.json .cache/verification/latest-${{ inputs.suite }}.json .cache/verification/spec/*/receipt.json include-hidden-files: true diff --git a/Project.sysml b/Project.sysml index 1bcb5dd8..57e1ef51 100644 --- a/Project.sysml +++ b/Project.sysml @@ -313,6 +313,10 @@ package WeaverProject { } part '.cache/verification/latest-bootstrap-build.json' : CIReceipt; part '.cache/verification/latest-bootstrap-proofs.json' : CIReceipt; + part '.cache/verification/latest-bootstrap-scheme.json' : CIReceipt { + doc /* Native Gerbil dependency preparation records its exit + and elapsed time separately from cold program verification. */ + } part '.cache/verification/latest-.json' : CIReceipt { doc /* weaver-dev owns suite receipts. Preserve committed input digests, stage status, exit, duration and output digest. diff --git a/go/cmd/weaver-dev/main.go b/go/cmd/weaver-dev/main.go index 8aaf3b99..4fe599bb 100644 --- a/go/cmd/weaver-dev/main.go +++ b/go/cmd/weaver-dev/main.go @@ -33,7 +33,7 @@ func run() error { return errors.New("-timeout must be nonnegative") } if flag.NArg() != 1 { - return errors.New("usage: weaver-dev [-go-bin PATH] [-clean-source] qualify-policy|bootstrap|bootstrap-build|bootstrap-proofs|check|check-rust|check-go|check-policy|check-architecture|check-scheme|check-storage|check-telemetry|bench|bench-runtime|bench-execution|render-diagrams|check-diagrams|generate-rpc|prepare-ci-host") + return errors.New("usage: weaver-dev [-go-bin PATH] [-clean-source] qualify-policy|bootstrap|bootstrap-build|bootstrap-proofs|bootstrap-scheme|check|check-rust|check-go|check-policy|check-architecture|check-scheme|check-storage|check-telemetry|bench|bench-runtime|bench-execution|render-diagrams|check-diagrams|generate-rpc|prepare-ci-host") } if flag.Arg(0) == "prepare-ci-host" { return devrunner.PrepareHostedCI(os.Stdout) diff --git a/go/internal/devrunner/ci.go b/go/internal/devrunner/ci.go index 53ff7053..cabbd5a0 100644 --- a/go/internal/devrunner/ci.go +++ b/go/internal/devrunner/ci.go @@ -51,9 +51,6 @@ func PrepareCITools(ctx context.Context, output io.Writer) error { return err } packages := []string{"apt-get", "install", "-y", "--no-install-recommends", "build-essential", "ca-certificates", "pkg-config", "libssl-dev", "zlib1g-dev", "protobuf-compiler"} - if suite == "check-scheme" { - packages = append(packages, "gdb", "jq") - } if suite == "check-policy" { packages = append(packages, "elan", "cvc5", "zstd") } diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index 04de1b8b..279e564e 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -200,6 +200,8 @@ func stagesForMode(mode, goBinary string) ([]Stage, error) { } } return append(selected, Stage{"storage-grpc-integration", goBinary, []string{"-C", "go", "test", "-count=1", "-race", "-tags=integration", "./dev", "-run", "^TestProvider", "-v"}}), nil + case "bootstrap-scheme": + return []Stage{{"scheme-dependencies", schemeTool(), []string{"-:1n,2n", "deps", "--install"}}}, nil case "bootstrap-build", "bootstrap-proofs": stages, err := stagesForMode("bootstrap", goBinary) if err != nil { diff --git a/go/internal/devrunner/runner.go b/go/internal/devrunner/runner.go index f1868303..6fd0527f 100644 --- a/go/internal/devrunner/runner.go +++ b/go/internal/devrunner/runner.go @@ -159,6 +159,16 @@ func Run(ctx context.Context, config Config, output io.Writer) (report string, r return directory, err } failed := false + if mode == "bootstrap-scheme" { + settings["GERBIL_BUILD_CORES"] = "4" + settings["CORCXXFLAGS_GAMBUILD"] = "-pipe -foptimize-sibling-calls -Wp,-U___SINGLE_HOST,-D___MULTIPLE_HOSTS -ftrack-macro-expansion=0" + settings["GAMBUILD_VERBOSE"] = "1" + settings["GAMBOPT"] = "debug=q5" + if inherited := os.Getenv("GAMBOPT"); inherited != "" { + settings["GAMBOPT"] = inherited + "," + settings["GAMBOPT"] + } + environment = Environment(settings) + } if mode == "check-scheme" || mode == "bench-runtime" { // These are Weaver's FFI link inputs and host resource policy, not // a Scheme package installer or SDK discovery layer. @@ -183,6 +193,8 @@ func Run(ctx context.Context, config Config, output io.Writer) (report string, r providerBuildFailure != "" { result = Result{Name: stage.Name, Status: "SKIP", Binary: stage.Binary, Args: stage.Args, Error: "required native build did not pass: " + providerBuildFailure} + } else if mode == "bootstrap-scheme" { + result = runStageObserved(ctx, root, directory, environment, stage, false, nil, output) } else { result = runStage(ctx, root, directory, environment, stage) } @@ -261,7 +273,7 @@ func runStage(ctx context.Context, root, directory string, environment []string, // The direct-file arm is retained solely for paired tests of the historical // output boundary. Both arms use the same public command and admission rules. func runStageCapture(ctx context.Context, root, directory string, environment []string, stage Stage, streamSchemeOutput bool) Result { - return runStageObserved(ctx, root, directory, environment, stage, streamSchemeOutput, nil) + return runStageObserved(ctx, root, directory, environment, stage, streamSchemeOutput, nil, nil) } // Package tests and the cold/hot build integration have separate budgets. @@ -272,7 +284,7 @@ const ( schemeProviderBuildTimeout = 8 * time.Minute ) -func runStageObserved(ctx context.Context, root, directory string, environment []string, stage Stage, streamSchemeOutput bool, onStart func(int)) Result { +func runStageObserved(ctx context.Context, root, directory string, environment []string, stage Stage, streamSchemeOutput bool, onStart func(int), live io.Writer) Result { tests := "" testTimeout := schemePackageTestTimeout deadline := time.Duration(0) @@ -319,6 +331,9 @@ func runStageObserved(ctx context.Context, root, directory string, environment [ cmd.Dir = root cmd.Env = environment var output io.Writer = log + if live != nil { + output = io.MultiWriter(log, live) + } var observation *schemeOutput if streamSchemeOutput && (tests != "" || stage.Name == "scheme-provider-server-build") { observation = &schemeOutput{destination: log, started: started} From 818ca68ad74a8bd32c603bf1c12c376632584756 Mon Sep 17 00:00:00 2001 From: guangtao Date: Mon, 9 Nov 2026 11:55:54 +0800 Subject: [PATCH 099/105] Exclude the race runtime exit sleep from native recovery timing --- go/dev/provider_control_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/go/dev/provider_control_test.go b/go/dev/provider_control_test.go index f61e21f3..a982a15b 100644 --- a/go/dev/provider_control_test.go +++ b/go/dev/provider_control_test.go @@ -100,6 +100,9 @@ func newControlProcess(t testing.TB, f *fixture, path string) *controlProcess { for name, value := range settings { c.env = append(c.env, "WEAVER_CONTROL_"+name+"="+value) } + // Measure the service drain and process exit without the race runtime's + // default one-second sleep after main returns. Keep all race checks active. + c.env = append(c.env, "GORACE="+strings.TrimSpace(os.Getenv("GORACE")+" atexit_sleep_ms=0")) t.Cleanup(func() { c.stop(t) }) return c } From c230f4132f8cfc03d374faf559048cf47ac1e7d3 Mon Sep 17 00:00:00 2001 From: guangtao Date: Tue, 10 Nov 2026 10:34:46 +0800 Subject: [PATCH 100/105] Prepare runtime execution and qualify retained Scheme decisions Reuse immutable execution inputs and SDK prepared programs while preserving fresh deciding reads, current authority, source barriers and retained holds. Carry publication-bound Governor topology and bounded facts through the existing affine owner and rooted C ABI; validate owned candidate indices. Specialize wholly nested retained programs with the public ASCENT factory. Add fixed four-worker benchmarks and SDK GC attribution, with preparation, queue, derivation, reply and natural cleanup measured separately. Keep retained/preopen/packed modes opt-in and preserve the original deadlines. The submillisecond target remains unqualified: the latest candidate owner P99 is 3.419-3.605 ms. Both four-way source-readiness waves failed before Governor derivation. Record passing local controls and these open gates in the delivery plan; this checkpoint makes no full CI or production claim. --- ...native-owner.gdb => sigpipe-backtrace.gdb} | 2 +- .github/workflows/verify-suite.yml | 2 +- Cargo.lock | 13 +- Cargo.toml | 6 +- Project.sysml | 6 +- crates/broker/benches/gateway.rs | 2 +- crates/broker/benches/support/header_seal.rs | 2 +- crates/broker/src/provider/runtime.rs | 71 +- crates/governance/Cargo.toml | 2 +- .../governance/benches/scheme_conversion.rs | 6 + .../benches/support/governor_owner.rs | 269 ++ .../benches/support/governor_usage.rs | 67 + crates/governance/src/host/client.rs | 50 +- crates/governance/src/host/mod.rs | 2 +- crates/governance/src/host/owner.rs | 36 +- crates/governance/src/host/state.rs | 49 +- crates/governance/src/lib.rs | 3 +- crates/governance/src/program/compiler.rs | 497 ++- crates/governance/src/scheme_input/values.rs | 5 + crates/governance/tests/unit/host.rs | 17 +- crates/ledger/Cargo.toml | 6 +- crates/ledger/src/domains/evidence.rs | 47 +- crates/ledger/src/domains/view.rs | 13 +- crates/ledger/src/execution_exposure.rs | 28 +- crates/ledger/src/exposure_manifest.rs | 90 +- crates/ledger/src/hard_fact.rs | 63 + crates/ledger/src/lib.rs | 7 +- .../ledger/src/persistence/driver_observer.rs | 245 ++ crates/ledger/src/persistence/mod.rs | 7 + crates/ledger/src/persistence/query.rs | 51 + crates/ledger/src/persistence/scheduler.rs | 22 + crates/ledger/src/persistence/scope.rs | 233 +- crates/ledger/src/persistence/scope_trace.rs | 182 +- crates/ledger/src/persistence/session.rs | 16 +- crates/ledger/src/persistence/timing.rs | 108 + crates/ledger/src/provider.rs | 166 +- crates/ledger/src/provider_admission.rs | 7 +- crates/ledger/src/provider_catalog.rs | 58 +- crates/ledger/src/provider_scope.rs | 101 + crates/ledger/src/provider_workflow.rs | 132 +- crates/ledger/src/provider_workflow_choice.rs | 22 +- crates/ledger/src/provider_workflow_nested.rs | 21 +- crates/ledger/src/publication.rs | 2 +- crates/ledger/src/reviewed_head.rs | 31 +- crates/ledger/src/store.rs | 26 + crates/ledger/src/task_origins.rs | 22 +- crates/ledger/src/task_publication.rs | 2 +- crates/ledger/tests/unit/driver_observer.rs | 287 ++ .../ledger/tests/unit/execution_exposure.rs | 4 + .../tests/unit/persistence_scheduler.rs | 20 + .../tests/unit/persistence_transactions.rs | 111 + crates/ledger/tests/unit/provider.rs | 74 + crates/ledger/tests/unit/provider/workflow.rs | 116 +- crates/ledger/tests/unit/provider_catalog.rs | 49 + crates/ledger/tests/unit/scope_trace.rs | 33 +- crates/server/src/admission.rs | 44 + crates/server/src/governance_owner.rs | 3 +- crates/server/src/grpc.rs | 14 +- crates/server/src/grpc_output.rs | 94 +- crates/server/src/grpc_provider.rs | 68 +- crates/server/src/session_workflow.rs | 309 +- crates/server/src/shutdown.rs | 9 +- crates/server/src/single_provider.rs | 52 +- crates/server/src/source_owner.rs | 173 +- crates/server/tests/unit/admission.rs | 33 + crates/server/tests/unit/governance_owner.rs | 5 +- crates/server/tests/unit/source_owner.rs | 164 + dev/sysml/ArchitectureEvolution.sysml | 105 +- dev/sysml/ProviderRpc.sysml | 8 + dev/sysml/WeaverExecution.sysml | 73 + dev/sysml/runtime-trace.json | 609 +--- .../59-provider-rpc/59.00-index.org | 6 +- .../59.64-governance-capture-ownership.org | 170 + .../59.87-spec-upgrade-and-delivery-plan.org | 3209 ++++++++++++++++- go/cmd/weaver-control/heap_observer_test.go | 74 + go/dev/contention_test.go | 7 +- go/dev/header_seal_bench_test.go | 4 +- go/dev/provider_control_bench_test.go | 561 ++- go/dev/provider_control_test.go | 38 +- go/dev/provider_domain_program_test.go | 15 + go/dev/provider_fixture_test.go | 52 + go/dev/provider_governor_performance_test.go | 141 +- go/dev/provider_module_routing_test.go | 21 +- go/dev/provider_process_accounting_test.go | 302 ++ go/dev/provider_range_group_test.go | 4 +- go/dev/provider_range_scopes_test.go | 6 + go/dev/provider_workflow_nested_test.go | 36 +- go/go.mod | 2 +- go/internal/controlplane/deployment.go | 2 +- go/internal/controlplane/deployment_source.go | 6 +- .../controlplane/deployment_source_test.go | 2 +- go/internal/controlplane/gateway.go | 92 +- .../controlplane/provider_binding_test.go | 103 + go/internal/controlplane/provider_catalog.go | 86 +- .../controlplane/provider_catalog_test.go | 174 + go/internal/controlplane/source_compile.go | 9 +- .../controlplane/source_compile_bench_test.go | 2 +- go/internal/devrunner/contention.go | 81 +- go/internal/devrunner/contention_test.go | 12 +- go/internal/devrunner/header_seal.go | 4 +- go/internal/devrunner/header_seal_test.go | 6 +- go/internal/devrunner/runner.go | 15 +- scheme/gateway/compiled.ss | 13 +- scheme/gateway/func.ss | 231 +- t/gateway-governor-retained-test.ss | 102 +- 105 files changed, 9493 insertions(+), 1367 deletions(-) rename .github/actions/prepare-toolchain/{native-owner.gdb => sigpipe-backtrace.gdb} (90%) create mode 100644 crates/governance/benches/support/governor_owner.rs create mode 100644 crates/governance/benches/support/governor_usage.rs create mode 100644 crates/ledger/src/persistence/driver_observer.rs create mode 100644 crates/ledger/src/provider_scope.rs create mode 100644 crates/ledger/tests/unit/driver_observer.rs create mode 100644 crates/ledger/tests/unit/provider_catalog.rs create mode 100644 go/cmd/weaver-control/heap_observer_test.go create mode 100644 go/dev/provider_process_accounting_test.go create mode 100644 go/internal/controlplane/provider_binding_test.go diff --git a/.github/actions/prepare-toolchain/native-owner.gdb b/.github/actions/prepare-toolchain/sigpipe-backtrace.gdb similarity index 90% rename from .github/actions/prepare-toolchain/native-owner.gdb rename to .github/actions/prepare-toolchain/sigpipe-backtrace.gdb index 7741664d..0146a5f4 100644 --- a/.github/actions/prepare-toolchain/native-owner.gdb +++ b/.github/actions/prepare-toolchain/sigpipe-backtrace.gdb @@ -16,7 +16,7 @@ commands silent set $weaver_sigpipe_events = $weaver_sigpipe_events + 1 if $weaver_sigpipe_events <= 16 - printf "WEAVER-NATIVE-SIGPIPE event=%d\n", $weaver_sigpipe_events + printf "WEAVER-SIGPIPE event=%d\n", $weaver_sigpipe_events thread bt 24 if $weaver_sigpipe_events == 1 diff --git a/.github/workflows/verify-suite.yml b/.github/workflows/verify-suite.yml index 8b60263c..b17f2d4b 100644 --- a/.github/workflows/verify-suite.yml +++ b/.github/workflows/verify-suite.yml @@ -68,7 +68,7 @@ jobs: id: scheme_sdk if: contains(fromJSON('["check-rust", "check-go", "check-policy", "check-scheme", "bench"]'), inputs.suite) timeout-minutes: 5 - uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@9aa4de6adc1f566f78586b046ba9452c1e996d7b + uses: tao3k/gerbil-scheme-rust/.github/actions/setup-gerbil@bfe803f597a15a3654b70a64c3a039980c31da8a with: release-root: ${{ runner.temp }}/gerbil-sdk - name: Prepare macOS Scheme build watchdog diff --git a/Cargo.lock b/Cargo.lock index 1e243b35..e2f23a22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "gerbil-scheme" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9aa4de6adc1f566f78586b046ba9452c1e996d7b#9aa4de6adc1f566f78586b046ba9452c1e996d7b" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bfe803f597a15a3654b70a64c3a039980c31da8a#bfe803f597a15a3654b70a64c3a039980c31da8a" dependencies = [ "gerbil-scheme-rust-project-harness-policy", "gerbil-scheme-sys", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-aot-build" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9aa4de6adc1f566f78586b046ba9452c1e996d7b#9aa4de6adc1f566f78586b046ba9452c1e996d7b" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bfe803f597a15a3654b70a64c3a039980c31da8a#bfe803f597a15a3654b70a64c3a039980c31da8a" dependencies = [ "cbindgen", "cc", @@ -1823,7 +1823,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness" version = "0.1.2" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9aa4de6adc1f566f78586b046ba9452c1e996d7b#9aa4de6adc1f566f78586b046ba9452c1e996d7b" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bfe803f597a15a3654b70a64c3a039980c31da8a#bfe803f597a15a3654b70a64c3a039980c31da8a" dependencies = [ "cargo-lock", "cargo_toml", @@ -1841,7 +1841,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-rust-project-harness-policy" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9aa4de6adc1f566f78586b046ba9452c1e996d7b#9aa4de6adc1f566f78586b046ba9452c1e996d7b" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bfe803f597a15a3654b70a64c3a039980c31da8a#bfe803f597a15a3654b70a64c3a039980c31da8a" dependencies = [ "gerbil-scheme-rust-project-harness", ] @@ -1849,7 +1849,7 @@ dependencies = [ [[package]] name = "gerbil-scheme-sys" version = "0.1.0" -source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=9aa4de6adc1f566f78586b046ba9452c1e996d7b#9aa4de6adc1f566f78586b046ba9452c1e996d7b" +source = "git+https://github.com/tao3k/gerbil-scheme-rust?rev=bfe803f597a15a3654b70a64c3a039980c31da8a#bfe803f597a15a3654b70a64c3a039980c31da8a" dependencies = [ "gerbil-scheme-aot-build", "gerbil-scheme-rust-project-harness-policy", @@ -5715,9 +5715,12 @@ dependencies = [ "mrr-data-backend", "proptest", "ring", + "rustix 1.1.5", "serde", "serde_json", "tempfile", + "tracing", + "tracing-subscriber", "weaver-contracts", "weaver-ledger", "weaver-policy", diff --git a/Cargo.toml b/Cargo.toml index 3d79bce8..aca043ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,9 +64,9 @@ arrow-array = "58.4.0" arrow-schema = "58.4.0" arrow-ipc = "58.4.0" criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } -gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "9aa4de6adc1f566f78586b046ba9452c1e996d7b" } -gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "9aa4de6adc1f566f78586b046ba9452c1e996d7b" } -gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "9aa4de6adc1f566f78586b046ba9452c1e996d7b", features = ["external-program"] } +gerbil-scheme-aot-build = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "bfe803f597a15a3654b70a64c3a039980c31da8a" } +gerbil-scheme = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "bfe803f597a15a3654b70a64c3a039980c31da8a" } +gerbil-scheme-sys = { git = "https://github.com/tao3k/gerbil-scheme-rust", rev = "bfe803f597a15a3654b70a64c3a039980c31da8a", features = ["external-program"] } asp-rust = { git = "https://github.com/tao3k/asp-rust", rev = "1ca41124b846dec947f3d05119cafa07eaa57924", default-features = false } diff --git a/Project.sysml b/Project.sysml index 57e1ef51..eb7b2622 100644 --- a/Project.sysml +++ b/Project.sysml @@ -133,7 +133,7 @@ package WeaverProject { part def SchemeArtifactDeclaration; part def RustArtifactMaterializer; part def ReproducibleInput; - part def NativeBuildProduct; + part def CargoAndGerbilBuildProduct; part def VerificationRun; part def DerivedView; part def LocalQualification; @@ -165,7 +165,7 @@ package WeaverProject { checked-in recipe and a reproducibility check. Site data, local digests, and individual execution verdicts stay outside Git. */ } - part nativeBuild : NativeBuildProduct { + part cargoAndGerbilBuild : CargoAndGerbilBuildProduct { doc /* Cargo and Gerbil Build Packages prepare and reuse their own outputs. The release consumer selects exact executable, linked image and package closure. Toolchain clean operates on owned @@ -553,7 +553,7 @@ package WeaverProject { part '.github/workflows/ci.yml' : File; part '.github/workflows/verify-suite.yml' : File; part '.github/actions/prepare-toolchain/action.yml' : File; - part '.github/actions/prepare-toolchain/native-owner.gdb' : File; + part '.github/actions/prepare-toolchain/sigpipe-backtrace.gdb' : File; part 'scheme/policy/cedar-ffi.ss' : File; part 'docs/50-59-research-program/59-provider-rpc/59.24-telemetry-service.org' : File; part 'docs/50-59-research-program/59-provider-rpc/59.25-openshell-and-tao3k-ecosystem.org' : File; diff --git a/crates/broker/benches/gateway.rs b/crates/broker/benches/gateway.rs index e0ec75da..5ebb1875 100644 --- a/crates/broker/benches/gateway.rs +++ b/crates/broker/benches/gateway.rs @@ -116,7 +116,7 @@ impl Provider { } }); Self { - runtime: fixture_runtime::fixture_runtime(None), + runtime: fixture_runtime::fixture_runtime(Some(4)), address, endpoint: format!("https://localhost:{}/v1/chat/completions", address.port()), pem, diff --git a/crates/broker/benches/support/header_seal.rs b/crates/broker/benches/support/header_seal.rs index da52c2d1..f4691575 100644 --- a/crates/broker/benches/support/header_seal.rs +++ b/crates/broker/benches/support/header_seal.rs @@ -17,7 +17,7 @@ struct Sample { held: u64, events: usize, calls: usize, - timings: weaver_ledger::persistence::TransactionTimings, + timings: weaver_ledger::TransactionTimings, } pub(super) fn run() { let provider = Provider::start(); diff --git a/crates/broker/src/provider/runtime.rs b/crates/broker/src/provider/runtime.rs index db8859d0..c44f162e 100644 --- a/crates/broker/src/provider/runtime.rs +++ b/crates/broker/src/provider/runtime.rs @@ -4,6 +4,8 @@ //! Guarded provider invocation; no retry, redirect, reconnect or automatic route fallback. use super::{anthropic_sse, openai_sse, wif}; +#[cfg(feature = "test-loopback")] +use std::time::Instant; use std::{ collections::{BTreeMap, BTreeSet}, sync::Arc, @@ -214,6 +216,15 @@ impl ProviderTransport { pub trait ProviderOutput { /// Bounded local diagnostics, never evidence that a send did not happen. fn observe_transport(&self, _phases: super::ProviderTransportPhases) {} + #[cfg(feature = "test-loopback")] + fn observe_admission( + &self, + _enqueue_nanos: u128, + _consume_nanos: u128, + _ledger: [weaver_ledger::TransactionTimings; 2], + ) {} + #[cfg(feature = "test-loopback")] + fn observe_dispatch(&self, _prepare_nanos: u128, _dispatch_nanos: u128) {} type Slot; type PreparedFrame; fn stopped(&self) -> bool; @@ -364,7 +375,6 @@ pub fn execute_provider_progression( format, batch_rows, } = request; - let ProviderExecutionAuthority { catalog, oauth } = admission.authority; if !(1..=32).contains(&batch_rows) || !matches!(format, "protobuf" | "arrow") || output.stopped() @@ -374,16 +384,7 @@ pub fn execute_provider_progression( for route in &plan.routes { crate::HttpsTransport::validate_endpoint(&route.endpoint)?; } - ledger.enqueue_provider_progression(plan, catalog, oauth, admission.progression)?; - if output.stopped() { - return Err(Error::Conflict("cancelled before provider consumption")); - } - let permit = ledger.consume_provider_with_oauth( - &plan.family, - &plan.node, - &transport.eligible(), - oauth, - )?; + let permit = admit_and_consume(ledger, plan, transport, output, admission)?; let result_capture = permit.expects_workflow_result().then(String::new); let response = open_guarded(ledger, &permit, transport, output)?; let (tokens, response) = super::range_output::relay( @@ -399,6 +400,46 @@ pub fn execute_provider_progression( ledger.complete_provider_with_result(&permit, format, tokens, response.as_deref()) } +fn admit_and_consume( + ledger: &mut Ledger, + plan: &ProviderPlan, + transport: &ProviderTransport, + output: &O, + admission: ProviderExecutionAdmission<'_>, +) -> Result { + let ProviderExecutionAuthority { catalog, oauth } = admission.authority; + #[cfg(feature = "test-loopback")] + let before_enqueue = ledger.transaction_timings(); + #[cfg(feature = "test-loopback")] + let enqueue_started = Instant::now(); + ledger.enqueue_provider_progression(plan, catalog, oauth, admission.progression)?; + #[cfg(feature = "test-loopback")] + let enqueue_nanos = enqueue_started.elapsed().as_nanos(); + #[cfg(feature = "test-loopback")] + let after_enqueue = ledger.transaction_timings(); + if output.stopped() { + return Err(Error::Conflict("cancelled before provider consumption")); + } + #[cfg(feature = "test-loopback")] + let consume_started = Instant::now(); + let permit = ledger.consume_provider_with_oauth( + &plan.family, + &plan.node, + &transport.eligible(), + oauth, + )?; + #[cfg(feature = "test-loopback")] + output.observe_admission( + enqueue_nanos, + consume_started.elapsed().as_nanos(), + [ + after_enqueue.since(before_enqueue), + ledger.transaction_timings().since(after_enqueue), + ], + ); + Ok(permit) +} + pub(super) enum StreamDecoder { OpenAi(openai_sse::Decoder), Anthropic(anthropic_sse::Decoder), @@ -447,17 +488,25 @@ fn open_guarded( return Err(Error::Conflict("cancelled after provider consumption")); } // WIF exchange and request preparation occur outside the deciding send scope. + #[cfg(feature = "test-loopback")] + let prepare_started = Instant::now(); let request = transport .prepare(permit.plan(), permit.route(), permit.protocol())? .with_oauth_expiration(permit.oauth_expires()); + #[cfg(feature = "test-loopback")] + let prepare_nanos = prepare_started.elapsed().as_nanos(); let phases = std::cell::Cell::new(super::ProviderTransportPhases::default()); let result = (|| { + #[cfg(feature = "test-loopback")] + let dispatch_started = Instant::now(); let sealed = ledger.dispatch_provider(permit, || { if output.stopped() { return Err(Error::Conflict("cancelled before provider invocation")); } request.write_and_seal(&phases) })?; + #[cfg(feature = "test-loopback")] + output.observe_dispatch(prepare_nanos, dispatch_started.elapsed().as_nanos()); if output.stopped() { return Err(Error::Conflict("cancelled after provider seal")); } diff --git a/crates/governance/Cargo.toml b/crates/governance/Cargo.toml index ad0bb291..5b921b35 100644 --- a/crates/governance/Cargo.toml +++ b/crates/governance/Cargo.toml @@ -47,7 +47,7 @@ harness = false [[bench]] name = "scheme_conversion" harness = false -required-features = ["scheme-qualification"] +required-features = ["scheme-program"] # Unsafe is scoped to the fixed Gerbil linker/export binding module; all typed # conversion, lifecycle, catalog and source ownership code retains deny mode. diff --git a/crates/governance/benches/scheme_conversion.rs b/crates/governance/benches/scheme_conversion.rs index ce643eaa..cbfc8609 100644 --- a/crates/governance/benches/scheme_conversion.rs +++ b/crates/governance/benches/scheme_conversion.rs @@ -7,10 +7,16 @@ use criterion::{BenchmarkId, Criterion, SamplingMode, Throughput}; use std::{hint::black_box, time::Duration}; #[path = "../tests/unit/fixture.rs"] mod fixture; +#[path = "support/governor_owner.rs"] +mod governor_owner; #[path = "../tests/integration/program.rs"] mod program; fn main() { + if std::env::var("WEAVER_TEST_GOVERNOR_OWNER_BENCH").as_deref() == Ok("1") { + governor_owner::run(); + return; + } let mut criterion = Criterion::default() .sample_size(30) .warm_up_time(Duration::from_secs(1)) diff --git a/crates/governance/benches/support/governor_owner.rs b/crates/governance/benches/support/governor_owner.rs new file mode 100644 index 00000000..776f4581 --- /dev/null +++ b/crates/governance/benches/support/governor_owner.rs @@ -0,0 +1,269 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Finite warm owner profile of the existing source lane, without effect authority. +use std::{ + num::NonZeroUsize, + sync::Arc, + time::{Duration, Instant}, +}; +use tokio::sync::{Barrier, oneshot}; +use weaver_governance::{ + Derivation, DerivationOutput, GovernorCut, GovernorTopology, SchemeCompiler, SourceClient, + source_lane, +}; +#[allow(unsafe_code)] +#[path = "governor_usage.rs"] +mod usage; + +const WAVES: usize = 32; +const WORKERS: usize = 4; +const EXPECTED: [&[&str]; 4] = [ + ["fork-a", "fork-b"].as_slice(), + ["inner-finish"].as_slice(), + ["finish"].as_slice(), + &[], +]; + +fn topology() -> Arc { + // The topology and ordering match runNestedSession's real Scheme fixture. + Arc::new(GovernorTopology { + nodes: [ + "infer", + "gate", + "next", + "side", + "fork-a", + "fork-b", + "inner-finish", + "outer-skip", + "finish", + ] + .map(str::to_owned) + .into(), + edges: [ + ("finish", "inner-finish"), + ("finish", "outer-skip"), + ("fork-a", "side"), + ("fork-b", "side"), + ("gate", "infer"), + ("inner-finish", "fork-a"), + ("inner-finish", "fork-b"), + ("inner-finish", "next"), + ("next", "gate"), + ("outer-skip", "infer"), + ("side", "gate"), + ] + .map(|(a, b)| (a.into(), b.into())) + .into(), + choice_arms: vec![], + choice_join: vec![], + nested_selectors: [["gate", "next", "side"], ["infer", "gate", "outer-skip"]] + .map(|row| row.map(str::to_owned)) + .into(), + }) +} + +fn cut(topology: &Arc, phase: usize) -> GovernorCut { + let mut complete: Vec = ["infer", "gate", "side"].map(str::to_owned).into(); + if phase != 0 { + complete.extend(["fork-a", "fork-b"].map(str::to_owned)); + } + if phase == 2 { + complete.push("inner-finish".into()); + } + GovernorCut { + topology: topology.clone(), + available: topology + .nodes + .iter() + .filter(|node| phase != 3 || *node != "fork-b") + .cloned() + .collect(), + pending: topology + .nodes + .iter() + .filter(|node| !complete.contains(node)) + .cloned() + .collect(), + complete, + choice_result: vec![], + choice_decided: vec![], + nested_results: vec![ + ("infer".into(), "left".into()), + ("gate".into(), "right".into()), + ], + nested_decisions: vec![ + ("infer".into(), "left".into()), + ("gate".into(), "right".into()), + ], + } +} + +fn phase(input: &Derivation) -> usize { + let Derivation::Governor(cut) = input else { + panic!("only Governor cuts in this profile") + }; + match (cut.complete.len(), cut.available.len()) { + (3, 9) => 0, + (5, 9) => 1, + (6, 9) => 2, + (5, 8) => 3, + _ => panic!("unexpected frozen snapshot"), + } +} + +fn verify(output: DerivationOutput, topology: &GovernorTopology, phase: usize) { + let mut nodes = match output { + DerivationOutput::Nodes(nodes) => nodes, + DerivationOutput::Indices(indices) => indices + .into_iter() + .map(|i| topology.nodes.get(i).expect("bound index").clone()) + .collect(), + }; + nodes.sort_unstable(); + assert_eq!(nodes, EXPECTED[phase], "wrong candidates for phase {phase}"); +} + +struct OwnerSample { + wave: usize, + phase: usize, + started: Instant, + finished: Instant, + usage: Option, +} +struct RequestSample { + wave: usize, + phase: usize, + submitted: Instant, + received: Instant, +} + +async fn wave( + client: &SourceClient, + topology: &Arc, + wave: usize, +) -> Vec { + let barrier = Arc::new(Barrier::new(WORKERS + 1)); + let mut jobs = Vec::with_capacity(WORKERS); + for phase in 0..WORKERS { + let (client, topology, barrier) = (client.clone(), topology.clone(), barrier.clone()); + let input = cut(&topology, phase); + jobs.push(tokio::spawn(async move { + barrier.wait().await; + let submitted = Instant::now(); + let output = client.derive(input).await.expect("owner derivation"); + let received = Instant::now(); + verify(output, &topology, phase); + RequestSample { + wave, + phase, + submitted, + received, + } + })); + } + barrier.wait().await; + let mut samples = Vec::with_capacity(WORKERS); + for job in jobs { + samples.push(job.await.expect("request task")); + } + samples +} + +fn ns(duration: Duration) -> u64 { + duration.as_nanos().try_into().expect("bounded interval") +} + +pub(super) fn run() { + assert!( + std::env::var_os("WEAVER_TEST_GOVERNOR_TIMING").is_none(), + "verbose timing changes the measured path" + ); + let runtime = tokio::runtime::Builder::new_multi_thread() + .worker_threads(WORKERS) + .max_blocking_threads(1) + .enable_all() + .build() + .expect("four-worker runtime"); + let topology = topology(); + let (client, inbox) = source_lane(NonZeroUsize::new(WORKERS).expect("capacity")); + let (ready, prepared) = oneshot::channel(); + let graph = topology.clone(); + let observe_usage = std::env::var("WEAVER_TEST_GOVERNOR_USAGE").as_deref() == Ok("1"); + let owner = runtime.spawn_blocking(move || { + let started = Instant::now(); + let mut compiler = SchemeCompiler::initialize().expect("approved linked application"); + verify( + compiler.derive(&cut(&graph, 0)).expect("preopen"), + &graph, + 0, + ); + ready + .send(ns(started.elapsed())) + .expect("readiness receiver"); + let mut samples = Vec::with_capacity(WAVES * WORKERS); + let mut waves = [0; WORKERS]; + inbox.run_with_cancellable_governor( + compiler, + |compiler, original, cancel| compiler.compile_cancellable(original, cancel), + |compiler, input| { + let phase = phase(input); + // Existing SDK counters allocate no Scheme objects. Keep the + // observation outside the derive clock, within request latency. + let before = observe_usage.then(usage::read); + let started = Instant::now(); + let result = compiler.evaluate(input); + let finished = Instant::now(); + let usage = before.map(|before| usage::read().delta(before)); + samples.push(OwnerSample { + wave: waves[phase], + phase, + started, + finished, + usage, + }); + waves[phase] += 1; + result + }, + ); + samples + }); + let readiness_ns = runtime.block_on(async { + tokio::time::timeout(Duration::from_secs(12), prepared) + .await + .expect("owner readiness deadline") + .expect("prepared owner") + }); + let requests = runtime.block_on(async { + tokio::time::timeout(Duration::from_secs(120), async { + let mut samples = Vec::with_capacity(WAVES * WORKERS); + for round in 0..WAVES { + samples.extend(wave(&client, &topology, round).await); + } + samples + }) + .await + .expect("finite measurement deadline") + }); + client.close(); + let draining = Instant::now(); + let samples = runtime.block_on(async { + tokio::time::timeout(Duration::from_secs(15), owner) + .await + .expect("natural owner drain deadline") + .expect("owner joined") + }); + let drain_ns = ns(draining.elapsed()); + assert_eq!(samples.len(), WAVES * WORKERS); + let rows = samples.into_iter().map(|owner| { + let request = requests.iter().find(|r| r.wave == owner.wave && r.phase == owner.phase).expect("unique request"); + assert!(request.submitted <= owner.started && owner.started <= owner.finished && owner.finished <= request.received); + serde_json::json!({"wave": owner.wave, "phase": owner.phase, "queue_ns": ns(owner.started - request.submitted), "derive_ns": ns(owner.finished - owner.started), "reply_ns": ns(request.received - owner.finished), "total_ns": ns(request.received - request.submitted), "usage": owner.usage}) + }).collect::>(); + println!( + "{}", + serde_json::json!({"profile": "governor-owner-warm", "usage_observed": observe_usage, "tokio_workers": WORKERS, "scheme_owners": 1, "queue_capacity": WORKERS, "waves": WAVES, "readiness_ns": readiness_ns, "drain_ns": drain_ns, "samples": rows}) + ); +} diff --git a/crates/governance/benches/support/governor_usage.rs b/crates/governance/benches/support/governor_usage.rs new file mode 100644 index 00000000..9b0ef083 --- /dev/null +++ b/crates/governance/benches/support/governor_usage.rs @@ -0,0 +1,67 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Existing SDK qualification ABI, called only on the live Scheme owner. +unsafe extern "C" { + fn gerbil_scheme_rust_objects_usage(gc: *mut f64, os: *mut u64) -> i32; +} + +pub(super) struct Snapshot { + gc: [f64; 4], + os: [u64; 4], +} + +#[derive(serde::Serialize)] +pub(super) struct Delta { + gc_count: f64, + gc_cpu_seconds: f64, + gc_wall_seconds: f64, + scheme_heap_capacity_bytes: f64, + process_cpu_ns: u64, + process_rss_high_water_bytes: u64, + process_voluntary_switches: u64, + process_involuntary_switches: u64, +} + +pub(super) fn read() -> Snapshot { + let mut snapshot = Snapshot { + gc: [0.0; 4], + os: [0; 4], + }; + // SAFETY: the benchmark invokes this on the initialized VM's affine owner, + // before cleanup. The pinned public SDK header specifies four doubles and + // four u64 outputs. Both arrays are complete, writable and disjoint; the + // SDK retains no pointer. This is the SDK's own objects-benchmark ABI. + let status = unsafe { + gerbil_scheme_rust_objects_usage(snapshot.gc.as_mut_ptr(), snapshot.os.as_mut_ptr()) + }; + assert_eq!(status, 0, "SDK owner usage snapshot"); + assert!( + snapshot + .gc + .iter() + .all(|value| value.is_finite() && *value >= 0.0) + ); + snapshot +} + +impl Snapshot { + pub(super) fn delta(self, before: Self) -> Delta { + assert!((0..3).all(|i| self.gc[i] >= before.gc[i])); + Delta { + gc_count: self.gc[0] - before.gc[0], + gc_cpu_seconds: self.gc[1] - before.gc[1], + gc_wall_seconds: self.gc[2] - before.gc[2], + scheme_heap_capacity_bytes: self.gc[3], + process_cpu_ns: self.os[0].checked_sub(before.os[0]).expect("monotonic CPU"), + process_rss_high_water_bytes: self.os[1], + process_voluntary_switches: self.os[2] + .checked_sub(before.os[2]) + .expect("monotonic switches"), + process_involuntary_switches: self.os[3] + .checked_sub(before.os[3]) + .expect("monotonic switches"), + } + } +} diff --git a/crates/governance/src/host/client.rs b/crates/governance/src/host/client.rs index 530d2826..7f6e5d5a 100644 --- a/crates/governance/src/host/client.rs +++ b/crates/governance/src/host/client.rs @@ -75,7 +75,10 @@ impl SourceClient { Ok(SourceJob::new(receiver, self.shared.clone(), state, cancel)) } /// Wait for space on the bounded Scheme owner so a Session wake is not lost. - pub async fn derive(&self, input: crate::GovernorCut) -> Result, SourceJobError> { + pub async fn derive( + &self, + input: crate::GovernorCut, + ) -> Result { self.evaluate(crate::Derivation::Governor(Box::new(input))) .await } @@ -84,13 +87,23 @@ impl SourceClient { &self, work: &weaver_contracts::FactWork, ) -> Result, SourceJobError> { - self.evaluate(crate::Derivation::FactImpact { - root: work.root.clone(), - dependencies: work.dependencies.clone(), - }) - .await + match self + .evaluate(crate::Derivation::FactImpact { + root: work.root.clone(), + dependencies: work.dependencies.clone(), + }) + .await? + { + crate::DerivationOutput::Nodes(nodes) => Ok(nodes), + crate::DerivationOutput::Indices(_) => Err(crate::SourceError::Contract.into()), + } } - async fn evaluate(&self, input: crate::Derivation) -> Result, SourceJobError> { + async fn evaluate( + &self, + input: crate::Derivation, + ) -> Result { + let started = super::governor_timing().then(std::time::Instant::now); + let governor = matches!(&input, crate::Derivation::Governor(_)); let capacity = self.capacity.clone(); let slot = match &input { crate::Derivation::Governor(_) => tokio::select! { @@ -102,6 +115,7 @@ impl SourceClient { .try_acquire_owned() .map_err(|_| SourceJobError::Busy)?, }; + let admitted = started.map(|_| std::time::Instant::now()); let (reply, receiver) = oneshot::channel(); { let closed = self.shared.gate(); @@ -120,11 +134,27 @@ impl SourceClient { mpsc::error::TrySendError::Closed(_) => SourceJobError::Closed, })?; } - tokio::select! { + let reply = tokio::select! { biased; - _ = self.shared.shutdown.cancelled() => Err(SourceJobError::Closed), - result = receiver => result.map_err(|_| SourceJobError::Closed)?.map_err(SourceJobError::from), + _ = self.shared.shutdown.cancelled() => return Err(SourceJobError::Closed), + result = receiver => result.map_err(|_| SourceJobError::Closed)?, + }; + if let (true, Some(started), Some(admitted), Some([queued, owner, finished, sent])) = + (governor, started, admitted, reply.timing) + { + let received = std::time::Instant::now(); + eprintln!( + "weaver-governor-roundtrip capacity_ns={} submit_ns={} wait_ns={} derive_ns={} trace_ns={} response_ns={} total_ns={}", + admitted.duration_since(started).as_nanos(), + queued.duration_since(admitted).as_nanos(), + owner.duration_since(queued).as_nanos(), + finished.duration_since(owner).as_nanos(), + sent.duration_since(finished).as_nanos(), + received.duration_since(sent).as_nanos(), + received.duration_since(started).as_nanos(), + ); } + reply.result.map_err(SourceJobError::from) } /// Close admission and wake callers/owner. This is not drain acknowledgment; /// an active synchronous compiler must return and clean its VM naturally. diff --git a/crates/governance/src/host/mod.rs b/crates/governance/src/host/mod.rs index c46062f8..84766d49 100644 --- a/crates/governance/src/host/mod.rs +++ b/crates/governance/src/host/mod.rs @@ -12,4 +12,4 @@ pub use owner::SourceInbox; pub(crate) use owner::governor_timing; pub use request::{SourceJob, SourceJobError}; use state::{Command, Phase, Reply, Shared, State, Work}; -pub use state::{Derivation, GovernorCut}; +pub use state::{Derivation, DerivationOutput, GovernorCut, GovernorTopology}; diff --git a/crates/governance/src/host/owner.rs b/crates/governance/src/host/owner.rs index 2c5c37f1..9e48831a 100644 --- a/crates/governance/src/host/owner.rs +++ b/crates/governance/src/host/owner.rs @@ -36,7 +36,9 @@ impl SourceInbox { owner, |owner, original, _| compile(owner, original), |owner, input| match input { - crate::Derivation::Governor(cut) => derive(owner, cut), + crate::Derivation::Governor(cut) => { + derive(owner, cut).map(crate::DerivationOutput::Nodes) + } crate::Derivation::FactImpact { .. } => Err(SourceError::Contract), }, ); @@ -50,7 +52,10 @@ impl SourceInbox { &OwnedSource, &CancellationToken, ) -> Result, - mut derive: impl FnMut(&mut C, &crate::Derivation) -> Result, SourceError>, + mut derive: impl FnMut( + &mut C, + &crate::Derivation, + ) -> Result, ) { while let Some(command) = self.receiver.blocking_recv() { if *self.shared.gate() { @@ -93,25 +98,37 @@ impl SourceInbox { fn execute_derivation( &self, input: &crate::Derivation, - reply: tokio::sync::oneshot::Sender, SourceError>>, + reply: tokio::sync::oneshot::Sender, queued: Option, - derive: impl FnOnce() -> Result, SourceError>, + derive: impl FnOnce() -> Result, ) { if reply.is_closed() { return; } let started = queued.map(|queued| (queued, std::time::Instant::now())); let result = derive(); + let finished = started.map(|_| std::time::Instant::now()); if matches!(result, Err(SourceError::Scheme)) { self.shared.stop(); } - if let Some((queued, started)) = started { - let derive_ns = started.elapsed().as_nanos(); + if let (Some((queued, started)), Some(finished)) = (started, finished) { + let derive_ns = finished.duration_since(started).as_nanos(); let cut_sha256 = match input { crate::Derivation::Governor(cut) => trace_digest(cut), crate::Derivation::FactImpact { .. } => trace_digest(input), }; - let ready_sha256 = result.as_ref().ok().map(trace_digest); + let ready_sha256 = match (input, result.as_ref().ok()) { + (_, Some(crate::DerivationOutput::Nodes(nodes))) => Some(trace_digest(nodes)), + ( + crate::Derivation::Governor(cut), + Some(crate::DerivationOutput::Indices(indices)), + ) => indices + .iter() + .map(|&index| cut.topology.nodes.get(index)) + .collect::>>() + .map(|nodes| trace_digest(&nodes)), + _ => None, + }; eprintln!( "weaver-governor-owner wait_ns={} derive_ns={derive_ns} ok={} cut_sha256={cut_sha256} ready_sha256={}", started.duration_since(queued).as_nanos(), @@ -119,7 +136,10 @@ impl SourceInbox { ready_sha256.as_deref().unwrap_or("unavailable"), ); } - let _ = reply.send(result); + let timing = started.zip(finished).map(|((queued, started), finished)| { + [queued, started, finished, std::time::Instant::now()] + }); + let _ = reply.send(super::state::DerivationReply { result, timing }); } fn execute( &self, diff --git a/crates/governance/src/host/state.rs b/crates/governance/src/host/state.rs index 0e067809..72def5e6 100644 --- a/crates/governance/src/host/state.rs +++ b/crates/governance/src/host/state.rs @@ -64,22 +64,46 @@ pub(super) struct Work { pub(super) slot: OwnedSemaphorePermit, pub(super) cancel: CancellationToken, } -/// Fixed Governor facts, detached from the authoritative ledger cut. -#[derive(serde::Serialize)] -pub struct GovernorCut { +/// Immutable graph owned by one prepared Workflow publication. +pub struct GovernorTopology { pub nodes: Vec, pub edges: Vec<(String, String)>, + pub choice_arms: Vec, + pub choice_join: Vec, + pub nested_selectors: Vec<[String; 3]>, +} + +/// Complete mutable facts detached from the authoritative ledger cut. +pub struct GovernorCut { + pub topology: Arc, pub complete: Vec, pub available: Vec, pub pending: Vec, - pub choice_arms: Vec, - pub choice_join: Vec, pub choice_result: Vec, pub choice_decided: Vec, - pub nested_selectors: Vec<[String; 3]>, pub nested_results: Vec<(String, String)>, pub nested_decisions: Vec<(String, String)>, } +impl serde::Serialize for GovernorCut { + fn serialize(&self, serializer: S) -> Result { + use serde::ser::SerializeStruct; + // Keep the semantic cut digest independent of the transport and its binding. + let mut cut = serializer.serialize_struct("GovernorCut", 12)?; + cut.serialize_field("nodes", &self.topology.nodes)?; + cut.serialize_field("edges", &self.topology.edges)?; + cut.serialize_field("complete", &self.complete)?; + cut.serialize_field("available", &self.available)?; + cut.serialize_field("pending", &self.pending)?; + cut.serialize_field("choice_arms", &self.topology.choice_arms)?; + cut.serialize_field("choice_join", &self.topology.choice_join)?; + cut.serialize_field("choice_result", &self.choice_result)?; + cut.serialize_field("choice_decided", &self.choice_decided)?; + cut.serialize_field("nested_selectors", &self.topology.nested_selectors)?; + cut.serialize_field("nested_results", &self.nested_results)?; + cut.serialize_field("nested_decisions", &self.nested_decisions)?; + cut.end() + } +} /// Inert observations evaluated by the existing linked Scheme owner. #[derive(serde::Serialize)] pub enum Derivation { @@ -89,10 +113,21 @@ pub enum Derivation { dependencies: Vec<(String, String)>, }, } +/// Detached node identities. Indices belong to the topology of this Governor request. +#[derive(Debug, PartialEq, Eq)] +pub enum DerivationOutput { + Nodes(Vec), + Indices(Vec), +} +pub(super) struct DerivationReply { + pub(super) result: Result, + /// Enqueued, owner start, derivation finished, and reply submission. + pub(super) timing: Option<[std::time::Instant; 4]>, +} pub(super) enum Command { Derive { input: Derivation, - reply: oneshot::Sender, crate::SourceError>>, + reply: oneshot::Sender, _slot: OwnedSemaphorePermit, queued: Option, }, diff --git a/crates/governance/src/lib.rs b/crates/governance/src/lib.rs index 37f7c007..41e9619d 100644 --- a/crates/governance/src/lib.rs +++ b/crates/governance/src/lib.rs @@ -12,7 +12,8 @@ mod source; pub use binding::{BoundSource, SourceExpectation}; pub use catalog::{ApprovedProducer, CatalogError, ProducerCatalog, ProducerClient}; pub use host::{ - Derivation, GovernorCut, SourceClient, SourceInbox, SourceJob, SourceJobError, source_lane, + Derivation, DerivationOutput, GovernorCut, GovernorTopology, SourceClient, SourceInbox, + SourceJob, SourceJobError, source_lane, }; pub use source::{MAX_SOURCE_BYTES, OwnedSource, SourceData, SourceError, SourceSelection}; diff --git a/crates/governance/src/program/compiler.rs b/crates/governance/src/program/compiler.rs index 8615a080..6ea7d22f 100644 --- a/crates/governance/src/program/compiler.rs +++ b/crates/governance/src/program/compiler.rs @@ -4,13 +4,26 @@ //! Fixed compiled Scheme application on the existing thread-affine Gerbil owner. use super::linked; -use crate::{OwnedSource, SourceError, materialize_source, root_source}; -use gerbil_scheme::GerbilRuntime; +use crate::{DerivationOutput, OwnedSource, SourceError, materialize_source, root_source}; +use gerbil_scheme::{ + BigIntegerBuffer, CollectionKind, GerbilRuntime, RootedObjectBatch, RootedSchemeObject, + SchemeScalar, +}; +use std::{ + collections::BTreeMap, + sync::{Arc, Weak}, +}; /// Neither this owner nor its Gerbil runtime is Send. Construct it on the tracked /// blocking thread; no borrowed root/object crosses a queue or await. pub struct SchemeCompiler { runtime: GerbilRuntime, + compact_governor: bool, + named_governor_result: bool, + packed_governor_facts: bool, + packed_node_indices: BTreeMap, + governor_generation: u64, + governor_topology: Weak, } impl SchemeCompiler { /// Initialize the linked approved graph and require an installed producer. @@ -22,9 +35,20 @@ impl SchemeCompiler { if !linked::ready(&runtime).map_err(|_| SourceError::Scheme)? { return Err(SourceError::Contract); } - Ok(Self { runtime }) + Ok(Self { + runtime, + compact_governor: std::env::var("WEAVER_TEST_GOVERNOR_RETAINED").as_deref() == Ok("1") + && std::env::var("WEAVER_TEST_GOVERNOR_FULL_CUT").as_deref() != Ok("1"), + named_governor_result: std::env::var("WEAVER_TEST_GOVERNOR_NAMED_RESULT").as_deref() + == Ok("1"), + packed_governor_facts: std::env::var("WEAVER_TEST_GOVERNOR_PACKED_FACTS").as_deref() + == Ok("1"), + packed_node_indices: BTreeMap::new(), + governor_generation: 0, + governor_topology: Weak::new(), + }) } - pub fn evaluate(&mut self, input: &crate::Derivation) -> Result, SourceError> { + pub fn evaluate(&mut self, input: &crate::Derivation) -> Result { match input { crate::Derivation::Governor(cut) => self.derive(cut), crate::Derivation::FactImpact { root, dependencies } => { @@ -35,49 +59,58 @@ impl SchemeCompiler { ])?; let output = linked::fact_impact(&self.runtime, &root).map_err(|_| SourceError::Scheme)?; - crate::scheme::materialize(output) + crate::scheme::materialize(output).map(DerivationOutput::Nodes) } } } - pub fn derive(&mut self, cut: &crate::GovernorCut) -> Result, SourceError> { + pub fn derive(&mut self, cut: &crate::GovernorCut) -> Result { let started = crate::host::governor_timing().then(std::time::Instant::now); + let topology = &cut.topology; + let send_topology = self.begin_governor_binding(topology); let input = crate::scheme_input::values::Input::new(&self.runtime); - let root = input.record(vec![ - ("nodes", input.strings(&cut.nodes)?), - ("edges", input.edges(&cut.edges)?), - ("complete", input.strings(&cut.complete)?), - ("available", input.strings(&cut.available)?), - ("pending", input.strings(&cut.pending)?), - ("choice_arms", input.strings(&cut.choice_arms)?), - ("choice_join", input.strings(&cut.choice_join)?), - ("choice_result", input.strings(&cut.choice_result)?), - ("choice_decided", input.strings(&cut.choice_decided)?), - ( - "nested_selectors", - input.vector( - cut.nested_selectors - .iter() - .map(|row| input.strings(row)) - .collect::, _>>()?, - )?, - ), - ("nested_results", input.edges(&cut.nested_results)?), - ("nested_decisions", input.edges(&cut.nested_decisions)?), - ])?; - let input_done = started.map(|_| std::time::Instant::now()); - let output = linked::derive(&self.runtime, &root).map_err(|_| SourceError::Scheme)?; - let ffi_done = started.map(|_| std::time::Instant::now()); - let result = crate::scheme::materialize(output); - if let (Some(started), Some(input_done), Some(ffi_done)) = (started, input_done, ffi_done) { - eprintln!( - "weaver-governor-ffi input_ns={} call_ns={} output_ns={}", - input_done.duration_since(started).as_nanos(), - ffi_done.duration_since(input_done).as_nanos(), - ffi_done.elapsed().as_nanos(), - ); + let indexed_result = self.compact_governor && !self.named_governor_result; + let packed_facts = indexed_result && self.packed_governor_facts && !send_topology; + let mut fields = + governor_fact_fields(&input, cut, packed_facts, &mut self.packed_node_indices)?; + if send_topology { + fields.extend(governor_topology_fields(&input, topology)?); } + append_governor_binding( + &input, + &mut fields, + self.compact_governor, + send_topology, + indexed_result, + &mut self.governor_generation, + )?; + let (output, called) = + call_prepared_governor(&self.runtime, input.record(fields)?, started.is_some())?; + let result = accept_governor_reply( + output, + indexed_result, + self.compact_governor, + self.governor_generation, + topology, + &mut self.governor_topology, + ); + trace_governor_ffi( + governor_transport(self.compact_governor, send_topology), + indexed_result, + packed_facts, + started, + called, + ); result } + fn begin_governor_binding(&mut self, topology: &Arc) -> bool { + let previous = std::mem::take(&mut self.governor_topology); + let send_topology = + !self.compact_governor || !Weak::ptr_eq(&previous, &Arc::downgrade(topology)); + if send_topology { + self.packed_node_indices.clear(); + } + send_topology + } /// Compilation is inert preparation; the source lane independently binds /// this result to its retained original before any caller can claim it. pub fn compile(&mut self, original: &OwnedSource) -> Result { @@ -102,3 +135,389 @@ impl SchemeCompiler { materialize_source(output) } } + +fn call_prepared_governor<'r>( + runtime: &'r GerbilRuntime, + input: RootedSchemeObject<'r>, + timing: bool, +) -> Result< + ( + RootedSchemeObject<'r>, + Option<(std::time::Instant, std::time::Instant)>, + ), + SourceError, +> { + let input_done = timing.then(std::time::Instant::now); + let output = linked::derive(runtime, &input).map_err(|_| SourceError::Scheme)?; + let ffi_done = timing.then(std::time::Instant::now); + Ok((output, input_done.zip(ffi_done))) +} + +fn accept_governor_reply( + output: RootedSchemeObject<'_>, + indexed: bool, + compact: bool, + binding: u64, + topology: &Arc, + retained: &mut Weak, +) -> Result { + let result = if indexed { + materialize_indices(output, binding, topology.nodes.len()).map(DerivationOutput::Indices) + } else { + crate::scheme::materialize(output).map(DerivationOutput::Nodes) + }; + if compact && result.is_ok() { + *retained = Arc::downgrade(topology); + } + result +} + +fn governor_transport(compact: bool, send_topology: bool) -> &'static str { + match (compact, send_topology) { + (false, _) => "full", + (true, true) => "bind", + (true, false) => "compact", + } +} + +fn append_governor_binding<'r>( + input: &crate::scheme_input::values::Input<'r>, + fields: &mut Vec<(&'static str, RootedSchemeObject<'r>)>, + compact: bool, + send_topology: bool, + indexed: bool, + generation: &mut u64, +) -> Result<(), SourceError> { + if compact { + if send_topology { + *generation = generation.checked_add(1).ok_or(SourceError::Bound)?; + } + fields.push(("topology_binding", input.number(*generation)?)); + } + if indexed { + fields.push(("indexed_result", input.number(1)?)); + } + Ok(()) +} + +fn governor_fact_fields<'r>( + input: &crate::scheme_input::values::Input<'r>, + cut: &crate::GovernorCut, + packed: bool, + indices: &mut BTreeMap, +) -> Result)>, SourceError> { + if packed { + if indices.is_empty() { + *indices = cut + .topology + .nodes + .iter() + .enumerate() + .map(|(index, node)| { + u8::try_from(index) + .map(|index| (node.clone(), index)) + .map_err(|_| SourceError::Bound) + }) + .collect::>()?; + } + let bytes = pack_governor_facts(cut, indices)?; + return Ok(vec![("packed_facts", input.bytes_vector(&bytes)?)]); + } + Ok(vec![ + ("complete", input.strings(&cut.complete)?), + ("available", input.strings(&cut.available)?), + ("pending", input.strings(&cut.pending)?), + ("choice_result", input.strings(&cut.choice_result)?), + ("choice_decided", input.strings(&cut.choice_decided)?), + ("nested_results", input.edges(&cut.nested_results)?), + ("nested_decisions", input.edges(&cut.nested_decisions)?), + ]) +} + +fn governor_topology_fields<'r>( + input: &crate::scheme_input::values::Input<'r>, + topology: &crate::GovernorTopology, +) -> Result<[(&'static str, RootedSchemeObject<'r>); 5], SourceError> { + Ok([ + ("nodes", input.strings(&topology.nodes)?), + ("edges", input.edges(&topology.edges)?), + ("choice_arms", input.strings(&topology.choice_arms)?), + ("choice_join", input.strings(&topology.choice_join)?), + ( + "nested_selectors", + input.vector( + topology + .nested_selectors + .iter() + .map(|row| input.strings(row)) + .collect::, _>>()?, + )?, + ), + ]) +} + +fn trace_governor_ffi( + transport: &str, + indexed: bool, + packed: bool, + started: Option, + called: Option<(std::time::Instant, std::time::Instant)>, +) { + if let (Some(started), Some((input_done, ffi_done))) = (started, called) { + let output_ns = ffi_done.elapsed().as_nanos(); + let result = if indexed { "indexed" } else { "named" }; + let facts = if packed { "packed" } else { "named" }; + eprintln!("weaver-governor-transport mode={transport}"); + eprintln!("weaver-governor-result mode={result}"); + eprintln!("weaver-governor-facts mode={facts}"); + eprintln!( + "weaver-governor-ffi input_ns={} call_ns={} output_ns={}", + input_done.duration_since(started).as_nanos(), + ffi_done.duration_since(input_done).as_nanos(), + output_ns + ); + } +} + +fn relation_count(rows: &[T]) -> Result { + if rows.len() > 64 { + return Err(SourceError::Bound); + } + Ok(rows.len() as u8) +} + +fn route_tag(value: &str) -> Result { + match value { + "left" => Ok(0), + "right" => Ok(1), + _ => Err(SourceError::Contract), + } +} + +fn pack_node_relation( + bytes: &mut Vec, + rows: &[String], + indices: &BTreeMap, +) -> Result<(), SourceError> { + bytes.push(relation_count(rows)?); + for name in rows { + bytes.push(*indices.get(name).ok_or(SourceError::Contract)?); + } + Ok(()) +} + +fn pack_route_relation( + bytes: &mut Vec, + rows: &[(String, String)], + indices: &BTreeMap, +) -> Result<(), SourceError> { + bytes.push(relation_count(rows)?); + for (name, result) in rows { + bytes.extend([ + *indices.get(name).ok_or(SourceError::Contract)?, + route_tag(result)?, + ]); + } + Ok(()) +} + +/// Seven length-prefixed relation groups in the order used by the Scheme +/// decoder. Node identities are positions in the already bound topology. +fn pack_governor_facts( + cut: &crate::GovernorCut, + indices: &BTreeMap, +) -> Result, SourceError> { + let mut bytes = Vec::with_capacity( + 7 + cut.complete.len() + + cut.available.len() + + cut.pending.len() + + cut.choice_result.len() + + cut.choice_decided.len() + + 2 * (cut.nested_results.len() + cut.nested_decisions.len()), + ); + for rows in [&cut.complete, &cut.available, &cut.pending] { + pack_node_relation(&mut bytes, rows, indices)?; + } + bytes.push(relation_count(&cut.choice_result)?); + for result in &cut.choice_result { + bytes.push(route_tag(result)?); + } + pack_node_relation(&mut bytes, &cut.choice_decided, indices)?; + for rows in [&cut.nested_results, &cut.nested_decisions] { + pack_route_relation(&mut bytes, rows, indices)?; + } + Ok(bytes) +} + +/// The bound reply is one generation followed by at most 64 node indices. +/// Borrow the SDK snapshot instead of allocating a root and a general integer +/// buffer per element. No Scheme reference escapes this synchronous owner call. +fn materialize_indices( + output: RootedSchemeObject<'_>, + binding: u64, + node_count: usize, +) -> Result, SourceError> { + if node_count > 64 { + return Err(SourceError::Bound); + } + let sequence = output + .into_collection(CollectionKind::Vector) + .map_err(|_| SourceError::Contract)?; + // Include the binding: a full 64-node result legitimately has 65 elements. + if sequence.is_empty() || sequence.len() > node_count + 1 { + return Err(SourceError::Contract); + } + let mut entries = RootedObjectBatch::default(); + sequence + .copy_into(&mut entries) + .map_err(|_| SourceError::Scheme)?; + let mut observed = BigIntegerBuffer::default(); + entries + .get(0) + .ok_or(SourceError::Contract)? + .copy_big_integer(&mut observed) + .map_err(|_| SourceError::Contract)?; + let observed = observed.value(); + if observed.is_negative() || observed.magnitude().len() > 8 { + return Err(SourceError::Contract); + } + let mut bytes = [0; 8]; + bytes[..observed.magnitude().len()].copy_from_slice(observed.magnitude()); + if u64::from_le_bytes(bytes) != binding { + return Err(SourceError::Contract); + } + (1..entries.len()) + .map(|position| { + match entries + .get(position) + .ok_or(SourceError::Contract)? + .scalar() + .map_err(|_| SourceError::Contract)? + { + SchemeScalar::Fixnum(index) => usize::try_from(index) + .ok() + .filter(|&index| index < node_count) + .ok_or(SourceError::Contract), + _ => Err(SourceError::Contract), + } + }) + .collect() +} + +#[cfg(test)] +fn bound_indices( + reply: Vec, + binding: u64, + node_count: usize, +) -> Result, SourceError> { + let (observed, indices) = reply.split_first().ok_or(SourceError::Contract)?; + if *observed != binding || indices.len() > node_count { + return Err(SourceError::Contract); + } + indices + .iter() + .map(|&index| { + usize::try_from(index) + .ok() + .filter(|&index| index < node_count) + .ok_or(SourceError::Contract) + }) + .collect() +} + +#[cfg(test)] +#[test] +fn governor_indices_reject_stale_binding_and_foreign_node() { + assert_eq!( + bound_indices(vec![3, 1, 0], 3, 2).expect("valid bound indices"), + [1, 0] + ); + assert!(bound_indices(vec![2, 1], 3, 2).is_err()); + assert!(bound_indices(vec![3, 2], 3, 2).is_err()); + assert!(bound_indices(Vec::new(), 3, 2).is_err()); +} + +#[cfg(test)] +#[test] +fn rooted_governor_indices_preserve_full_width_binding_and_all_64_candidates() { + let compiler = SchemeCompiler::initialize().expect("approved linked application"); + let vm = &compiler.runtime; + let input = crate::scheme_input::values::Input::new(vm); + let vector = |values: Vec>| { + vm.collection_from_objects(CollectionKind::Vector, &values.iter().collect::>()) + .expect("native vector") + .into_object() + }; + let reply = |values: &[u64]| { + vector( + values + .iter() + .map(|&value| input.number(value).expect("exact integer")) + .collect(), + ) + }; + for binding in [0, 3, u64::MAX] { + for count in [0, 1, 2, 32, 63, 64] { + let mut values = vec![binding]; + values.extend((0..count as u64).rev()); + let expected = bound_indices(values.clone(), binding, count).expect("reference"); + assert_eq!( + materialize_indices(reply(&values), binding, count).expect("typed result"), + expected + ); + if count < 64 { + assert_eq!( + crate::scheme::materialize::>(reply(&values)).expect("general result"), + values + ); + } else { + assert!(matches!( + crate::scheme::materialize::>(reply(&values)), + Err(SourceError::Bound) + )); + } + } + } + // Repeated candidates retain the previous contract; the Session consumer + // sorts/deduplicates them before any deciding transaction. + assert_eq!( + materialize_indices(reply(&[3, 1, 1]), 3, 2).expect("repeated candidate"), + [1, 1] + ); + for values in [&[][..], &[2, 1], &[3, 2], &[3, u64::MAX], &[3, 0, 1, 0]] { + assert!(materialize_indices(reply(values), 3, 2).is_err()); + } + assert!(materialize_indices(reply(&[3]), 3, 65).is_err()); + for value in [ + SchemeScalar::Boolean(false), + SchemeScalar::Fixnum(-1), + SchemeScalar::Flonum(1.0), + SchemeScalar::Char('a'), + ] { + let malformed = || vm.scalar_object(value).expect("malformed scalar"); + assert!(materialize_indices(malformed(), 3, 2).is_err()); + assert!( + materialize_indices( + vector(vec![input.number(3).expect("binding"), malformed()]), + 3, + 2 + ) + .is_err() + ); + assert!(materialize_indices(vector(vec![malformed()]), 3, 2).is_err()); + } + let wide = gerbil_scheme::BinaryInteger::new(false, vec![1; 9]).expect("wide integer"); + assert!( + materialize_indices( + vector(vec![vm.big_integer(&wide).expect("wide root")]), + 3, + 2 + ) + .is_err() + ); + // A decline cannot poison the owner or replay the previous successful set. + assert_eq!( + materialize_indices(reply(&[4, 0]), 4, 2).expect("replacement binding"), + [0] + ); +} diff --git a/crates/governance/src/scheme_input/values.rs b/crates/governance/src/scheme_input/values.rs index a32d4f3a..a17083c3 100644 --- a/crates/governance/src/scheme_input/values.rs +++ b/crates/governance/src/scheme_input/values.rs @@ -45,6 +45,11 @@ impl<'r> Input<'r> { self.bytes(value.len())?; Ok(scheme_result(self.vm.string_from_utf8(value))?.into_object()) } + pub(crate) fn bytes_vector(&self, value: &[u8]) -> Result> { + self.node()?; + self.bytes(value.len())?; + Ok(scheme_result(self.vm.bytevector_from_bytes(value))?.into_object()) + } pub(crate) fn number(&self, value: u64) -> Result> { self.node()?; let mut bytes = value.to_le_bytes().to_vec(); diff --git a/crates/governance/tests/unit/host.rs b/crates/governance/tests/unit/host.rs index 364d322f..cd3cdc3f 100644 --- a/crates/governance/tests/unit/host.rs +++ b/crates/governance/tests/unit/host.rs @@ -119,16 +119,18 @@ async fn governor_observation_waits_for_capacity_or_shutdown() { .submit(original()) .expect("occupy the only slot"); let observation = owner.client.derive(crate::GovernorCut { - nodes: vec!["next".into()], - edges: vec![], + topology: Arc::new(crate::GovernorTopology { + nodes: vec!["next".into()], + edges: vec![], + choice_arms: vec![], + choice_join: vec![], + nested_selectors: vec![], + }), complete: vec![], available: vec!["next".into()], pending: vec!["next".into()], - choice_arms: vec![], - choice_join: vec![], choice_result: vec![], choice_decided: vec![], - nested_selectors: vec![], nested_results: vec![], nested_decisions: vec![], }); @@ -150,7 +152,10 @@ async fn governor_observation_waits_for_capacity_or_shutdown() { if close_owner { assert_eq!(result, Err(SourceJobError::Closed)); } else { - assert_eq!(result.expect("derived"), ["next"]); + assert_eq!( + result.expect("derived"), + crate::DerivationOutput::Nodes(vec!["next".into()]) + ); } } } diff --git a/crates/ledger/Cargo.toml b/crates/ledger/Cargo.toml index 0f75dc66..2cea95f0 100644 --- a/crates/ledger/Cargo.toml +++ b/crates/ledger/Cargo.toml @@ -10,7 +10,7 @@ license.workspace = true [features] default = [] # Explicitly selected by the observed server's dev dependency, never by its binary. -commit-observer = [] +commit-observer = ["dep:rustix", "dep:tracing", "dep:tracing-subscriber"] [dependencies] weaver-contracts.workspace = true weaver-policy.workspace = true @@ -18,6 +18,10 @@ mrr-data-backend.workspace = true futures-executor.workspace = true serde_json.workspace = true serde.workspace = true +tracing = { version = "0.1.44", optional = true, default-features = false, features = ["std"] } +tracing-subscriber = { version = "0.3.23", optional = true, default-features = false, features = ["registry"] } +[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies] +rustix = { version = "1.1.5", default-features = false, features = ["time"], optional = true } [dev-dependencies] # Standard Cargo self dev-dependency: tests/benches expose fault-host APIs; production does not. weaver-ledger = { workspace = true, features = ["commit-observer"] } diff --git a/crates/ledger/src/domains/evidence.rs b/crates/ledger/src/domains/evidence.rs index 7656ab16..d707ac4b 100644 --- a/crates/ledger/src/domains/evidence.rs +++ b/crates/ledger/src/domains/evidence.rs @@ -22,24 +22,9 @@ pub(crate) fn require_view( if current.canonical_family != current.family { return Err(Error::Conflict("alias has no independent original claim")); } - let rows = persistence::read_all_current( - tx, - "SELECT canonical_family FROM execution_origins WHERE budget_root=?1", - [current.stamp.budget_root.as_str()], - |r| r.get::(0), - ) - .map_err(db)?; - let origins = persistence::read_all_current( - tx, - "SELECT id,canonical_family FROM execution_origins WHERE history_root=?1", - [current.stamp.history_root.as_str()], - |r| Ok((r.get::(0)?, r.get::(1)?)), - ) - .map_err(db)?; - let mut history_members: HistoryMembers = origins - .into_iter() - .map(|(origin, family)| (family, (origin, None))) - .collect(); + let (rows, mut history_members) = tx.provider_claim_membership(|| { + membership(tx, ¤t.stamp.budget_root, ¤t.stamp.history_root) + })?; let mut held = 0u64; for member in rows { let (verified, amount) = @@ -59,6 +44,32 @@ pub(crate) fn require_view( require_history(tx, current, history_members, prepared) } +fn membership( + tx: &WriteScope<'_>, + budget_root: &str, + history_root: &str, +) -> Result<(Vec, HistoryMembers)> { + let rows = persistence::read_all_current( + tx, + "SELECT canonical_family FROM execution_origins WHERE budget_root=?1", + [budget_root], + |r| r.get::(0), + ) + .map_err(db)?; + let origins = persistence::read_all_current( + tx, + "SELECT id,canonical_family FROM execution_origins WHERE history_root=?1", + [history_root], + |r| Ok((r.get::(0)?, r.get::(1)?)), + ) + .map_err(db)?; + let history_members: HistoryMembers = origins + .into_iter() + .map(|(origin, family)| (family, (origin, None))) + .collect(); + Ok((rows, history_members)) +} + fn verified_family( tx: &WriteScope<'_>, family: &str, diff --git a/crates/ledger/src/domains/view.rs b/crates/ledger/src/domains/view.rs index 1a51bc13..3b922678 100644 --- a/crates/ledger/src/domains/view.rs +++ b/crates/ledger/src/domains/view.rs @@ -12,7 +12,7 @@ use weaver_contracts::{DomainStamp, DomainView, Error, Result}; const DOMAIN_VIEW: &str = "SELECT o.id,o.canonical_family,o.budget_root,o.history_root,b.epoch,h.epoch,b.ceiling,b.held,h.events,registration.task_key FROM family_origins f JOIN execution_origins o ON o.id=f.origin JOIN original_tasks registration ON registration.origin=o.id AND registration.family=o.canonical_family JOIN budget_domains b ON b.id=o.budget_root AND b.root=b.id JOIN history_domains h ON h.id=o.history_root AND h.root=h.id JOIN budget_domains original_budget ON original_budget.id=json_extract(o.binding,'$.budget') AND original_budget.root=b.id AND original_budget.declared_limit=json_extract(o.binding,'$.budget_limit') JOIN history_domains original_history ON original_history.id=json_extract(o.binding,'$.history') AND original_history.root=h.id WHERE f.family=?1 AND json_extract(o.binding,'$.origin')=o.id"; pub(crate) fn view(connection: &driver::Connection, family: &str) -> Result { - require_view(persistence::maybe( + require_view(persistence::maybe_prepared( connection, DOMAIN_VIEW, [family], @@ -55,11 +55,12 @@ pub(crate) fn provider_view(tx: &WriteScope<'_>, family: &str) -> Result>) -> Result { diff --git a/crates/ledger/src/execution_exposure.rs b/crates/ledger/src/execution_exposure.rs index b3b34de0..5a7a8613 100644 --- a/crates/ledger/src/execution_exposure.rs +++ b/crates/ledger/src/execution_exposure.rs @@ -5,7 +5,7 @@ //! One deciding projection for all retained execution kinds; never repairs authority. use crate::persistence::WriteScope; use crate::store::db; -use weaver_contracts::{Error, MessageBinding, Proposal, ProviderPlan, Result}; +use weaver_contracts::{Error, MessageBinding, MeteringDeployment, Proposal, ProviderPlan, Result}; pub(crate) enum ClaimKind { Request, @@ -129,13 +129,31 @@ pub(crate) fn provider( |r| r.get(0), ).map_err(db)?; require(matches)?; - if let Some(config) = crate::metering::deployment(tx)? { - crate::provider_quota::require(tx, &config, &plan.family, &plan.node)?; - crate::metering::require_quote(tx, &config, plan, digest)?; - } + provider_metering(tx, plan, digest)?; crate::domains::require_view(tx, current, prepared) } +pub(crate) fn provider_metering( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + digest: &str, +) -> Result<()> { + provider_metering_with_deployment(tx, plan, digest, crate::metering::deployment(tx)?.as_ref()) +} + +pub(crate) fn provider_metering_with_deployment( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + digest: &str, + deployment: Option<&MeteringDeployment>, +) -> Result<()> { + if let Some(config) = deployment { + crate::provider_quota::require(tx, config, &plan.family, &plan.node)?; + crate::metering::require_quote(tx, config, plan, digest)?; + } + Ok(()) +} + fn require(retained: bool) -> Result<()> { if retained { Ok(()) diff --git a/crates/ledger/src/exposure_manifest.rs b/crates/ledger/src/exposure_manifest.rs index a8f48157..8d06b023 100644 --- a/crates/ledger/src/exposure_manifest.rs +++ b/crates/ledger/src/exposure_manifest.rs @@ -72,24 +72,73 @@ impl<'de> Deserialize<'de> for Members { } pub(crate) type Family = BTreeMap<(String, String, String), Member>; +const COMMITTED: &str = "SELECT node,kind,reservations FROM execution_claims WHERE family=?1"; +const PROJECTED: &str = + "SELECT node,'' AS member,digest,reserved,'request' AS kind,json_extract(proposal,'$.ceiling') AS original FROM operations WHERE family=?1 + UNION ALL SELECT node,message,digest,reserved,'stream',json_extract(proposal,'$.ceiling') FROM stream_messages WHERE family=?1 + UNION ALL SELECT node,'',digest,reserved,'provider',json_extract(plan,'$.ceiling') FROM provider_runs WHERE family=?1"; + +#[cfg(feature = "commit-observer")] +thread_local! { + static PREPARE_MANIFEST_PROGRAMS: std::cell::Cell = const { std::cell::Cell::new(true) }; +} + +/// Select fixed manifest program preflight in the observed worker. +#[cfg(feature = "commit-observer")] +pub fn use_prepared_manifest_programs(prepared: bool) { + PREPARE_MANIFEST_PROGRAMS.set(prepared); +} + +pub(crate) fn warm_programs(connection: &persistence::driver::Connection) { + if prepared_programs() { + for sql in [COMMITTED, PROJECTED] { + let _ = futures_executor::block_on(connection.prepare_cached(sql)); + } + } +} + +fn prepared_programs() -> bool { + #[cfg(feature = "commit-observer")] + { + PREPARE_MANIFEST_PROGRAMS.get() + } + #[cfg(not(feature = "commit-observer"))] + { + true + } +} + +fn read_members( + tx: &WriteScope<'_>, + sql: &'static str, + family: &str, + decode: impl FnMut(&persistence::Row) -> persistence::driver::Result, +) -> Result> { + tx.provider_manifest_reads(|| { + let rows = persistence::read_all_manifest( + tx, + sql, + family, + prepared_programs(), + sql == PROJECTED, + decode, + ); + rows.map_err(db) + }) +} + fn conflict() -> Error { Error::Conflict("original claims or shared execution exposure not retained") } fn committed(tx: &WriteScope<'_>, family: &str) -> Result { - let rows = persistence::read_all_current( - tx, - "SELECT node,kind,reservations FROM execution_claims WHERE family=?1", - [family], - |r| { - Ok(( - r.get::(0)?, - r.get::(1)?, - r.get::(2)?, - )) - }, - ) - .map_err(db)?; + let rows = read_members(tx, COMMITTED, family, |r| { + Ok(( + r.get::(0)?, + r.get::(1)?, + r.get::(2)?, + )) + })?; let mut result = Family::new(); for (node, kind, body) in rows { if !matches!(kind.as_str(), "request" | "stream" | "provider") { @@ -112,11 +161,16 @@ fn committed(tx: &WriteScope<'_>, family: &str) -> Result { } fn projected(tx: &WriteScope<'_>, family: &str) -> Result<(Family, u64)> { - let rows=persistence::read_all_current(tx, - "SELECT node,'' AS member,digest,reserved,'request' AS kind,json_extract(proposal,'$.ceiling') AS original FROM operations WHERE family=?1 - UNION ALL SELECT node,message,digest,reserved,'stream',json_extract(proposal,'$.ceiling') FROM stream_messages WHERE family=?1 - UNION ALL SELECT node,'',digest,reserved,'provider',json_extract(plan,'$.ceiling') FROM provider_runs WHERE family=?1", - [family],|r|Ok((r.get::(0)?,r.get::(1)?,r.get::(2)?,integer(r,3)?,r.get::(4)?,integer(r,5)?))).map_err(db)?; + let rows = read_members(tx, PROJECTED, family, |r| { + Ok(( + r.get::(0)?, + r.get::(1)?, + r.get::(2)?, + integer(r, 3)?, + r.get::(4)?, + integer(r, 5)?, + )) + })?; let mut result = Family::new(); let mut total = 0u64; for (node, id, digest, ceiling, kind, original) in rows { diff --git a/crates/ledger/src/hard_fact.rs b/crates/ledger/src/hard_fact.rs index 4ff363ef..d141e581 100644 --- a/crates/ledger/src/hard_fact.rs +++ b/crates/ledger/src/hard_fact.rs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 //! One local ordered fact feed. Staging and installation are separate authority transactions. +use std::collections::BTreeSet; + use crate::{ Ledger, persistence::{begin, driver::Connection, exec, maybe_current, params}, @@ -145,6 +147,67 @@ fn selects(feed: &FactFeed, node: &str) -> bool { || feed.workflow_selectors.iter().any(|row| row[0] == node) } +pub(crate) struct WorkflowFacts { + pub(crate) feed: FactFeed, + pub(crate) floor: u64, + pub(crate) snapshot: String, + pub(crate) available: Vec, +} + +/// Read the exact deployed topology and availability in one observation. +pub(crate) fn observe_workflow<'a>( + c: &Connection, + family: &str, + successor: &str, + nodes: impl IntoIterator, +) -> Result { + let (record, floor, snapshot, revision, pending, unavailable) = maybe_current( + c, + "SELECT record,floor,snapshot,revision,pending IS NOT NULL,unavailable + FROM main.hard_fact_feed WHERE singleton=1 AND family=?1", + params![family.to_owned()], + |row| { + Ok(( + row.get::(0)?, + integer(row, 1)?, + row.get::(2)?, + integer(row, 3)?, + row.get::(4)?, + row.get::(5)?, + )) + }, + ) + .map_err(db)? + .ok_or(Error::Conflict("Session fact scope changed"))?; + let feed: FactFeed = decode(record.as_bytes())?; + if feed.family != family || feed.workflow_predecessors(successor).is_empty() { + return Err(Error::Conflict("Session fact cut unavailable")); + } + let mut available = Vec::new(); + if revision != 0 && !pending { + let unavailable: BTreeSet = decode(unavailable.as_bytes())?; + available.extend( + nodes + .into_iter() + .filter(|node| !unavailable.contains(*node)) + .map(str::to_owned), + ); + } + if !available.is_empty() { + match source_authority::current(c) { + Ok(authority) if authority.as_ref() == Some(&feed.authority) => {} + Ok(_) | Err(Error::Conflict(_)) => available.clear(), + Err(error) => return Err(error), + } + } + Ok(WorkflowFacts { + feed, + floor, + snapshot, + available, + }) +} + pub(crate) fn is_workflow_selector(c: &Connection, family: &str, node: &str) -> Result { Ok(head(c)?.is_some_and(|head| head.feed.family == family && selects(&head.feed, node))) } diff --git a/crates/ledger/src/lib.rs b/crates/ledger/src/lib.rs index 6bf7fd86..b328663f 100644 --- a/crates/ledger/src/lib.rs +++ b/crates/ledger/src/lib.rs @@ -19,6 +19,8 @@ mod execution_exposure; mod hard_fact; pub use hard_fact::FactPreparation; mod exposure_manifest; +#[cfg(feature = "commit-observer")] +pub use exposure_manifest::use_prepared_manifest_programs; mod metering; mod metering_credentials; mod provider; @@ -30,6 +32,7 @@ pub use provider_delivery::{ ProviderDelivery, }; mod provider_catalog; +pub use provider_catalog::ProviderCatalogProjection; mod provider_oauth; mod provider_oauth_witness; mod provider_profiles; @@ -75,6 +78,8 @@ mod stream_ranges; mod stream_state; mod task_publication; pub use store::{Dispatch, Ledger}; +#[cfg(feature = "commit-observer")] +pub use store::ParkedProviderConnection; pub(crate) use store::{db, integer}; pub use stream_custody::{StreamClaim, StreamOwner}; pub use stream_ranges::RangePermit; @@ -83,7 +88,7 @@ pub use stream_ranges::RangePermit; asp_rust::asp_rust_cargo_test_gate!(mode = deny, config = asp_rust::default_asp_rust_config()); #[cfg(feature = "commit-observer")] -pub use task_origins::use_locked_original_evidence; +pub use task_origins::{use_locked_original_evidence, use_prepared_original_program}; #[cfg(feature = "commit-observer")] pub use domains::use_fresh_provider_domain_plan; diff --git a/crates/ledger/src/persistence/driver_observer.rs b/crates/ledger/src/persistence/driver_observer.rs new file mode 100644 index 00000000..ed49ebc3 --- /dev/null +++ b/crates/ledger/src/persistence/driver_observer.rs @@ -0,0 +1,245 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Observe Turso driver spans during BEGIN and COMMIT. +use super::timing::{Timing, thread_cpu_time}; +use std::{ + cell::RefCell, + sync::OnceLock, + time::{Duration, Instant}, +}; +use tracing::{Dispatch, Metadata, Subscriber, span::Id, subscriber::NoSubscriber}; +use tracing_subscriber::{ + Layer, + filter::dynamic_filter_fn, + layer::{Context, SubscriberExt}, + registry::LookupSpan, +}; + +const UNIX_IO_NAMES: [&str; 6] = ["pread", "pwrite", "pwritev", "sync", "size", "truncate"]; + +#[derive(Default)] +struct SpanTiming { + depth: usize, + start: Option<(Instant, Option)>, + wall: Timing, + cpu: Timing, +} + +impl SpanTiming { + fn enter(&mut self) { + if self.depth == 0 { + self.start = Some((Instant::now(), thread_cpu_time())); + } + self.depth += 1; + } + + fn exit(&mut self) { + self.depth -= 1; + if self.depth == 0 + && let Some((wall, cpu)) = self.start.take() + { + if let (Some(cpu), Some(end)) = (cpu, thread_cpu_time()) + && let Some(elapsed) = end.checked_sub(cpu) + { + self.cpu.record(elapsed); + } + self.wall.record(wall.elapsed()); + } + } + + fn counters(&self) -> [u64; 3] { + [self.wall.nanos, self.cpu.nanos, self.wall.attempts] + } +} + +/// Union of Unix I/O spans, followed by each fixed I/O kind. Kind intervals may overlap. +#[derive(Clone, Copy, Default)] +pub(super) struct CommitIo { + rows: [[u64; 3]; 7], +} + +impl CommitIo { + pub(super) fn append(observation: Option, line: &mut String) { + use std::fmt::Write; + let _ = write!(line, ":{}", u8::from(observation.is_some())); + for row in observation.unwrap_or_default().rows { + let [wall, cpu, calls] = row; + let _ = write!(line, ":{wall}:{cpu}:{calls}"); + } + } +} + +#[derive(Default)] +struct Observation { + span: Option, + selected: SpanTiming, + capture_io: bool, + io_total: SpanTiming, + io: [SpanTiming; 6], +} + +impl Observation { + fn enter(&mut self, observed: Option, io: Option) { + if observed.is_some() && observed == self.span { + self.selected.enter(); + } + if self.capture_io + && let Some(kind) = io + { + self.io_total.enter(); + self.io[kind].enter(); + } + } + + fn exit(&mut self, observed: Option, io: Option) { + if self.capture_io + && let Some(kind) = io + { + self.io[kind].exit(); + self.io_total.exit(); + } + if observed.is_some() && observed == self.span { + self.selected.exit(); + } + } + + fn commit_io(&self) -> CommitIo { + CommitIo { + rows: std::array::from_fn(|index| { + if index == 0 { + self.io_total.counters() + } else { + self.io[index - 1].counters() + } + }), + } + } +} + +fn unix_io_kind(meta: &Metadata<'_>) -> Option { + (meta.target() == "turso_core::io::unix") + .then(|| UNIX_IO_NAMES.iter().position(|name| *name == meta.name())) + .flatten() +} + +thread_local! { + static SAMPLE: RefCell = RefCell::default(); +} + +struct DriverLayer; + +impl LookupSpan<'span>> Layer for DriverLayer { + fn on_enter(&self, id: &Id, context: Context<'_, S>) { + if let Some(span) = context.span(id) { + let meta = span.metadata(); + SAMPLE.with_borrow_mut(|sample| { + sample.enter(DriverSpan::identify(meta), unix_io_kind(meta)) + }); + } + } + + fn on_exit(&self, id: &Id, context: Context<'_, S>) { + if let Some(span) = context.span(id) { + let meta = span.metadata(); + SAMPLE.with_borrow_mut(|sample| { + sample.exit(DriverSpan::identify(meta), unix_io_kind(meta)) + }); + } + } +} + +#[derive(Clone, Copy, PartialEq, Eq)] +pub(super) enum DriverSpan { + Prepare, + UnixSync, +} + +impl DriverSpan { + fn identify(meta: &Metadata<'_>) -> Option { + match (meta.target(), meta.name()) { + ("turso_core::connection", "_prepare") => Some(Self::Prepare), + ("turso_core::io::unix", "sync") => Some(Self::UnixSync), + _ => None, + } + } +} + +fn driver_dispatch() -> &'static Dispatch { + static DRIVER: OnceLock<(Dispatch, Dispatch)> = OnceLock::new(); + let (_, observer) = DRIVER.get_or_init(|| { + // With one registered dispatcher, tracing caches a new callsite's + // interest from the registering thread's current default. Keep a + // silent dispatcher registered so interest accounts for both observed + // and unobserved calls regardless of which thread reaches Turso first. + let silent = Dispatch::new(NoSubscriber::new()); + let layer = DriverLayer.with_filter(dynamic_filter_fn(|meta, _| { + meta.is_span() + && (DriverSpan::identify(meta).is_some() + || (unix_io_kind(meta).is_some() + && SAMPLE.with_borrow(|sample| sample.capture_io))) + })); + let observer = Dispatch::new(tracing_subscriber::registry().with(layer)); + (silent, observer) + }); + observer +} + +fn observe_sample( + span: DriverSpan, + capture_io: bool, + run: impl FnOnce() -> T, +) -> (T, Observation) { + let dispatch = driver_dispatch(); + SAMPLE.with_borrow_mut(|sample| { + *sample = Observation { + span: Some(span), + capture_io, + ..Observation::default() + } + }); + let result = tracing::dispatcher::with_default(dispatch, run); + (result, SAMPLE.take()) +} + +pub(super) fn observe(span: DriverSpan, run: impl FnOnce() -> T) -> (T, Timing, Timing) { + let (result, observation) = observe_sample(span, false, run); + (result, observation.selected.wall, observation.selected.cpu) +} + +pub(super) fn observe_commit( + capture_io: bool, + run: impl FnOnce() -> T, +) -> (T, Timing, Option) { + let (result, observation) = observe_sample(DriverSpan::UnixSync, capture_io, run); + let io = capture_io.then(|| observation.commit_io()); + (result, observation.selected.wall, io) +} + +#[cfg(test)] +#[path = "../../tests/unit/driver_observer.rs"] +mod tests; + +/// Wall, poll wall/CPU, prepare wall/CPU, pending, polls, and reads. +pub(super) fn observe_read(future: F) -> (F::Output, [u64; 8]) { + let start = Instant::now(); + let (mut poll, mut cpu, mut pending) = (Timing::default(), Timing::default(), 0); + let (result, prepare, prepare_cpu) = observe(DriverSpan::Prepare, || { + super::timing::observe_polls(future, &mut poll, &mut cpu, &mut pending) + }); + let wall = u64::try_from(start.elapsed().as_nanos()).unwrap_or(u64::MAX); + ( + result, + [ + wall, + poll.nanos, + cpu.nanos, + prepare.nanos, + prepare_cpu.nanos, + pending, + poll.attempts, + 1, + ], + ) +} diff --git a/crates/ledger/src/persistence/mod.rs b/crates/ledger/src/persistence/mod.rs index 59c89381..8a23deb6 100644 --- a/crates/ledger/src/persistence/mod.rs +++ b/crates/ledger/src/persistence/mod.rs @@ -12,6 +12,8 @@ pub(crate) mod scheduler; pub(crate) use catalog::engine_metadata; #[cfg(any(test, feature = "commit-observer"))] pub mod commit_observer; +#[cfg(feature = "commit-observer")] +mod driver_observer; mod query; mod scope; mod scope_keys; @@ -23,6 +25,8 @@ mod session; mod timing; pub use mrr_data_backend::turso_driver::{self as driver, Error, Result, Row, params}; pub use owner::Journal; +pub(crate) use query::maybe_prepared; +pub(crate) use query::read_all_manifest; #[cfg(feature = "commit-observer")] pub use query::use_cached_currentness_plans; pub use query::{exec, maybe, one, read_all, script}; @@ -34,6 +38,9 @@ pub(crate) use scope::ProviderScopePhase; pub use scope::{WriteScope, begin}; pub(crate) use scope::{ begin_family, begin_provider_admission, begin_provider_lifecycle, begin_provider_progress, + begin_workflow_observation, }; pub use session::{LedgerCustody, Session}; +#[cfg(feature = "commit-observer")] +pub use timing::provider_observation_nanos; pub use timing::{Timing, TransactionTimings}; diff --git a/crates/ledger/src/persistence/query.rs b/crates/ledger/src/persistence/query.rs index e480ba16..7b9b2216 100644 --- a/crates/ledger/src/persistence/query.rs +++ b/crates/ledger/src/persistence/query.rs @@ -103,6 +103,57 @@ pub(crate) fn read_all_current( block_on(async { decode_all(currentness_rows(connection, sql, params).await?, decode).await }) } +pub(crate) fn read_all_manifest( + tx: &super::WriteScope<'_>, + sql: &'static str, + family: &str, + prepared: bool, + projected: bool, + decode: impl FnMut(&Row) -> Result, +) -> Result> { + let read = async { + let rows = if prepared { + tx.prepare_cached(sql).await?.query([family]).await? + } else { + currentness_rows(tx, sql, [family]).await? + }; + decode_all(rows, decode).await + }; + #[cfg(feature = "commit-observer")] + { + tx.observe_manifest_driver(projected, read) + } + #[cfg(not(feature = "commit-observer"))] + { + let _ = projected; + block_on(read) + } +} + +/// Execute a fixed query returning at most one row. Reach Done before dropping +/// its cursor so the engine can finish the read instead of aborting it. +pub(crate) fn maybe_prepared( + connection: &Connection, + sql: &'static str, + params: impl IntoParams, + decode: impl FnOnce(&Row) -> Result, +) -> Result> { + block_on(async { + let mut statement = connection.prepare_cached(sql).await?; + let mut rows = statement.query(params).await?; + let Some(row) = rows.next().await? else { + return Ok(None); + }; + let value = decode(&row)?; + if rows.next().await?.is_some() { + return Err(Error::Misuse( + "prepared singleton query returned multiple rows".into(), + )); + } + Ok(Some(value)) + }) +} + async fn decode_all( mut rows: super::driver::Rows, mut decode: impl FnMut(&Row) -> Result, diff --git a/crates/ledger/src/persistence/scheduler.rs b/crates/ledger/src/persistence/scheduler.rs index ea510192..df5065b3 100644 --- a/crates/ledger/src/persistence/scheduler.rs +++ b/crates/ledger/src/persistence/scheduler.rs @@ -183,16 +183,38 @@ impl Grant<'_> { impl Drop for Grant<'_> { fn drop(&mut self) { + #[cfg(feature = "commit-observer")] + let requested = super::scope_trace::capturing_release().then(std::time::Instant::now); let mut state = self .scheduler .state .lock() .unwrap_or_else(std::sync::PoisonError::into_inner); + #[cfg(feature = "commit-observer")] + let locked = requested.map(|_| std::time::Instant::now()); state.active.retain(|ticket| ticket.id != self.id); if self.global { state.generation += 1; } + #[cfg(feature = "commit-observer")] + let removed = requested.map(|_| std::time::Instant::now()); self.scheduler.changed.notify_all(); + #[cfg(feature = "commit-observer")] + { + let notified = requested.map(|_| std::time::Instant::now()); + drop(state); + if let (Some(requested), Some(locked), Some(removed), Some(notified)) = + (requested, locked, removed, notified) + { + super::scope_trace::record_release(super::scope_trace::ReleaseTiming { + requested, + locked, + removed, + notified, + returned: std::time::Instant::now(), + }); + } + } } } diff --git a/crates/ledger/src/persistence/scope.rs b/crates/ledger/src/persistence/scope.rs index 076ba827..ce708ac3 100644 --- a/crates/ledger/src/persistence/scope.rs +++ b/crates/ledger/src/persistence/scope.rs @@ -24,6 +24,7 @@ pub enum ProviderScopePhase { enum Change<'a> { Semantic, + WorkflowObservation, Admission(&'a crate::provider::AdmissionRequest), Progress(&'a crate::provider::RangeProgress), Lifecycle(&'a crate::provider::OriginLifecycle), @@ -47,9 +48,17 @@ pub struct WriteScope<'a> { current_birth: Cell, current_profile: Cell, current_claim: Cell, + #[cfg(feature = "commit-observer")] + claim_membership: Cell, + #[cfg(feature = "commit-observer")] + manifest_reads: Cell, + #[cfg(feature = "commit-observer")] + manifest_driver: [Cell<[u64; 8]>; 2], current_history: Cell, current_manifest: Cell, current_original: Cell, + #[cfg(feature = "commit-observer")] + current_reservation: Cell, cedar: Cell, owner_entered: Option, domains_entered: Option, @@ -80,6 +89,20 @@ pub fn begin_family<'a>(session: &'a mut Session, family: &str) -> driver::Resul Change::Semantic, ) } + +/// Open the snapshot used to derive inert Workflow candidates. +pub(crate) fn begin_workflow_observation<'a>( + session: &'a mut Session, + family: &str, +) -> driver::Result> { + start( + session, + Some(family), + None, + ProviderScopePhase::Other, + Change::WorkflowObservation, + ) +} /// Queued execution waits for its deciding turn before closing. MVCC rechecks /// scheduler roots before SQL. WAL acquires the native writer before closing /// and performs admission inside that transaction. Source changes, OAuth @@ -187,7 +210,7 @@ fn start<'a>( .owner .authority .close_lifecycle(close_scope.clone(), proof)?, - Change::Semantic | Change::Admission(_) => { + Change::Semantic | Change::WorkflowObservation | Change::Admission(_) => { session.owner.authority.close(close_scope.clone())? } }) @@ -266,18 +289,44 @@ fn start<'a>( } else { authority.map(|close| (close, authority_entered)) }; - let parallel = concurrent && family.is_some(); + use driver::transaction::TransactionBehavior; + let behavior = if concurrent && family.is_some() { + TransactionBehavior::Concurrent + } else if matches!(change, Change::WorkflowObservation) { + TransactionBehavior::Deferred + } else { + TransactionBehavior::Immediate + }; // The mutable Session borrow provides exclusive custody for the whole scope. - let native = super::timing::measure(&mut session.timings.transaction_begin, || { - block_on(driver::transaction::Transaction::new_unchecked( - &session.connection, - if parallel { - driver::transaction::TransactionBehavior::Concurrent - } else { - driver::transaction::TransactionBehavior::Immediate - }, - )) - })?; + #[cfg(feature = "commit-observer")] + let begin_before = session.timings.transaction_begin.nanos; + #[cfg(feature = "commit-observer")] + let driver_before = scope_trace + .as_ref() + .filter(|trace| trace.has_timeline()) + .map(|_| session.timings.begin_driver_counters()); + let native = begin_driver_transaction( + &session.connection, + behavior, + &mut session.timings, + #[cfg(feature = "commit-observer")] + scope_trace.is_some(), + )?; + #[cfg(feature = "commit-observer")] + if let Some(trace) = scope_trace.as_mut() { + trace.opened( + session + .timings + .transaction_begin + .nanos + .saturating_sub(begin_before), + session.timings.commit.nanos, + driver_before.map_or([0; 6], |before| { + let after = session.timings.begin_driver_counters(); + std::array::from_fn(|i| after[i].saturating_sub(before[i])) + }), + ); + } let (authority, authority_entered) = if let Some(authority) = authority { authority } else { @@ -318,9 +367,17 @@ fn start<'a>( current_birth: Cell::default(), current_profile: Cell::default(), current_claim: Cell::default(), + #[cfg(feature = "commit-observer")] + claim_membership: Cell::default(), + #[cfg(feature = "commit-observer")] + manifest_reads: Cell::default(), + #[cfg(feature = "commit-observer")] + manifest_driver: Default::default(), current_history: Cell::default(), current_manifest: Cell::default(), current_original: Cell::default(), + #[cfg(feature = "commit-observer")] + current_reservation: Cell::default(), cedar: Cell::default(), owner_entered, domains_entered, @@ -331,6 +388,58 @@ fn start<'a>( observer: session.commit_observer.clone(), }) } + +fn begin_driver_transaction<'a>( + connection: &'a driver::Connection, + behavior: driver::transaction::TransactionBehavior, + timings: &mut super::TransactionTimings, + #[cfg(feature = "commit-observer")] observed: bool, +) -> driver::Result> { + let future = driver::transaction::Transaction::new_unchecked(connection, behavior); + super::timing::measure(&mut timings.transaction_begin, || { + #[cfg(feature = "commit-observer")] + if observed { + use super::driver_observer::{DriverSpan, observe}; + let (result, prepare, prepare_cpu) = observe(DriverSpan::Prepare, || { + super::timing::observe_polls( + future, + &mut timings.transaction_begin_poll, + &mut timings.transaction_begin_cpu, + &mut timings.transaction_begin_pending, + ) + }); + timings.transaction_begin_prepare.merge(prepare); + timings.transaction_begin_prepare_cpu.merge(prepare_cpu); + return result; + } + block_on(future) + }) +} +fn commit_driver_transaction( + native: driver::transaction::Transaction<'_>, + timings: &mut super::TransactionTimings, + #[cfg(feature = "commit-observer")] observed: Option<&mut super::scope_trace::Granted<'_>>, +) -> driver::Result<()> { + let future = native.commit(); + super::timing::measure(&mut timings.commit, || { + #[cfg(feature = "commit-observer")] + if let Some(trace) = observed { + use super::driver_observer::observe_commit; + let (result, sync, io) = observe_commit(trace.has_timeline(), || { + super::timing::observe_polls( + future, + &mut timings.commit_poll, + &mut timings.commit_cpu, + &mut timings.commit_pending, + ) + }); + timings.commit_sync.merge(sync); + trace.committed_io(io); + return result; + } + block_on(future) + }) +} impl WriteScope<'_> { pub(crate) fn project_metering( &mut self, @@ -455,6 +564,49 @@ impl WriteScope<'_> { pub(crate) fn provider_claim(&self, run: impl FnOnce() -> T) -> T { observe(&self.current_claim, run) } + pub(crate) fn provider_claim_membership(&self, run: impl FnOnce() -> T) -> T { + #[cfg(feature = "commit-observer")] + if self + .scope_trace + .as_ref() + .is_some_and(|trace| trace.has_timeline()) + { + return observe(&self.claim_membership, run); + } + run() + } + pub(crate) fn provider_manifest_reads(&self, run: impl FnOnce() -> T) -> T { + #[cfg(feature = "commit-observer")] + if self + .scope_trace + .as_ref() + .is_some_and(|trace| trace.has_timeline()) + { + return observe(&self.manifest_reads, run); + } + run() + } + #[cfg(feature = "commit-observer")] + pub(super) fn observe_manifest_driver( + &self, + projected: bool, + future: F, + ) -> F::Output { + if !self + .scope_trace + .as_ref() + .is_some_and(|trace| trace.has_timeline()) + { + return block_on(future); + } + let (result, sample) = super::driver_observer::observe_read(future); + let counter = &self.manifest_driver[usize::from(projected)]; + let previous = counter.get(); + counter.set(std::array::from_fn(|i| { + previous[i].saturating_add(sample[i]) + })); + result + } pub(crate) fn provider_original(&self, run: impl FnOnce() -> T) -> T { observe(&self.current_original, run) } @@ -464,6 +616,18 @@ impl WriteScope<'_> { pub(crate) fn provider_history(&self, run: impl FnOnce() -> T) -> T { observe(&self.current_history, run) } + #[cfg(feature = "commit-observer")] + pub(crate) fn provider_reservation(&self, run: impl FnOnce() -> T) -> T { + if self + .scope_trace + .as_ref() + .is_some_and(|trace| trace.has_timeline()) + { + observe(&self.current_reservation, run) + } else { + run() + } + } pub(crate) fn provider_cedar(&self, run: impl FnOnce() -> T) -> T { observe(&self.cedar, run) } @@ -484,7 +648,12 @@ impl WriteScope<'_> { .native .take() .ok_or_else(|| driver::Error::Misuse("transaction already ended".into()))?; - match super::timing::measure(&mut self.timings.commit, || block_on(native.commit())) { + match commit_driver_transaction( + native, + self.timings, + #[cfg(feature = "commit-observer")] + self.scope_trace.as_mut(), + ) { Ok(()) => { if let Some(config) = self.quota_update.take() { *self.quota_projection.lock().map_err(super::owner::error)? = Some(config); @@ -544,7 +713,8 @@ impl Drop for WriteScope<'_> { self.poisoned.store(true, Ordering::Release); let _ = release_failed_transaction(self.connection); } - self.timings.transaction_hold.record(self.entered.elapsed()); + let transaction_hold = self.entered.elapsed(); + self.timings.transaction_hold.record(transaction_hold); for (total, sample) in [ ( &mut self.timings.provider_oauth_check, @@ -583,6 +753,20 @@ impl Drop for WriteScope<'_> { self.timings .authority_span .record(self.authority_entered.elapsed()); + #[cfg(feature = "commit-observer")] + let releasing = self.scope_trace.as_ref().map(|_| Instant::now()); + #[cfg(feature = "commit-observer")] + let release = if self + .scope_trace + .as_ref() + .is_some_and(|trace| trace.has_timeline()) + { + super::scope_trace::observe_release(|| drop(self.grant.take())) + } else { + drop(self.grant.take()); + None + }; + #[cfg(not(feature = "commit-observer"))] drop(self.grant.take()); if let Some(entered) = self.domains_entered { self.timings.domain_hold.record(entered.elapsed()); @@ -591,8 +775,25 @@ impl Drop for WriteScope<'_> { self.timings.owner_gate_hold.record(entered.elapsed()); } #[cfg(feature = "commit-observer")] - if let Some(trace) = self.scope_trace.take() { - trace.record(self.authority_entered.elapsed()); + if let (Some(trace), Some(releasing)) = (self.scope_trace.take(), releasing) { + trace.record(super::scope_trace::Completion { + authority_span: self.authority_entered.elapsed(), + releasing, + transaction_nanos: u64::try_from(transaction_hold.as_nanos()).unwrap_or(u64::MAX), + commit_total: self.timings.commit.nanos, + admission_nanos: [ + self.current_claim.get().nanos, + self.current_original.get().nanos, + self.current_manifest.get().nanos, + self.current_history.get().nanos, + self.current_reservation.get().nanos, + self.cedar.get().nanos, + self.claim_membership.get().nanos, + self.manifest_reads.get().nanos, + ], + manifest_driver: self.manifest_driver.each_ref().map(Cell::get), + release, + }); } } } diff --git a/crates/ledger/src/persistence/scope_trace.rs b/crates/ledger/src/persistence/scope_trace.rs index 1d6f4e0a..4c3d3531 100644 --- a/crates/ledger/src/persistence/scope_trace.rs +++ b/crates/ledger/src/persistence/scope_trace.rs @@ -4,9 +4,66 @@ //! Bounded, observed-server timing records. No admission decisions use them. use super::ProviderScopePhase; -use std::time::{Duration, Instant}; +use std::{ + cell::Cell, + sync::OnceLock, + time::{Duration, Instant}, +}; pub(super) const CAPACITY: usize = 64; +#[derive(Clone, Copy)] +pub(super) struct ReleaseTiming { + pub requested: Instant, + pub locked: Instant, + pub removed: Instant, + pub notified: Instant, + pub returned: Instant, +} + +pub(super) struct Completion { + pub authority_span: Duration, + pub releasing: Instant, + pub transaction_nanos: u64, + pub commit_total: u64, + pub admission_nanos: [u64; 8], + pub manifest_driver: [[u64; 8]; 2], + pub release: Option, +} + +#[derive(Clone, Copy)] +enum ReleaseCapture { + Idle, + Armed, + Complete(ReleaseTiming), +} + +thread_local! { + static RELEASE: Cell = const { Cell::new(ReleaseCapture::Idle) }; +} + +pub(super) fn observe_release(release: impl FnOnce()) -> Option { + struct Restore(ReleaseCapture); + impl Drop for Restore { + fn drop(&mut self) { + RELEASE.set(self.0); + } + } + let _restore = Restore(RELEASE.replace(ReleaseCapture::Armed)); + release(); + match RELEASE.get() { + ReleaseCapture::Complete(timing) => Some(timing), + _ => None, + } +} + +pub(super) fn capturing_release() -> bool { + matches!(RELEASE.get(), ReleaseCapture::Armed) +} + +pub(super) fn record_release(timing: ReleaseTiming) { + RELEASE.set(ReleaseCapture::Complete(timing)); +} + pub(super) struct Arrival { phase: ProviderScopePhase, order: u64, @@ -19,6 +76,24 @@ pub(super) struct Granted<'a> { arrival: Arrival, order: u64, at: Instant, + begin_nanos: u64, + begin_driver: [u64; 6], + commit_before: u64, + commit_io: Option, +} + +struct Timeline { + arrived: Instant, + granted: Instant, + releasing: Instant, + begin_nanos: u64, + transaction_nanos: u64, + commit_nanos: u64, + admission_nanos: [u64; 8], + manifest_driver: [[u64; 8]; 2], + begin_driver: [u64; 6], + release: Option, + commit_io: Option, } /// Process-local observations of atomic domain admission. @@ -54,6 +129,10 @@ impl Arrival { arrival: self, order, at: Instant::now(), + begin_nanos: 0, + begin_driver: [0; 6], + commit_before: 0, + commit_io: None, } } } @@ -62,6 +141,8 @@ pub(super) struct Trace { family: String, samples: Vec, flushed: usize, + request: Option, + timeline: Vec, } impl Trace { pub(super) fn new(family: &str) -> Self { @@ -69,8 +150,15 @@ impl Trace { family: family.to_owned(), samples: Vec::with_capacity(CAPACITY), flushed: 0, + request: None, + timeline: Vec::new(), } } + pub(super) fn with_request(mut self, request: &str) -> Self { + self.request = Some(request.to_owned()); + self.timeline = Vec::with_capacity(CAPACITY); + self + } pub(super) fn flush(&mut self, final_chunk: bool) { use std::fmt::Write; let mut line = format!( @@ -103,6 +191,58 @@ impl Trace { ); } eprintln!("{line}"); + if let Some(request) = &self.request { + static CLOCK: OnceLock = OnceLock::new(); + let clock = *CLOCK.get_or_init(Instant::now); + let before_epoch = |at: Instant| { + at.checked_duration_since(clock).map_or_else( + || -(clock.duration_since(at).as_nanos() as i128), + |elapsed| elapsed.as_nanos() as i128, + ) + }; + let mut line = format!("weaver-provider-scope-timeline {} {}", self.family, request); + for (sample, time) in self.samples.iter().zip(self.timeline.drain(..)) { + let _ = write!( + line, + " {}:{}:{}:{}:{}:{}:{}", + sample.arrival, + before_epoch(time.arrived), + before_epoch(time.granted), + before_epoch(time.releasing), + time.begin_nanos, + time.transaction_nanos, + time.commit_nanos, + ); + for nanos in time.admission_nanos { + let _ = write!(line, ":{nanos}"); + } + // Poll wall/CPU, prepare wall/CPU, pending count, poll count. + for count in time + .begin_driver + .into_iter() + .chain(time.manifest_driver.into_iter().flatten()) + { + let _ = write!(line, ":{count}"); + } + super::driver_observer::CommitIo::append(time.commit_io, &mut line); + // Versioned extension. The earlier releasing timestamp is a + // request to drop the lease, before acquiring the scheduler lock. + if let Some(release) = time.release { + let _ = write!( + line, + ":1:{}:{}:{}:{}:{}", + before_epoch(release.requested), + before_epoch(release.locked), + before_epoch(release.removed), + before_epoch(release.notified), + before_epoch(release.returned), + ); + } else { + let _ = write!(line, ":0:0:0:0:0:0"); + } + } + eprintln!("{line}"); + } self.flushed = self .flushed .checked_add(self.samples.len()) @@ -117,7 +257,30 @@ impl Trace { } } impl Granted<'_> { - pub(super) fn record(self, authority_span: Duration) { + pub(super) fn committed_io(&mut self, io: Option) { + self.commit_io = io; + } + + pub(super) fn has_timeline(&self) -> bool { + self.trace.request.is_some() + } + + pub(super) fn opened(&mut self, begin_nanos: u64, commit_before: u64, begin_driver: [u64; 6]) { + self.begin_nanos = begin_nanos; + self.commit_before = commit_before; + self.begin_driver = begin_driver; + } + + pub(super) fn record(self, completion: Completion) { + let Completion { + authority_span, + releasing, + transaction_nanos, + commit_total, + admission_nanos, + manifest_driver, + release, + } = completion; self.trace.record(ProviderScopeSample { phase: self.arrival.phase, authority_span, @@ -127,6 +290,21 @@ impl Granted<'_> { wait: self.at.duration_since(self.arrival.at), hold: self.at.elapsed(), }); + if self.trace.request.is_some() { + self.trace.timeline.push(Timeline { + arrived: self.arrival.at, + granted: self.at, + releasing, + begin_nanos: self.begin_nanos, + transaction_nanos, + commit_nanos: commit_total.saturating_sub(self.commit_before), + admission_nanos, + manifest_driver, + begin_driver: self.begin_driver, + release, + commit_io: self.commit_io, + }); + } } } diff --git a/crates/ledger/src/persistence/session.rs b/crates/ledger/src/persistence/session.rs index ba93dfa0..3e4cb589 100644 --- a/crates/ledger/src/persistence/session.rs +++ b/crates/ledger/src/persistence/session.rs @@ -79,8 +79,12 @@ impl Session { self.timings } #[cfg(feature = "commit-observer")] - pub(crate) fn trace_provider_scopes(&mut self, family: &str) { - self.scope_trace = Some(super::scope_trace::Trace::new(family)); + pub(crate) fn trace_provider_scopes(&mut self, family: &str, node: Option<&str>) { + let trace = super::scope_trace::Trace::new(family); + self.scope_trace = Some(match node { + Some(node) => trace.with_request(node), + None => trace, + }); } #[cfg(feature = "commit-observer")] pub(crate) fn finish_provider_scope_trace(&mut self) { @@ -88,9 +92,17 @@ impl Session { trace.flush(true); } } + #[cfg(feature = "commit-observer")] + pub(crate) fn reset_provider_request(&mut self) { + self.range_cancelled = None; + self.timings = super::TransactionTimings::default(); + self.scope_trace = None; + self.commit_observer = None; + } pub(crate) fn prepare_provider_domain(&mut self) { super::timing::measure(&mut self.timings.provider_domain_prepare, || { crate::domains::warm_provider_domain_plan(&self.connection); + crate::exposure_manifest::warm_programs(&self.connection); }); } pub(crate) fn prepare_provider_original( diff --git a/crates/ledger/src/persistence/timing.rs b/crates/ledger/src/persistence/timing.rs index 0157c6e3..28e8ec6d 100644 --- a/crates/ledger/src/persistence/timing.rs +++ b/crates/ledger/src/persistence/timing.rs @@ -19,6 +19,11 @@ impl Timing { .nanos .saturating_add(u64::try_from(elapsed.as_nanos()).unwrap_or(u64::MAX)); } + #[cfg(feature = "commit-observer")] + pub(super) fn merge(&mut self, sample: Self) { + self.attempts = self.attempts.saturating_add(sample.attempts); + self.nanos = self.nanos.saturating_add(sample.nanos); + } } /// Intervals overlap: never sum them into a critical-path latency or a receipt. /// Reset on session replacement; failed attempts are included, not just successes. @@ -29,10 +34,28 @@ pub struct TransactionTimings { pub domain_wait: Timing, pub authority_span: Timing, pub transaction_begin: Timing, + #[cfg(feature = "commit-observer")] + pub transaction_begin_poll: Timing, + #[cfg(feature = "commit-observer")] + pub transaction_begin_cpu: Timing, + #[cfg(feature = "commit-observer")] + pub transaction_begin_prepare: Timing, + #[cfg(feature = "commit-observer")] + pub transaction_begin_prepare_cpu: Timing, + #[cfg(feature = "commit-observer")] + pub transaction_begin_pending: u64, pub owner_gate_hold: Timing, pub domain_hold: Timing, pub transaction_hold: Timing, pub commit: Timing, + #[cfg(feature = "commit-observer")] + pub commit_poll: Timing, + #[cfg(feature = "commit-observer")] + pub commit_cpu: Timing, + #[cfg(feature = "commit-observer")] + pub commit_sync: Timing, + #[cfg(feature = "commit-observer")] + pub commit_pending: u64, pub rollback: Timing, pub provider_oauth_prepare: Timing, pub provider_oauth_check: Timing, @@ -71,7 +94,63 @@ pub(super) fn measure(sample: &mut Timing, run: impl FnOnce() -> T) -> T { result } +/// Host monotonic timestamp shared by the Rust and Go test processes. +#[cfg(feature = "commit-observer")] +pub fn provider_observation_nanos() -> u128 { + let stamp = rustix::time::clock_gettime(rustix::time::ClockId::Monotonic); + stamp.tv_sec as u128 * 1_000_000_000 + stamp.tv_nsec as u128 +} + +#[cfg(feature = "commit-observer")] +pub(super) fn thread_cpu_time() -> Option { + #[cfg(any(target_os = "linux", target_os = "macos"))] + { + use rustix::time::{ClockId, clock_gettime}; + clock_gettime(ClockId::ThreadCPUTime).try_into().ok() + } + #[cfg(not(any(target_os = "linux", target_os = "macos")))] + None +} + +#[cfg(feature = "commit-observer")] +pub(super) fn observe_polls( + future: F, + wall: &mut Timing, + cpu: &mut Timing, + pending: &mut u64, +) -> F::Output { + let mut future = std::pin::pin!(future); + futures_executor::block_on(std::future::poll_fn(|cx| { + let result = measure(wall, || { + let start = thread_cpu_time(); + let result = future.as_mut().poll(cx); + if let (Some(start), Some(end)) = (start, thread_cpu_time()) + && let Some(elapsed) = end.checked_sub(start) + { + cpu.record(elapsed); + } + result + }); + if result.is_pending() { + *pending = pending.saturating_add(1); + } + result + })) +} + impl TransactionTimings { + #[cfg(feature = "commit-observer")] + pub(super) fn begin_driver_counters(&self) -> [u64; 6] { + [ + self.transaction_begin_poll.nanos, + self.transaction_begin_cpu.nanos, + self.transaction_begin_prepare.nanos, + self.transaction_begin_prepare_cpu.nanos, + self.transaction_begin_pending, + self.transaction_begin_poll.attempts, + ] + } + /// Subtract observations from this same live session. Not a recovery check. pub fn since(self, earlier: Self) -> Self { fn delta(now: Timing, old: Timing) -> Timing { @@ -86,10 +165,39 @@ impl TransactionTimings { domain_wait: delta(self.domain_wait, earlier.domain_wait), authority_span: delta(self.authority_span, earlier.authority_span), transaction_begin: delta(self.transaction_begin, earlier.transaction_begin), + #[cfg(feature = "commit-observer")] + transaction_begin_poll: delta( + self.transaction_begin_poll, + earlier.transaction_begin_poll, + ), + #[cfg(feature = "commit-observer")] + transaction_begin_cpu: delta(self.transaction_begin_cpu, earlier.transaction_begin_cpu), + #[cfg(feature = "commit-observer")] + transaction_begin_prepare: delta( + self.transaction_begin_prepare, + earlier.transaction_begin_prepare, + ), + #[cfg(feature = "commit-observer")] + transaction_begin_prepare_cpu: delta( + self.transaction_begin_prepare_cpu, + earlier.transaction_begin_prepare_cpu, + ), + #[cfg(feature = "commit-observer")] + transaction_begin_pending: self + .transaction_begin_pending + .saturating_sub(earlier.transaction_begin_pending), owner_gate_hold: delta(self.owner_gate_hold, earlier.owner_gate_hold), domain_hold: delta(self.domain_hold, earlier.domain_hold), transaction_hold: delta(self.transaction_hold, earlier.transaction_hold), commit: delta(self.commit, earlier.commit), + #[cfg(feature = "commit-observer")] + commit_poll: delta(self.commit_poll, earlier.commit_poll), + #[cfg(feature = "commit-observer")] + commit_cpu: delta(self.commit_cpu, earlier.commit_cpu), + #[cfg(feature = "commit-observer")] + commit_sync: delta(self.commit_sync, earlier.commit_sync), + #[cfg(feature = "commit-observer")] + commit_pending: self.commit_pending.saturating_sub(earlier.commit_pending), rollback: delta(self.rollback, earlier.rollback), provider_oauth_prepare: delta( self.provider_oauth_prepare, diff --git a/crates/ledger/src/provider.rs b/crates/ledger/src/provider.rs index 1fd11cf8..df9a9799 100644 --- a/crates/ledger/src/provider.rs +++ b/crates/ledger/src/provider.rs @@ -5,6 +5,14 @@ //! One canonical provider invocation and affine response releases; no retry reset exists. #[path = "provider_admission.rs"] mod admission; +#[path = "provider_scope.rs"] +mod scope; +pub(crate) use scope::{AdmissionRequest, OriginLifecycle, RangeProgress, shared_provider_reads}; +#[cfg(feature = "commit-observer")] +pub use scope::{ + use_conservative_range_invalidation, use_early_admission_barrier, use_exclusive_provider_reads, + use_full_lifecycle_invalidation, +}; #[path = "provider_release_group.rs"] mod release_group; pub use release_group::{MAX_PROVIDER_PREPARATION_RANGES, MAX_PROVIDER_PREPARATION_ROWS}; @@ -42,102 +50,6 @@ fn governor_commit_trace(phase: &str, plan: &ProviderPlan, transaction: Option = const { std::cell::Cell::new(false) }; -} -/// Safe same-image control retaining closure while an admission request waits. -#[cfg(feature = "commit-observer")] -pub fn use_early_admission_barrier(early: bool) { - EARLY_ADMISSION_BARRIER.set(early); -} -impl AdmissionRequest { - pub(crate) fn wait_before_close(&self) -> bool { - #[cfg(feature = "commit-observer")] - { - !EARLY_ADMISSION_BARRIER.get() - } - #[cfg(not(feature = "commit-observer"))] - { - true - } - } -} -/// Sealed write-set obligation: only run state/target, dispatch marker or raw -/// terminal usage changes; no reservation, history, quota or publication write. -pub(crate) struct OriginLifecycle { - _sealed: (), -} -#[cfg(feature = "commit-observer")] -thread_local! { - static FULL_LIFECYCLE_INVALIDATION: std::cell::Cell = const { std::cell::Cell::new(false) }; -} -#[cfg(feature = "commit-observer")] -/// Safe same-image test control: retain broad lifecycle invalidation. -pub fn use_full_lifecycle_invalidation(full: bool) { - FULL_LIFECYCLE_INVALIDATION.set(full); -} -#[cfg(feature = "commit-observer")] -thread_local! { - static EXCLUSIVE_PROVIDER_READS: std::cell::Cell = const { std::cell::Cell::new(false) }; -} -/// Safe same-image control retaining full-domain exclusive read custody. -#[cfg(feature = "commit-observer")] -pub fn use_exclusive_provider_reads(exclusive: bool) { - EXCLUSIVE_PROVIDER_READS.set(exclusive); -} -pub(crate) fn shared_provider_reads() -> bool { - #[cfg(feature = "commit-observer")] - { - !EXCLUSIVE_PROVIDER_READS.get() - } - #[cfg(not(feature = "commit-observer"))] - { - true - } -} -impl OriginLifecycle { - pub(crate) fn origin_only(&self) -> bool { - #[cfg(feature = "commit-observer")] - { - !FULL_LIFECYCLE_INVALIDATION.get() - } - #[cfg(not(feature = "commit-observer"))] - { - true - } - } -} -#[cfg(feature = "commit-observer")] -thread_local! { - static CONSERVATIVE_RANGE_INVALIDATION: std::cell::Cell = const { std::cell::Cell::new(false) }; -} -/// Same-image safe control: treat exact progress writes as semantic mutations. -#[cfg(feature = "commit-observer")] -pub fn use_conservative_range_invalidation(conservative: bool) { - CONSERVATIVE_RANGE_INVALIDATION.set(conservative); -} -impl RangeProgress { - pub(crate) fn invalidates(&self) -> bool { - #[cfg(feature = "commit-observer")] - return CONSERVATIVE_RANGE_INVALIDATION.get(); - #[cfg(not(feature = "commit-observer"))] - false - } -} - /// Affine deciding-owner custody for one selected original provider invocation. pub struct ProviderDispatch { pub(super) plan: ProviderPlan, @@ -209,8 +121,8 @@ impl Ledger { } /// Enable bounded diagnostic observations for this ledger only. #[cfg(feature = "commit-observer")] - pub fn trace_provider_scopes(&mut self, family: &str) { - self.connection.trace_provider_scopes(family); + pub fn trace_provider_scopes(&mut self, family: &str, node: Option<&str>) { + self.connection.trace_provider_scopes(family, node); } /// Finish the complete bounded diagnostic stream after all deciding scopes. @@ -359,12 +271,24 @@ impl Ledger { if progress.pending { return Err(Error::Conflict("response release unresolved")); } - crate::persistence::exec( + // Keep the original ceiling for exposure reconciliation. The full + // request is only needed by the queued dispatch path. + let completed = crate::persistence::exec( &tx, - "UPDATE provider_runs SET state='complete' WHERE family=?1 AND node=?2", - crate::persistence::params![permit.plan.family.to_owned(), permit.plan.node.to_owned()], + "UPDATE provider_runs + SET state='complete',plan=json_object('ceiling',json_extract(plan,'$.ceiling')) + WHERE family=?1 AND node=?2 AND state='unknown' + AND json_extract(plan,'$.ceiling')=?3", + crate::persistence::params![ + permit.plan.family.as_str(), + permit.plan.node.as_str(), + permit.plan.ceiling as i64 + ], ) .map_err(db)?; + if completed != 1 { + return Err(Error::Conflict("original provider plan not retained")); + } if let Some(response) = response { crate::provider_workflow_choice::record_result( &tx, @@ -830,7 +754,45 @@ pub(crate) fn receipt( family: &str, node: &str, ) -> Result> { - crate::persistence::maybe(c, "SELECT r.digest,r.state,r.target,r.reserved,t.held,r.next_event FROM provider_runs r JOIN tasks t ON t.family=r.family WHERE r.family=?1 AND r.node=?2", crate::persistence::params![(family).to_owned(),(node).to_owned()], |r|Ok(ProviderReceipt{family:family.into(),node:node.into(),digest:r.get(0)?,state:provider_state(r)?,target:r.get(2)?,reserved:integer(r,3)?,held:integer(r,4)?,events:integer(r,5)?})).map_err(db) + crate::persistence::maybe_prepared(c, "SELECT r.digest,r.state,r.target,r.reserved,t.held,r.next_event FROM provider_runs r JOIN tasks t ON t.family=r.family WHERE r.family=?1 AND r.node=?2", crate::persistence::params![family.to_owned(),node.to_owned()], |row| decode_receipt(row, family, node.to_owned())).map_err(db) +} + +pub(crate) fn workflow_receipts( + c: &crate::persistence::driver::Connection, + family: &str, + nodes: &[&str], +) -> Result> { + let nodes = serde_json::to_string(nodes).map_err(|_| Error::Invalid("Session nodes"))?; + let receipts = crate::persistence::read_all_current( + c, + "SELECT r.digest,r.state,r.target,r.reserved,t.held,r.next_event,r.node + FROM main.provider_runs r JOIN main.tasks t ON t.family=r.family + WHERE r.family=?1 AND r.node IN (SELECT value FROM json_each(?2))", + crate::persistence::params![family.to_owned(), nodes], + |row| decode_receipt(row, family, row.get(6)?), + ) + .map_err(db)?; + Ok(receipts + .into_iter() + .map(|receipt| (receipt.node.clone(), receipt)) + .collect()) +} + +fn decode_receipt( + row: &crate::persistence::Row, + family: &str, + node: String, +) -> crate::persistence::Result { + Ok(ProviderReceipt { + family: family.into(), + node, + digest: row.get(0)?, + state: provider_state(row)?, + target: row.get(2)?, + reserved: integer(row, 3)?, + held: integer(row, 4)?, + events: integer(row, 5)?, + }) } fn provider_state(row: &crate::persistence::Row) -> crate::persistence::Result { let state: String = row.get(1)?; diff --git a/crates/ledger/src/provider_admission.rs b/crates/ledger/src/provider_admission.rs index 1321d028..7afe0412 100644 --- a/crates/ledger/src/provider_admission.rs +++ b/crates/ledger/src/provider_admission.rs @@ -121,7 +121,12 @@ fn store_authorized_provider_plan( let selected = any_authorized(tx, plan, "admitProvider", None, publication)?; tx.provider_claim(|| crate::domains::require_view(tx, &selected.domains, original))?; if new_claim { - reserve_provider_claim(tx, plan, digest, encoded, catalog, &selected.domains)?; + let reserve = + || reserve_provider_claim(tx, plan, digest, encoded, catalog, &selected.domains); + #[cfg(feature = "commit-observer")] + tx.provider_reservation(reserve)?; + #[cfg(not(feature = "commit-observer"))] + reserve()?; } else { crate::persistence::exec( tx, diff --git a/crates/ledger/src/provider_catalog.rs b/crates/ledger/src/provider_catalog.rs index dc38629d..dabb7b4d 100644 --- a/crates/ledger/src/provider_catalog.rs +++ b/crates/ledger/src/provider_catalog.rs @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 +//! Read current provider catalogs and verify their published content. + use crate::{ Ledger, persistence::{self, driver}, @@ -12,14 +14,26 @@ use weaver_contracts::{Error, MAX_CREDITS, ProviderCatalog, Result}; pub(crate) fn current( connection: &driver::Connection, ) -> Result> { - let record: Option<(String, String)> = persistence::maybe( + current_record(connection)? + .map(|(digest, record)| { + let catalog = decode(&digest, &record)?; + Ok((digest, catalog)) + }) + .transpose() +} + +#[cfg(test)] +#[path = "../tests/unit/provider_catalog.rs"] +mod tests; + +fn current_record(connection: &driver::Connection) -> Result> { + persistence::maybe( connection, "SELECT digest,record FROM provider_catalog_publications ORDER BY revision DESC LIMIT 1", (), |row| Ok((row.get(0)?, row.get(1)?)), ) - .map_err(db)?; - record.map(decode).transpose() + .map_err(db) } pub(crate) fn historical(connection: &driver::Connection, digest: &str) -> Result { @@ -30,15 +44,36 @@ pub(crate) fn historical(connection: &driver::Connection, digest: &str) -> Resul |row| row.get(0), ) .map_err(db)?; - decode((digest.to_owned(), record)).map(|(_, catalog)| catalog) + decode(digest, &record) } -fn decode((digest, record): (String, String)) -> Result<(String, ProviderCatalog)> { +fn decode(digest: &str, record: &str) -> Result { let catalog: ProviderCatalog = weaver_contracts::decode(record.as_bytes())?; if catalog.digest()? != digest { return Err(Error::Conflict("provider catalog content mismatch")); } - Ok((digest, catalog)) + Ok(catalog) +} + +/// One source owner's verified wire projection. Current source authority and +/// current stored bytes must be read before it can be reused. +#[derive(Default)] +pub struct ProviderCatalogProjection { + canonical: Option<(String, Vec)>, +} + +impl ProviderCatalogProjection { + fn project(&mut self, version: String, record: String) -> Result<(String, Vec)> { + if self.canonical.as_ref().is_some_and(|(digest, bytes)| { + *digest == version && bytes.as_slice() == record.as_bytes() + }) { + return Ok((version, record.into_bytes())); + } + let canonical = decode(&version, &record)?.record()?; + self.canonical = (canonical.len() <= 262_144 && canonical == record.as_bytes()) + .then(|| (version.clone(), canonical.clone())); + Ok((version, canonical)) + } } impl Ledger { @@ -47,6 +82,17 @@ impl Ledger { current(&self.connection) } + /// Read and verify the current catalog for the authenticated source RPC. + pub fn inspect_provider_catalog( + &self, + projection: &mut ProviderCatalogProjection, + ) -> Result)>> { + crate::source_authority::require(&self.connection, self.source.as_ref())?; + current_record(&self.connection)? + .map(|(version, record)| projection.project(version, record)) + .transpose() + } + pub fn publish_provider_catalog(&mut self, catalog: &ProviderCatalog) -> Result { let digest = catalog.digest()?; let tx = persistence::begin(&mut self.connection).map_err(db)?; diff --git a/crates/ledger/src/provider_scope.rs b/crates/ledger/src/provider_scope.rs new file mode 100644 index 00000000..d1cca89d --- /dev/null +++ b/crates/ledger/src/provider_scope.rs @@ -0,0 +1,101 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Provider scope write-set obligations and their observed comparison controls. + +/// Sealed proof obligation for the two progress-only write paths in this module. +/// No external caller or other ledger module can construct this token. +/// Its transaction may only append fresh ranges/advance next_event, or CAS an +/// exact unknown release to released. All authorization inputs stay unchanged. +pub(crate) struct RangeProgress { + pub(super) _sealed: (), +} +/// Unaccepted execution request. It cannot mutate shared facts or expose an +/// authoritative outcome before the scheduler selects its writer turn. +pub(crate) struct AdmissionRequest { + pub(super) _sealed: (), +} +#[cfg(feature = "commit-observer")] +thread_local! { + static EARLY_ADMISSION_BARRIER: std::cell::Cell = const { std::cell::Cell::new(false) }; +} +/// Safe same-image control retaining closure while an admission request waits. +#[cfg(feature = "commit-observer")] +pub fn use_early_admission_barrier(early: bool) { + EARLY_ADMISSION_BARRIER.set(early); +} +impl AdmissionRequest { + pub(crate) fn wait_before_close(&self) -> bool { + #[cfg(feature = "commit-observer")] + { + !EARLY_ADMISSION_BARRIER.get() + } + #[cfg(not(feature = "commit-observer"))] + { + true + } + } +} +/// Sealed write-set obligation: only run state/target, dispatch marker or raw +/// terminal usage changes; no reservation, history, quota or publication write. +pub(crate) struct OriginLifecycle { + pub(super) _sealed: (), +} +#[cfg(feature = "commit-observer")] +thread_local! { + static FULL_LIFECYCLE_INVALIDATION: std::cell::Cell = const { std::cell::Cell::new(false) }; +} +#[cfg(feature = "commit-observer")] +/// Safe same-image test control: retain broad lifecycle invalidation. +pub fn use_full_lifecycle_invalidation(full: bool) { + FULL_LIFECYCLE_INVALIDATION.set(full); +} +#[cfg(feature = "commit-observer")] +thread_local! { + static EXCLUSIVE_PROVIDER_READS: std::cell::Cell = const { std::cell::Cell::new(false) }; +} +/// Safe same-image control retaining full-domain exclusive read custody. +#[cfg(feature = "commit-observer")] +pub fn use_exclusive_provider_reads(exclusive: bool) { + EXCLUSIVE_PROVIDER_READS.set(exclusive); +} +pub(crate) fn shared_provider_reads() -> bool { + #[cfg(feature = "commit-observer")] + { + !EXCLUSIVE_PROVIDER_READS.get() + } + #[cfg(not(feature = "commit-observer"))] + { + true + } +} +impl OriginLifecycle { + pub(crate) fn origin_only(&self) -> bool { + #[cfg(feature = "commit-observer")] + { + !FULL_LIFECYCLE_INVALIDATION.get() + } + #[cfg(not(feature = "commit-observer"))] + { + true + } + } +} +#[cfg(feature = "commit-observer")] +thread_local! { + static CONSERVATIVE_RANGE_INVALIDATION: std::cell::Cell = const { std::cell::Cell::new(false) }; +} +/// Same-image safe control: treat exact progress writes as semantic mutations. +#[cfg(feature = "commit-observer")] +pub fn use_conservative_range_invalidation(conservative: bool) { + CONSERVATIVE_RANGE_INVALIDATION.set(conservative); +} +impl RangeProgress { + pub(crate) fn invalidates(&self) -> bool { + #[cfg(feature = "commit-observer")] + return CONSERVATIVE_RANGE_INVALIDATION.get(); + #[cfg(not(feature = "commit-observer"))] + false + } +} diff --git a/crates/ledger/src/provider_workflow.rs b/crates/ledger/src/provider_workflow.rs index dadd2a76..9d011992 100644 --- a/crates/ledger/src/provider_workflow.rs +++ b/crates/ledger/src/provider_workflow.rs @@ -4,7 +4,9 @@ //! Compiled workflow edges using the existing provider claim and response outcome. use crate::{ Ledger, - persistence::{WriteScope, begin_family, exec, one_current, params}, + persistence::{ + WriteScope, begin_family, begin_workflow_observation, exec, one_current, params, + }, provider_workflow_choice::{self as choice, ChoiceBasis, WorkflowChoiceObservation}, provider_workflow_nested::{self as nested, NestedDraft, NestedObservation}, store::{db, integer}, @@ -48,10 +50,8 @@ pub struct WorkflowObservation { fn released_response( tx: &WriteScope<'_>, predecessor: &ProviderPlan, - domains: &weaver_contracts::DomainView, + digest: &str, ) -> Result { - let digest = predecessor.digest()?; - require_winner(tx, predecessor, &digest)?; // The provider owner records 2 only after the actual dispatch callback. // The earlier burn (1) does not establish that a response was observed. let released_events = one_current( @@ -65,7 +65,7 @@ fn released_response( params![ predecessor.family.clone(), predecessor.node.clone(), - digest.clone(), + digest, predecessor.ceiling as i64 ], |row| integer(row, 0), @@ -76,9 +76,8 @@ fn released_response( } other => db(other), })?; - crate::execution_exposure::provider(tx, predecessor, &digest, domains, None, None)?; Ok(ReleasedResponse { - digest, + digest: digest.to_owned(), reserved: predecessor.ceiling, released_events, }) @@ -88,10 +87,9 @@ fn prepare( tx: &WriteScope<'_>, predecessors: &[ProviderPlan], successor: &ProviderPlan, + current: (Vec, u64, String), ) -> Result { - let (mut expected, fact_floor, fact_snapshot) = - crate::hard_fact::workflow_cut(tx, &successor.family, &successor.node)? - .ok_or(Error::Conflict("provider workflow not admitted"))?; + let (mut expected, fact_floor, fact_snapshot) = current; let domains = crate::domains::provider_view(tx, &successor.family)?; let choice = choice::prepare( tx, @@ -129,7 +127,11 @@ fn prepare( .iter() .map(|plan| { crate::hard_fact::require_available(tx, &plan.family, &plan.node)?; - released_response(tx, plan, &domains) + let digest = plan.digest()?; + require_winner(tx, plan, &digest)?; + let release = released_response(tx, plan, &digest)?; + crate::execution_exposure::provider(tx, plan, &digest, &domains, None, None)?; + Ok(release) }) .collect::>>()?; let successor_digest = successor.digest()?; @@ -176,7 +178,9 @@ impl Ledger { observed: Option<&WorkflowObservation>, ) -> Result { let tx = begin_family(&mut self.connection, &successor.family).map_err(db)?; - let proposal = prepare(&tx, predecessors, successor)?; + let current = crate::hard_fact::workflow_cut(&tx, &successor.family, &successor.node)? + .ok_or(Error::Conflict("provider workflow not admitted"))?; + let proposal = prepare(&tx, predecessors, successor, current)?; if observed.is_some_and(|cut| { cut.floor != proposal.fact_floor || cut.snapshot != proposal.fact_snapshot }) { @@ -190,39 +194,66 @@ impl Ledger { let [root, successor, ..] = plans else { return Err(Error::Invalid("Session plan set")); }; - let tx = begin_family(&mut self.connection, &root.family).map_err(db)?; - let (_, floor, snapshot) = - crate::hard_fact::workflow_cut(&tx, &root.family, &successor.node)? - .ok_or(Error::Conflict("Session fact cut unavailable"))?; + if plans.iter().any(|plan| plan.family != root.family) { + return Err(Error::Invalid("Session plans span multiple families")); + } + let tx = begin_workflow_observation(&mut self.connection, &root.family).map_err(db)?; + let nodes: Vec<_> = plans.iter().map(|plan| plan.node.as_str()).collect(); + let facts = crate::hard_fact::observe_workflow( + &tx, + &root.family, + &successor.node, + nodes.iter().copied(), + )?; let domains = crate::domains::provider_view(&tx, &root.family)?; + let origin = &domains.stamp.origin; + let choice_nodes = facts.feed.choice_nodes(); let mut cut = WorkflowObservation { complete: vec![], - available: vec![], + available: facts.available, pending: vec![], - choice: choice::observe(&tx, &root.family, &domains.stamp.origin)?, - nested: nested::observe(&tx, &root.family, &domains.stamp.origin)?, - floor, - snapshot, + choice: choice::observe(&tx, &root.family, origin, choice_nodes)?, + nested: nested::observe(&tx, origin, &facts.feed)?, + floor: facts.floor, + snapshot: facts.snapshot, }; + let receipts = crate::provider::workflow_receipts(&tx, &root.family, &nodes)?; + // This read-only transaction has one deployment, including its absence. + // Load it only after the first complete node proves its release. + let mut metering = None; for plan in plans { - match crate::hard_fact::require_available(&tx, &plan.family, &plan.node) { - Ok(Some(_)) => cut.available.push(plan.node.clone()), - Err(Error::Conflict(_)) => {} - Ok(None) => return Err(Error::Conflict("Session fact scope changed")), - Err(error) => return Err(error), - } - match crate::provider::receipt(&tx, &plan.family, &plan.node)? { + match receipts.get(&plan.node) { Some(receipt) if receipt.digest != plan.digest()? => { return Err(Error::Conflict("Session plan changed")); } Some(receipt) if receipt.state == ProviderState::Complete => { - released_response(&tx, plan, &domains)?; + let digest = &receipt.digest; + if !facts.feed.workflow_predecessors(&plan.node).is_empty() { + require_transition(&tx, plan, origin, digest)?; + choice::require_in_choice(&tx, plan, origin, digest, choice_nodes)?; + nested::require_in_graph(&tx, plan, origin, digest, &facts.feed)?; + } + released_response(&tx, plan, digest)?; + if metering.is_none() { + metering = Some(crate::metering::deployment(&tx)?); + } + crate::execution_exposure::provider_metering_with_deployment( + &tx, + plan, + digest, + metering.as_ref().and_then(Option::as_ref), + )?; cut.complete.push(plan.node.clone()); } Some(receipt) if receipt.state == ProviderState::Unknown => {} _ => cut.pending.push(plan.node.clone()), } } + // Each complete run proved its exact digest and reservation. Shared + // exposure and history describe the whole family in this read scope. + if !cut.complete.is_empty() { + crate::domains::require_view(&tx, &domains, None)?; + } tx.commit().map_err(db)?; Ok(cut) } @@ -233,11 +264,18 @@ pub(crate) fn require_admission( plan: &ProviderPlan, proposal: Option<&ProviderProgression>, ) -> Result<()> { - let governed = crate::hard_fact::workflow_cut(tx, &plan.family, &plan.node)?.is_some(); - match (governed, proposal) { - (false, None) => Ok(()), - (true, Some(proposal)) if prepare(tx, &proposal.predecessors, plan)? == *proposal => Ok(()), - _ => Err(Error::Conflict("provider workflow frontier changed")), + let current = crate::hard_fact::workflow_cut(tx, &plan.family, &plan.node)?; + let retained = match (current, proposal) { + (None, None) => true, + (Some(current), Some(proposal)) => { + prepare(tx, &proposal.predecessors, plan, current)? == *proposal + } + _ => false, + }; + if retained { + Ok(()) + } else { + Err(Error::Conflict("provider workflow frontier changed")) } } @@ -308,16 +346,26 @@ pub(crate) fn require_winner(tx: &WriteScope<'_>, plan: &ProviderPlan, digest: & let origin = crate::domains::provider_view(tx, &plan.family)? .stamp .origin; - let valid: bool = one_current(tx, - "SELECT EXISTS(SELECT 1 FROM main.provider_workflow_transitions WHERE origin=?1 AND successor=?2 AND successor_digest=?3)", - params![origin.clone(), plan.node.clone(), digest.to_owned()], |row| row.get(0)).map_err(db)?; - if !valid { - return Err(Error::Conflict( - "provider successor has no committed transition", - )); - } + require_transition(tx, plan, &origin, digest)?; choice::require(tx, plan, &origin, digest)?; nested::require_entry(tx, plan, &origin, digest)?; } Ok(()) } + +fn require_transition( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + origin: &str, + digest: &str, +) -> Result<()> { + let valid: bool = one_current(tx, + "SELECT EXISTS(SELECT 1 FROM main.provider_workflow_transitions WHERE origin=?1 AND successor=?2 AND successor_digest=?3)", + params![origin, plan.node.as_str(), digest], |row| row.get(0)).map_err(db)?; + if !valid { + return Err(Error::Conflict( + "provider successor has no committed transition", + )); + } + Ok(()) +} diff --git a/crates/ledger/src/provider_workflow_choice.rs b/crates/ledger/src/provider_workflow_choice.rs index dc2f6719..9630e9c6 100644 --- a/crates/ledger/src/provider_workflow_choice.rs +++ b/crates/ledger/src/provider_workflow_choice.rs @@ -171,12 +171,13 @@ pub(crate) fn observe( tx: &WriteScope<'_>, family: &str, origin: &str, + nodes: Option<&[String; 4]>, ) -> Result> { - let Some(nodes) = crate::hard_fact::choice_nodes(tx, family)? else { + let Some(nodes) = nodes else { return Ok(None); }; - let (result, decision) = read_basis(tx, family, origin, &nodes)?; - let [_, left, right, join] = nodes; + let (result, decision) = read_basis(tx, family, origin, nodes)?; + let [_, left, right, join] = nodes.clone(); Ok(Some(WorkflowChoiceObservation { arms: [left, right], join, @@ -249,10 +250,21 @@ pub(crate) fn require( origin: &str, digest: &str, ) -> Result<()> { - let Some(nodes) = crate::hard_fact::choice_nodes(tx, &plan.family)? else { + let nodes = crate::hard_fact::choice_nodes(tx, &plan.family)?; + require_in_choice(tx, plan, origin, digest, nodes.as_ref()) +} + +pub(crate) fn require_in_choice( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + origin: &str, + digest: &str, + nodes: Option<&[String; 4]>, +) -> Result<()> { + let Some(nodes) = nodes else { return Ok(()); }; - let (_, decision) = read_basis(tx, &plan.family, origin, &nodes)?; + let (_, decision) = read_basis(tx, &plan.family, origin, nodes)?; let decision = decision.ok_or(Error::Conflict("workflow choice is uncommitted"))?; if plan.node == nodes[3] { let valid: bool = crate::persistence::one_current( diff --git a/crates/ledger/src/provider_workflow_nested.rs b/crates/ledger/src/provider_workflow_nested.rs index 26d70a82..835c2aa1 100644 --- a/crates/ledger/src/provider_workflow_nested.rs +++ b/crates/ledger/src/provider_workflow_nested.rs @@ -9,7 +9,7 @@ use crate::{ store::db, }; use std::collections::BTreeMap; -use weaver_contracts::{Error, ProviderPlan, Result, WorkflowRoute}; +use weaver_contracts::{Error, FactFeed, ProviderPlan, Result, WorkflowRoute}; /// Complete selector observations and the active predecessors of eligible nodes. pub struct NestedObservation { @@ -154,12 +154,13 @@ fn active_parents( pub(crate) fn observe( tx: &WriteScope<'_>, - family: &str, origin: &str, + graph: &FactFeed, ) -> Result> { - crate::hard_fact::nested_feed(tx, family)? - .map(|graph| load(tx, family, origin, &graph).map(|(observed, _)| observed)) - .transpose() + if graph.workflow_selectors.is_empty() { + return Ok(None); + } + load(tx, &graph.family, origin, graph).map(|(observed, _)| Some(observed)) } pub(crate) fn prepare( @@ -221,6 +222,16 @@ pub(crate) fn require_entry( let Some(graph) = crate::hard_fact::nested_feed(tx, &plan.family)? else { return Ok(()); }; + require_in_graph(tx, plan, origin, digest, &graph) +} + +pub(crate) fn require_in_graph( + tx: &WriteScope<'_>, + plan: &ProviderPlan, + origin: &str, + digest: &str, + graph: &FactFeed, +) -> Result<()> { let Some([selector, left, right]) = graph .workflow_selectors .iter() diff --git a/crates/ledger/src/publication.rs b/crates/ledger/src/publication.rs index 396d030f..2bcef509 100644 --- a/crates/ledger/src/publication.rs +++ b/crates/ledger/src/publication.rs @@ -87,7 +87,7 @@ pub(crate) fn receipt_record( connection: &crate::persistence::driver::Connection, operation_id: &str, ) -> Result> { - let record: Option<(String, String)> = crate::persistence::maybe( + let record: Option<(String, String)> = crate::persistence::maybe_prepared( connection, "SELECT digest,receipt FROM authority_publications WHERE operation_id=?1", crate::persistence::params![(operation_id).to_owned()], diff --git a/crates/ledger/src/reviewed_head.rs b/crates/ledger/src/reviewed_head.rs index 37100b84..1bb78ed5 100644 --- a/crates/ledger/src/reviewed_head.rs +++ b/crates/ledger/src/reviewed_head.rs @@ -30,20 +30,21 @@ macro_rules! no_review { AND NOT EXISTS(SELECT 1 FROM authority_delta_reviews)"# }; } -macro_rules! valid_review { () => { r#" FROM authority_review_heads h - JOIN authority a ON a.singleton=1 AND a.revision=h.revision AND a.fence=h.fence - JOIN authority_schema s ON s.singleton=1 - JOIN authority_publications p ON p.operation_id=h.operation_id AND p.digest=h.digest - JOIN authority_reviews r ON r.operation_id=h.operation_id AND r.digest=h.digest AND r.record=h.review_record - JOIN authority_delta_reviews d ON d.operation_id=h.operation_id AND d.reviewer_epoch=h.reviewer_epoch AND d.source_epoch=h.source_epoch AND d.record=h.delta_record - JOIN review_authority v ON v.singleton=1 AND v.epoch=h.reviewer_epoch AND v.record=h.issuer_record - JOIN review_keys k ON k.epoch=v.epoch AND k.record=v.record +macro_rules! valid_review { + () => { valid_review!("JOIN") }; + ($join:literal) => { concat!(r#" FROM authority_review_heads h + "#, $join, r#" authority a ON a.singleton=1 AND a.revision=h.revision AND a.fence=h.fence + "#, $join, r#" authority_schema s ON s.singleton=1 + "#, $join, r#" authority_publications p ON p.operation_id=h.operation_id AND p.digest=h.digest + "#, $join, r#" authority_reviews r ON r.operation_id=h.operation_id AND r.digest=h.digest AND r.record=h.review_record + "#, $join, r#" authority_delta_reviews d ON d.operation_id=h.operation_id AND d.reviewer_epoch=h.reviewer_epoch AND d.source_epoch=h.source_epoch AND d.record=h.delta_record + "#, $join, r#" review_authority v ON v.singleton=1 AND v.epoch=h.reviewer_epoch AND v.record=h.issuer_record + "#, $join, r#" review_keys k ON k.epoch=v.epoch AND k.record=v.record WHERE EXISTS(SELECT 1 FROM review_deployment) AND h.singleton=1 AND k.epoch=(SELECT MAX(epoch) FROM review_keys) AND json_extract(p.request,'$.policy')=a.policy AND json_extract(p.request,'$.schema')=s.schema AND (json_extract(d.record,'$.disposition')!='no_execution_gain' OR json_type(v.record,'$.qualified_catalog')='text') AND json_extract(p.receipt,'$.outcome')='committed' - AND json_extract(p.receipt,'$.revision')=h.revision AND json_extract(p.receipt,'$.fence')=h.fence -"# }; } + AND json_extract(p.receipt,'$.revision')=h.revision AND json_extract(p.receipt,'$.fence')=h.fence"#) }; } const REQUIRE_REVIEW: &str = concat!( "SELECT CASE WHEN ", no_review!(), @@ -54,7 +55,7 @@ const REQUIRE_REVIEW: &str = concat!( const LEGACY: &str = concat!("SELECT ", no_review!()); const PREPARE: &str = concat!( "SELECT h.operation_id,h.digest,h.revision,h.fence,h.reviewer_epoch,h.source_epoch,h.issuer_record,h.review_record,h.delta_record,p.request,p.receipt,s.schema,a.policy,r.artifact_digest,d.digest", - valid_review!() + valid_review!("CROSS JOIN") ); /// No historical receipt, raw native publication or missing key projection is a @@ -114,7 +115,9 @@ pub(crate) fn prepare(c: &Connection) -> Result { if legacy(c)? { return Ok(Prepared(None)); } - let image = crate::persistence::maybe(c, PREPARE, (), |r| { + // Reuse only the native SQL program. Every invocation opens a fresh cursor; + // current() still compares all exact projections in the deciding scope. + let image = crate::persistence::maybe_prepared(c, PREPARE, (), |r| { Ok(ReviewImage { operation: r.get(0)?, digest: r.get(1)?, @@ -141,7 +144,9 @@ pub(crate) fn prepare(c: &Connection) -> Result { } fn legacy(c: &Connection) -> Result { - crate::persistence::one(c, LEGACY, (), |r| r.get(0)).map_err(db) + crate::persistence::maybe_prepared(c, LEGACY, (), |r| r.get(0)) + .and_then(|row| row.ok_or(crate::persistence::driver::Error::QueryReturnedNoRows)) + .map_err(db) } fn stale() -> Error { diff --git a/crates/ledger/src/store.rs b/crates/ledger/src/store.rs index 119fa09b..4fb24456 100644 --- a/crates/ledger/src/store.rs +++ b/crates/ledger/src/store.rs @@ -18,6 +18,17 @@ pub struct Ledger { pub(crate) source: Option, } +/// Physical custody only. A new request must establish a fresh logical Ledger. +#[cfg(feature = "commit-observer")] +pub struct ParkedProviderConnection(Session); + +#[cfg(feature = "commit-observer")] +impl ParkedProviderConnection { + pub fn checkout(self) -> Result { + Ledger::from_connection(self.0) + } +} + /// Unforgeable within the public API, deliberately not Clone or serializable. pub struct Dispatch { proposal: Proposal, @@ -45,6 +56,9 @@ impl Ledger { pub fn open(path: impl AsRef) -> Result { let mut connection = Session::open(path).map_err(db)?; connection.initialize_ledger().map_err(db)?; + Self::from_connection(connection) + } + fn from_connection(connection: Session) -> Result { // A missing retained manifest cannot be reconstructed from outcome rows. // Older images require explicit authoritative recovery, never backfill. let _: Vec = crate::persistence::read_all( @@ -66,6 +80,18 @@ impl Ledger { }) } + /// Return physical custody after a known provider completion. A poisoned or + /// source-authorized logical session is ineligible. + #[cfg(feature = "commit-observer")] + pub fn park_provider_connection(mut self) -> Result { + self.require_quiescent()?; + if self.source.is_some() { + return Err(Error::Conflict("source session cannot park as provider")); + } + self.connection.reset_provider_request(); + Ok(ParkedProviderConnection(self.connection)) + } + /// Trusted publication CAS. It cannot be called through the adapter wire protocol. pub fn publish( &mut self, diff --git a/crates/ledger/src/task_origins.rs b/crates/ledger/src/task_origins.rs index 8ee0eb28..7a303c80 100644 --- a/crates/ledger/src/task_origins.rs +++ b/crates/ledger/src/task_origins.rs @@ -134,11 +134,23 @@ const ORIGINAL: &str = "SELECT r.task_digest,r.binding_digest,t.record,o.binding JOIN tasks t ON t.family=r.family JOIN execution_origins o ON o.id=r.origin AND o.canonical_family=r.family LEFT JOIN task_publications p ON p.family=r.family WHERE r.family=?1"; + +#[cfg(feature = "commit-observer")] +thread_local! { + static PREPARE_ORIGINAL_PROGRAM: std::cell::Cell = const { std::cell::Cell::new(true) }; +} + +/// Select native original-task program preparation in the observed worker. +#[cfg(feature = "commit-observer")] +pub fn use_prepared_original_program(prepared: bool) { + PREPARE_ORIGINAL_PROGRAM.set(prepared); +} + fn read( connection: &persistence::driver::Connection, family: &str, ) -> Result> { - persistence::maybe_current(connection, ORIGINAL, [family], |r| { + let decode = |r: &persistence::Row| { let publication = if let Some(operation_id) = r.get::>(6)? { Some(weaver_contracts::PublicationKey { operation_id, @@ -160,8 +172,12 @@ fn read( held: crate::store::integer(r, 8)?, budget: crate::store::integer(r, 9)?, }) - }) - .map_err(db) + }; + #[cfg(feature = "commit-observer")] + if !PREPARE_ORIGINAL_PROGRAM.get() { + return persistence::maybe_current(connection, ORIGINAL, [family], decode).map_err(db); + } + persistence::maybe_prepared(connection, ORIGINAL, [family], decode).map_err(db) } fn verify(original: &Original) -> Result { diff --git a/crates/ledger/src/task_publication.rs b/crates/ledger/src/task_publication.rs index a6dd8298..37ee9c35 100644 --- a/crates/ledger/src/task_publication.rs +++ b/crates/ledger/src/task_publication.rs @@ -10,7 +10,7 @@ pub(crate) fn binding( connection: &crate::persistence::driver::Connection, family: &str, ) -> Result> { - crate::persistence::maybe_current( + crate::persistence::maybe_prepared( connection, "SELECT operation_id,digest FROM task_publications WHERE family=?1", crate::persistence::params![(family).to_owned()], diff --git a/crates/ledger/tests/unit/driver_observer.rs b/crates/ledger/tests/unit/driver_observer.rs new file mode 100644 index 00000000..73b51acb --- /dev/null +++ b/crates/ledger/tests/unit/driver_observer.rs @@ -0,0 +1,287 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +use super::{DriverSpan, driver_dispatch, observe}; +#[path = "../../../contracts/benches/support/fixtures.rs"] +mod provider_fixture; + +#[test] +fn manifest_programs_rebind_current_members_and_reject_divergence() { + use crate::persistence::{Journal, Session}; + driver_dispatch(); + for journal in [Journal::Wal, Journal::Mvcc] { + let dir = tempfile::tempdir().expect("ledger directory"); + let path = dir.path().join("members.db"); + let storage = Session::open_with_journal(&path, journal).expect("journal"); + let mut ledger = crate::Ledger::open(&path).expect("ledger"); + ledger + .publish_typed( + None, + include_str!("../../../../prod/policies/provider/provider.cedar"), + include_str!("../../../../prod/policies/provider/schema.json"), + 1, + ) + .expect("policy"); + let (task, plan) = + provider_fixture::task_plan(8, "https://provider.invalid/v1/chat/completions"); + ledger.register_task(&task).expect("original task"); + let mut peer = task.clone(); + peer.family = "g".into(); + let mut peer_plan = plan.clone(); + peer_plan.family = peer.family.clone(); + peer.stream_contracts.insert( + peer_plan.node.clone(), + peer_plan.digest().expect("peer commitment"), + ); + ledger.register_task(&peer).expect("peer original"); + ledger + .enqueue_provider(&plan) + .expect("native claim and hold"); + let scope = crate::persistence::begin(&mut ledger.connection).expect("deciding scope"); + let exposure = crate::task_origins::require_prepared(&scope, &task.family, None) + .expect("original exposure"); + let expected = crate::exposure_manifest::verified_members(&scope, &task.family, &exposure) + .expect("members"); + assert_eq!(expected.len(), 1); + let (actual, warm, _) = observe(DriverSpan::Prepare, || { + crate::exposure_manifest::verified_members(&scope, &task.family, &exposure) + }); + assert_eq!(actual.expect("fresh current members"), expected); + eprintln!( + "manifest native preparations journal={journal:?} warm={} (one metering query, no manifest compilation)", + warm.attempts + ); + assert_eq!(warm.attempts, 1, "fixed manifest programs recompiled"); + let peer_exposure = crate::task_origins::require_prepared(&scope, &peer.family, None) + .expect("peer exposure"); + assert!( + crate::exposure_manifest::verified_members(&scope, &peer.family, &peer_exposure) + .expect("fresh parameter binding") + .is_empty() + ); + crate::persistence::exec( + &scope, + "UPDATE provider_runs SET reserved=3 WHERE family='f'", + (), + ) + .expect("projection fault"); + assert!( + crate::exposure_manifest::verified_members(&scope, &task.family, &exposure).is_err() + ); + drop(scope); + assert_eq!( + ledger.held(&task.family).expect("original hold retained"), + 4 + ); + drop(storage); + } +} + +#[test] +fn review_program_reuse_preserves_native_receipts_and_currentness() { + use crate::persistence::{Journal, Session}; + use crate::review_fixture::{change, evidence, issuer, source}; + driver_dispatch(); + for journal in [Journal::Wal, Journal::Mvcc] { + let dir = tempfile::tempdir().expect("ledger directory"); + let path = dir.path().join("request.db"); + let storage = Session::open_with_journal(&path, journal).expect("journal"); + let mut ledger = crate::Ledger::open(&path).expect("ledger"); + ledger + .install_review_authority(&issuer(0)) + .expect("reviewer"); + let mut publication = change("request", None); + publication.policy = + include_str!("../../../../prod/policies/provider/provider.cedar").into(); + let proof = evidence(&mut ledger, &publication); + ledger + .with_authenticated_source(&source(), |l| l.register_delta_review(&proof)) + .expect("review"); + let published = ledger + .with_authenticated_source(&source(), |l| l.publish_authority(&publication)) + .expect("publication"); + let (task, plan) = + provider_fixture::task_plan(8, "https://provider.invalid/v1/chat/completions"); + let key = weaver_contracts::PublicationKey { + operation_id: published.operation_id, + digest: published.digest, + }; + ledger + .register_published_task(&task, &key) + .expect("published original task"); + crate::reviewed_head::prepare(&ledger.connection).expect("prepare review"); + ledger + .enqueue_provider(&plan) + .expect("native admission and receipt"); + let (candidate, after_enqueue, _) = observe(DriverSpan::Prepare, || { + crate::reviewed_head::prepare(&ledger.connection) + }); + candidate.expect("current review after admission"); + let permit = ledger + .consume_provider(&plan.family, &plan.node, &["primary".into()].into()) + .expect("native consume"); + let (candidate, after_consume, _) = observe(DriverSpan::Prepare, || { + crate::reviewed_head::prepare(&ledger.connection) + }); + candidate.expect("current review after consumption"); + eprintln!( + "review consumer preparations journal={journal:?} after_enqueue={} after_consume={}", + after_enqueue.attempts, after_consume.attempts + ); + assert_eq!( + after_enqueue.attempts, 0, + "admission/receipt invalidated the review program: {journal:?}" + ); + assert_eq!( + after_consume.attempts, 0, + "consumption invalidated the review program: {journal:?}" + ); + let candidate = crate::reviewed_head::prepare(&ledger.connection).expect("fresh candidate"); + let scope = crate::persistence::begin(&mut ledger.connection).expect("deciding scope"); + assert_eq!( + candidate + .current(&scope, plan.revision, plan.fence) + .expect("exact current projection"), + Some(publication.policy.as_str()) + ); + crate::persistence::exec(&scope, "UPDATE authority SET policy=policy||' '", ()) + .expect("projection fault"); + assert!( + candidate + .current(&scope, plan.revision, plan.fence) + .is_err() + ); + drop(scope); + assert_eq!(permit.plan(), &plan); + assert_eq!(ledger.held(&plan.family).expect("original hold"), 4); + drop(storage); + } +} + +#[test] +fn review_program_reuse_reads_replacement_and_rejects_projection_loss() { + use crate::review_fixture::{change, evidence, issuer, source}; + driver_dispatch(); + let dir = tempfile::tempdir().expect("ledger directory"); + let mut ledger = crate::Ledger::open(dir.path().join("review-program.db")).expect("ledger"); + ledger + .install_review_authority(&issuer(0)) + .expect("reviewer"); + for (name, parent) in [("first", None), ("replacement", Some(0))] { + let publication = change(name, parent); + let proof = evidence(&mut ledger, &publication); + ledger + .with_authenticated_source(&source(), |l| l.register_delta_review(&proof)) + .expect("review"); + let receipt = ledger + .with_authenticated_source(&source(), |l| l.publish_authority(&publication)) + .expect("publication"); + let (first, cold, _) = observe(DriverSpan::Prepare, || { + crate::reviewed_head::prepare(&ledger.connection) + }); + let first = first.expect("fresh projection"); + let (second, warm, _) = observe(DriverSpan::Prepare, || { + crate::reviewed_head::prepare(&ledger.connection) + }); + let second = second.expect("rebound projection"); + if parent.is_none() { + eprintln!( + "review native preparations cold={} warm={}", + cold.attempts, warm.attempts + ); + assert_eq!(warm.attempts, 0, "native program was recompiled"); + } + let scope = crate::persistence::begin(&mut ledger.connection).expect("deciding scope"); + for candidate in [&first, &second] { + assert_eq!( + candidate + .current( + &scope, + receipt.revision.expect("revision"), + receipt.fence.expect("fence") + ) + .expect("current projection"), + Some(publication.policy.as_str()) + ); + } + } + crate::persistence::exec(&ledger.connection, "DELETE FROM review_authority", ()) + .expect("lose projection"); + assert!( + crate::reviewed_head::prepare(&ledger.connection).is_err(), + "cached SQL cannot retain authority" + ); +} + +#[test] +fn prepared_singleton_finishes_and_rebinds_without_replaying_a_cursor() { + let dir = tempfile::tempdir().expect("ledger directory"); + let session = + crate::persistence::Session::open(dir.path().join("singleton.db")).expect("ledger"); + for value in [1_i64, 2] { + assert_eq!( + crate::persistence::maybe_prepared(&session, "SELECT ?1", [value], |row| row + .get::(0)) + .expect("bound query"), + Some(value) + ); + } + assert!( + crate::persistence::maybe_prepared(&session, "SELECT 1 WHERE 0", (), |row| row + .get::(0)) + .expect("empty query") + .is_none() + ); + assert!( + crate::persistence::maybe_prepared(&session, "SELECT 1 UNION ALL SELECT 2", (), |row| row + .get::( + 0 + )) + .is_err() + ); +} + +#[cfg(unix)] +#[test] +fn commit_io_observes_native_spans_after_unobserved_setup() { + driver_dispatch(); + let dir = tempfile::tempdir().expect("ledger directory"); + let session = + crate::persistence::Session::open(dir.path().join("commit-io.db")).expect("ledger"); + crate::persistence::script(&session, "CREATE TABLE observed_io(value INTEGER)") + .expect("schema"); + let tx = futures_executor::block_on( + crate::persistence::driver::transaction::Transaction::new_unchecked( + &session, + crate::persistence::driver::transaction::TransactionBehavior::Immediate, + ), + ) + .expect("transaction"); + crate::persistence::exec(&tx, "INSERT INTO observed_io VALUES(1)", ()).expect("write"); + let (result, sync, io) = + super::observe_commit(true, || futures_executor::block_on(tx.commit())); + result.expect("commit"); + let io = io.expect("I/O observation"); + assert!(io.rows[0][0] > 0); + assert!(io.rows[2][2] + io.rows[3][2] > 0, "missing native writes"); + assert!(sync.attempts > 0, "missing native sync"); + assert_eq!(io.rows[4][2], sync.attempts); + assert!(io.rows[4][0] <= io.rows[0][0]); + let (_, _, disabled) = super::observe_commit(false, || {}); + assert!(disabled.is_none()); +} + +#[test] +fn prepare_first_seen_outside_scoped_dispatch_is_still_observed() { + driver_dispatch(); + // Open issues Turso statements before the observer is active on this thread. + let dir = tempfile::tempdir().expect("ledger directory"); + let session = + crate::persistence::Session::open(dir.path().join("observer.db")).expect("open ledger"); + let (statement, wall, _) = observe(DriverSpan::Prepare, || { + futures_executor::block_on(session.prepare("BEGIN IMMEDIATE")) + }); + assert!(statement.is_ok()); + assert_eq!(wall.attempts, 1, "missing Turso prepare span"); +} diff --git a/crates/ledger/tests/unit/execution_exposure.rs b/crates/ledger/tests/unit/execution_exposure.rs index f44475f8..e8e65ac0 100644 --- a/crates/ledger/tests/unit/execution_exposure.rs +++ b/crates/ledger/tests/unit/execution_exposure.rs @@ -513,6 +513,10 @@ proptest! { #![proptest_config(Config::with_cases(64))] #[test] fn exact_message_manifest_guards_recovery_and_existing_write_handles(fault in 0u8..4, restart in proptest::bool::ANY) { + #[cfg(feature = "commit-observer")] + weaver_ledger::use_prepared_manifest_programs( + std::env::var("WEAVER_TEST_PREPARED_MANIFEST_PROGRAMS").as_deref() == Ok("1"), + ); let temp=tempfile::tempdir().expect("directory");let path=temp.path().join("manifest.db"); let (mut ledger,contract)=stream_properties::fixture(&path); ledger.enqueue_message(&stream_properties::message(&contract,0,0,1)).expect("first hold"); diff --git a/crates/ledger/tests/unit/persistence_scheduler.rs b/crates/ledger/tests/unit/persistence_scheduler.rs index fec9d761..d609a2b7 100644 --- a/crates/ledger/tests/unit/persistence_scheduler.rs +++ b/crates/ledger/tests/unit/persistence_scheduler.rs @@ -17,6 +17,26 @@ fn scope(roots: [u8; 3]) -> Scope { Scope::Domains(roots.map(|id| id.to_string()).into()) } +#[cfg(feature = "commit-observer")] +#[test] +fn observed_release_covers_lease_removal_without_retaining_a_grant() { + use crate::persistence::scope_trace::{capturing_release, observe_release}; + + let scheduler = Scheduler::default(); + let grant = scheduler.acquire(Scope::All, None).expect("grant"); + let release = observe_release(|| drop(grant)).expect("observed release"); + assert!(release.requested <= release.locked); + assert!(release.locked <= release.removed); + assert!(release.removed <= release.notified); + assert!(release.notified <= release.returned); + let state = scheduler.state.lock().expect("scheduler"); + assert!(state.active.is_empty()); + assert_eq!(state.generation, 1); + drop(state); + assert!(!capturing_release()); + assert!(observe_release(|| {}).is_none()); +} + proptest! { #[test] fn grants_depend_only_on_exact_older_or_active_conflicts( diff --git a/crates/ledger/tests/unit/persistence_transactions.rs b/crates/ledger/tests/unit/persistence_transactions.rs index 36abed47..b5ec9164 100644 --- a/crates/ledger/tests/unit/persistence_transactions.rs +++ b/crates/ledger/tests/unit/persistence_transactions.rs @@ -4,6 +4,87 @@ use crate::persistence::{self, Session}; +#[cfg(any(target_os = "linux", target_os = "macos"))] +#[test] +#[ignore = "bounded performance probe using the real native transaction scope"] +fn provider_begin_temp_pager_probe() { + use crate::persistence::timing::thread_cpu_time; + use std::time::Instant; + let directory = tempfile::tempdir().expect("store"); + let path = directory.path().join("temp-pager.db"); + let mut owner = + Session::open_with_journal(&path, persistence::Journal::Mvcc).expect("native owner"); + roots(&mut owner); + let variants = ["default", "prewarm-file", "memory-diagnostic"]; + for round in 0..24 { + for offset in 0..variants.len() { + let variant = variants[(round + offset) % variants.len()]; + let mut session = Session::open(&path).expect("new connection"); + let setup_wall = Instant::now(); + let setup_cpu = thread_cpu_time().expect("thread CPU"); + match variant { + "default" => {} + "prewarm-file" => { + let objects: i64 = persistence::one( + &session, + "SELECT count(*) FROM temp.sqlite_schema", + (), + |row| row.get(0), + ) + .expect("prepare connection-local TEMP pager"); + assert_eq!(objects, 0); + } + "memory-diagnostic" => { + persistence::exec(&session, "PRAGMA temp_store=MEMORY", ()) + .expect("diagnostic TEMP mode"); + } + _ => unreachable!(), + } + let setup_cpu = thread_cpu_time().expect("thread CPU") - setup_cpu; + let setup_wall = setup_wall.elapsed(); + session.trace_provider_scopes("a", None); + for pass in 0..2 { + let before = session.timings(); + let transaction = + persistence::begin_family(&mut session, "a").expect("native BEGIN"); + drop(transaction); + session.require_quiescent().expect("native rollback"); + let timing = session.timings().since(before); + assert_eq!(timing.transaction_begin_cpu.attempts, 1); + assert_eq!(timing.transaction_begin_prepare.attempts, 1); + println!( + "weaver-temp-pager {{\"round\":{round},\"arm\":\"{variant}\",\"pass\":{pass},\"setupWallNS\":{},\"setupCpuNS\":{},\"beginWallNS\":{},\"beginCpuNS\":{},\"prepareCpuNS\":{}}}", + setup_wall.as_nanos(), + setup_cpu.as_nanos(), + timing.transaction_begin.nanos, + timing.transaction_begin_cpu.nanos, + timing.transaction_begin_prepare_cpu.nanos + ); + } + let journal: String = + persistence::one(&session, "PRAGMA journal_mode", (), |row| row.get(0)) + .expect("journal"); + let synchronous: i64 = + persistence::one(&session, "PRAGMA synchronous", (), |row| row.get(0)) + .expect("sync"); + let foreign_keys: i64 = + persistence::one(&session, "PRAGMA foreign_keys", (), |row| row.get(0)) + .expect("foreign keys"); + assert_eq!( + (journal.as_str(), synchronous, foreign_keys), + ("mvcc", 2, 1) + ); + session.close().expect("clean connection"); + } + } + let holds: i64 = persistence::one(&owner, "SELECT sum(held) FROM budget_domains", (), |row| { + row.get(0) + }) + .expect("unchanged reservations"); + assert_eq!(holds, 0); + owner.close().expect("natural owner drain"); +} + struct CommitFault { after: bool, } @@ -20,6 +101,36 @@ impl persistence::commit_observer::Observer for CommitFault { } } } + +#[test] +fn applied_commit_with_lost_ack_cannot_park_as_provider() { + let directory = tempfile::tempdir().expect("store"); + let path = directory.path().join("provider-reuse-lost-ack.db"); + let mut ledger = crate::Ledger::open(&path).expect("ledger"); + persistence::exec( + &ledger.connection, + "CREATE TABLE probe(id INTEGER PRIMARY KEY)", + (), + ) + .expect("probe schema"); + ledger.connection.commit_observer = Some(std::sync::Arc::new(CommitFault { after: true })); + let tx = persistence::begin(&mut ledger.connection).expect("writer"); + persistence::exec(&tx, "INSERT INTO probe VALUES(1)", ()).expect("stage marker"); + assert!(tx.commit_provider().is_err()); + assert!( + ledger + .connection + .is_autocommit() + .expect("native transaction ended") + ); + assert!(ledger.park_provider_connection().is_err()); + let recovered = crate::Ledger::open(&path).expect("fresh physical connection"); + let marker: i64 = persistence::one(&recovered.connection, "SELECT id FROM probe", (), |row| { + row.get(0) + }) + .expect("applied marker recovered"); + assert_eq!(marker, 1); +} proptest::proptest! { #![proptest_config(proptest::test_runner::Config::with_cases(16))] #[test] diff --git a/crates/ledger/tests/unit/provider.rs b/crates/ledger/tests/unit/provider.rs index e389d5b8..813096e2 100644 --- a/crates/ledger/tests/unit/provider.rs +++ b/crates/ledger/tests/unit/provider.rs @@ -30,6 +30,80 @@ fn fixture(path: &std::path::Path) -> (Ledger, ProviderPlan) { fixture_nodes(path, &["infer"]) } +#[test] +fn terminal_provider_plan_keeps_original_ceiling_across_restart() { + use weaver_ledger::persistence::{Session, exec, one}; + + let temp = tempfile::tempdir().expect("directory"); + let path = temp.path().join("terminal-plan.db"); + let (mut ledger, plan) = fixture_nodes(&path, &["infer", "second"]); + let mut second = plan.clone(); + second.node = "second".into(); + ledger.enqueue_provider(&plan).expect("reserve first"); + ledger.enqueue_provider(&second).expect("reserve second"); + let targets = BTreeSet::from(["primary".into()]); + let permit = ledger + .consume_provider("f", "infer", &targets) + .expect("consume"); + ledger + .dispatch_provider(&permit, || Ok(())) + .expect("dispatch"); + ledger + .complete_provider(&permit, "protobuf") + .expect("complete"); + drop(permit); + ledger.close().expect("close"); + + let storage = Session::open(&path).expect("restart storage"); + let stored: String = one( + &storage, + "SELECT plan FROM provider_runs WHERE family='f' AND node='infer'", + (), + |row| row.get(0), + ) + .expect("terminal plan"); + assert_eq!(stored, r#"{"ceiling":4}"#); + + let mut restarted = Ledger::open(&path).expect("restart ledger"); + let receipt = restarted + .provider_receipt("f", "infer") + .expect("read terminal receipt") + .expect("terminal receipt retained"); + assert_eq!(receipt.digest, plan.digest().expect("original digest")); + assert_eq!(receipt.state, weaver_contracts::ProviderState::Complete); + assert!(restarted.consume_provider("f", "infer", &targets).is_err()); + let update = "UPDATE provider_runs SET plan=?1 WHERE family='f' AND node='infer'"; + exec(&storage, update, [r#"{"ceiling":3}"#]).expect("corrupt terminal ceiling"); + assert!(restarted.consume_provider("f", "second", &targets).is_err()); + exec(&storage, update, [stored.as_str()]).expect("restore terminal ceiling"); + restarted + .consume_provider("f", "second", &targets) + .expect("consume second"); + assert_eq!(restarted.held("f").expect("shared hold"), 8); +} + +#[test] +fn reusing_physical_connection_rejects_old_provider_dispatch() { + let temp = tempfile::tempdir().expect("directory"); + let (mut ledger, plan) = fixture(&temp.path().join("reused-provider.db")); + ledger.enqueue_provider(&plan).expect("original hold"); + let permit = ledger + .consume_provider("f", "infer", &BTreeSet::from(["primary".into()])) + .expect("consume"); + let mut next = ledger + .park_provider_connection() + .expect("healthy physical connection") + .checkout() + .expect("fresh logical session"); + let mut calls = 0; + assert!(next.dispatch_provider(&permit, || { + calls += 1; + Ok(()) + }).is_err()); + assert_eq!(calls, 0); + assert_eq!(next.held("f").expect("original hold"), 4); +} + fn fixture_nodes(path: &std::path::Path, nodes: &[&str]) -> (Ledger, ProviderPlan) { fixture_with_ceiling(path, nodes, 4) } diff --git a/crates/ledger/tests/unit/provider/workflow.rs b/crates/ledger/tests/unit/provider/workflow.rs index e16492c5..ebd88282 100644 --- a/crates/ledger/tests/unit/provider/workflow.rs +++ b/crates/ledger/tests/unit/provider/workflow.rs @@ -308,14 +308,14 @@ fn check_workflow_rechecks_prepared_floor(nested: bool) { let stale = ledger .prepare_provider_progression(&predecessor, &successor) .expect("first frontier"); - project( + let b = project( &mut ledger, &FactIntent { operation_id: "second-fact".into(), revision: 2, previous_snapshot: a.snapshot, expected_floor: a.floor, - ..intent + ..intent.clone() }, ); assert!( @@ -334,14 +334,14 @@ fn check_workflow_rechecks_prepared_floor(nested: bool) { ..predecessor.clone() }) .collect(); + let cut = ledger.observe_workflow(&plans).expect("frontier"); + assert_eq!(cut.available, nodes); + assert_eq!(cut.complete, ["infer"]); + assert_eq!(cut.pending, nodes[1..]); if nested { - let cut = ledger - .observe_workflow(&plans) - .expect("frontier") - .nested - .expect("nested graph"); - assert!(cut.decisions.is_empty()); - assert!(!cut.predecessors.contains_key("join")); + let graph = cut.nested.expect("nested graph"); + assert!(graph.decisions.is_empty()); + assert!(!graph.predecessors.contains_key("join")); } let current = ledger .prepare_provider_progression(&predecessor, &successor) @@ -361,7 +361,69 @@ fn check_workflow_rechecks_prepared_floor(nested: bool) { .enqueue_provider_progression(&successor, "", None, Some(&replay)) .expect("exact replay"); assert_eq!(ledger.held("f").expect("one successor hold"), 8); - if nested { + if !nested { + let permit = ledger + .consume_provider("f", "second", &BTreeSet::from(["primary".into()])) + .expect("consume successor"); + ledger + .dispatch_provider(&permit, || Ok(())) + .expect("dispatch successor"); + let release = ledger + .prepare_provider_release(&permit, "response", "protobuf", 1) + .expect("prepare successor response"); + ledger + .release_provider(&permit, release, "protobuf", |_| Ok(())) + .expect("release successor response"); + ledger + .complete_provider_with_result(&permit, "protobuf", None, None) + .expect("complete successor"); + assert_eq!( + ledger.observe_workflow(&plans).expect("frontier").complete, + ["infer", "second"] + ); + let mut storage = + weaver_ledger::persistence::Session::open(&path).expect("fault injection"); + weaver_ledger::persistence::exec( + &storage, + "INSERT INTO metering_deployment(singleton,record) VALUES(1,'{}')", + (), + ) + .expect("change metering deployment after a completed observation"); + assert!( + ledger.observe_workflow(&plans).is_err(), + "a new frontier transaction must read the current deployment" + ); + weaver_ledger::persistence::exec(&storage, "DELETE FROM metering_deployment", ()) + .expect("restore deployment"); + assert_eq!( + ledger + .observe_workflow(&plans) + .expect("restored frontier") + .complete, + ["infer", "second"] + ); + let fault = weaver_ledger::persistence::begin(&mut storage).expect("open WAL writer"); + weaver_ledger::persistence::exec( + &fault, + "DELETE FROM provider_workflow_transitions WHERE successor=?1", + ["second"], + ) + .expect("remove successor transition"); + assert_eq!( + ledger + .observe_workflow(&plans) + .expect("committed frontier") + .complete, + ["infer", "second"] + ); + fault.commit().expect("commit missing transition"); + assert!(matches!( + ledger.observe_workflow(&plans), + Err(weaver_contracts::Error::Conflict( + "provider successor has no committed transition" + )) + )); + } else { ledger.close().expect("close"); let mut ledger = Ledger::open(&path).expect("reopen"); let cut = ledger @@ -378,5 +440,39 @@ fn check_workflow_rechecks_prepared_floor(nested: bool) { ); assert!(!cut.predecessors.contains_key("join")); assert_eq!(ledger.held("f").expect("preserved winner hold"), 8); + ledger + .with_authenticated_source(&caller, |ledger| { + let barrier = ledger.stage_fact_intent(&FactIntent { + operation_id: "withdraw-after-reopen".into(), + revision: 3, + previous_snapshot: b.snapshot, + expected_floor: b.floor, + available: false, + ..intent + })?; + let pending = ledger.observe_workflow(&plans)?; + assert!(pending.available.is_empty()); + assert_eq!(pending.complete, ["infer"]); + let FactPreparation::Pending(work) = ledger.prepare_fact_projection(&barrier)? + else { + panic!("expected pending withdrawal"); + }; + ledger.resolve_fact_projection(&work, affected.clone())?; + let withdrawn = ledger.observe_workflow(&plans)?; + assert!(withdrawn.available.is_empty()); + assert_eq!(withdrawn.complete, ["infer"]); + assert_eq!(withdrawn.pending, nodes[1..]); + Ok(()) + }) + .expect("withdrawal fences batched frontier after reopen"); + let storage = weaver_ledger::persistence::Session::open(&path).expect("fault injection"); + weaver_ledger::persistence::exec(&storage, "DELETE FROM domain_history", ()) + .expect("remove shared history"); + assert!(matches!( + ledger.observe_workflow(&plans), + Err(weaver_contracts::Error::Conflict( + "original domain history missing or inconsistent" + )) + )); } } diff --git a/crates/ledger/tests/unit/provider_catalog.rs b/crates/ledger/tests/unit/provider_catalog.rs new file mode 100644 index 00000000..74be77e7 --- /dev/null +++ b/crates/ledger/tests/unit/provider_catalog.rs @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +use super::ProviderCatalogProjection; +use weaver_contracts::ProviderCatalog; + +#[test] +fn inspection_reuses_only_verified_catalog_bytes() { + let catalog = ProviderCatalog { + parent: String::new(), + entries: Default::default(), + }; + let digest = catalog.digest().expect("catalog digest"); + let record = + String::from_utf8(catalog.record().expect("catalog record")).expect("catalog UTF-8"); + let mut projection = ProviderCatalogProjection::default(); + let project = |projection: &mut ProviderCatalogProjection, bytes: String| { + projection.project(digest.clone(), bytes) + }; + + project(&mut projection, record.clone()).expect("verify first snapshot"); + assert_eq!( + project(&mut projection, record.clone()) + .expect("reuse exact snapshot") + .1, + record.as_bytes(), + ); + assert!(project(&mut projection, String::from("{}")).is_err()); + assert!( + project( + &mut projection, + record.replace("\"parent\":\"\"", "\"parent\":\"other\"") + ) + .is_err() + ); + assert_eq!( + project(&mut projection, format!(" {record}\n")) + .expect("normalize older record") + .1, + record.as_bytes(), + ); + assert!(projection.canonical.is_none()); + assert!( + projection + .project(String::from("wrong-version"), record) + .is_err() + ); +} diff --git a/crates/ledger/tests/unit/scope_trace.rs b/crates/ledger/tests/unit/scope_trace.rs index 94d6a200..23505bcc 100644 --- a/crates/ledger/tests/unit/scope_trace.rs +++ b/crates/ledger/tests/unit/scope_trace.rs @@ -2,9 +2,38 @@ // // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 -use super::{CAPACITY, ProviderScopePhase, ProviderScopeSample, Trace}; +use super::{Arrival, CAPACITY, Completion, ProviderScopePhase, ProviderScopeSample, Trace}; use proptest::{prop_assert, prop_assert_eq, proptest}; -use std::time::Duration; +use std::time::{Duration, Instant}; + +#[test] +fn begin_driver_counters_follow_their_admission_grant() { + let mut trace = Trace::new("trace-test").with_request("request"); + for (ordinal, counters) in [(1, [17, 13, 7, 5, 1, 2]), (3, [31, 29, 0, 0, 0, 1])] { + let mut grant = Arrival::capture( + ProviderScopePhase::Admission, + ordinal, + Instant::now(), + false, + ) + .granted(&mut trace, ordinal + 1); + grant.opened(41, 23, counters); + grant.record(Completion { + authority_span: Duration::ZERO, + releasing: Instant::now(), + transaction_nanos: 53, + commit_total: 37, + admission_nanos: [0; 8], + manifest_driver: [[ordinal; 8], [ordinal + 1; 8]], + release: None, + }); + } + assert_eq!(trace.samples[0].arrival, 1); + assert_eq!(trace.samples[1].arrival, 3); + assert_eq!(trace.timeline[0].begin_driver, [17, 13, 7, 5, 1, 2]); + assert_eq!(trace.timeline[1].begin_driver, [31, 29, 0, 0, 0, 1]); + assert_eq!(trace.timeline[1].manifest_driver, [[3; 8], [4; 8]]); +} proptest! { #[test] diff --git a/crates/server/src/admission.rs b/crates/server/src/admission.rs index 3381dd34..deefc3be 100644 --- a/crates/server/src/admission.rs +++ b/crates/server/src/admission.rs @@ -12,6 +12,8 @@ pub(crate) struct Admission { execution: Arc, publication: Arc, observation: Arc, + #[cfg(test)] + provider_idle: Arc>>, } impl Admission { pub(crate) fn new(execution: usize) -> Self { @@ -19,6 +21,8 @@ impl Admission { execution: Arc::new(Semaphore::new(execution)), publication: Arc::new(Semaphore::new(1)), observation: Arc::new(Semaphore::new(2)), + #[cfg(test)] + provider_idle: Arc::new(std::sync::Mutex::new(Vec::new())), } } pub(crate) fn execution(&self) -> Result, Status> { @@ -38,6 +42,46 @@ impl Admission { pub(crate) fn observation(&self) -> Result, Status> { acquire(&self.observation) } + + /// Called once by a tracked provider worker holding its execution permit. + /// A new connection is created only when the idle set is empty. + #[cfg(test)] + pub(crate) fn checkout_provider( + &self, + path: &std::path::Path, + shutdown: &tokio_util::sync::CancellationToken, + ) -> weaver_contracts::Result<(weaver_ledger::Ledger, bool)> { + let parked = { + let mut idle = self + .provider_idle + .lock() + .map_err(|_| weaver_contracts::Error::Conflict("provider custody poisoned"))?; + if shutdown.is_cancelled() { + return Err(weaver_contracts::Error::Conflict("provider custody closed")); + } + idle.pop() + }; + match parked { + Some(parked) => parked.checkout().map(|ledger| (ledger, true)), + None => weaver_ledger::Ledger::open(path).map(|ledger| (ledger, false)), + } + } + + /// Return before releasing the execution permit. Failed workers drop their + /// ledger in the worker instead. Idle custody ends with the tracked owner. + #[cfg(test)] + pub(crate) fn park_provider( + &self, + ledger: weaver_ledger::Ledger, + shutdown: &tokio_util::sync::CancellationToken, + ) { + if let Ok(parked) = ledger.park_provider_connection() + && let Ok(mut idle) = self.provider_idle.lock() + && !shutdown.is_cancelled() + { + idle.push(parked); + } + } } fn acquire(lane: &Arc) -> Result, Status> { lane.clone() diff --git a/crates/server/src/governance_owner.rs b/crates/server/src/governance_owner.rs index 0a2e427d..ca56dcf4 100644 --- a/crates/server/src/governance_owner.rs +++ b/crates/server/src/governance_owner.rs @@ -58,7 +58,8 @@ impl RuntimeOwner { derive: impl FnMut( &mut C, &weaver_governance::Derivation, - ) -> std::result::Result, SourceError> + ) + -> std::result::Result + Send + 'static, ) -> Result { diff --git a/crates/server/src/grpc.rs b/crates/server/src/grpc.rs index 632e36b3..a9324e48 100644 --- a/crates/server/src/grpc.rs +++ b/crates/server/src/grpc.rs @@ -639,8 +639,13 @@ impl pb::gateway_server::Gateway for Gateway { )); } if let Some(lifecycle) = lifecycle { - let prepared = - crate::single_provider::Prepared::new(&reply, after, bound).map_err(status)?; + let prepared = crate::single_provider::Prepared::new( + &reply, + after, + bound, + self.runtime.fact_feed(), + ) + .map_err(status)?; lifecycle .ready .set(prepared) @@ -891,12 +896,9 @@ impl pb::gateway_server::Gateway for Gateway { ) -> std::result::Result, Status> { let caller = self.source_identity(&request)?; let snapshot = self.ingress.source()?.provider_catalog(caller).await?; - let Some((version, catalog)) = snapshot else { + let Some((version, record)) = snapshot else { return Ok(Response::new(pb::ProviderCatalogSnapshot::default())); }; - let record = catalog - .record() - .map_err(|_| Status::internal("provider catalog serialization"))?; Ok(Response::new(pb::ProviderCatalogSnapshot { version, record, diff --git a/crates/server/src/grpc_output.rs b/crates/server/src/grpc_output.rs index d5f2b376..96f81a0c 100644 --- a/crates/server/src/grpc_output.rs +++ b/crates/server/src/grpc_output.rs @@ -15,10 +15,57 @@ use weaver_contracts::{Error, ProviderEvent, ProviderRoute, Result}; thread_local! { static HANDOFFS: std::cell::RefCell> = const { std::cell::RefCell::new(Vec::new()) }; static DELIVERIES: std::cell::RefCell> = const { std::cell::RefCell::new(Vec::new()) }; - static TRANSPORT: std::cell::Cell> = const { std::cell::Cell::new(None) }; + static TRANSPORT: std::cell::Cell> = const { std::cell::Cell::new(None) }; + static FIRST_QUEUE_TICKS: std::cell::Cell> = const { std::cell::Cell::new(None) }; + static BROKER_PHASES: std::cell::Cell<[u128; 4]> = const { std::cell::Cell::new([0; 4]) }; + static ADMISSION_LEDGER: std::cell::Cell> = const { std::cell::Cell::new(None) }; static ENCODING_NANOS: std::cell::Cell = const { std::cell::Cell::new(0) }; } +#[cfg(test)] +pub(crate) fn append_admission_ledger( + first_frame: &mut String, + admission_ledger: [weaver_ledger::TransactionTimings; 2], +) { + use std::fmt::Write; + for timing in admission_ledger { + for nanos in [ + timing.owner_gate_wait.nanos, + timing.domain_wait.nanos, + timing.transaction_begin.nanos, + timing.domain_hold.nanos, + timing.transaction_hold.nanos, + timing.commit.nanos, + timing.provider_cedar.nanos, + timing.provider_publication_prepare.nanos, + timing.provider_original_prepare.nanos, + timing.provider_domain_prepare.nanos, + timing.transaction_begin_poll.nanos, + timing.transaction_begin_cpu.nanos, + timing.transaction_begin_prepare.nanos, + timing.transaction_begin_prepare_cpu.nanos, + timing.commit_poll.nanos, + timing.commit_cpu.nanos, + timing.commit_sync.nanos, + ] { + let _ = write!(first_frame, " {nanos}"); + } + let _ = write!( + first_frame, + " {} {} {} {} {} {} {} {} {}", + timing.transaction_begin_poll.attempts, + timing.transaction_begin_pending, + timing.transaction_begin_cpu.attempts, + timing.transaction_begin_prepare.attempts, + timing.transaction_begin_prepare_cpu.attempts, + timing.commit_poll.attempts, + timing.commit_pending, + timing.commit_cpu.attempts, + timing.commit_sync.attempts, + ); + } +} + #[cfg(test)] pub(crate) fn take_encoding_nanos() -> u128 { ENCODING_NANOS.with(|total| total.replace(0)) @@ -35,10 +82,25 @@ pub(crate) fn take_deliveries() -> Vec { } #[cfg(test)] -pub(crate) fn take_transport() -> Option { +pub(crate) fn take_transport() -> Option<(weaver_broker::ProviderTransportPhases, u128)> { TRANSPORT.with(|phases| phases.take()) } +#[cfg(test)] +pub(crate) fn take_first_queue_ticks() -> Option { + FIRST_QUEUE_TICKS.with(|slot| slot.take()) +} + +#[cfg(test)] +pub(crate) fn take_broker_phases() -> [u128; 4] { + BROKER_PHASES.with(|phases| phases.replace([0; 4])) +} + +#[cfg(test)] +pub(crate) fn take_admission_ledger() -> Option<[weaver_ledger::TransactionTimings; 2]> { + ADMISSION_LEDGER.with(|phases| phases.take()) +} + /// Only Output constructs the packet. Other server owners cannot inspect or /// modify its bytes before the deciding receiver consumes the proof. pub(crate) struct InertFrame { @@ -83,7 +145,25 @@ pub(crate) struct PreparedFrame { impl ProviderOutput for Output { #[cfg(test)] fn observe_transport(&self, phases: weaver_broker::ProviderTransportPhases) { - TRANSPORT.with(|slot| slot.set(Some(phases))); + let timestamp = weaver_ledger::persistence::provider_observation_nanos(); + TRANSPORT.with(|slot| slot.set(Some((phases, timestamp)))); + } + #[cfg(test)] + fn observe_admission( + &self, + enqueue_nanos: u128, + consume_nanos: u128, + ledger: [weaver_ledger::TransactionTimings; 2], + ) { + BROKER_PHASES.with(|phases| phases.set([enqueue_nanos, consume_nanos, 0, 0])); + ADMISSION_LEDGER.with(|phases| phases.set(Some(ledger))); + } + #[cfg(test)] + fn observe_dispatch(&self, prepare_nanos: u128, dispatch_nanos: u128) { + BROKER_PHASES.with(|phases| { + let [enqueue, consume, ..] = phases.get(); + phases.set([enqueue, consume, prepare_nanos, dispatch_nanos]); + }); } type PreparedFrame = PreparedFrame; type Slot = mpsc::OwnedPermit>; @@ -205,6 +285,14 @@ impl ProviderOutput for Output { let (producer, proof) = receipt.split(); self.pending = Some(producer); #[cfg(test)] + if prepared.first == 0 && std::env::var_os("WEAVER_TEST_PROVIDER_SCOPE_TRACE").is_some() { + FIRST_QUEUE_TICKS.with(|slot| { + slot.set(Some( + weaver_ledger::persistence::provider_observation_nanos(), + )); + }); + } + #[cfg(test)] if std::env::var_os("WEAVER_TEST_PROVIDER_SCOPE_TRACE").is_some() && let Ok(time) = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH) { diff --git a/crates/server/src/grpc_provider.rs b/crates/server/src/grpc_provider.rs index 0eebaee8..0e0c561b 100644 --- a/crates/server/src/grpc_provider.rs +++ b/crates/server/src/grpc_provider.rs @@ -183,6 +183,15 @@ impl Gateway { .cloned(); let session_root = wakeup.is_some() && workflow.predecessors.is_empty(); #[cfg(test)] + let trace_scopes = std::env::var_os("WEAVER_TEST_PROVIDER_SCOPE_TRACE").is_some(); + #[cfg(test)] + let reuse = std::env::var_os("WEAVER_TEST_REUSE_PROVIDER_CONNECTION").is_some(); + #[cfg(test)] + let custody = self.admission.clone(); + #[cfg(test)] + let queued_ticks = + trace_scopes.then(weaver_ledger::persistence::provider_observation_nanos); + #[cfg(test)] let queued_at = std::time::Instant::now(); let job = self .runtime @@ -193,6 +202,13 @@ impl Gateway { let result = (|| { #[cfg(test)] let open_started = std::time::Instant::now(); + #[cfg(test)] + let (mut ledger, reused) = if reuse { + custody.checkout_provider(&config.database, &output.shutdown)? + } else { + (Ledger::open(&config.database)?, false) + }; + #[cfg(not(test))] let mut ledger = Ledger::open(&config.database)?; let client = output.cancelled.clone(); let server = output.shutdown.clone(); @@ -207,6 +223,14 @@ impl Gateway { std::env::var("WEAVER_TEST_CACHE_CURRENTNESS_PLANS").as_deref() == Ok("1"), ); #[cfg(test)] + weaver_ledger::use_prepared_manifest_programs( + std::env::var("WEAVER_TEST_PREPARED_MANIFEST_PROGRAMS").as_deref() == Ok("1"), + ); + #[cfg(test)] + weaver_ledger::use_prepared_original_program( + std::env::var("WEAVER_TEST_PREPARED_ORIGINAL_PROGRAM").as_deref() == Ok("1"), + ); + #[cfg(test)] weaver_ledger::use_locked_publication_review( std::env::var("WEAVER_TEST_LOCKED_PUBLICATION_REVIEW").as_deref() == Ok("1"), ); @@ -238,10 +262,11 @@ impl Gateway { std::env::var_os("WEAVER_TEST_CONSERVATIVE_RANGE_INVALIDATION").is_some(), ); #[cfg(test)] - let trace_scopes = std::env::var_os("WEAVER_TEST_PROVIDER_SCOPE_TRACE").is_some(); - #[cfg(test)] if trace_scopes { - ledger.trace_provider_scopes(&plan.family); + let node = std::env::var_os("WEAVER_TEST_PROVIDER_SCOPE_TIMELINE") + .is_some() + .then_some(plan.node.as_str()); + ledger.trace_provider_scopes(&plan.family, node); } #[cfg(test)] weaver_ledger::use_cached_release_programs( @@ -251,7 +276,10 @@ impl Gateway { { crate::grpc_output::take_encoding_nanos(); crate::grpc_output::take_transport(); + crate::grpc_output::take_broker_phases(); + crate::grpc_output::take_admission_ledger(); crate::grpc_output::take_handoffs(); + crate::grpc_output::take_first_queue_ticks(); crate::grpc_output::take_deliveries(); } let progression = if workflow.predecessors.is_empty() { @@ -259,6 +287,8 @@ impl Gateway { } else { Some(ledger.prepare_workflow_candidate(&workflow.predecessors, &plan, workflow.observed.as_deref())?) }; + #[cfg(test)] + let broker_started = std::time::Instant::now(); let execution = weaver_broker::execute_provider_progression( &mut ledger, @@ -342,7 +372,8 @@ impl Gateway { if trace_scopes { eprintln!("weaver-provider-encode {} {}", plan.family, crate::grpc_output::take_encoding_nanos()); use std::fmt::Write; - if let Some(phases) = crate::grpc_output::take_transport() { + let transport_phases = crate::grpc_output::take_transport(); + if let Some((phases, _)) = transport_phases { let mut line = format!("weaver-provider-transport {}", plan.family); for stage in [phases.connect, phases.tls, phases.write, phases.headers] { let _ = write!(line, " {}:{}:{}", stage.nanos, u8::from(stage.attempted), u8::from(stage.completed)); @@ -352,7 +383,30 @@ impl Gateway { ledger.finish_provider_scope_trace(); let mut handoff = format!("weaver-provider-handoff {}", plan.family); - for (sequence, time) in crate::grpc_output::take_handoffs() { + let handoffs = crate::grpc_output::take_handoffs(); + let admission_ledger = crate::grpc_output::take_admission_ledger(); + if let (Some(queued), Some((phases, headers)), Some(first), Some(admission_ledger)) = + (queued_ticks, transport_phases, crate::grpc_output::take_first_queue_ticks(), admission_ledger) + { + let [connect, tls, write, response_head] = + [phases.connect, phases.tls, phases.write, phases.headers] + .map(|stage| u128::from(stage.nanos)); + let write_transport = connect + tls + write; + let transport = write_transport + response_head; + let [enqueue, consume, prepare, dispatch] = + crate::grpc_output::take_broker_phases(); + let mut first_frame = format!( + "weaver-provider-first-frame {} {} {queued} {} {} {headers} {first} {transport} {enqueue} {consume} {prepare} {dispatch} {write_transport} {open_nanos} {} {connect} {tls} {write} {response_head}", + plan.family, + plan.node, + worker_started.duration_since(queued_at).as_nanos(), + broker_started.duration_since(worker_started).as_nanos(), + u8::from(reused), + ); + crate::grpc_output::append_admission_ledger(&mut first_frame, admission_ledger); + eprintln!("{first_frame}"); + } + for (sequence, time) in handoffs { let _ = write!(handoff, " {sequence}:{time}"); } eprintln!("{handoff}"); @@ -364,6 +418,10 @@ impl Gateway { eprintln!("{delivery}"); } + #[cfg(test)] + if reuse && execution.is_ok() && !output.cancelled.is_cancelled() { + custody.park_provider(ledger, &output.shutdown); + } execution })(); output.telemetry.record(if result.is_ok() { diff --git a/crates/server/src/session_workflow.rs b/crates/server/src/session_workflow.rs index 6648c027..c2137c8f 100644 --- a/crates/server/src/session_workflow.rs +++ b/crates/server/src/session_workflow.rs @@ -7,9 +7,13 @@ use crate::{ grpc::Gateway, grpc_provider::{StreamSettings, WorkflowAdmission}, }; -use std::{collections::BTreeSet, sync::Arc}; +use std::{ + collections::{BTreeMap, BTreeSet}, + sync::Arc, +}; use tokio_stream::StreamExt; -use weaver_contracts::{Error, ProviderPlan, ProviderState, Result}; +use weaver_contracts::{Error, FactFeed, ProviderPlan, ProviderState, Result}; +use weaver_governance::{GovernorCut, GovernorTopology}; use weaver_ledger::{Ledger, WorkflowObservation}; struct SessionStep { @@ -24,10 +28,97 @@ enum SessionWork { } struct SessionGraph { - plans: Vec, + topology: Arc, cut: WorkflowObservation, catalog: String, - edges: Vec<(String, String)>, +} + +/// Immutable bindings from the compiled original and its deployed fact feed. +pub(crate) struct SessionTopology { + plans: Vec, + by_node: BTreeMap, + predecessors: Vec>, + governor: Arc, +} + +impl SessionTopology { + pub(crate) fn prepare(feed: &FactFeed, plans: &[ProviderPlan]) -> Result { + let plans = feed + .workflow_path + .iter() + .map(|node| { + plans + .iter() + .find(|plan| plan.family == feed.family && plan.node == *node) + .cloned() + .ok_or(Error::Conflict("compiled Session plan missing")) + }) + .collect::>>()?; + let by_node: BTreeMap<_, _> = plans + .iter() + .enumerate() + .map(|(index, plan)| (plan.node.clone(), index)) + .collect(); + let mut predecessors = vec![Vec::new(); plans.len()]; + if feed.workflow_dag { + for (child, parent) in &feed.dependencies { + let child = by_node + .get(child) + .ok_or(Error::Conflict("compiled Session child missing"))?; + let parent = by_node + .get(parent) + .ok_or(Error::Conflict("Session predecessor missing"))?; + predecessors[*child].push(*parent); + } + } + Ok(Self { + plans, + by_node, + predecessors, + governor: Arc::new(GovernorTopology { + nodes: feed.workflow_path.clone(), + edges: feed.dependencies.clone(), + choice_arms: feed + .choice_nodes() + .map(|nodes| nodes[1..3].to_vec()) + .unwrap_or_default(), + choice_join: feed + .choice_nodes() + .iter() + .map(|nodes| nodes[3].clone()) + .collect(), + nested_selectors: feed.workflow_selectors.clone(), + }), + }) + } + + pub(crate) async fn preopen(&self, governor: &weaver_governance::SourceClient) { + let started = governor_timing().then(std::time::Instant::now); + if started.is_some() { + eprintln!("weaver-governor-preopen begin"); + } + // This empty input initializes relations but proposes no executable + // step. The first live wake supplies the complete ledger observation. + let reply = governor + .derive(GovernorCut { + topology: self.governor.clone(), + complete: Vec::new(), + available: Vec::new(), + pending: Vec::new(), + choice_result: Vec::new(), + choice_decided: Vec::new(), + nested_results: Vec::new(), + nested_decisions: Vec::new(), + }) + .await; + let ready = matches!(reply, Ok(weaver_governance::DerivationOutput::Indices(indices)) if indices.is_empty()); + if let Some(started) = started { + eprintln!( + "weaver-governor-preopen end ok={ready} elapsed_ns={}", + started.elapsed().as_nanos() + ); + } + } } impl Gateway { @@ -114,89 +205,103 @@ impl Gateway { } async fn derive_session_steps(&self, graph: SessionGraph) -> Result> { + let started = governor_timing().then(std::time::Instant::now); let SessionGraph { - plans, + topology, cut, - edges, catalog, } = graph; - let nodes = plans.iter().map(|plan| plan.node.clone()).collect(); - let ready = self - .runtime - .governor()? - .derive(weaver_governance::GovernorCut { - nodes, - edges: edges.clone(), - complete: cut.complete.clone(), - available: cut.available.clone(), - pending: cut.pending.clone(), - nested_selectors: cut - .nested - .as_ref() - .map(|n| n.selectors.clone()) - .unwrap_or_default(), - nested_results: cut - .nested - .as_ref() - .map(|n| n.results.clone()) - .unwrap_or_default(), - nested_decisions: cut - .nested - .as_ref() - .map(|n| n.decisions.clone()) - .unwrap_or_default(), - choice_arms: cut - .choice - .as_ref() - .map(|choice| choice.arms.to_vec()) - .unwrap_or_default(), - choice_join: cut - .choice - .iter() - .map(|choice| choice.join.clone()) - .collect(), - choice_result: cut - .choice - .iter() - .filter_map(|choice| choice.route.map(|route| route.as_str().to_owned())) - .collect(), - choice_decided: cut - .choice - .iter() - .filter_map(|choice| choice.decided.clone()) - .collect(), - }) + let graph = &topology.governor; + let observed_selectors = cut + .nested + .as_ref() + .map_or(&[][..], |nested| nested.selectors.as_slice()); + let observed_arms = cut + .choice + .as_ref() + .map_or(&[][..], |choice| choice.arms.as_slice()); + let observed_join = cut + .choice + .as_ref() + .map_or(&[][..], |choice| std::slice::from_ref(&choice.join)); + if graph.nested_selectors != observed_selectors + || graph.choice_arms != observed_arms + || graph.choice_join != observed_join + { + return Err(Error::Conflict("Session Governor topology changed")); + } + let request = GovernorCut { + topology: graph.clone(), + complete: cut.complete.clone(), + available: cut.available.clone(), + pending: cut.pending.clone(), + nested_results: cut + .nested + .as_ref() + .map(|n| n.results.clone()) + .unwrap_or_default(), + nested_decisions: cut + .nested + .as_ref() + .map(|n| n.decisions.clone()) + .unwrap_or_default(), + choice_result: cut + .choice + .iter() + .filter_map(|choice| choice.route.map(|route| route.as_str().to_owned())) + .collect(), + choice_decided: cut + .choice + .iter() + .filter_map(|choice| choice.decided.clone()) + .collect(), + }; + let governor = self.runtime.governor()?; + let submitted = started.map(|_| std::time::Instant::now()); + let ready = governor + .derive(request) .await .map_err(|_| Error::Conflict("Scheme Governor derivation unavailable"))?; - let mut ready = std::collections::BTreeSet::from_iter(ready); - let cut = Arc::new(cut); - let mut steps = Vec::new(); - for next in &plans { - if !ready.remove(&next.node) { - continue; - } - let predecessors = edges + let received = started.map(|_| std::time::Instant::now()); + // Keep the compiled path order for admission regardless of the order + // returned by Scheme, including repeated candidate identities. + let mut ready = match ready { + weaver_governance::DerivationOutput::Nodes(nodes) => nodes .iter() - .filter(|(child, parent)| { - child == &next.node - && cut.nested.as_ref().is_none_or(|nested| { - nested - .predecessors - .get(child) - .is_some_and(|parents| parents.contains(parent)) - }) - && cut.choice.as_ref().is_none_or(|choice| { - child != &choice.join || choice.decided.as_ref() == Some(parent) - }) + .map(|node| { + topology + .by_node + .get(node) + .copied() + .ok_or(Error::Conflict("foreign Scheme Governor candidate")) }) - .map(|(_, parent)| { - plans - .iter() - .find(|plan| &plan.node == parent) - .cloned() - .ok_or(Error::Conflict("Session predecessor missing")) + .collect::>>()?, + weaver_governance::DerivationOutput::Indices(indices) => indices, + }; + ready.sort_unstable(); + ready.dedup(); + let cut = Arc::new(cut); + let mut steps = Vec::with_capacity(ready.len()); + for index in ready { + let next = topology + .plans + .get(index) + .ok_or(Error::Conflict("foreign Scheme Governor candidate"))?; + let predecessors: Vec<_> = topology.predecessors[index] + .iter() + .map(|&parent| &topology.plans[parent]) + .filter(|parent| { + cut.nested.as_ref().is_none_or(|nested| { + nested + .predecessors + .get(&next.node) + .is_some_and(|parents| parents.contains(&parent.node)) + }) && cut.choice.as_ref().is_none_or(|choice| { + next.node != choice.join || choice.decided.as_ref() == Some(&parent.node) + }) }) - .collect::>>()?; + .cloned() + .collect(); if predecessors.is_empty() || !cut.pending.contains(&next.node) { return Err(Error::Conflict("invalid Scheme Governor candidate")); } @@ -209,8 +314,15 @@ impl Gateway { catalog: catalog.clone(), }); } - if !ready.is_empty() { - return Err(Error::Conflict("foreign Scheme Governor candidate")); + if let (Some(started), Some(submitted), Some(received)) = (started, submitted, received) { + let finished = std::time::Instant::now(); + eprintln!( + "weaver-governor-resolve elapsed_ns={} prepare_ns={} roundtrip_ns={} validate_ns={}", + finished.duration_since(started).as_nanos(), + submitted.duration_since(started).as_nanos(), + received.duration_since(submitted).as_nanos(), + finished.duration_since(received).as_nanos(), + ); } Ok(steps) } @@ -219,12 +331,12 @@ impl Gateway { let Some(feed) = self.runtime.fact_feed() else { return Ok(None); }; - let Some(source) = self + let Some(topology) = self .runtime .single_provider() .filter(|lifecycle| lifecycle.activated()) .and_then(|lifecycle| lifecycle.ready.get()) - .map(crate::single_provider::Prepared::source) + .and_then(crate::single_provider::Prepared::session) else { return Ok(None); }; @@ -240,28 +352,13 @@ impl Gateway { { return Ok(None); } - let plans = feed - .workflow_path - .iter() - .map(|node| { - source - .plans() - .iter() - .find(|plan| plan.family == feed.family && plan.node == *node) - .cloned() - .ok_or(Error::Conflict("compiled Session plan missing")) - }) - .collect::>>()?; let catalog = ledger .provider_catalog()? .map(|(version, _)| version) .unwrap_or_default(); if feed.workflow_dag { - static TIMING: std::sync::OnceLock = std::sync::OnceLock::new(); - let started = TIMING - .get_or_init(|| std::env::var_os("WEAVER_TEST_GOVERNOR_TIMING").is_some()) - .then(std::time::Instant::now); - let cut = ledger.observe_workflow(&plans)?; + let started = governor_timing().then(std::time::Instant::now); + let cut = ledger.observe_workflow(&topology.plans)?; if let Some(started) = started { eprintln!( "weaver-governor-observe ledger_ns={}", @@ -269,14 +366,13 @@ impl Gateway { ); } return Ok(Some(SessionWork::Graph(Box::new(SessionGraph { - plans, + topology: topology.clone(), cut, catalog, - edges: feed.dependencies.clone(), })))); } let mut previous = None; - for current in plans { + for current in &topology.plans { let receipt = ledger.provider_receipt(¤t.family, ¤t.node)?; match receipt { Some(receipt) if receipt.digest != current.digest()? => { @@ -292,10 +388,10 @@ impl Gateway { return Ok(previous.map(|previous| { SessionWork::Linear(vec![SessionStep { admission: WorkflowAdmission { - predecessors: vec![previous], + predecessors: vec![ProviderPlan::clone(previous)], observed: None, }, - next: current, + next: current.clone(), catalog, }]) })); @@ -305,3 +401,8 @@ impl Gateway { Ok(None) } } + +fn governor_timing() -> bool { + static TIMING: std::sync::OnceLock = std::sync::OnceLock::new(); + *TIMING.get_or_init(|| std::env::var_os("WEAVER_TEST_GOVERNOR_TIMING").is_some()) +} diff --git a/crates/server/src/shutdown.rs b/crates/server/src/shutdown.rs index 240f10ae..7a299369 100644 --- a/crates/server/src/shutdown.rs +++ b/crates/server/src/shutdown.rs @@ -6,11 +6,18 @@ use weaver_contracts::Result; pub(crate) fn trace(stage: &str) { + use std::io::{self, Write}; use std::time::{SystemTime, UNIX_EPOCH}; let wall = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap_or_default(); - eprintln!("weaver shutdown stage={stage} wall_ns={}", wall.as_nanos()); + // The linked Scheme runtime also writes to stderr. Format before writing + // so its diagnostics cannot land between this record's fields. + let line = format!( + "weaver shutdown stage={stage} wall_ns={}\n", + wall.as_nanos() + ); + let _ = io::stderr().lock().write_all(line.as_bytes()); } #[cfg(unix)] diff --git a/crates/server/src/single_provider.rs b/crates/server/src/single_provider.rs index 4f8c793e..2b141203 100644 --- a/crates/server/src/single_provider.rs +++ b/crates/server/src/single_provider.rs @@ -3,12 +3,17 @@ // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 //! One startup preparation, exact durable activation, and natural compiler retirement. -use crate::{grpc::Gateway, grpc_contracts::status, pb, source_owner::SourceOwner}; -use std::sync::OnceLock; -use tokio::sync::Mutex; +use crate::{ + grpc::Gateway, grpc_contracts::status, pb, session_workflow::SessionTopology, + source_owner::SourceOwner, +}; +use std::sync::{Arc, OnceLock}; +use tokio::sync::{Mutex, OnceCell}; use tokio_util::sync::CancellationToken; use tonic::Status; -use weaver_contracts::{PublicationOutcome, PublicationReceipt, SourceAuthority, SourceIdentity}; +use weaver_contracts::{ + FactFeed, PublicationOutcome, PublicationReceipt, SourceAuthority, SourceIdentity, +}; use weaver_governance::{BoundSource, OwnedSource}; #[derive(Default)] @@ -18,6 +23,7 @@ pub(crate) struct SingleProvider { retire: CancellationToken, retired: CancellationToken, live: CancellationToken, + preopened: OnceCell<()>, } pub(crate) struct Prepared { @@ -25,6 +31,7 @@ pub(crate) struct Prepared { pub(crate) authority: SourceAuthority, wire_authority: Option, bound: BoundSource, + session: Option>, operation_id: String, digest: String, revision: u64, @@ -36,6 +43,7 @@ impl Prepared { reply: &pb::CompiledSource, authority: SourceAuthority, bound: BoundSource, + feed: Option<&FactFeed>, ) -> weaver_contracts::Result { let publication = bound.source().publication(); let revision = match publication.expected_revision { @@ -48,6 +56,10 @@ impl Prepared { None => 0, }; let digest = publication.digest()?; + let session = feed + .filter(|feed| !feed.workflow_path.is_empty()) + .map(|feed| SessionTopology::prepare(feed, bound.source().plans()).map(Arc::new)) + .transpose()?; Ok(Self { producer: reply.producer.clone(), wire_authority: reply.authority.clone(), @@ -57,6 +69,7 @@ impl Prepared { fence: publication.fence, authority, bound, + session, }) } @@ -64,6 +77,10 @@ impl Prepared { self.bound.source() } + pub(crate) fn session(&self) -> Option<&Arc> { + self.session.as_ref() + } + pub(crate) fn reply(&self) -> pb::CompiledSource { pb::CompiledSource { producer: self.producer.clone(), @@ -126,10 +143,26 @@ impl Gateway { }; if prepared.matches_commit(receipt) && prepared.authority.identity == caller - && prepared.authority == source.authority(caller).await? + && prepared.authority == source.authority(caller.clone()).await? { - if self.runtime.fact_feed().is_some() { + if let Some(feed) = self.runtime.fact_feed() { if let Some(lifecycle) = self.runtime.single_provider() { + if feed.workflow_dag + && governor_preopen_enabled() + && let Some(topology) = prepared.session() + { + lifecycle + .preopened + .get_or_init(|| async { + if let Ok(governor) = self.runtime.governor() { + topology.preopen(&governor).await; + } + }) + .await; + if prepared.authority != source.authority(caller).await? { + return Ok(()); + } + } lifecycle.activate_governor(); self.runtime.wake_session(); } @@ -143,3 +176,10 @@ impl Gateway { Ok(()) } } + +fn governor_preopen_enabled() -> bool { + std::env::var("WEAVER_TEST_GOVERNOR_PREOPEN").as_deref() == Ok("1") + && std::env::var("WEAVER_TEST_GOVERNOR_RETAINED").as_deref() == Ok("1") + && std::env::var("WEAVER_TEST_GOVERNOR_FULL_CUT").as_deref() != Ok("1") + && std::env::var("WEAVER_TEST_GOVERNOR_NAMED_RESULT").as_deref() != Ok("1") +} diff --git a/crates/server/src/source_owner.rs b/crates/server/src/source_owner.rs index 002d0ac0..7987d7ef 100644 --- a/crates/server/src/source_owner.rs +++ b/crates/server/src/source_owner.rs @@ -18,11 +18,53 @@ use weaver_contracts::{ }; use weaver_ledger::{FactPreparation, Ledger}; +type CatalogRead = Result)>>; + #[derive(Clone)] pub(crate) struct SourceOwner { sender: mpsc::Sender, capacity: Arc, + waiting: Arc, + next_mutation: Arc, +} +#[derive(Default)] +struct MutationHandoff { + pending: std::sync::atomic::AtomicBool, + released: tokio::sync::Notify, } +impl MutationHandoff { + fn pending(&self) -> bool { + self.pending.load(std::sync::atomic::Ordering::Acquire) + } + + fn reserve(&self) -> Option> { + use std::sync::atomic::Ordering; + self.pending + .compare_exchange(false, true, Ordering::AcqRel, Ordering::Acquire) + .ok() + .map(|_| MutationReservation(self)) + } + + async fn released(&self) { + loop { + let released = self.released.notified(); + if !self.pending() { + return; + } + released.await; + } + } +} +struct MutationReservation<'a>(&'a MutationHandoff); +impl Drop for MutationReservation<'_> { + fn drop(&mut self) { + self.0 + .pending + .store(false, std::sync::atomic::Ordering::Release); + self.0.released.notify_waiters(); + } +} + struct Envelope { caller: SourceIdentity, command: Command, @@ -74,7 +116,7 @@ enum Command { }, ReadCatalog { - reply: oneshot::Sender>>, + reply: oneshot::Sender, slot: OwnedSemaphorePermit, }, PublishCatalog { @@ -181,7 +223,7 @@ impl SourceOwner { caller: SourceIdentity, intent: FactIntent, ) -> std::result::Result { - self.submit(caller, |reply, slot| Command::StageFact { + self.submit_priority(caller, |reply, slot| Command::StageFact { intent, reply, slot, @@ -193,7 +235,7 @@ impl SourceOwner { caller: SourceIdentity, barrier: FactBarrier, ) -> std::result::Result { - self.submit(caller, |reply, slot| Command::PrepareFact { + self.submit_priority(caller, |reply, slot| Command::PrepareFact { barrier, reply, slot, @@ -206,7 +248,7 @@ impl SourceOwner { work: FactWork, affected: Vec, ) -> std::result::Result { - self.submit(caller, |reply, slot| Command::ResolveFact { + self.submit_priority(caller, |reply, slot| Command::ResolveFact { work, affected, reply, @@ -414,6 +456,8 @@ impl SourceOwner { client: Self { sender, capacity: Arc::new(Semaphore::new(1)), + waiting: Arc::new(Semaphore::new(3)), + next_mutation: Arc::new(MutationHandoff::default()), }, job, }) @@ -423,11 +467,89 @@ impl SourceOwner { caller: SourceIdentity, make: impl FnOnce(oneshot::Sender>, OwnedSemaphorePermit) -> Command, ) -> std::result::Result { - let slot = self - .capacity + self.submit_with_wait(caller, false, make).await + } + async fn command_slot(&self, wait: bool) -> std::result::Result { + if let Ok(slot) = self.capacity.clone().try_acquire_owned() + && !self.next_mutation.pending() + { + return Ok(slot); + } + if !wait { + return Err(Status::resource_exhausted("source command lane full")); + } + let _waiting = self + .waiting .clone() .try_acquire_owned() - .map_err(|_| Status::resource_exhausted("source command lane full"))?; + .map_err(|_| Status::resource_exhausted("source command wait limit"))?; + self.wait_slot(async { + loop { + let slot = self + .capacity + .clone() + .acquire_owned() + .await + .map_err(|_| Status::unavailable("source owner stopped"))?; + if !self.next_mutation.pending() { + return Ok(slot); + } + // Yield this handoff to the reserved mutation. Retain only the + // bounded waiting slot while the mutation reaches the owner. + drop(slot); + self.next_mutation.released().await; + } + }) + .await + } + async fn wait_slot( + &self, + future: impl std::future::Future>, + ) -> std::result::Result { + tokio::select! { + biased; + _ = self.sender.closed() => Err(Status::unavailable("source owner stopped")), + slot = tokio::time::timeout(std::time::Duration::from_millis(50), future) => + slot.map_err(|_| Status::resource_exhausted("source command wait expired"))?, + } + } + async fn priority_slot(&self) -> std::result::Result { + let _next = self + .next_mutation + .reserve() + .ok_or_else(|| Status::resource_exhausted("source mutation wait limit"))?; + self.wait_slot(async { + self.capacity + .clone() + .acquire_owned() + .await + .map_err(|_| Status::unavailable("source owner stopped")) + }) + .await + } + async fn submit_priority( + &self, + caller: SourceIdentity, + make: impl FnOnce(oneshot::Sender>, OwnedSemaphorePermit) -> Command, + ) -> std::result::Result { + let slot = self.priority_slot().await?; + self.submit_acquired(caller, slot, make).await + } + async fn submit_with_wait( + &self, + caller: SourceIdentity, + wait: bool, + make: impl FnOnce(oneshot::Sender>, OwnedSemaphorePermit) -> Command, + ) -> std::result::Result { + let slot = self.command_slot(wait).await?; + self.submit_acquired(caller, slot, make).await + } + async fn submit_acquired( + &self, + caller: SourceIdentity, + slot: OwnedSemaphorePermit, + make: impl FnOnce(oneshot::Sender>, OwnedSemaphorePermit) -> Command, + ) -> std::result::Result { let (reply, receiver) = oneshot::channel(); self.sender .try_send(Envelope { @@ -451,11 +573,13 @@ impl SourceOwner { task: Task, publication: Option, ) -> std::result::Result<(), Status> { - self.submit(caller, |reply, slot| Command::Register { - task: Box::new(task), - publication, - reply, - slot, + self.submit_with_wait(caller, publication.is_some(), |reply, slot| { + Command::Register { + task: Box::new(task), + publication, + reply, + slot, + } }) .await } @@ -464,7 +588,7 @@ impl SourceOwner { caller: SourceIdentity, change: Publication, ) -> std::result::Result { - self.submit(caller, |reply, slot| Command::Publish { + self.submit_priority(caller, |reply, slot| Command::Publish { change, reply, slot, @@ -476,7 +600,7 @@ impl SourceOwner { caller: SourceIdentity, change: Publication, ) -> std::result::Result { - self.submit(caller, |reply, slot| Command::Stage { + self.submit_priority(caller, |reply, slot| Command::Stage { change, reply, slot, @@ -496,7 +620,7 @@ impl SourceOwner { caller: SourceIdentity, change: Publication, ) -> std::result::Result { - self.submit(caller, |reply, slot| Command::StageReviewed { + self.submit_priority(caller, |reply, slot| Command::StageReviewed { change, reply, slot, @@ -530,16 +654,19 @@ impl SourceOwner { pub(crate) async fn provider_catalog( &self, caller: SourceIdentity, - ) -> std::result::Result, Status> { - self.submit(caller, |reply, slot| Command::ReadCatalog { reply, slot }) - .await + ) -> std::result::Result)>, Status> { + self.submit_with_wait(caller, true, |reply, slot| Command::ReadCatalog { + reply, + slot, + }) + .await } pub(crate) async fn publish_catalog( &self, caller: SourceIdentity, catalog: weaver_contracts::ProviderCatalog, ) -> std::result::Result { - self.submit(caller, |reply, slot| Command::PublishCatalog { + self.submit_priority(caller, |reply, slot| Command::PublishCatalog { catalog, reply, slot, @@ -558,7 +685,7 @@ impl SourceOwner { caller: SourceIdentity, change: SourceRotation, ) -> std::result::Result { - self.submit(caller, |reply, slot| Command::Rotate { + self.submit_priority(caller, |reply, slot| Command::Rotate { change, reply, slot, @@ -630,6 +757,7 @@ fn process( cancel: CancellationToken, session_wakeup: Option>, ) -> Result<()> { + let mut catalog_projection = weaver_ledger::ProviderCatalogProjection::default(); loop { let command = handle.block_on(async { tokio::select! { @@ -712,8 +840,9 @@ fn process( answer(ledger, reply, result, slot)?; } Command::ReadCatalog { reply, slot } => { - let result = - ledger.with_authenticated_source(&caller, |ledger| ledger.provider_catalog()); + let result = ledger.with_authenticated_source(&caller, |ledger| { + ledger.inspect_provider_catalog(&mut catalog_projection) + }); answer(ledger, reply, result, slot)?; } Command::PublishCatalog { diff --git a/crates/server/tests/unit/admission.rs b/crates/server/tests/unit/admission.rs index fdc79a3a..3d24e6d4 100644 --- a/crates/server/tests/unit/admission.rs +++ b/crates/server/tests/unit/admission.rs @@ -71,3 +71,36 @@ proptest::proptest! { } } } +#[test] +fn provider_connection_checkout_respects_execution_capacity_and_close() { + use tokio_util::sync::CancellationToken; + let store = tempfile::tempdir().expect("store"); + let path = store.path().join("provider-capacity.db"); + let admission = super::Admission::new(4); + let shutdown = CancellationToken::new(); + let mut workers = Vec::new(); + for _ in 0..4 { + let slot = admission.execution().expect("worker permit"); + let (ledger, reused) = admission + .checkout_provider(&path, &shutdown) + .expect("new lease"); + assert!(!reused); + workers.push((slot, ledger)); + } + assert!(admission.execution().is_err()); + for (slot, ledger) in workers { + admission.park_provider(ledger, &shutdown); + drop(slot); + } + assert_eq!(admission.provider_idle.lock().expect("idle").len(), 4); + let slot = admission.execution().expect("new permit"); + let (ledger, reused) = admission + .checkout_provider(&path, &shutdown) + .expect("reused lease"); + assert!(reused); + shutdown.cancel(); + admission.park_provider(ledger, &shutdown); + assert!(admission.checkout_provider(&path, &shutdown).is_err()); + assert_eq!(admission.provider_idle.lock().expect("idle").len(), 3); + drop(slot); +} diff --git a/crates/server/tests/unit/governance_owner.rs b/crates/server/tests/unit/governance_owner.rs index e55b7cfd..ce8a77b5 100644 --- a/crates/server/tests/unit/governance_owner.rs +++ b/crates/server/tests/unit/governance_owner.rs @@ -111,8 +111,9 @@ fn single_provider_activation_requires_the_exact_committed_cut() { let bound = weaver_governance::SourceExpectation::capture(&original) .bind(original.clone()) .expect("bound original"); - let prepared = crate::single_provider::Prepared::new(&Default::default(), authority(), bound) - .expect("prepared"); + let prepared = + crate::single_provider::Prepared::new(&Default::default(), authority(), bound, None) + .expect("prepared"); let receipt = PublicationReceipt { operation_id: publication.operation_id.clone(), digest: publication.digest().expect("publication"), diff --git a/crates/server/tests/unit/source_owner.rs b/crates/server/tests/unit/source_owner.rs index 8040ddaa..9e755f83 100644 --- a/crates/server/tests/unit/source_owner.rs +++ b/crates/server/tests/unit/source_owner.rs @@ -267,3 +267,167 @@ async fn review_context_uses_provisioned_metadata_and_does_not_publish() { runtime.drain().await; worker.finish().await.expect("natural drain"); } + +#[tokio::test] +async fn bounded_catalog_wait_releases_cancelled_waiter_and_preserves_active_slot() { + use std::{future::Future, task::Poll}; + let (sender, _receiver) = tokio::sync::mpsc::channel(1); + let source = SourceOwner { + sender, + capacity: Arc::new(Semaphore::new(1)), + waiting: Arc::new(Semaphore::new(3)), + next_mutation: Arc::new(super::MutationHandoff::default()), + }; + let held = source.command_slot(false).await.expect("active slot"); + let mut first = Box::pin(source.command_slot(true)); + let mut second = Box::pin(source.command_slot(true)); + let mut third = Box::pin(source.command_slot(true)); + std::future::poll_fn(|cx| { + assert!(first.as_mut().poll(cx).is_pending()); + assert!(second.as_mut().poll(cx).is_pending()); + assert!(third.as_mut().poll(cx).is_pending()); + Poll::Ready(()) + }) + .await; + let full = source.command_slot(true).await.expect_err("wait bound"); + assert_eq!(full.message(), "source command wait limit"); + drop(first); + assert_eq!(source.waiting.available_permits(), 1); + assert_eq!(source.capacity.available_permits(), 0); + assert_eq!( + source + .command_slot(false) + .await + .expect_err("write remains bounded") + .message(), + "source command lane full" + ); + drop(held); + let next = second.await.expect("oldest remaining waiter"); + assert_eq!(source.capacity.available_permits(), 0); + drop(next); + drop(third.await.expect("last waiter")); + assert_eq!(source.waiting.available_permits(), 3); + assert_eq!(source.capacity.available_permits(), 1); +} + +#[tokio::test] +async fn cancelled_priority_wait_does_not_send_a_source_command() { + use std::{future::Future, task::Poll}; + let (sender, mut receiver) = tokio::sync::mpsc::channel(1); + let source = SourceOwner { + sender, + capacity: Arc::new(Semaphore::new(1)), + waiting: Arc::new(Semaphore::new(3)), + next_mutation: Arc::new(super::MutationHandoff::default()), + }; + let held = source.command_slot(false).await.expect("active slot"); + let mut command = Box::pin(source.publish(caller(), change("cancel", None))); + std::future::poll_fn(|cx| { + assert!(command.as_mut().poll(cx).is_pending()); + Poll::Ready(()) + }) + .await; + assert!(source.next_mutation.pending()); + assert_eq!( + source + .priority_slot() + .await + .expect_err("one priority waiter") + .message(), + "source mutation wait limit" + ); + drop(command); + assert!(!source.next_mutation.pending()); + assert!(matches!( + receiver.try_recv(), + Err(tokio::sync::mpsc::error::TryRecvError::Empty) + )); + assert_eq!(source.capacity.available_permits(), 0); + assert_eq!( + source + .priority_slot() + .await + .expect_err("bounded wait") + .message(), + "source command wait expired" + ); + assert!(!source.next_mutation.pending()); + drop(held); + drop(source.priority_slot().await.expect("reservation returned")); +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 4)] +async fn source_rotation_commits_before_queued_catalog_reads_recheck_identity() { + use std::{future::Future, task::Poll}; + let directory = tempfile::tempdir().expect("store"); + let runtime = RuntimeOwner::new(); + let path = directory.path().join("source.db"); + let mut setup = Ledger::open(&path).expect("source enrollment store"); + setup + .with_authenticated_source(&caller(), |_| Ok(())) + .expect("enroll first source"); + setup.close().expect("finish enrollment"); + let worker = SourceOwner::start(runtime.clone(), slot(), path) + .await + .expect("owner"); + let source = worker.client.clone(); + let mut current = caller(); + for epoch in 0..3 { + let next = weaver_contracts::SourceIdentity { + certificate_sha256: weaver_contracts::body_digest(&format!("rotation-leaf-{epoch}")), + public_key_sha256: weaver_contracts::body_digest(&format!("rotation-key-{epoch}")), + credential_sha256: weaver_contracts::body_digest(&format!("rotation-token-{epoch}")), + }; + let held = source.command_slot(false).await.expect("active slot"); + let mut reads = + std::array::from_fn::<_, 3, _>(|_| Box::pin(source.provider_catalog(current.clone()))); + let mut rotation = Box::pin(source.rotate( + current.clone(), + weaver_contracts::SourceRotation { + operation_id: format!("rotate-catalog-{epoch}"), + expected_epoch: epoch, + next: next.clone(), + }, + )); + std::future::poll_fn(|cx| { + for read in &mut reads { + assert!(read.as_mut().poll(cx).is_pending()); + } + assert!(rotation.as_mut().poll(cx).is_pending()); + Poll::Ready(()) + }) + .await; + drop(held); + std::future::poll_fn(|cx| { + for read in &mut reads { + assert!(read.as_mut().poll(cx).is_pending()); + } + Poll::Ready(()) + }) + .await; + let receipt = rotation.await.expect("rotation commit"); + assert_eq!( + receipt.outcome, + weaver_contracts::SourceRotationOutcome::Committed + ); + let [a, b, c] = reads; + let (a, b, c) = tokio::join!(a, b, c); + for read in [a, b, c] { + assert_eq!( + read.expect_err("retired identity cannot read").code(), + tonic::Code::PermissionDenied + ); + } + assert!( + source + .provider_catalog(next.clone()) + .await + .expect("new identity") + .is_none() + ); + current = next; + } + runtime.drain().await; + worker.finish().await.expect("natural source drain"); +} diff --git a/dev/sysml/ArchitectureEvolution.sysml b/dev/sysml/ArchitectureEvolution.sysml index eece87b1..539e6bcd 100644 --- a/dev/sysml/ArchitectureEvolution.sysml +++ b/dev/sysml/ArchitectureEvolution.sysml @@ -89,6 +89,86 @@ package ArchitectureEvolution { preparation at exact activation. Hard-fact projection keeps its linked Scheme owner while the Session is active. */ } + item def GovernorPublicationBinding { + item workflow : PolicyEvidenceDesign::PreparedSessionWorkflow; + attribute publicationIdentity : String; + attribute ownerEpoch : String; + doc /* Target binding for the retained ASCENT program and the Rust + plan index. The Workflow's ordered node identities define indices + only within this binding. Prepare rule and topology state after + source admission and before admitting the first live graph wake. + A replacement or owner restart requires a new binding. Rich POO + composition remains in Scheme; its stable executable projection + and retained rule session are prepared once per binding. Opening + the first rule session on a live wake violates this target readiness + boundary. This is a design obligation, not a production-default or + submillisecond acceptance claim. */ + } + item def GovernorFrontierBinding { + attribute publicationIdentity : String; + attribute frontierIdentity : String; + item facts : PolicyEvidenceDesign::FactUseContext; + doc /* Identity of one coherent ledger observation, including complete + release and committed selector evidence. The retained program + applies this cut's mutable relations, including removals. */ + } + item def GovernorCandidates { + attribute publicationIdentity : String; + attribute ownerEpoch : String; + attribute frontierIdentity : String; + attribute nodeIndex : Integer[0..64]; + doc /* Advisory indices resolved against the matching Rust plan index + in compiled order. The deciding transaction checks current facts, + release evidence and frontier before claim and reservation. The + indexed ABI has one exact generation followed by at most 64 node + indices: the binding is not part of the candidate-count bound. + Keep the SDK snapshot rooted while borrowing its elements; reject + stale generations, wrong shapes and foreign indices before use. */ + } + action def DerivePreparedGovernorCandidates { + in item prepared : GovernorPublicationBinding; + in item cut : GovernorFrontierBinding; + out item candidates : GovernorCandidates; + doc /* Target specialization of AdvanceGovernedRoutine. Reuse the + fixed owner and rooted ABI. Compare a full mutable relation set + first. Invalidate retained state on owner or publication change. + Recover from the durable frontier before resuming derivation. + Cross the ABI once per coherent frontier with bounded typed facts + and receive bounded node indices; avoid repeated topology transfer + and per-node calls. Replacements include removals. Repeated wake + demand may be coalesced, but source intents, complete receipts, + branch decisions and claims must remain durable. Measure owner + capacity and queue wait separately from input construction, rooted + call and result materialization. The proposed local hot-decision + P99 target is below one millisecond including owner waiting, on a + declared graph/fact bound and four-way workload. Network/provider + latency and durable deciding transactions have separate clocks and + acceptance. Existing finite observations do not qualify this target. + Rust still rechecks current authority and reserves in its deciding + transaction; a fast advisory result cannot waive that transaction. + The existing scheme_conversion benchmark also hosts a quiet finite + source-lane profile: one prepared owner, four Tokio workers, complete + snapshots of the nine-node nested Workflow, and matched per-request + submission/start/finish/reply clocks. Join by snapshot and wave, + check interval nesting, and report preparation and natural owner + drain separately. These advisory-only inputs confer no ledger + authority and do not qualify Gateway latency or source admission. + Optional owner-local SDK usage snapshots correlate collection counts + and GC duration with individual calls without a Scheme callback or + per-call logging. Heap capacity and RSS high-water are not live + allocation. Keep quiet controls around diagnostics. The current + linked owner shares source capture and inference in one VM; private + image isolation would require an explicit SDK backend migration, + not mixing InstancePool with the process-global linked backend. + A prepared retained program may specialize an immutable wholly + nested topology with no flat arms/joins: omit only empty private + flat relations and the flat rules whose guards cannot hold. Keep + every source-bearing declaration, mutable source name and original + fact limit. Reconstruct through ASCENT's canonical public program + factory and retain its admission/replacement transaction. The full + fresh program is the semantic and failure reference. A topology or + owner replacement must rebuild the chosen program. */ + } action def AdvanceGovernedRoutine { in item original : PolicyEvidenceDesign::SemanticCommitment; in item workflow : PolicyEvidenceDesign::PreparedSessionWorkflow[0..1]; @@ -214,12 +294,35 @@ package ArchitectureEvolution { attribute :>> phase = ControllerObjectLifecycle::Phase::reuse; attribute :>> nativeAsset = "Fixed Scheme owner, bounded SourceClient, ASCENT Session and durable provider frontier"; attribute :>> learningWitness = "SDK Mailbox separates native entry from repeated work in one VM"; - attribute :>> reuseSeam = "AdvanceGovernedRoutine;IncrementalRelations;BoundedOperations;Governor release preregistration in 59.64-governance-capture-ownership.org"; + attribute :>> reuseSeam = "AdvanceGovernedRoutine;DerivePreparedGovernorCandidates;IncrementalRelations;BoundedOperations;Governor release preregistration in 59.64-governance-capture-ownership.org"; attribute :>> causalMechanism = "Relational reuse targets computation; persistent batches target foreign entry; isolation targets queue delay caused by source preparation"; attribute :>> cost = "Retained relations, queue residence, invalidation, independent image lifecycle and drain"; attribute :>> preservedBoundary = "Complete release precedes proposal; exact facts and current frontier govern claim and reservation; coalesce only wakeups"; attribute :>> falsifier = "Matched workload has no reproducible improvement from durable release to committed reservation, or admission and owner-drain controls regress"; attribute :>> qualificationOwner = "WeaverProject::AssuranceResponsibilities::implementation"; + doc /* Target P99 below one millisecond from a coherent observed cut + to resolved Rust candidates, including queue residence, ABI + conversion and ASCENT. Also measure release to observation and + release to durable claim separately. Keep provider first-frame, + ready-frame and throughput gates on their respective clocks. */ + doc /* Runtime design priority: prepare and bind the compiled program, + topology and retained relations before activation. Keep one bounded + affine runtime per assigned owner; do not create a VM per decision. + SourceInbox currently serializes Compile and Derive. A live derivation + owner must not wait behind source compilation; qualify preparation + isolation using the existing tracked-owner lifecycle before adoption. + Stable publication binding plus complete current facts identify reuse; + selector retraction and A-to-B-to-A must invalidate dependent results. + Coalesce recomputation demand only, never receipts or authority intents. + Share no mutable VM across owners. Partition independent sessions only + after exact frontier and ledger claim controls remain satisfied. + Packed facts and checked candidate indices bound ABI conversion. + Arrow is appropriate for column batches, not required for small cuts. + A fast mailbox is not evidence of low durable claim latency. Attribute + shared admission wait to actual lease holders and commit I/O before + changing custody; asynchronous waiting alone cannot shorten a lease. + Do not infer a sub-millisecond network or durable-commit guarantee + from the cut-to-candidate target. */ doc /* The matched release workload retains the 12-second recovery window and the 15-second natural exit fence. A readiness timeout before the workload is a failed trial. Resolve any claimed diff --git a/dev/sysml/ProviderRpc.sysml b/dev/sysml/ProviderRpc.sysml index 34455efd..5575b278 100644 --- a/dev/sysml/ProviderRpc.sysml +++ b/dev/sysml/ProviderRpc.sysml @@ -168,6 +168,14 @@ package ProviderRpc { } requirement def OwnedSourceConnection { doc /* A tracked blocking worker exclusively owns one reusable source connection. Command capacity stays held through SQL completion despite caller loss, then returns before the command acknowledgment is observable. Quiescent boundaries and fresh CAS reads prevent stale snapshot reuse. Storage or close failure terminates the owner and cannot produce successful drain acknowledgment. */ + doc /* Catalogue inspection and published task registration can wait + in three bounded slots. One separate priority reservation has + precedence for publication, source rotation and hard-fact work. + Waiting expires after 50 ms. Cancellation before grant creates + no command. The owner authenticates each command when it executes. + The fact preparation acknowledgment returns command capacity + before Scheme derivation. Its result needs a separate deciding + source command with current authority and durable barrier checks. */ } requirement def FinalInvocationCancellation { doc /* A pre-lock cancellation read is not final send admission. After durable dispatch burn and the final deciding lock/current Cedar guard, Rust rechecks the original output context immediately before transport entry. Unknown execution retains its hold; new contexts cannot reuse the burned invocation. Already admitted transport is not retroactively unsent. */ diff --git a/dev/sysml/WeaverExecution.sysml b/dev/sysml/WeaverExecution.sysml index 819df4e2..bc56f24a 100644 --- a/dev/sysml/WeaverExecution.sysml +++ b/dev/sysml/WeaverExecution.sysml @@ -119,6 +119,16 @@ package WeaverExecution { that transaction. Program reuse preserves the full domain join. The domain view and reservation reconciliation are scope-local. History equality, capacity, revocation, Policy and fence remain live. */ + doc /* Target design. Prepare immutable provider execution inputs once + for the exact admitted publication and profile, using the existing + Scheme owner and Rust publication projection. Bind a prepared input + to the catalog version, source revision and fence, reviewed Policy + digest, profile digest, and original plan commitment. Carry owned + Rust data across the worker handoff. Validate the queued commitment + and join the current authority in the deciding transaction before + reuse. Reconstruct from durable source on a miss. Keep claims, + budget, history, revocation, cancellation and each Cedar decision + within the corresponding live custody. */ doc /* Overlapping semantic writers serialize; certified provider work may share semantic reads while writing distinct original origins. Measure actual granted modes and reader/writer waits separately. @@ -304,6 +314,32 @@ package WeaverExecution { } requirement def ProviderAdmissionTurn { + doc /* Native prepared-program reuse may retain only compatible SQL + programs. A singleton preflight must finish its cursor; each use + binds fresh parameters and reads current rows. The deciding scope + still compares every exact reviewed projection, task birth, fence + and pending barrier. A reused program or previous successful read + conveys no authority after replacement or projection loss. */ + doc /* Original-task, birth-publication and provider-receipt reads must + finish their singleton cursors before releasing the native read. + Constraining singleton join order may reduce preflight planning work + without changing any predicate. Engine schema/root generation changes + may still require recompilation, especially across MVCC snapshots; + do not bypass compatibility to claim zero compilation. A frozen Rust + release A/B uses identical Go forwarding and workload in both arms, + separate from the existing Go-versus-direct-Rust comparison. */ + doc /* Domain-key discovery also completes its native singleton cursor. + Reusing its SQL program cannot retain discovered roots across waits: + capture scheduler generation before the hint query and keep the + existing deciding-scope root and generation rechecks. Completing this + read avoids invalidating compatible prepared programs as a side effect + of abandoning an otherwise successful autocommit read. */ + doc /* Retained-member and projected-member queries reuse only compatible + fixed SQL programs, prepared before provider admission where possible. + Each deciding use binds the current family, consumes the complete row + set, rejects duplicate members and verifies exact member bijection, + original ceilings and held-budget conservation. A preparation success + or a previous matching set is never a substitute for those fresh reads. */ doc /* A pending execution request has no accepted authority outcome, native claim, reservation or semantic publication. It waits in the existing bounded runtime lane and conflicting-writer FIFO without @@ -331,6 +367,12 @@ package WeaverExecution { before serving ingress. Runtime catalogue selection retains it. Unknown activation never becomes readiness. Connection release changes no authority view, claim, hold, publication or pending-intent outcome. */ + doc /* Runtime catalogue requests read current source authority independently. + Concurrent requests for the same exact version and record bytes share + one immutable projection. Registration and deciding admission still + validate the current source and catalogue. The Rust source owner can + return the current ledger bytes directly after matching the version + and bytes of its previously verified canonical response. */ } part def ProviderAdmissionOverlapExperiment { @@ -699,6 +741,28 @@ package WeaverExecution { existing receipts. A queued claim may resume and an unknown outcome stops progression. Pending and resolved withdrawals block affected successors until a new available revision is admitted. */ + doc /* Rust prepares immutable node and predecessor bindings with the + compiled original. Session uses them after exact publication + activation and resolves candidates in the compiled path order. + The existing Scheme Governor owner can retain its ASCENT program. + A wake reads a coherent durable cut. Ledger observation batches + availability and receipts for the original family in one transaction, + reuses its deployed topology and origin to verify each completed + node's committed transition and branch decision, and verifies its + release and metering evidence. The observation + reconciles the shared budget and history once in that transaction. + WAL observation opens a deferred snapshot under the same authority + closure. Claim and reservation use the deciding transaction. + Target design. Send changing relations to the retained owner with + the publication identity and cut. An incremental + update must name its base cut and carry retractions. An identity or + base mismatch requires a coherent full observation. Rebuild from the + durable frontier after owner loss. */ + doc /* The Governor returns candidate node identities for the same cut. + Rust resolves them against the prepared plans. Admission atomically + validates the current cut and complete releases, records any branch + decision and acquires the claim and reservation. Reuse of a prepared + plan or a retained derivation cannot supply authority for an effect. */ } requirement def DevelopmentPolicy { doc /* ASP Rust is a deny-mode Cargo test dependency and is absent from the runtime graph. */ @@ -1004,6 +1068,15 @@ package WeaverExecution { Rust validates provenance and equality; it cannot infer whether two entirely relabeled tasks are the same original from body equality. Retain claim, domain lineage and unknown holds across source handoff. + The default Gateway deployment uses one authoritative Turso store. + Claim and accounting views share this store. Provider SSE payloads + use bounded runtime buffers. Persist release intervals and digests, + and persist the typed terminal result needed for a Workflow choice. + Provider completion reduces the stored plan to its original ceiling + in the terminal transaction. The run digest and independent claim + still bind exposure. Queued and unresolved runs retain their plan. + Arrow frames are an output format. Keep analytical projections in + memory or approved exports, outside the deciding authority boundary. Model allocation does not close the authentic-key issuance gap. */ attribute leanDeclaration : String = "CedarPooSpec.Gateway.ZeroTrust.Proposal"; attribute leanFields : String = "before,receipt,contextBound,authorityId,after,consumption"; diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index 73c46d3d..f5dc9448 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -1,608 +1 @@ -[{"id":"ProviderAdmissionTurn","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let selected_admission"},{"file":"crates/ledger/src/provider.rs","pattern":"struct AdmissionRequest"},{"file":"crates/ledger/tests/unit/provider_admission_turn.rs","pattern":"fn queued_unaccepted_admission_preserves_old_frame_and_original_hold"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionTurnProperty"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionCommitRecovery"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderAdmissionTurn"},{"file":"crates/broker/src/provider/request.rs","pattern":"Stage::Tls"},{"file":"go/dev/provider_transport_phases_test.go","pattern":"func reportProviderTransport"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run eagerQueueBlocksOldFrameCounterexampleTest"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem queue_preserves_arbitrary_requirement","declaration":"Weaver.ProviderAdmissionTurn.queue_preserves_arbitrary_requirement"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem finite_queue_preserves_final_offer","declaration":"Weaver.ProviderAdmissionTurn.finite_queue_preserves_final_offer"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem open_writer_cannot_mutate","declaration":"Weaver.ProviderAdmissionTurn.open_writer_cannot_mutate"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem accepted_hard_intent_blocks","declaration":"Weaver.ProviderAdmissionTurn.accepted_hard_intent_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_outcome_blocks","declaration":"Weaver.ProviderAdmissionTurn.unknown_outcome_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem changed_image_blocks","declaration":"Weaver.ProviderAdmissionTurn.changed_image_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem queued_admission_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.queued_admission_preserves_spec_final_use"},{"file":"go/internal/controlplane/deployment.go","pattern":"if gateway.source == nil"},{"file":"go/dev/provider_control_bench_test.go","pattern":"func TestProviderGoControlMeasuredChain"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem runtime_catalog_requires_source","declaration":"Weaver.ProviderAdmissionTurn.runtime_catalog_requires_source"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_activation_blocks_source_handoff","declaration":"Weaver.ProviderAdmissionTurn.unknown_activation_blocks_source_handoff"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem bootstrap_source_close_preserves_actual","declaration":"Weaver.ProviderAdmissionTurn.bootstrap_source_close_preserves_actual"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run failedBootstrapCleanupDoesNotActivateIngressTest"},{"file":"go/dev/provider_admission_overlap_bench_test.go","pattern":"func BenchmarkProviderAdmissionOverlap"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn collect_buffered"}]}, - {"id":"ProviderReadCustody","witnesses":[{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn conflicts"},{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn acquire_origin"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let shared_reads"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn compatible_origins_share_reads_but_an_older_writer_blocks_younger_readers"},{"file":"crates/ledger/tests/unit/provider_read_custody.rs","pattern":"fn shared_reads_keep_distinct_origin_native_writes_concurrent"},{"file":"go/dev/provider_read_custody_test.go","pattern":"func TestProviderReadCustodyProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderReadCustody"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem arbitrary_policy_preserved","declaration":"Weaver.ProviderReadCustody.arbitrary_policy_preserved"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem finite_interleaving_preserves_policy","declaration":"Weaver.ProviderReadCustody.finite_interleaving_preserves_policy"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem overlapping_writes_conflict","declaration":"Weaver.ProviderReadCustody.overlapping_writes_conflict"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessRetainsWriterAndSameOriginBarriers"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_binding_blocks","declaration":"Weaver.ProviderReadCustody.changed_binding_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_shared_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_shared_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_origin_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_origin_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_owner_blocks","declaration":"Weaver.ProviderReadCustody.changed_owner_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem shared_writer_conflicts","declaration":"Weaver.ProviderReadCustody.shared_writer_conflicts"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem older_conflicting_writer_blocks","declaration":"Weaver.ProviderReadCustody.older_conflicting_writer_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem read_custody_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.read_custody_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderReadCustody.qnt","pattern":"run unsafeSharedMutationCounterexampleTest"}]}, - {"id":"ProviderLifecycleFootprint","witnesses":[{"file":"crates/ledger/src/provider.rs","pattern":"struct OriginLifecycle"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"enum Impact"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_lifecycle"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_provider_lifecycle"},{"file":"crates/ledger/tests/unit/provider_lifecycle.rs","pattern":"fn peer_lifecycle_preserves_complete_view_but_shared_admission_does_not"},{"file":"go/dev/provider_lifecycle_test.go","pattern":"func TestProviderLifecycleCommitRecovery"},{"file":"crates/ledger/tests/unit/authority_footprint.rs","pattern":"fn local_commit_retires_whole_and_own_but_preserves_peer"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem origin_commit_retires_whole_reader","declaration":"Weaver.ProviderLifecycleFootprint.origin_commit_retires_whole_reader"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem arbitrary_cedar_predicate_preserved","declaration":"Weaver.ProviderLifecycleFootprint.arbitrary_cedar_predicate_preserved"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem shared_admission_requires_shared_invalidation","declaration":"Weaver.ProviderLifecycleFootprint.shared_admission_requires_shared_invalidation"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem peer_lifecycle_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.peer_lifecycle_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderLifecycleFootprint.qnt","pattern":"run unsafeNarrowAdmissionCounterexampleTest"}]}, - - {"id":"ProviderSnapshotPublication","witnesses":[{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn release_provider_group_for_delivery"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"struct Snapshot"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn share_qualification"},{"file":"crates/ledger/src/provider.rs","pattern":"fn begin_snapshot_validation"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn take_refresh"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem pending_close_defers_renewal","declaration":"Weaver.ProviderSnapshotPublication.pending_close_defers_renewal"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn a_request_arriving_during_qualification_cannot_trigger_a_second_native_read"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn one_snapshot_requalification_covers_every_exact_frame"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn post_staging_native_failure_cannot_publish_a_partial_snapshot"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn queue_snapshot"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func awaitDeliveryCuts"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem final_use_joins_snapshot","declaration":"Weaver.ProviderSnapshotPublication.final_use_joins_snapshot"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem published_snapshot_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.published_snapshot_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSnapshotPublication.qnt","pattern":"run ungatedArcLoadIsCounterexampleTest"}]}, - {"id":"ProviderSemanticProgress","witnesses":[{"file":"crates/ledger/src/provider.rs","pattern":"struct RangeProgress"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_progress"},{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn stage_group"},{"file":"crates/ledger/tests/unit/provider_delivery.rs","pattern":"fn exact_range_progress_preserves_queued_authorization"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderSemanticProgressProperty"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_released_binding","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_released_binding"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_image","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_image"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem range_progress_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.range_progress_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSemanticProgress.qnt","pattern":"run hiddenSemanticEditIsCounterexampleTest"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"}]}, - {"id":"ProviderDeliveryJoin","witnesses":[{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn bounded_trace_retains_every_requalification"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeTraceChunksPreserveAllRecords"},{"file":"crates/ledger/tests/unit/persistence_owner.rs","pattern":"fn descriptor_copy_is_not_a_retained_execution_owner"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem retained_role_blocks_custody_retirement","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.retained_role_blocks_custody_retirement"},{"file":"dev/proofs/quint/ProviderDeliveryPipeline.qnt","pattern":"run threeInertFramesNeedNoStopAndWaitTest"},{"file":"crates/server/src/grpc_delivery_producer.rs","pattern":"fn reserve_guarded"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"pub fn poll"},{"file":"crates/server/src/grpc_delivery.rs","pattern":"impl Stream for ResponseStream"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryCommitAndReceiverRecovery"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryReceiverProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem orphaned_witness_cannot_activate","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.orphaned_witness_cannot_activate"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem acknowledged_delivery_preserves_same_actual_view","declaration":"Weaver.DomainMigrationComposition.acknowledged_delivery_preserves_same_actual_view"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run committedWithoutAcknowledgmentCannotAcceptTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run rollbackCannotEraseIndependentWitnessTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run oldOwnerCannotRequalifyAfterRestartTest"}]}, - {"id":"ProviderEgressPromotion","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_close_receipt_cannot_resolve_new_intent","declaration":"Weaver.ProviderEgressWindow.Promotion.old_close_receipt_cannot_resolve_new_intent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem expired_clock_blocks_receiver","declaration":"Weaver.ProviderEgressWindow.Promotion.expired_clock_blocks_receiver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem every_effect_writer_needs_mediation","declaration":"Weaver.ProviderEgressWindow.Promotion.every_effect_writer_needs_mediation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem other_writer_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.other_writer_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem uncertain_effect_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.uncertain_effect_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem unchanged_database_does_not_revalidate_old_read","declaration":"Weaver.ProviderEgressWindow.Promotion.unchanged_database_does_not_revalidate_old_read"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem witness_ahead_blocks_old_image","declaration":"Weaver.ProviderEgressWindow.Promotion.witness_ahead_blocks_old_image"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem only_current_owner_can_deliver","declaration":"Weaver.ProviderEgressWindow.Promotion.only_current_owner_can_deliver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_queued_frame_cannot_follow_replacement","declaration":"Weaver.ProviderEgressWindow.Promotion.old_queued_frame_cannot_follow_replacement"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem delivered_frame_cannot_be_delivered_twice","declaration":"Weaver.ProviderEgressWindow.Promotion.delivered_frame_cannot_be_delivered_twice"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem receiver_promotion_refines_interval_admission","declaration":"Weaver.ProviderEgressWindow.Promotion.receiver_promotion_refines_interval_admission"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run firstCommitCannotDeliverAnotherPendingWriterTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run independentWitnessBeforeDatabaseBlocksDeliveryTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run oldWorkerDeliveryCounterexampleTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run allWriterClassesUseTheSameCutTest"}]}, - {"id":"BoundedProviderEgressWindow","witnesses":[ - {"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem any_accepted_trace_keeps_disjoint_prefix","declaration":"Weaver.ProviderEgressWindow.any_accepted_trace_keeps_disjoint_prefix"}, - {"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem loss_and_restart_close_old_window","declaration":"Weaver.ProviderEgressWindow.loss_and_restart_close_old_window"}, - {"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem matching_image_does_not_reopen_old_cut","declaration":"Weaver.ProviderEgressWindow.matching_image_does_not_reopen_old_cut"}, - {"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem connected_roots_cannot_use_distinct_lanes","declaration":"Weaver.ProviderEgressWindow.connected_roots_cannot_use_distinct_lanes"}, - {"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem admitted_four_turn_envelope","declaration":"Weaver.ProviderEgressWindow.admitted_four_turn_envelope"}, - {"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem settlement_is_idempotent","declaration":"Weaver.ProviderEgressWindow.settlement_is_idempotent"}, - {"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem holder_stage_overlap_cannot_exceed_ticket_wait","declaration":"Weaver.ProviderEgressWindow.holder_stage_overlap_cannot_exceed_ticket_wait"}, - {"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run coherentStoreRollbackActuallyDuplicatesOfferTest"}, - {"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run pendingRevocationStopsActualOfferTest"}, - {"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run lostBurnAckSealsOriginalTest"}, - {"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run rehydratingOldWindowActuallyDuplicatesOfferTest"}]}, - {"id":"OriginalFloorDecision","witnesses":[ - {"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run lostCommitResponseResolvesSameOperationTest"}, - {"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run unknownCommitCannotActivateTest"}, - {"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"}]}, - {"id":"ProviderCurrentnessPerformance","witnesses":[ - {"file":"go/dev/provider_domain_program_test.go","pattern":"func BenchmarkProviderDomainProgram"}, - {"file":"go/dev/provider_domain_tail_test.go","pattern":"func BenchmarkProviderSharedLongTail"}, - {"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem prepared_domain_program_preserves_live_decision"}]}, - {"id":"ProviderSchedulerOwnership","witnesses":[ - {"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn waiting_multi_root_range_precedes_younger_conflicts"}, - {"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessCountsArrivalGrantInversions"}, - {"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"}]}, - {"id":"SenderBoundProviderOAuth","witnesses":[ - {"file":"go/dev/provider_oauth_relay_test.go","pattern":"func TestProviderOAuthTwoHopRevocationAndRecovery"}, - {"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem retained_root_revocation_blocks_child"}]}, - {"id":"TransportAndExecutionLatencySeparation","witnesses":[ - {"file":"go/dev/provider_scheduler_bench_test.go","pattern":"func BenchmarkProviderScheduledEncoding"}, - {"file":"go/dev/provider_range_group_test.go","pattern":"func BenchmarkProviderRangePreparationGroup"}]}, - {"id":"TelemetryNoninterference","witnesses":[ - {"file":"crates/telemetry/tests/unit/metrics.rs","pattern":"fn observations_are_monotone_and_restart_local"}, - {"file":"go/internal/telemetry/metrics_test.go","pattern":"func TestPropertyCountersAreBoundedMonotoneAndRestartLocal"}, - {"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderTelemetryCannotRefundOrRedispatchUnknownSend"}, - {"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderControlTelemetryObservesBothServices"}, - {"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryReadsAndRestartCannotRefundTest"}, - {"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryAsRefundCounterexampleTest"}, - {"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem arbitrary_observations_keep_execution","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.arbitrary_observations_keep_execution"}, - {"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem telemetry_reset_keeps_unknown_hold","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.telemetry_reset_keeps_unknown_hold"}, - {"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem observations_preserve_effect_safety","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.observations_preserve_effect_safety"}]}, - {"id":"SharedDomainAuthority","witnesses":[ - {"file":"crates/ledger/src/domains/binding.rs","pattern":"fn bind"}, - {"file":"crates/ledger/src/domains/migration.rs","pattern":"fn migrate_execution_domains"}, - {"file":"crates/ledger/src/domains/view.rs","pattern":"fn require_stamp"}, - {"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_cross_family_shared_history_serializes_final_use"}, - {"file":"crates/ledger/tests/unit/shared_domains.rs","pattern":"fn finite_families_never_split_a_shared_cap"}, - {"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsProperty"}, - {"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsCedarReadsCurrentAuthority"}, - {"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run overCapacityUnionKeepsOriginalDecisionTest"}, - {"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run domainSplitCounterexampleTest"}, - {"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_cannot_split_any_shared_pair","declaration":"Weaver.SharedDomains.union_cannot_split_any_shared_pair"}, - {"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem admitted_union_conserves_capacity","declaration":"Weaver.SharedDomains.admitted_union_conserves_capacity"}, - {"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_retains_history","declaration":"Weaver.SharedDomains.union_retains_history"}, - {"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_fences_both_old_permits","declaration":"Weaver.SharedDomains.union_fences_both_old_permits"}]}, - {"id":"TursoMvccCustody","witnesses":[ - {"file":"crates/ledger/src/persistence/owner.rs","pattern":"fn open"}, - {"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_family"}, - {"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_final_domains_overlap_including_new_executor_connection"}, - {"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_same_budget_and_history_family_keeps_final_order"}, - {"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn mvcc_effect_before_failed_observation_never_releases_or_replays"}, - {"file":"go/dev/provider_final_domains_test.go","pattern":"func TestProviderMVCCIndependentFinalSendsAndRevocation"}, - {"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run postSendCommitConflictKeepsPhysicalEffectTest"}, - {"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem shared_final_readers_keep_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.shared_final_readers_keep_current_fence"}, - {"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem failed_observation_after_send_keeps_spent_hold","declaration":"Weaver.RuntimeAdmission.MVCC.failed_observation_after_send_keeps_spent_hold"}, - {"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_disjoint_admissions_have_overlapping_turso_writes"}, - {"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_process_custody_refuses_a_second_process"}, - {"file":"crates/ledger/tests/unit/mvcc.rs","pattern":"fn mvcc_concurrent_family_budget_has_one_original_reservation"}, - {"file":"go/dev/provider_mvcc_test.go","pattern":"func TestProviderMVCCExecutionBoundary"}, - {"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run snapshotWriteSkewCounterexampleTest"}, - {"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem disjoint_domain_commits_commute","declaration":"Weaver.RuntimeAdmission.MVCC.disjoint_domain_commits_commute"}, - {"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem family_step_preserves_all_budgets","declaration":"Weaver.RuntimeAdmission.MVCC.family_step_preserves_all_budgets"}, - {"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exclusive_final_use_keeps_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.exclusive_final_use_keeps_current_fence"}]}, - {"id":"ArchitectureViewGrammar","witnesses":[ - {"file":"dev/sysml/ArchitectureViews.sysml","pattern":"view zeroTrust"}, - {"file":"go/internal/devrunner/model_views.go","pattern":"func CaptureModelViews"}, - {"file":"go/internal/devrunner/model_views_test.go","pattern":"func TestModelViewsUseActualSDK"}, - {"file":"go/internal/devrunner/model_views_test.go","pattern":"func FuzzModelViewCaptureTracksSource"}, - {"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestArchitectureDiagramsUseDifferentViewProfiles"}, - {"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramProfilesAreExplicitAndLocal"}, - {"file":"go/internal/devrunner/diagrams.go","pattern":"func RenderDiagrams"}, - {"file":"dev/d2/src/render.ts","pattern":"composeFigure[(]input,composer[)]"}, - {"file":"dev/d2/test/model-view.test.ts","pattern":"public Library binds SDK SysML identity"}, - {"file":"dev/d2/src/objects.ts","pattern":"export const composeObjects"}, - {"file":"dev/d2/test/model-view.test.ts","pattern":"missing captured views and unsupported source ports refuse"}, - {"file":"dev/d2/test/vector-readability.test.ts","pattern":"Preserve the original ordered-sequence line-overlap check"}, - {"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramEvidenceRejectsLostNodesAndRelationships"}]}, - {"id":"ProductionAssetBoundary","witnesses":[ - {"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRuntimeAssetBoundary"}, - {"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRejectsRuntimeDevReferences"}]}, - {"id":"OriginalTaskBinding","witnesses":[ - {"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem first_birth_seal_cannot_broaden","declaration":"Weaver.TaskOrigin.first_birth_seal_cannot_broaden"}, - {"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem sealed_birth_cannot_be_replaced","declaration":"Weaver.TaskOrigin.sealed_birth_cannot_be_replaced"}, - {"file":"crates/ledger/tests/unit/task_publication.rs","pattern":"fn lost_birth_projection_cannot_authorize_or_be_silently_repaired"}, - {"file":"crates/ledger/src/task_origins.rs","pattern":"fn register_original_task"}, - {"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn source_rotation_cannot_reallocate_task_and_lost_reply_recovers_original_commit"}, - {"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn trusted_issuer_relabeling_every_identity_is_outside_local_deduplication"}, - {"file":"go/dev/provider_task_origin_test.go","pattern":"func TestProviderOriginalTaskOriginLostReplySourceSwitchAndRestart"}, - {"file":"dev/proofs/quint/TaskOrigin.qnt","pattern":"run issuerTrustCounterexampleTest"}, - {"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem assigned_task_cannot_rebind","declaration":"Weaver.TaskOrigin.assigned_task_cannot_rebind"}, - {"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem source_epoch_does_not_change_task_scope","declaration":"Weaver.TaskOrigin.source_epoch_does_not_change_task_scope"}, - {"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem stale_source_command_cannot_commit","declaration":"Weaver.TaskOrigin.stale_source_command_cannot_commit"}, - {"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn original_task_body_and_profile_cannot_be_replaced"}, - {"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalBindingTest"}]}, - {"id":"SharedBudget","witnesses":[ - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn finite_manifest_siblings_cannot_mask_a_missing_original_member"}, - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn maximum_manifest_cannot_replace_a_lost_sibling_after_restart"}, - {"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityRecoveryGuardTest"}, - {"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityFinalUseGuardTest"}, - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn selected_message_binding_must_match_its_committed_digest_at_final_write"}, - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn concurrent_message_admission_preserves_both_manifest_members"}, - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exhausted_budget_cannot_publish_a_manifest_member_without_its_row"}, - {"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem manifest_bound_runtime_step"}, - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn surviving_stream_message_cannot_hide_a_lost_unknown_reservation"}, - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exact_message_manifest_guards_recovery_and_existing_write_handles"}, - {"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialMessageLossCounterexampleTest"}, - {"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run digestSubstitutionFinalUseGuardTest"}, - {"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exact_manifest_admission_covers_original_exposure"}, - {"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn balanced_provider_projection_never_funds_a_different_original_plan"}, - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_stream_projection_never_funds_the_next_logical_message"}, - {"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem admission_covers_original_exposure"}, - {"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run balancedProjectionCounterexampleTest"}, - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_shrink_never_admits_a_different_node"}, - {"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn require_family"}, - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn mixed_request_and_stream_exposure_cannot_be_checked_in_separate_domains"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem orphaned_hold_blocks_new_admission"}, - {"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run separateEffectDomainsCounterexampleTest"}, - {"file":"crates/ledger/tests/unit/properties.rs","pattern":"fn arbitrary_replays_restarts_and_consumption_preserve_claims"}, - {"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run sharedBudgetTest"}, - {"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalCostBoundTest"}, - {"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn authored_ceiling_cannot_underreserve_the_original_wire_cost"}]}, - {"id":"ZeroTrustContractRefinement","witnesses":[ - {"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem final_use_on_committed_union","declaration":"Weaver.DomainMigrationComposition.final_use_on_committed_union"}, - {"file":"crates/ledger/src/provider.rs","pattern":"actual.stamp != p.domains"}, - {"file":"crates/ledger/tests/unit/provider_domains.rs","pattern":"fn same_actual_domains_fence_original_provider_capability"}, - {"file":"go/dev/provider_shared_domains_test.go","pattern":"actual migration committed; response discarded"}, - {"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run committedUnionLostReplyKeepsBothOriginalsTest"}, - {"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem gateway_final_use_preserves_domain_contract","declaration":"Weaver.DomainMigrationComposition.gateway_final_use_preserves_domain_contract"}, - {"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem head_cas_preserves_original_obligations","declaration":"Weaver.DomainMigrationComposition.head_cas_preserves_original_obligations"}, - {"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem overbooked_actual_view_cannot_supply_final_run","declaration":"Weaver.DomainMigrationComposition.overbooked_actual_view_cannot_supply_final_run"}, - {"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureResearchModels"}, - {"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainCommitRestartPositiveTest"}, - {"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainRevocationKeepsOriginalExposureTest"}, - {"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run detachedLogicalLedgerCounterexampleTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget","declaration":"Weaver.ProviderRpc.shared_exposure_keeps_original_budget"}, - {"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework","declaration":"Weaver.ZeroTrustEnrichment.gateway_specialization_retains_generic_framework"}, - {"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway","declaration":"Weaver.ZeroTrustEnrichment.retained_parent_and_selected_object_reach_gateway"}, - {"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption","declaration":"Weaver.ZeroTrustEnrichment.usage_control_keeps_current_consumption"}, - {"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use","declaration":"Weaver.ZeroTrustEnrichment.pending_policy_blocks_ongoing_use"}, - {"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"}, - {"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"}, - {"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"}]}, - {"id":"ConsumeBeforeSend","witnesses":[ - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn final_write_requires_exact_durable_range"}, - {"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run stateOnlyRangeCounterexampleTest"}, - {"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem inexact_cannot_refine_execution","declaration":"Weaver.StreamingExecution.RangeReceipt.inexact_cannot_refine_execution"}, - {"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn crash_after_consumption_never_reopens_or_refunds"}, - {"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run consumeBeforeSendTest"}]}, - {"id":"CurrentFinalGuard","witnesses":[ - {"file":"crates/ledger/tests/unit/serialization.rs","pattern":"fn effective_publication_cannot_overtake_the_locked_send_boundary"}, - {"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run stalePermitTest"}]}, - {"id":"UnknownRetainsHold","witnesses":[ - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restart_never_backfills_request_claims_from_operations"}, - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn orphaned_request_claim_cannot_admit_a_replacement_operation"}, - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn next_stream_message_cannot_recreate_a_lost_node_claim"}, - {"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn lost_message_projection_cannot_recycle_original_unknown_hold"}, - {"file":"crates/broker/tests/unit/https_transport.rs","pattern":"fn partial_transport_failure_is_unknown_and_never_retried"}, - {"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run unknownRefundCounterexampleTest"}]}, - {"id":"NoImplicitRetry","witnesses":[ - {"file":"crates/ledger/tests/unit/concurrency.rs","pattern":"fn concurrent_consumers_invoke_once"}, - {"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run duplicateRetryCounterexampleTest"}]}, - {"id":"DevelopmentPolicy","witnesses":[ - {"file":"crates/contracts/src/lib.rs","pattern":"mode = deny"}]}, - {"id":"MessageScopedAuthority","witnesses":[ - {"file":"crates/ledger/tests/unit/stream_properties.rs","pattern":"fn unknown_range_after_restart_blocks_new_nonce_and_authority"}, - {"file":"crates/policy/tests/unit/stream_policy.rs","pattern":"fn specification_derived_policy_is_typed_and_constrains_actual_range_facts"}]}, - {"id":"RangeFinalGuard","witnesses":[ - {"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn effective_revocation_stops_actual_next_range_and_prefix_reconnect"}, - {"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run revokedBetweenBurnAndWriteTest"}]}, - {"id":"UnknownPrefixRecovery","witnesses":[ - {"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn rust_partial_write_freezes_tail_and_never_refunds"}, - {"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unknown_cannot_resume"}]}, - {"id":"PrivateBufferCustody","witnesses":[ - {"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn tls_flush_cannot_release_a_tail_after_effective_revocation"}, - {"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn recovered_old_worker_socket_cannot_use_new_custody"}]}, - {"id":"BoundedPerformanceWork","witnesses":[ - {"file":"crates/policy/tests/unit/cache_storage.rs","pattern":"fn compiled_storage_caps_slots_and_exact_hits_do_not_allocate_new_entries"}, - {"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem bounded_range_copy_work"}]}, - {"id":"TrackedWriterDrain","witnesses":[ - {"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"async fn detached_executor_writer_keeps_slot_until_drain_acknowledges_completion"}, - {"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"fn arbitrary_disconnect_shutdown_and_drain_schedules_keep_executor_custody"}, - {"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"}, - {"file":"dev/proofs/quint/RuntimeLifecycle.qnt","pattern":"run prematureAckCounterexampleTest"}, - {"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem execution_and_drain_composition"}]}, - {"id":"GrpcCallerBinding","witnesses":[ - {"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderRPCIdentityAndCancellation"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_name_is_not_key_authority"}]}, - {"id":"TransportSetupIsolation","witnesses":[ - {"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run reconnectCannotUncancelOriginalStreamTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem crash_cannot_recreate_unknown_release"}, - {"file":"go/internal/gatewayclient/connection_test.go","pattern":"func TestConnectionSetupRetainsCallerDeadlineAndCancellation"}, - {"file":"go/dev/provider_startup_test.go","pattern":"func TestProviderFreshImageAndRestartStartup"}, - {"file":"dev/proofs/quint/GatewayComposition.qnt","pattern":"run reconnectRetainsSpentRootTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem gateway_run_preserves_original_execution_and_custody"}]}, - {"id":"CommittedProviderRouting","witnesses":[ - {"file":"go/internal/routing/provider_test.go","pattern":"func TestProviderRoutingCannotRewriteOriginalContract"}, - {"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderGRPCStreamingAndArrowOption"}]}, - {"id":"UnambiguousProviderRequestBounds","witnesses":[ - {"file":"crates/contracts/tests/unit/provider_bounds.rs","pattern":"fn exactly_one_provider_cap_is_bounded"}, - {"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn rejected_competing_caps_leave_no_claim_or_hold_after_restart"}, - {"file":"go/internal/routing/provider_test.go","pattern":"func FuzzProviderRequestBounds"}, - {"file":"go/dev/provider_bounds_test.go","pattern":"func TestProviderCompetingCapsCannotReachDispatch"}, - {"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preferredCapPrecedenceCounterexampleTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem request_bounds_and_affine_execution_composition"}]}, - {"id":"SourceProviderProfileBinding","witnesses":[ - {"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceProfileAndCedarBindFinalSendAcrossRestart"}, - {"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn concurrent_profile_registrations_cannot_fork_one_identity"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_task_registration_cannot_rebind"}]}, - {"id":"ClosedProviderRequestSchema","witnesses":[ - {"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn provider_profile_cannot_fall_back_to_untyped_request_or_raw_stream"}, - {"file":"crates/contracts/tests/unit/provider_profiles.rs","pattern":"fn shared_closed_request_corpus_has_the_declared_semantics"}, - {"file":"go/api/v1/provider_profile_test.go","pattern":"func TestProviderProfileSharedClosedRequestCorpus"}, - {"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceCommittedExtensionsCannotBypassProfile"}, - {"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingSchemaGuardCounterexampleTest"}]}, - {"id":"RecoverableProfileFloor","witnesses":[ - {"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn original_task_floor_prevents_missing_registry_from_rebinding_identity"}, - {"file":"crates/ledger/tests/unit/profile_floor_plan.rs","pattern":"fn semantic_floor_uses_two_composite_range_seeks"}, - {"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingFloorCounterexampleTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem missing_registry_cannot_erase_original_floor"}]}, - {"id":"CanonicalProfileConfiguration","witnesses":[ - {"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileJSONAndYAMLHaveOneCanonicalCommitment"}, - {"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileRejectsAmbiguousConfiguration"}, - {"file":"go/internal/config/provider_profile_test.go","pattern":"func FuzzProviderProfileConfiguration"}]}, - {"id":"AffineProviderAttempt","witnesses":[ - {"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn arbitrary_provider_replays_restarts_and_release_batches_keep_original_claim"}, - {"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run sdkRetryCannotConsumeAgainTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem consumed_unknown_retains_original_hold"}]}, - {"id":"EncodingAuthorityEquivalence","witnesses":[ - {"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPolicyChangeDuringCapacityWait"}, - {"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowWireBoundDoesNotBoundDecodedText"}, - {"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowInvalidLaterRowReturnsNoPartialBatch"}, - {"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preparedEncodingCannotSwitchTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem final_guard_checks_actual_owner_rows"}, - {"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderArrowChecksEveryRow"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem arrow_cannot_weaken_row_authority"}]}, - {"id":"ProviderUnknownRetention","witnesses":[ - {"file":"crates/broker/src/provider/runtime.rs","pattern":"fn open_guarded"}, - {"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn commit_provider"}, - {"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn failed_callback_never_enters_final_commit_and_retains_original_exposure"}, - {"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn turso_applied_commit_without_ack_poison_is_not_reusable"}, - {"file":"go/dev/provider_commit_fault_test.go","pattern":"func TestProviderSealedTursoCommitRecovery"}, - {"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run appliedLostAckPoisonsOldWorkerTest"}, - {"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run durableCommitThenFenceThenLateAckTest"}, - {"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run committingFailedCallbackCounterexampleTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem failed_callback_cannot_enter_commit","declaration":"Weaver.ProviderRpc.RequestWriteFence.failed_callback_cannot_enter_commit"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem applied_commit_without_ack_does_not_activate","declaration":"Weaver.ProviderRpc.RequestWriteFence.applied_commit_without_ack_does_not_activate"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem late_commit_ack_cannot_bypass_new_fence","declaration":"Weaver.ProviderRpc.RequestWriteFence.late_commit_ack_cannot_bypass_new_fence"}, - {"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider[(]"}, - {"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"}, - {"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run individualHoldOnlyCounterexampleTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_provider_exposure_cannot_be_released"}, - {"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem provider_exposure_strengthens_continuing_zero_trust"}, - {"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerEnqueueBeforeCommitCrashCannotReplayPendingRange"}, - {"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerCancellationAndReconnectRetainHistory"}, - {"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run enqueueThenLostCommitRetainsUnknownTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem transport_history_preserves_original_hold"}, - {"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderPartialRequestAndRestartRetainUnknownClaim"}, - {"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run unknownRefundCounterexampleTest"}]}, - {"id":"ReservedAuthorityAdmission","witnesses":[ - {"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption"}, - {"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run recoveryDoesNotRefreshUsageEvidenceTest"}, - {"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"}, - {"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use"}, - {"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn final_release_keeps_current_guard_and_unknown_commit_in_one_transaction"}, - {"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway"}, - {"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run childOnlyPredicateDropsParentCounterexampleTest"}, - {"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework"}, - {"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem continuing_uses_current_state_and_original_consumption"}, - {"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"}, - {"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem capacity_cannot_rebase_changed_floor"}, - {"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn waiting_capacity_does_not_hold_sql_or_authorize_after_publication"}, - {"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn pending_range_history_created_during_capacity_wait_cannot_be_replayed"}, - {"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPositiveControlCompletesAfterCapacityReturns"}, - {"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run returnedCapacityDoesNotAuthorizeStaleReleaseTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_backpressure_composition"}, - {"file":"crates/server/tests/unit/admission.rs","pattern":"async fn saturated_detached_execution_preserves_publication_and_observation_custody"}, - {"file":"go/dev/provider_capacity_test.go","pattern":"func TestProviderSaturatedExecutionPreservesRevocationAndObservation"}, - {"file":"dev/proofs/quint/AuthorityAdmission.qnt","pattern":"run sharedLaneStarvationCounterexampleTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_admission_composition"}]}, - {"id":"ConnectionCustodyBound","witnesses":[ - {"file":"crates/server/tests/unit/connections.rs","pattern":"async fn tcp_socket_owns_capacity_until_destruction_and_preserves_io_and_peer_identity"}, - {"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderPreTLSConnectionsAreBoundedAndExpire"}, - {"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderShutdownDestroysStalledTLSBeforeAcknowledgingExit"}, - {"file":"dev/proofs/quint/ConnectionAdmission.qnt","pattern":"run earlyReturnCounterexampleTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem provider_and_connection_composition"}]}, - {"id":"SourceIngressBinding","witnesses":[ - {"file":"go/dev/provider_source_test.go","pattern":"func TestProviderSourceIngressBindsCertificateCredentialAndMethod"}, - {"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledCatalogRequiresExactSourceEpoch"}, - {"file":"go/dev/provider_capacity_test.go","pattern":"full operation ingress blocked new source session"}, - {"file":"crates/server/tests/unit/grpc_ingress.rs","pattern":"async fn aliased_or_empty_source_identity_is_rejected_before_serving"}, - {"file":"dev/proofs/quint/SourceIngress.qnt","pattern":"run forwardedCredentialCounterexampleTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem ingress_step_preserves_independent_custody"}]}, - {"id":"DurablePublicationDecision","witnesses":[ - {"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn outcome_insert_failure_rolls_back_policy_schema_and_result_together"}, - {"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn concurrent_same_identity_commits_only_one_revision"}, - {"file":"go/dev/publication_recovery_test.go","pattern":"func TestProviderPublicationLostReplyRestartAndHistoricalDecision"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run deletedOutcomeCounterexampleTest"}, - {"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_and_provider_accounting_composition"}]}, - {"id":"OwnedSourceConnection","witnesses":[ - {"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run newCommandCanPrecedeOldReplyTest"}, - {"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn completed_source_acknowledgment_returns_command_capacity"}, - {"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run replyBeforeCapacityCounterexampleTest"}, - {"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem command_ack_requires_returned_capacity"}, - {"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn reused_source_connection_observes_other_writer_and_preserves_historical_result"}, - {"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn disconnected_source_caller_keeps_capacity_until_original_sql_work_finishes"}, - {"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn connection_reuse_rejects_an_unresolved_explicit_transaction"}, - {"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run swallowedCloseErrorCounterexampleTest"}, - {"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem owned_worker_and_publication_composition"}]}, - {"id":"FinalInvocationCancellation","witnesses":[ - {"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn cancellation_during_sql_wait_blocks_transport_and_keeps_spent_claim"}, - {"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn uncancelled_control_reaches_real_https_transport_once"}, - {"file":"dev/proofs/quint/DispatchCancellation.qnt","pattern":"run skippedRecheckCounterexampleTest"}, - {"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run missingFinalCancellationCheckCounterexampleTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem cancellation_and_original_hold_composition"}]}, - {"id":"OriginalReleaseCapability","witnesses":[ - {"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityBudgetHistoryChangeInvalidatesReleaseReadTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_plan_survives_batching"}, - {"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn equal_batch_digests_cannot_transfer_release_between_original_nodes"}, - {"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn release_encoding_cannot_change_after_preparation"}, - {"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn release_capabilities_bind_plan_encoding_and_restart_session"}, - {"file":"dev/proofs/quint/ReleaseBinding.qnt","pattern":"run crossPlanCounterexampleTest"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem release_binding_and_execution_composition"}]}, - {"id":"SpecificSourceContracts","witnesses":[ - {"file":"crates/server/src/single_provider.rs","pattern":"bound: BoundSource"}, - {"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"}, - {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run governanceCannotReplaceGovernorTest"}, - {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run missingGovernorCounterexampleTest"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_cannot_replace_governor","declaration":"Weaver.PolicyBridge.governance_cannot_replace_governor"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governor_cannot_replace_governance","declaration":"Weaver.PolicyBridge.governor_cannot_replace_governance"}, - {"file":"scheme/governance/types.ss","pattern":"def GovernanceScopeContract\\s+\\(\\.cc \\(Record"}, - {"file":"scheme/gateway/contracts.ss","pattern":"def GatewayArtifact"}, - {"file":"t/gateway-contracts-test.ss","pattern":"def gateway-contracts-test"}, - {"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityUncompiledSourceCannotRegisterTest"}, - {"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"}, - {"file":"t/gateway-contracts-test.ss","pattern":"module scopes use native POO Types and refuse evidence protocol hooks"}]}, - {"id":"GovernancePolicyProjection","witnesses":[ - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrApprovalCannotOutliveExposureProjectionRollbackTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrCommitReplyLossAndReplayCannotMintAnotherTicketTest"}, - {"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn candidate_only_replay_cannot_register_for_a_real_predecessor"}, - {"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn replay_cannot_substitute_the_captured_predecessor"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem matched_replay_preserves_both_images"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run exactReplayPairSurvivesLostReplyAndCommitsOriginalTest"}, - {"file":"crates/ledger/tests/unit/source_authority.rs","pattern":"fn source_handoffs_and_old_workers_preserve_original_unknown_budget"}, - {"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn consistent_whole_store_rollback_remains_a_local_authority_counterexample"}, - {"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn residual_policy_schema_cannot_be_treated_as_an_empty_store_after_restart"}, - {"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn first_enrollment_uses_all_durable_tables_without_temporary_aliases"}, - {"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn committed_writer_before_enrollment_cannot_be_hidden_by_an_old_empty_read"}, - {"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn callback_failure_after_enrollment_does_not_allow_a_replacement_identity"}, - {"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem complete_catalog_refusal_preserves_original_state"}, - {"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem source_enrollment_refusal_preserves_unknown_accounting"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run omittedProjectionEnrollmentCounterexampleTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateCatalogCommitMustReachDecidingGuardTest"}, - {"file":"go/dev/provider_source_authority_test.go","pattern":"func TestProviderPersistentSourceRotationLostReplyFencesExistingWorkerAndReissuedKey"}, - {"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem retired_source_key_cannot_become_fresh"}, - {"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_preserves_source_key_uniqueness"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run burnWithoutRetainedConfirmationCannotAdmitTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run cachedQualificationCannotAdmitWithZeroHeldProjectionTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run repairedProjectionDoesNotRecreateLostSendHandleTest"}, - {"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"}, - {"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_prefix_failure_atomically_rolls_back_burn"}, - {"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_prefix_without_burn_projection_cannot_repeat_admission"}, - {"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_burn_fenced_before_callback_keeps_original_unknown_exposure"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run confirmedRevocationAndHandoffRejectConsistentSourceRollbackTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run retainedRegistrationCannotReplaceAfterSnapshotRollbackTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run sameLengthArtifactReplacementCannotConfirmRetainedPrefixTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run wholeRetainedRootRollbackCanReplayQualificationCounterexampleTest"}, - {"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn identical_prefix_after_whole_store_restore_can_replay_dispatch_counterexample"}, - {"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn prefix_qualification_does_not_reconstruct_rolled_back_budget_counterexample"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run copiedRowsWithoutRecoveryQualificationCannotPublishTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateQualificationAfterRegistryAppendIsRefusedTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run recoveredNewOwnerRequalifiesOriginalArtifactTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run consistentAuthorityRollbackCanReplaySavedQualificationCounterexampleTest"}, - {"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn stale_registry_read_and_reopened_worker_preserve_unknown_provider_exposure"}, - {"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn text_rendering_cannot_silently_replace_original_policy_ids"}, - {"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn actual_spec_replay_registration_persists_before_original_final_cas"}, - {"file":"go/dev/provider_policy_json_test.go","pattern":"func TestProviderControlNamedPolicyJSONRevocationAndRestart"}, - {"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem finite_replay_does_not_certify_no_gain"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run observerRestartCannotRestoreReadCapabilityTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateRegistryReceiptAfterHandoffIsHistoricalTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run independentSnapshotRollbackResurrectsCredentialCounterexampleTest"}, - {"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn losing_verifier_metadata_cannot_downgrade_a_committed_served_profile"}, - {"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem missing_verifier_cannot_downgrade"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run missingVerifierCannotDowngradeAfterRestartTest"}, - {"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureComposition"}, - {"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureRejectsFalseArithmetic"}, - {"file":"dev/proofs/cedar/SpecProofClosure.lean","pattern":"def proveClosedArithmetic"}, - {"file":"prod/policies/provider/ProviderReview.lean","pattern":"def entry"}, - {"file":"go/internal/specreview/producer.go","pattern":"Issue"}, - {"file":"crates/policy/src/qualified_delta.rs","pattern":"pub fn verify_qualified_delta"}, - {"file":"go/dev/provider_spec_review_test.go","pattern":"func TestProviderRealSPECReviewRevocationLostRepliesAndRestart"}, - {"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn historical_signature_only_nogain_is_not_semantic_qualification"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run signatureOnlyGainCounterexampleTest"}, - {"file":"dev/proofs/cedar/QualifiedReview.lean","pattern":"theorem qualified_execution_and_recovery_preserve_original","declaration":"Weaver.QualifiedReview.qualified_execution_and_recovery_preserve_original"}, - {"file":"crates/ledger/src/delta_registration.rs","pattern":"fn require_current"}, - {"file":"crates/ledger/src/reviewed_head.rs","pattern":"fn require"}, - {"file":"go/dev/provider_review_test.go","pattern":"func TestProviderReviewedPublicationLostRepliesAndRestart"}, - {"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem reviewed_commit_composes_with_original_recovery"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run producerSignatureCannotReplaceQualificationTest"}, - {"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn consistent_snapshot_rollback_can_replace_local_registered_artifact_counterexample"}, - {"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceLateCommitReplyAfterRotationRemainsHistorical"}, - {"file":"crates/ledger/tests/unit/publication_review.rs","pattern":"fn reviewed_prefixes_match_an_independent_model"}, - {"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn stage_review_requirement_and_legacy_final_cas_have_one_serial_order"}, - {"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_registration_recovery_composes_without_releasing_unknown"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run latchedReviewCannotUseLegacyPublicationTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run configurationImageCannotErasePersistentRevocationTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registryAppendBetweenReadAndCASRequiresRejoinTest"}, - {"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRollbackLostReplyRetainsUnknownConsumption"}, - {"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem registrar_binding_reaches_final_cas"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run revocationBetweenValidationAndFinalCASTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run delayedIssuanceDecisionCannotReactivateOldEpochTest"}, - {"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateRotationRecoversLostReplyAndPending"}, - {"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateConfigRollbackReacceptsOldKeyCounterexample"}, - {"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_recovery_keeps_original_constraints"}, - {"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem durable_review_binding_survives_final_cas"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registrationLostReplyCannotPublishUnrecoveredProjectionTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run oldRegistrarCannotPublishAlreadyRegisteredArtifactTest"}, - {"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderStagingLostReplyRetainsConcurrentPendingAcrossRestart"}, - {"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRoleCredentialIsNotRegistrarIncarnationEvidence"}, - {"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem reviewed_publication_keeps_recovery_contract"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run substitutedArtifactGetsOriginalRejectionTest"}, - {"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run crossStoreReviewRollbackCounterexampleTest"}, - {"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderPendingCommandSubstitutionAndHistoricalRecovery"}, - {"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn typed_publication_does_not_yet_require_delta_evidence"}, - {"file":"scheme/policy/func.ss","pattern":"project-policy profile"}, - {"file":"scheme/policy/assets.ss","pattern":"read-policy-assets profile"}, - {"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"}, - {"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"}]}, - {"id":"CompiledSourceStartup","witnesses":[ - {"file":"scheme/gateway/compiled.ss","pattern":"weaver_governance_ready_v1"}, - {"file":"crates/governance-build/src/application.rs","pattern":"pub fn approved"}, - {"file":"build.ss","pattern":"approved application root mismatch"}, - {"file":"crates/governance/src/program/compiler.rs","pattern":"pub fn initialize"}, - {"file":"crates/governance/src/catalog/configuration.rs","pattern":"pub fn from_configuration"}, - {"file":"crates/server/src/governance_deployment.rs","pattern":"async fn start_compiler"}, - {"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRequiresRealInstallation"}, - {"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"metadataAsInitializationCounterexampleTest"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem graph_membership_cannot_replace_initialization"}]}, - {"id":"GovernorSourceHandoff","witnesses":[ - {"file":"scheme/gateway/types.ss","pattern":"def GatewayProgram"}, - {"file":"scheme/gateway/program.ss","pattern":"def \\(make-gateway-program"}, - {"file":"t/gateway-source-test.ss","pattern":"program installation and close follow an irreversible lifecycle"}, - {"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"caughtReentryPoisonsOuterDeliveryTest"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem program_result_composes_with_registered_original"}, - {"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"}, - {"file":"go/internal/controlplane/deployment_source_test.go","pattern":"func FuzzDeploymentSourceHasOneOwner"}, - {"file":"go/internal/controlplane/producer_deployment_test.go","pattern":"func exerciseProducerDeployment"}, - {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"deploymentCannotFallBackToFileTest"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem producer_deployment_keeps_registered_original"}, - {"file":"crates/server/src/grpc.rs","pattern":"async fn compile_source"}, - {"file":"go/internal/controlplane/source_compile.go","pattern":"func BootstrapProducer"}, - {"file":"go/internal/controlplane/approved_source_rpc_test.go","pattern":"func TestApprovedSourceMTLSBootstrap"}, - {"file":"go/internal/config/freeze_test.go","pattern":"func FuzzFrozenSourceDoesNotFollowCallerMutation"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem compilation_reply_keeps_registered_original"}, - {"file":"crates/governance/src/catalog/admission.rs","pattern":"pub struct ProducerCatalog"}, - {"file":"crates/governance/src/catalog/client.rs","pattern":"pub fn submit"}, - {"file":"crates/governance/tests/unit/catalog.rs","pattern":"changed_source_observations_and_fresh_names_cannot_select_original"}, - {"file":"crates/server/src/governance_owner.rs","pattern":"pub fn publish_producers"}, - {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"oldCatalogObservationStillCannotPublishThroughNewFenceTest"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"producer_selection_keeps_all_original_fields"}, - {"file":"crates/server/src/governance_owner.rs","pattern":"pub async fn start_governance"}, - {"file":"crates/server/src/grpc.rs","pattern":"pub async fn serve_grpc_with_runtime"}, - {"file":"crates/server/tests/unit/governance_owner.rs","pattern":"shared_owner_schedules_preserve_cleanup_and_terminal_admission"}, - {"file":"crates/server/tests/integration/governance_owner.rs","pattern":"actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain"}, - {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"lateFactoryActivationCounterexampleTest"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_owner_join_preserves_cleanup"}, - {"file":"crates/governance/src/scheme_input/records.rs","pattern":"pub fn root_source"}, - {"file":"crates/governance/src/scheme_input/values.rs","pattern":"fn bytes"}, - {"file":"crates/governance/src/host/client.rs","pattern":"pub fn source_lane"}, - {"file":"crates/governance/src/host/owner.rs","pattern":"pub fn run"}, - {"file":"crates/governance/tests/unit/host.rs","pattern":"cancelled_running_work_keeps_its_slot_until_natural_return"}, - {"file":"crates/governance/tests/unit/host.rs","pattern":"active_compiler_observes_both_request_and_owner_cancellation"}, - {"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSourceCancellationDrainsSchemeOwner"}, - {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"checkThenSendCloseRaceCounterexampleTest"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_host_delivery_requires_open_gate"}, - {"file":"crates/governance/src/binding.rs","pattern":"pub struct SourceExpectation"}, - {"file":"crates/governance/tests/unit/binding.rs","pattern":"coherent_replacements_cannot_change_original_content"}, - {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"unsafeSelfConsistentReplacementWitness"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"coherent_replacement_cannot_redefine_original"}, - {"file":"crates/governance/build.rs","pattern":"run_package_main"}, - {"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeQualificationStaysWithPreparedSchemeOwner"}, - {"file":"t/gateway-source-test.ss","pattern":"SDK field symbols and identifier strings cannot be interchanged"}, - {"file":"crates/governance/src/scheme.rs","pattern":"pub fn materialize_source"}, - {"file":"crates/governance/tests/integration/scheme_vm.rs","pattern":"actual_aa_capture_materializes_owned_data_before_vm_cleanup"}, - {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run unsafeEncodedBlobWitness"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem encoded_blob_cannot_claim_typed_capture"}, - {"file":"scheme/gateway/capture.ss","pattern":"Gateway capture requires one source emission"}, - {"file":"scheme/gateway/func.ss","pattern":"def \\(capture-governed-gateway"}, - {"file":"t/gateway-source-test.ss","pattern":"native PBT requires one completed emission"}, - {"file":"t/gateway-source-test.ss","pattern":"a late inherited sink cannot replace an active next capture"}, - {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run ignoredCaptureFuseCounterexampleTest"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem caught_duplicate_cannot_clear_capture_fuse"}, - {"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"}, - {"file":"scheme/governance/capture.ss","pattern":"def \\(governance-profile-snapshot"}, - {"file":"t/governance-test.ss","pattern":"native PBT preserves every original assessment binding"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_assessment_snapshot_cannot_reuse_boundary"}, - {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run coordinatedLiveProfileLabelsCannotReplaceOriginalCaptureTest"}, - {"file":"scheme/gateway/func.ss","pattern":"assq 'open-patterns"}, - {"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"}, - {"file":"scheme/governance/types.ss","pattern":"def GovernanceAssessmentContext"}, - {"file":"scheme/gateway/func.ss","pattern":"same-node-set?"}, - {"file":"t/gateway-source-test.ss","pattern":"a false Governance assessment cannot emit a source handoff"}, - {"file":"t/governance-test.ss","pattern":"a typed ready assessment cannot omit an original blocking threat"}, - {"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityChangedCompiledSourceCannotRecoverTest"}, - {"file":"scheme/policy/func.ss","pattern":"project-policy profile"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"}, - {"file":"t/integration/governed-control-test.ss","pattern":"def governed-control-test"}, - {"file":"go/internal/config/bundle_test.go","pattern":"func TestBundleRejectsSelectionAndCommitmentSubstitution"}]}, - {"id":"SourceStartupObservation","witnesses":[ - {"file":"scheme/gateway/provider-program.ss","pattern":"call-with-module-source-operation-measurement"}, - {"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeVerificationUsesOnlyPublicPackageEntries"}, - {"file":"crates/governance-build/src/program.rs","pattern":"build_program_archive_with_contract"}, - {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run releaseTagCannotRebaseCapturedSourceCounterexampleTest"}, - {"file":"go/internal/devrunner/retention_test.go","pattern":"func TestSchemePreparationFailureKeepsOriginalCutWithoutAmbientReceipt"}, - {"file":"go/internal/devrunner/retention_test.go","pattern":"func TestLateCleanupFailureCannotRetainPassingReceipt"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_preparation_cut_cannot_rebase_boundary","declaration":"Weaver.PolicyBridge.changed_preparation_cut_cannot_rebase_boundary"}, - {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run changedPackageMetadataCannotRebaseSnapshotTest"}, - {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run stalePreparationReceiptCounterexampleTest"}, - {"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"}, - {"file":"go/internal/controlplane/deployment.go","pattern":"trace\\(\"authority-reconciled\"\\)"}, - {"file":"scheme/gateway/func.ss","pattern":"source-selection-loaded"}, - {"file":"scheme/gateway/func.ss","pattern":"source-module-view-loaded"}, - {"file":"scheme/gateway/func.ss","pattern":"source-contracts-checked"}, - {"file":"scheme/gateway/func.ss","pattern":"source-advisory-derived"}, - {"file":"go/dev/provider_governor_performance_test.go","pattern":"status=failed drain_ns"}, - {"file":"crates/governance/src/host/owner.rs","pattern":"scheme-owner-drop-begin"}, - {"file":"t/fixtures/governed-control.ss","pattern":"fixture-module-ready"}, - {"file":"go/dev/provider_control_test.go","pattern":"These unauthenticated diagnostics never replace readiness or exit checks"}, - {"file":"crates/governance-build/src/tooling.rs","pattern":"fn bind_package_sources"}, - {"file":"crates/governance-build/tests/unit/package_sources.rs","pattern":"fn native_package_inputs_follow_the_selected_store_without_overwriting_sources"}]}, - {"id":"PolicyCAbiIsInert","witnesses":[ - {"file":"scheme/policy/func.ss","pattern":"def \\(validate-policy-projection!"}, - {"file":"scheme/gateway/func.ss","pattern":"validate-policy-projection! projection"}, - {"file":"t/policy-test.ss","pattern":"real Rust preflight refuses cross-document syntax assembly"}, - {"file":"t/policy-projection-test.ss","pattern":"every named document precedes aggregate validation"}, - {"file":"crates/policy-ffi/tests/unit/validation.rs","pattern":"fn aggregate_validity_does_not_establish_complete_source_documents"}, - {"file":"crates/policy/tests/unit/decisions.rs","pattern":"fn default_deny_forbid_and_evaluation_error_are_fail_closed"}, - {"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem incomplete_policy_document_cannot_admit"}, - {"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run aggregateOnlyPolicyValidationCounterexampleTest"}, - {"file":"scheme/policy/source-bytes.ss","pattern":"def \\(cedar-source-utf8"}, - {"file":"t/policy-test.ss","pattern":"native PBT checks Unicode source bounds before the C ABI"}, - {"file":"crates/policy-ffi/tests/unit/abi.rs","pattern":"fn unicode_byte_limits_apply_to_each_actual_abi_region"}, - {"file":"crates/policy-ffi/src/abi.rs","pattern":"pub unsafe extern \"C\" fn weaver_policy_validate_v1"}, - {"file":"scheme/policy/cedar-ffi.ss","pattern":"def-C-lambda policy-validate/raw"}, - {"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authoritySourceCommitNeverSendsTest"}]}, - {"id":"ControlActivationAcknowledgment","witnesses":[ - {"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"}, - {"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsStagingReplyLossAndRestart"}, - {"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlPublicationReplyLossCannotActivateOrRebase"}, - {"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityLostReplyCannotActivateTest"}, - {"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"}]}, - {"id":"ControlStreamRecoveryBinding","witnesses":[ - {"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPartialRequestAndRestart"}, - {"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlCompleteStreamsShareBudgetAndRejectSDKRetry"}, - {"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"}, - {"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem profile_recovery_retains_original_hold"}]}, - {"id":"WorkspaceBenchmarkCoverage","witnesses":[ - {"file":"go/internal/devrunner/benchmark_test.go","pattern":"func TestBenchmarkEvidenceRequiresEveryCase"}, - {"file":"go/dev/workspace_test.go","pattern":"func TestCargoWorkspaceAndDevelopmentGates"}, - {"file":"crates/broker/benches/gateway.rs","pattern":"fn guarded_provider"}, - {"file":"go/dev/provider_bench_test.go","pattern":"func BenchmarkGatewayInspect"}]}, - {"id":"DurableRangeProgressJoin","witnesses":[{"file":"crates/ledger/src/stream_progress.rs","pattern":"fn message"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_message_cursor_cannot_hide_consumed_range"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_progress_cannot_release_old_writer_or_connection"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run restoredUnknownProjectionBlocksAdmissionTest"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run unknownResetDuplicatesRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unresolved_tail_blocks_admission","declaration":"Weaver.StreamingExecution.RangeProgress.unresolved_tail_blocks_admission"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem changed_progress_cannot_execute","declaration":"Weaver.StreamingExecution.RangeProgress.changed_progress_cannot_execute"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem joined_execution_preserves_safety","declaration":"Weaver.StreamingExecution.RangeProgress.joined_execution_preserves_safety"}]}, - {"id":"TursoAdmissionAtomicity","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"pub fn begin"},{"file":"crates/ledger/src/exposure_manifest.rs","pattern":"fn verified_members"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn failed_commit_releases_writer_and_poisoned_session_cannot_reenter"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn duplicate_claim_members_cannot_be_normalized_out_of_recovery"},{"file":"go/dev/workspace_test.go","pattern":"func TestProjectArchitectureStorageUsesMRRDataTursoOnly"},{"file":"dev/proofs/quint/TursoAdmission.qnt","pattern":"run tornCommitRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem storage_step_retains_admission_safety","declaration":"Weaver.RuntimeAdmission.Persistence.storage_step_retains_admission_safety"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem committed_consume_survives_reply_loss_and_restart","declaration":"Weaver.RuntimeAdmission.Persistence.committed_consume_survives_reply_loss_and_restart"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem commit_itself_does_not_send","declaration":"Weaver.RuntimeAdmission.Persistence.commit_itself_does_not_send"}]}, - {"id":"BoundedAdvisoryDerivation","witnesses":[ - {"file":"scheme/gateway/derivation.ss","pattern":"def \\(make-gateway-derivation"}, - {"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-gateway"}, - {"file":"t/gateway-derivation-test.ss","pattern":"generated source replacements agree with graph traversal and fresh results"}, - {"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run derivedAdviceCannotChangeImageOrSpendTest"}, - {"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run adviceAsOriginalCounterexampleTest"}]}, - {"id":"SessionWorkflowFrontier","witnesses":[ - {"file":"scheme/gateway/program.ss","pattern":"def \\(hard-fact-affected"}, - {"file":"go/dev/provider_hard_fact_test.go","pattern":"func TestProviderControlHardFactWithdrawalRestartAndABA"}, - {"file":"scheme/gateway/func.ss","pattern":"def \\(session-workflow-path"}, - {"file":"crates/server/src/governance_deployment.rs","pattern":"admits_session_workflow"}, - {"file":"crates/ledger/src/provider_workflow.rs","pattern":"fn bind_winner"}, - {"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn provider_workflow_rechecks_prepared_floor_and_frontier_before_one_reservation"}, - {"file":"crates/server/src/session_workflow.rs","pattern":"async fn run_session_workflow"}, - {"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionWorkflowAutomaticallyResumes"}, - {"file":"scheme/gateway/func.ss","pattern":"def \\(governor-ready-steps"}, - {"file":"crates/ledger/src/provider_workflow.rs","pattern":"pub fn observe_workflow"}, - {"file":"crates/governance/src/host/owner.rs","pattern":"cut_sha256=.*ready_sha256="}, - {"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched inner-join cut_sha256="}, - {"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched outer-join cut_sha256="}, - {"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionDAGConcurrentJoinAndRecovery"}, - {"file":"crates/ledger/src/provider_workflow_choice.rs","pattern":"fn record_result"}, - {"file":"go/dev/provider_workflow_choice_test.go","pattern":"func TestProviderControlSessionChoiceFromReleasedResult"}, - {"file":"crates/ledger/src/provider_workflow_nested.rs","pattern":"fn load"}, - {"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn nested_workflow_rejects_stale_decision_and_keeps_winner_after_reopen"}, - {"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSessionNestedChoiceAndParallelRecovery"}]} -] +[{"id":"ProviderAdmissionTurn","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let selected_admission"},{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn begin_driver_counters_follow_their_admission_grant"},{"file":"crates/ledger/src/persistence/driver_observer.rs","pattern":"fn observe_read"},{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct AdmissionRequest"},{"file":"crates/ledger/tests/unit/provider_admission_turn.rs","pattern":"fn queued_unaccepted_admission_preserves_old_frame_and_original_hold"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionTurnProperty"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionCommitRecovery"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderAdmissionTurn"},{"file":"crates/broker/src/provider/request.rs","pattern":"Stage::Tls"},{"file":"go/dev/provider_transport_phases_test.go","pattern":"func reportProviderTransport"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run eagerQueueBlocksOldFrameCounterexampleTest"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem queue_preserves_arbitrary_requirement","declaration":"Weaver.ProviderAdmissionTurn.queue_preserves_arbitrary_requirement"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem finite_queue_preserves_final_offer","declaration":"Weaver.ProviderAdmissionTurn.finite_queue_preserves_final_offer"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem open_writer_cannot_mutate","declaration":"Weaver.ProviderAdmissionTurn.open_writer_cannot_mutate"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem accepted_hard_intent_blocks","declaration":"Weaver.ProviderAdmissionTurn.accepted_hard_intent_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_outcome_blocks","declaration":"Weaver.ProviderAdmissionTurn.unknown_outcome_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem changed_image_blocks","declaration":"Weaver.ProviderAdmissionTurn.changed_image_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem queued_admission_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.queued_admission_preserves_spec_final_use"},{"file":"go/internal/controlplane/deployment.go","pattern":"if gateway.source == nil"},{"file":"go/dev/provider_control_bench_test.go","pattern":"func TestProviderGoControlMeasuredChain"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem runtime_catalog_requires_source","declaration":"Weaver.ProviderAdmissionTurn.runtime_catalog_requires_source"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_activation_blocks_source_handoff","declaration":"Weaver.ProviderAdmissionTurn.unknown_activation_blocks_source_handoff"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem bootstrap_source_close_preserves_actual","declaration":"Weaver.ProviderAdmissionTurn.bootstrap_source_close_preserves_actual"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run failedBootstrapCleanupDoesNotActivateIngressTest"},{"file":"go/dev/provider_admission_overlap_bench_test.go","pattern":"func BenchmarkProviderAdmissionOverlap"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn collect_buffered"},{"file":"go/dev/provider_control_bench_test.go","pattern":"image := serverBinary"},{"file":"go/dev/provider_fixture_test.go","pattern":"test-owned Go control image sha256"},{"file":"crates/ledger/src/persistence/scope_trace.rs","pattern":"pub\\(super\\) fn observe_release"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"observed_release_covers_lease_removal_without_retaining_a_grant"},{"file":"crates/ledger/src/persistence/driver_observer.rs","pattern":"pub\\(super\\) fn observe_commit"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"commit_io_observes_native_spans_after_unobserved_setup"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"maybe_prepared\\(c, PREPARE"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn review_program_reuse_reads_replacement_and_rejects_projection_loss"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn review_program_reuse_preserves_native_receipts_and_currentness"},{"file":"go/dev/provider_control_bench_test.go","pattern":"both arms use Go forwarding"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"valid_review!\\(\"CROSS JOIN\"\\)"},{"file":"crates/ledger/src/domains/view.rs","pattern":"require_view\\(persistence::maybe_prepared"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn manifest_programs_rebind_current_members_and_reject_divergence"}]},{"id":"ProviderReadCustody","witnesses":[{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn conflicts"},{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn acquire_origin"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let shared_reads"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn compatible_origins_share_reads_but_an_older_writer_blocks_younger_readers"},{"file":"crates/ledger/tests/unit/provider_read_custody.rs","pattern":"fn shared_reads_keep_distinct_origin_native_writes_concurrent"},{"file":"go/dev/provider_read_custody_test.go","pattern":"func TestProviderReadCustodyProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderReadCustody"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem arbitrary_policy_preserved","declaration":"Weaver.ProviderReadCustody.arbitrary_policy_preserved"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem finite_interleaving_preserves_policy","declaration":"Weaver.ProviderReadCustody.finite_interleaving_preserves_policy"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem overlapping_writes_conflict","declaration":"Weaver.ProviderReadCustody.overlapping_writes_conflict"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessRetainsWriterAndSameOriginBarriers"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_binding_blocks","declaration":"Weaver.ProviderReadCustody.changed_binding_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_shared_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_shared_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_origin_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_origin_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_owner_blocks","declaration":"Weaver.ProviderReadCustody.changed_owner_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem shared_writer_conflicts","declaration":"Weaver.ProviderReadCustody.shared_writer_conflicts"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem older_conflicting_writer_blocks","declaration":"Weaver.ProviderReadCustody.older_conflicting_writer_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem read_custody_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.read_custody_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderReadCustody.qnt","pattern":"run unsafeSharedMutationCounterexampleTest"}]},{"id":"ProviderLifecycleFootprint","witnesses":[{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct OriginLifecycle"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"enum Impact"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_lifecycle"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_provider_lifecycle"},{"file":"crates/ledger/tests/unit/provider_lifecycle.rs","pattern":"fn peer_lifecycle_preserves_complete_view_but_shared_admission_does_not"},{"file":"go/dev/provider_lifecycle_test.go","pattern":"func TestProviderLifecycleCommitRecovery"},{"file":"crates/ledger/tests/unit/authority_footprint.rs","pattern":"fn local_commit_retires_whole_and_own_but_preserves_peer"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem origin_commit_retires_whole_reader","declaration":"Weaver.ProviderLifecycleFootprint.origin_commit_retires_whole_reader"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem arbitrary_cedar_predicate_preserved","declaration":"Weaver.ProviderLifecycleFootprint.arbitrary_cedar_predicate_preserved"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem shared_admission_requires_shared_invalidation","declaration":"Weaver.ProviderLifecycleFootprint.shared_admission_requires_shared_invalidation"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem peer_lifecycle_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.peer_lifecycle_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderLifecycleFootprint.qnt","pattern":"run unsafeNarrowAdmissionCounterexampleTest"}]},{"id":"ProviderSnapshotPublication","witnesses":[{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn release_provider_group_for_delivery"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"struct Snapshot"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn share_qualification"},{"file":"crates/ledger/src/provider.rs","pattern":"fn begin_snapshot_validation"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn take_refresh"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem pending_close_defers_renewal","declaration":"Weaver.ProviderSnapshotPublication.pending_close_defers_renewal"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn a_request_arriving_during_qualification_cannot_trigger_a_second_native_read"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn one_snapshot_requalification_covers_every_exact_frame"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn post_staging_native_failure_cannot_publish_a_partial_snapshot"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn queue_snapshot"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func awaitDeliveryCuts"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem final_use_joins_snapshot","declaration":"Weaver.ProviderSnapshotPublication.final_use_joins_snapshot"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem published_snapshot_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.published_snapshot_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSnapshotPublication.qnt","pattern":"run ungatedArcLoadIsCounterexampleTest"}]},{"id":"ProviderSemanticProgress","witnesses":[{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct RangeProgress"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_progress"},{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn stage_group"},{"file":"crates/ledger/tests/unit/provider_delivery.rs","pattern":"fn exact_range_progress_preserves_queued_authorization"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderSemanticProgressProperty"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_released_binding","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_released_binding"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_image","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_image"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem range_progress_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.range_progress_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSemanticProgress.qnt","pattern":"run hiddenSemanticEditIsCounterexampleTest"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"}]},{"id":"ProviderDeliveryJoin","witnesses":[{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn bounded_trace_retains_every_requalification"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeTraceChunksPreserveAllRecords"},{"file":"crates/ledger/tests/unit/persistence_owner.rs","pattern":"fn descriptor_copy_is_not_a_retained_execution_owner"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem retained_role_blocks_custody_retirement","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.retained_role_blocks_custody_retirement"},{"file":"dev/proofs/quint/ProviderDeliveryPipeline.qnt","pattern":"run threeInertFramesNeedNoStopAndWaitTest"},{"file":"crates/server/src/grpc_delivery_producer.rs","pattern":"fn reserve_guarded"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"pub fn poll"},{"file":"crates/server/src/grpc_delivery.rs","pattern":"impl Stream for ResponseStream"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryCommitAndReceiverRecovery"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryReceiverProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem orphaned_witness_cannot_activate","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.orphaned_witness_cannot_activate"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem acknowledged_delivery_preserves_same_actual_view","declaration":"Weaver.DomainMigrationComposition.acknowledged_delivery_preserves_same_actual_view"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run committedWithoutAcknowledgmentCannotAcceptTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run rollbackCannotEraseIndependentWitnessTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run oldOwnerCannotRequalifyAfterRestartTest"}]},{"id":"ProviderEgressPromotion","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_close_receipt_cannot_resolve_new_intent","declaration":"Weaver.ProviderEgressWindow.Promotion.old_close_receipt_cannot_resolve_new_intent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem expired_clock_blocks_receiver","declaration":"Weaver.ProviderEgressWindow.Promotion.expired_clock_blocks_receiver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem every_effect_writer_needs_mediation","declaration":"Weaver.ProviderEgressWindow.Promotion.every_effect_writer_needs_mediation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem other_writer_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.other_writer_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem uncertain_effect_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.uncertain_effect_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem unchanged_database_does_not_revalidate_old_read","declaration":"Weaver.ProviderEgressWindow.Promotion.unchanged_database_does_not_revalidate_old_read"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem witness_ahead_blocks_old_image","declaration":"Weaver.ProviderEgressWindow.Promotion.witness_ahead_blocks_old_image"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem only_current_owner_can_deliver","declaration":"Weaver.ProviderEgressWindow.Promotion.only_current_owner_can_deliver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_queued_frame_cannot_follow_replacement","declaration":"Weaver.ProviderEgressWindow.Promotion.old_queued_frame_cannot_follow_replacement"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem delivered_frame_cannot_be_delivered_twice","declaration":"Weaver.ProviderEgressWindow.Promotion.delivered_frame_cannot_be_delivered_twice"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem receiver_promotion_refines_interval_admission","declaration":"Weaver.ProviderEgressWindow.Promotion.receiver_promotion_refines_interval_admission"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run firstCommitCannotDeliverAnotherPendingWriterTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run independentWitnessBeforeDatabaseBlocksDeliveryTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run oldWorkerDeliveryCounterexampleTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run allWriterClassesUseTheSameCutTest"}]},{"id":"BoundedProviderEgressWindow","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem any_accepted_trace_keeps_disjoint_prefix","declaration":"Weaver.ProviderEgressWindow.any_accepted_trace_keeps_disjoint_prefix"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem loss_and_restart_close_old_window","declaration":"Weaver.ProviderEgressWindow.loss_and_restart_close_old_window"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem matching_image_does_not_reopen_old_cut","declaration":"Weaver.ProviderEgressWindow.matching_image_does_not_reopen_old_cut"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem connected_roots_cannot_use_distinct_lanes","declaration":"Weaver.ProviderEgressWindow.connected_roots_cannot_use_distinct_lanes"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem admitted_four_turn_envelope","declaration":"Weaver.ProviderEgressWindow.admitted_four_turn_envelope"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem settlement_is_idempotent","declaration":"Weaver.ProviderEgressWindow.settlement_is_idempotent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem holder_stage_overlap_cannot_exceed_ticket_wait","declaration":"Weaver.ProviderEgressWindow.holder_stage_overlap_cannot_exceed_ticket_wait"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run coherentStoreRollbackActuallyDuplicatesOfferTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run pendingRevocationStopsActualOfferTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run lostBurnAckSealsOriginalTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run rehydratingOldWindowActuallyDuplicatesOfferTest"}]},{"id":"OriginalFloorDecision","witnesses":[{"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run lostCommitResponseResolvesSameOperationTest"},{"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run unknownCommitCannotActivateTest"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"}]},{"id":"ProviderCurrentnessPerformance","witnesses":[{"file":"go/dev/provider_domain_program_test.go","pattern":"func BenchmarkProviderDomainProgram"},{"file":"go/dev/provider_domain_tail_test.go","pattern":"func BenchmarkProviderSharedLongTail"},{"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem prepared_domain_program_preserves_live_decision"}]},{"id":"ProviderSchedulerOwnership","witnesses":[{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn waiting_multi_root_range_precedes_younger_conflicts"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessCountsArrivalGrantInversions"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"}]},{"id":"SenderBoundProviderOAuth","witnesses":[{"file":"go/dev/provider_oauth_relay_test.go","pattern":"func TestProviderOAuthTwoHopRevocationAndRecovery"},{"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem retained_root_revocation_blocks_child"}]},{"id":"TransportAndExecutionLatencySeparation","witnesses":[{"file":"go/dev/provider_scheduler_bench_test.go","pattern":"func BenchmarkProviderScheduledEncoding"},{"file":"go/dev/provider_range_group_test.go","pattern":"func BenchmarkProviderRangePreparationGroup"}]},{"id":"TelemetryNoninterference","witnesses":[{"file":"crates/telemetry/tests/unit/metrics.rs","pattern":"fn observations_are_monotone_and_restart_local"},{"file":"go/internal/telemetry/metrics_test.go","pattern":"func TestPropertyCountersAreBoundedMonotoneAndRestartLocal"},{"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderTelemetryCannotRefundOrRedispatchUnknownSend"},{"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderControlTelemetryObservesBothServices"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryReadsAndRestartCannotRefundTest"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryAsRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem arbitrary_observations_keep_execution","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.arbitrary_observations_keep_execution"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem telemetry_reset_keeps_unknown_hold","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.telemetry_reset_keeps_unknown_hold"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem observations_preserve_effect_safety","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.observations_preserve_effect_safety"}]},{"id":"SharedDomainAuthority","witnesses":[{"file":"crates/ledger/src/domains/binding.rs","pattern":"fn bind"},{"file":"crates/ledger/src/domains/migration.rs","pattern":"fn migrate_execution_domains"},{"file":"crates/ledger/src/domains/view.rs","pattern":"fn require_stamp"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_cross_family_shared_history_serializes_final_use"},{"file":"crates/ledger/tests/unit/shared_domains.rs","pattern":"fn finite_families_never_split_a_shared_cap"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsProperty"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsCedarReadsCurrentAuthority"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run overCapacityUnionKeepsOriginalDecisionTest"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run domainSplitCounterexampleTest"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_cannot_split_any_shared_pair","declaration":"Weaver.SharedDomains.union_cannot_split_any_shared_pair"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem admitted_union_conserves_capacity","declaration":"Weaver.SharedDomains.admitted_union_conserves_capacity"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_retains_history","declaration":"Weaver.SharedDomains.union_retains_history"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_fences_both_old_permits","declaration":"Weaver.SharedDomains.union_fences_both_old_permits"}]},{"id":"TursoMvccCustody","witnesses":[{"file":"crates/ledger/src/persistence/owner.rs","pattern":"fn open"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_family"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_final_domains_overlap_including_new_executor_connection"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_same_budget_and_history_family_keeps_final_order"},{"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn mvcc_effect_before_failed_observation_never_releases_or_replays"},{"file":"go/dev/provider_final_domains_test.go","pattern":"func TestProviderMVCCIndependentFinalSendsAndRevocation"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run postSendCommitConflictKeepsPhysicalEffectTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem shared_final_readers_keep_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.shared_final_readers_keep_current_fence"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem failed_observation_after_send_keeps_spent_hold","declaration":"Weaver.RuntimeAdmission.MVCC.failed_observation_after_send_keeps_spent_hold"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_disjoint_admissions_have_overlapping_turso_writes"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_process_custody_refuses_a_second_process"},{"file":"crates/ledger/tests/unit/mvcc.rs","pattern":"fn mvcc_concurrent_family_budget_has_one_original_reservation"},{"file":"go/dev/provider_mvcc_test.go","pattern":"func TestProviderMVCCExecutionBoundary"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run snapshotWriteSkewCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem disjoint_domain_commits_commute","declaration":"Weaver.RuntimeAdmission.MVCC.disjoint_domain_commits_commute"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem family_step_preserves_all_budgets","declaration":"Weaver.RuntimeAdmission.MVCC.family_step_preserves_all_budgets"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exclusive_final_use_keeps_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.exclusive_final_use_keeps_current_fence"}]},{"id":"ArchitectureViewGrammar","witnesses":[{"file":"dev/sysml/ArchitectureViews.sysml","pattern":"view zeroTrust"},{"file":"go/internal/devrunner/model_views.go","pattern":"func CaptureModelViews"},{"file":"go/internal/devrunner/model_views_test.go","pattern":"func TestModelViewsUseActualSDK"},{"file":"go/internal/devrunner/model_views_test.go","pattern":"func FuzzModelViewCaptureTracksSource"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestArchitectureDiagramsUseDifferentViewProfiles"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramProfilesAreExplicitAndLocal"},{"file":"go/internal/devrunner/diagrams.go","pattern":"func RenderDiagrams"},{"file":"dev/d2/src/render.ts","pattern":"composeFigure[(]input,composer[)]"},{"file":"dev/d2/test/model-view.test.ts","pattern":"public Library binds SDK SysML identity"},{"file":"dev/d2/src/objects.ts","pattern":"export const composeObjects"},{"file":"dev/d2/test/model-view.test.ts","pattern":"missing captured views and unsupported source ports refuse"},{"file":"dev/d2/test/vector-readability.test.ts","pattern":"Preserve the original ordered-sequence line-overlap check"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramEvidenceRejectsLostNodesAndRelationships"}]},{"id":"ProductionAssetBoundary","witnesses":[{"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRuntimeAssetBoundary"},{"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRejectsRuntimeDevReferences"}]},{"id":"OriginalTaskBinding","witnesses":[{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem first_birth_seal_cannot_broaden","declaration":"Weaver.TaskOrigin.first_birth_seal_cannot_broaden"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem sealed_birth_cannot_be_replaced","declaration":"Weaver.TaskOrigin.sealed_birth_cannot_be_replaced"},{"file":"crates/ledger/tests/unit/task_publication.rs","pattern":"fn lost_birth_projection_cannot_authorize_or_be_silently_repaired"},{"file":"crates/ledger/src/task_origins.rs","pattern":"fn register_original_task"},{"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn source_rotation_cannot_reallocate_task_and_lost_reply_recovers_original_commit"},{"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn trusted_issuer_relabeling_every_identity_is_outside_local_deduplication"},{"file":"go/dev/provider_task_origin_test.go","pattern":"func TestProviderOriginalTaskOriginLostReplySourceSwitchAndRestart"},{"file":"dev/proofs/quint/TaskOrigin.qnt","pattern":"run issuerTrustCounterexampleTest"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem assigned_task_cannot_rebind","declaration":"Weaver.TaskOrigin.assigned_task_cannot_rebind"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem source_epoch_does_not_change_task_scope","declaration":"Weaver.TaskOrigin.source_epoch_does_not_change_task_scope"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem stale_source_command_cannot_commit","declaration":"Weaver.TaskOrigin.stale_source_command_cannot_commit"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn original_task_body_and_profile_cannot_be_replaced"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalBindingTest"}]},{"id":"SharedBudget","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn finite_manifest_siblings_cannot_mask_a_missing_original_member"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn maximum_manifest_cannot_replace_a_lost_sibling_after_restart"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityRecoveryGuardTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityFinalUseGuardTest"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn selected_message_binding_must_match_its_committed_digest_at_final_write"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn concurrent_message_admission_preserves_both_manifest_members"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exhausted_budget_cannot_publish_a_manifest_member_without_its_row"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem manifest_bound_runtime_step"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn surviving_stream_message_cannot_hide_a_lost_unknown_reservation"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exact_message_manifest_guards_recovery_and_existing_write_handles"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialMessageLossCounterexampleTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run digestSubstitutionFinalUseGuardTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exact_manifest_admission_covers_original_exposure"},{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn balanced_provider_projection_never_funds_a_different_original_plan"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_stream_projection_never_funds_the_next_logical_message"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem admission_covers_original_exposure"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run balancedProjectionCounterexampleTest"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_shrink_never_admits_a_different_node"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn require_family"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn mixed_request_and_stream_exposure_cannot_be_checked_in_separate_domains"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem orphaned_hold_blocks_new_admission"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run separateEffectDomainsCounterexampleTest"},{"file":"crates/ledger/tests/unit/properties.rs","pattern":"fn arbitrary_replays_restarts_and_consumption_preserve_claims"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run sharedBudgetTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalCostBoundTest"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn authored_ceiling_cannot_underreserve_the_original_wire_cost"}]},{"id":"ZeroTrustContractRefinement","witnesses":[{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem final_use_on_committed_union","declaration":"Weaver.DomainMigrationComposition.final_use_on_committed_union"},{"file":"crates/ledger/src/provider.rs","pattern":"actual.stamp != p.domains"},{"file":"crates/ledger/tests/unit/provider_domains.rs","pattern":"fn same_actual_domains_fence_original_provider_capability"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"actual migration committed; response discarded"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run committedUnionLostReplyKeepsBothOriginalsTest"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem gateway_final_use_preserves_domain_contract","declaration":"Weaver.DomainMigrationComposition.gateway_final_use_preserves_domain_contract"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem head_cas_preserves_original_obligations","declaration":"Weaver.DomainMigrationComposition.head_cas_preserves_original_obligations"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem overbooked_actual_view_cannot_supply_final_run","declaration":"Weaver.DomainMigrationComposition.overbooked_actual_view_cannot_supply_final_run"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureResearchModels"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainCommitRestartPositiveTest"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainRevocationKeepsOriginalExposureTest"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run detachedLogicalLedgerCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget","declaration":"Weaver.ProviderRpc.shared_exposure_keeps_original_budget"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework","declaration":"Weaver.ZeroTrustEnrichment.gateway_specialization_retains_generic_framework"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway","declaration":"Weaver.ZeroTrustEnrichment.retained_parent_and_selected_object_reach_gateway"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption","declaration":"Weaver.ZeroTrustEnrichment.usage_control_keeps_current_consumption"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use","declaration":"Weaver.ZeroTrustEnrichment.pending_policy_blocks_ongoing_use"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"}]},{"id":"ConsumeBeforeSend","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn final_write_requires_exact_durable_range"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run stateOnlyRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem inexact_cannot_refine_execution","declaration":"Weaver.StreamingExecution.RangeReceipt.inexact_cannot_refine_execution"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn crash_after_consumption_never_reopens_or_refunds"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run consumeBeforeSendTest"}]},{"id":"CurrentFinalGuard","witnesses":[{"file":"crates/ledger/tests/unit/serialization.rs","pattern":"fn effective_publication_cannot_overtake_the_locked_send_boundary"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run stalePermitTest"}]},{"id":"UnknownRetainsHold","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restart_never_backfills_request_claims_from_operations"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn orphaned_request_claim_cannot_admit_a_replacement_operation"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn next_stream_message_cannot_recreate_a_lost_node_claim"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn lost_message_projection_cannot_recycle_original_unknown_hold"},{"file":"crates/broker/tests/unit/https_transport.rs","pattern":"fn partial_transport_failure_is_unknown_and_never_retried"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run unknownRefundCounterexampleTest"}]},{"id":"NoImplicitRetry","witnesses":[{"file":"crates/ledger/tests/unit/concurrency.rs","pattern":"fn concurrent_consumers_invoke_once"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run duplicateRetryCounterexampleTest"}]},{"id":"DevelopmentPolicy","witnesses":[{"file":"crates/contracts/src/lib.rs","pattern":"mode = deny"}]},{"id":"MessageScopedAuthority","witnesses":[{"file":"crates/ledger/tests/unit/stream_properties.rs","pattern":"fn unknown_range_after_restart_blocks_new_nonce_and_authority"},{"file":"crates/policy/tests/unit/stream_policy.rs","pattern":"fn specification_derived_policy_is_typed_and_constrains_actual_range_facts"}]},{"id":"RangeFinalGuard","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn effective_revocation_stops_actual_next_range_and_prefix_reconnect"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run revokedBetweenBurnAndWriteTest"}]},{"id":"UnknownPrefixRecovery","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn rust_partial_write_freezes_tail_and_never_refunds"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unknown_cannot_resume"}]},{"id":"PrivateBufferCustody","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn tls_flush_cannot_release_a_tail_after_effective_revocation"},{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn recovered_old_worker_socket_cannot_use_new_custody"}]},{"id":"BoundedPerformanceWork","witnesses":[{"file":"crates/policy/tests/unit/cache_storage.rs","pattern":"fn compiled_storage_caps_slots_and_exact_hits_do_not_allocate_new_entries"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem bounded_range_copy_work"}]},{"id":"TrackedWriterDrain","witnesses":[{"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"async fn detached_executor_writer_keeps_slot_until_drain_acknowledges_completion"},{"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"fn arbitrary_disconnect_shutdown_and_drain_schedules_keep_executor_custody"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"},{"file":"dev/proofs/quint/RuntimeLifecycle.qnt","pattern":"run prematureAckCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem execution_and_drain_composition"}]},{"id":"GrpcCallerBinding","witnesses":[{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderRPCIdentityAndCancellation"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_name_is_not_key_authority"}]},{"id":"TransportSetupIsolation","witnesses":[{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run reconnectCannotUncancelOriginalStreamTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem crash_cannot_recreate_unknown_release"},{"file":"go/internal/gatewayclient/connection_test.go","pattern":"func TestConnectionSetupRetainsCallerDeadlineAndCancellation"},{"file":"go/dev/provider_startup_test.go","pattern":"func TestProviderFreshImageAndRestartStartup"},{"file":"dev/proofs/quint/GatewayComposition.qnt","pattern":"run reconnectRetainsSpentRootTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem gateway_run_preserves_original_execution_and_custody"}]},{"id":"CommittedProviderRouting","witnesses":[{"file":"go/internal/routing/provider_test.go","pattern":"func TestProviderRoutingCannotRewriteOriginalContract"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderGRPCStreamingAndArrowOption"}]},{"id":"UnambiguousProviderRequestBounds","witnesses":[{"file":"crates/contracts/tests/unit/provider_bounds.rs","pattern":"fn exactly_one_provider_cap_is_bounded"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn rejected_competing_caps_leave_no_claim_or_hold_after_restart"},{"file":"go/internal/routing/provider_test.go","pattern":"func FuzzProviderRequestBounds"},{"file":"go/dev/provider_bounds_test.go","pattern":"func TestProviderCompetingCapsCannotReachDispatch"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preferredCapPrecedenceCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem request_bounds_and_affine_execution_composition"}]},{"id":"SourceProviderProfileBinding","witnesses":[{"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceProfileAndCedarBindFinalSendAcrossRestart"},{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn concurrent_profile_registrations_cannot_fork_one_identity"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_task_registration_cannot_rebind"}]},{"id":"ClosedProviderRequestSchema","witnesses":[{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn provider_profile_cannot_fall_back_to_untyped_request_or_raw_stream"},{"file":"crates/contracts/tests/unit/provider_profiles.rs","pattern":"fn shared_closed_request_corpus_has_the_declared_semantics"},{"file":"go/api/v1/provider_profile_test.go","pattern":"func TestProviderProfileSharedClosedRequestCorpus"},{"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceCommittedExtensionsCannotBypassProfile"},{"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingSchemaGuardCounterexampleTest"}]},{"id":"RecoverableProfileFloor","witnesses":[{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn original_task_floor_prevents_missing_registry_from_rebinding_identity"},{"file":"crates/ledger/tests/unit/profile_floor_plan.rs","pattern":"fn semantic_floor_uses_two_composite_range_seeks"},{"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingFloorCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem missing_registry_cannot_erase_original_floor"}]},{"id":"CanonicalProfileConfiguration","witnesses":[{"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileJSONAndYAMLHaveOneCanonicalCommitment"},{"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileRejectsAmbiguousConfiguration"},{"file":"go/internal/config/provider_profile_test.go","pattern":"func FuzzProviderProfileConfiguration"}]},{"id":"AffineProviderAttempt","witnesses":[{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn arbitrary_provider_replays_restarts_and_release_batches_keep_original_claim"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run sdkRetryCannotConsumeAgainTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem consumed_unknown_retains_original_hold"}]},{"id":"EncodingAuthorityEquivalence","witnesses":[{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPolicyChangeDuringCapacityWait"},{"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowWireBoundDoesNotBoundDecodedText"},{"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowInvalidLaterRowReturnsNoPartialBatch"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preparedEncodingCannotSwitchTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem final_guard_checks_actual_owner_rows"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderArrowChecksEveryRow"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem arrow_cannot_weaken_row_authority"}]},{"id":"ProviderUnknownRetention","witnesses":[{"file":"crates/broker/src/provider/runtime.rs","pattern":"fn open_guarded"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn commit_provider"},{"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn failed_callback_never_enters_final_commit_and_retains_original_exposure"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn turso_applied_commit_without_ack_poison_is_not_reusable"},{"file":"go/dev/provider_commit_fault_test.go","pattern":"func TestProviderSealedTursoCommitRecovery"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run appliedLostAckPoisonsOldWorkerTest"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run durableCommitThenFenceThenLateAckTest"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run committingFailedCallbackCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem failed_callback_cannot_enter_commit","declaration":"Weaver.ProviderRpc.RequestWriteFence.failed_callback_cannot_enter_commit"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem applied_commit_without_ack_does_not_activate","declaration":"Weaver.ProviderRpc.RequestWriteFence.applied_commit_without_ack_does_not_activate"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem late_commit_ack_cannot_bypass_new_fence","declaration":"Weaver.ProviderRpc.RequestWriteFence.late_commit_ack_cannot_bypass_new_fence"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider[(]"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run individualHoldOnlyCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_provider_exposure_cannot_be_released"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem provider_exposure_strengthens_continuing_zero_trust"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerEnqueueBeforeCommitCrashCannotReplayPendingRange"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerCancellationAndReconnectRetainHistory"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run enqueueThenLostCommitRetainsUnknownTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem transport_history_preserves_original_hold"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderPartialRequestAndRestartRetainUnknownClaim"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run unknownRefundCounterexampleTest"}]},{"id":"ReservedAuthorityAdmission","witnesses":[{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run recoveryDoesNotRefreshUsageEvidenceTest"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn final_release_keeps_current_guard_and_unknown_commit_in_one_transaction"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run childOnlyPredicateDropsParentCounterexampleTest"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem continuing_uses_current_state_and_original_consumption"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem capacity_cannot_rebase_changed_floor"},{"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn waiting_capacity_does_not_hold_sql_or_authorize_after_publication"},{"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn pending_range_history_created_during_capacity_wait_cannot_be_replayed"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPositiveControlCompletesAfterCapacityReturns"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run returnedCapacityDoesNotAuthorizeStaleReleaseTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_backpressure_composition"},{"file":"crates/server/tests/unit/admission.rs","pattern":"async fn saturated_detached_execution_preserves_publication_and_observation_custody"},{"file":"go/dev/provider_capacity_test.go","pattern":"func TestProviderSaturatedExecutionPreservesRevocationAndObservation"},{"file":"dev/proofs/quint/AuthorityAdmission.qnt","pattern":"run sharedLaneStarvationCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_admission_composition"}]},{"id":"ConnectionCustodyBound","witnesses":[{"file":"crates/server/tests/unit/connections.rs","pattern":"async fn tcp_socket_owns_capacity_until_destruction_and_preserves_io_and_peer_identity"},{"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderPreTLSConnectionsAreBoundedAndExpire"},{"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderShutdownDestroysStalledTLSBeforeAcknowledgingExit"},{"file":"dev/proofs/quint/ConnectionAdmission.qnt","pattern":"run earlyReturnCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem provider_and_connection_composition"}]},{"id":"SourceIngressBinding","witnesses":[{"file":"go/dev/provider_source_test.go","pattern":"func TestProviderSourceIngressBindsCertificateCredentialAndMethod"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledCatalogRequiresExactSourceEpoch"},{"file":"go/dev/provider_capacity_test.go","pattern":"full operation ingress blocked new source session"},{"file":"crates/server/tests/unit/grpc_ingress.rs","pattern":"async fn aliased_or_empty_source_identity_is_rejected_before_serving"},{"file":"dev/proofs/quint/SourceIngress.qnt","pattern":"run forwardedCredentialCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem ingress_step_preserves_independent_custody"}]},{"id":"DurablePublicationDecision","witnesses":[{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn outcome_insert_failure_rolls_back_policy_schema_and_result_together"},{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn concurrent_same_identity_commits_only_one_revision"},{"file":"go/dev/publication_recovery_test.go","pattern":"func TestProviderPublicationLostReplyRestartAndHistoricalDecision"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run deletedOutcomeCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_and_provider_accounting_composition"}]},{"id":"OwnedSourceConnection","witnesses":[{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn cancelled_priority_wait_does_not_send_a_source_command"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn source_rotation_commits_before_queued_catalog_reads_recheck_identity"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run newCommandCanPrecedeOldReplyTest"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn completed_source_acknowledgment_returns_command_capacity"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run replyBeforeCapacityCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem command_ack_requires_returned_capacity"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn reused_source_connection_observes_other_writer_and_preserves_historical_result"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn disconnected_source_caller_keeps_capacity_until_original_sql_work_finishes"},{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn connection_reuse_rejects_an_unresolved_explicit_transaction"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run swallowedCloseErrorCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem owned_worker_and_publication_composition"}]},{"id":"FinalInvocationCancellation","witnesses":[{"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn cancellation_during_sql_wait_blocks_transport_and_keeps_spent_claim"},{"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn uncancelled_control_reaches_real_https_transport_once"},{"file":"dev/proofs/quint/DispatchCancellation.qnt","pattern":"run skippedRecheckCounterexampleTest"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run missingFinalCancellationCheckCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem cancellation_and_original_hold_composition"}]},{"id":"OriginalReleaseCapability","witnesses":[{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityBudgetHistoryChangeInvalidatesReleaseReadTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_plan_survives_batching"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn equal_batch_digests_cannot_transfer_release_between_original_nodes"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn release_encoding_cannot_change_after_preparation"},{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn release_capabilities_bind_plan_encoding_and_restart_session"},{"file":"dev/proofs/quint/ReleaseBinding.qnt","pattern":"run crossPlanCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem release_binding_and_execution_composition"}]},{"id":"SpecificSourceContracts","witnesses":[{"file":"crates/server/src/single_provider.rs","pattern":"bound: BoundSource"},{"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run governanceCannotReplaceGovernorTest"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run missingGovernorCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_cannot_replace_governor","declaration":"Weaver.PolicyBridge.governance_cannot_replace_governor"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governor_cannot_replace_governance","declaration":"Weaver.PolicyBridge.governor_cannot_replace_governance"},{"file":"scheme/governance/types.ss","pattern":"def GovernanceScopeContract\\s+\\(\\.cc \\(Record"},{"file":"scheme/gateway/contracts.ss","pattern":"def GatewayArtifact"},{"file":"t/gateway-contracts-test.ss","pattern":"def gateway-contracts-test"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityUncompiledSourceCannotRegisterTest"},{"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"},{"file":"t/gateway-contracts-test.ss","pattern":"module scopes use native POO Types and refuse evidence protocol hooks"}]},{"id":"GovernancePolicyProjection","witnesses":[{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrApprovalCannotOutliveExposureProjectionRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrCommitReplyLossAndReplayCannotMintAnotherTicketTest"},{"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn candidate_only_replay_cannot_register_for_a_real_predecessor"},{"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn replay_cannot_substitute_the_captured_predecessor"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem matched_replay_preserves_both_images"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run exactReplayPairSurvivesLostReplyAndCommitsOriginalTest"},{"file":"crates/ledger/tests/unit/source_authority.rs","pattern":"fn source_handoffs_and_old_workers_preserve_original_unknown_budget"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn consistent_whole_store_rollback_remains_a_local_authority_counterexample"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn residual_policy_schema_cannot_be_treated_as_an_empty_store_after_restart"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn first_enrollment_uses_all_durable_tables_without_temporary_aliases"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn committed_writer_before_enrollment_cannot_be_hidden_by_an_old_empty_read"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn callback_failure_after_enrollment_does_not_allow_a_replacement_identity"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem complete_catalog_refusal_preserves_original_state"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem source_enrollment_refusal_preserves_unknown_accounting"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run omittedProjectionEnrollmentCounterexampleTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateCatalogCommitMustReachDecidingGuardTest"},{"file":"go/dev/provider_source_authority_test.go","pattern":"func TestProviderPersistentSourceRotationLostReplyFencesExistingWorkerAndReissuedKey"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem retired_source_key_cannot_become_fresh"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_preserves_source_key_uniqueness"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run burnWithoutRetainedConfirmationCannotAdmitTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run cachedQualificationCannotAdmitWithZeroHeldProjectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run repairedProjectionDoesNotRecreateLostSendHandleTest"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_prefix_failure_atomically_rolls_back_burn"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_prefix_without_burn_projection_cannot_repeat_admission"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_burn_fenced_before_callback_keeps_original_unknown_exposure"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run confirmedRevocationAndHandoffRejectConsistentSourceRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run retainedRegistrationCannotReplaceAfterSnapshotRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run sameLengthArtifactReplacementCannotConfirmRetainedPrefixTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run wholeRetainedRootRollbackCanReplayQualificationCounterexampleTest"},{"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn identical_prefix_after_whole_store_restore_can_replay_dispatch_counterexample"},{"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn prefix_qualification_does_not_reconstruct_rolled_back_budget_counterexample"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run copiedRowsWithoutRecoveryQualificationCannotPublishTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateQualificationAfterRegistryAppendIsRefusedTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run recoveredNewOwnerRequalifiesOriginalArtifactTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run consistentAuthorityRollbackCanReplaySavedQualificationCounterexampleTest"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn stale_registry_read_and_reopened_worker_preserve_unknown_provider_exposure"},{"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn text_rendering_cannot_silently_replace_original_policy_ids"},{"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn actual_spec_replay_registration_persists_before_original_final_cas"},{"file":"go/dev/provider_policy_json_test.go","pattern":"func TestProviderControlNamedPolicyJSONRevocationAndRestart"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem finite_replay_does_not_certify_no_gain"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run observerRestartCannotRestoreReadCapabilityTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateRegistryReceiptAfterHandoffIsHistoricalTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run independentSnapshotRollbackResurrectsCredentialCounterexampleTest"},{"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn losing_verifier_metadata_cannot_downgrade_a_committed_served_profile"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem missing_verifier_cannot_downgrade"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run missingVerifierCannotDowngradeAfterRestartTest"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureComposition"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureRejectsFalseArithmetic"},{"file":"dev/proofs/cedar/SpecProofClosure.lean","pattern":"def proveClosedArithmetic"},{"file":"prod/policies/provider/ProviderReview.lean","pattern":"def entry"},{"file":"go/internal/specreview/producer.go","pattern":"Issue"},{"file":"crates/policy/src/qualified_delta.rs","pattern":"pub fn verify_qualified_delta"},{"file":"go/dev/provider_spec_review_test.go","pattern":"func TestProviderRealSPECReviewRevocationLostRepliesAndRestart"},{"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn historical_signature_only_nogain_is_not_semantic_qualification"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run signatureOnlyGainCounterexampleTest"},{"file":"dev/proofs/cedar/QualifiedReview.lean","pattern":"theorem qualified_execution_and_recovery_preserve_original","declaration":"Weaver.QualifiedReview.qualified_execution_and_recovery_preserve_original"},{"file":"crates/ledger/src/delta_registration.rs","pattern":"fn require_current"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"fn require"},{"file":"go/dev/provider_review_test.go","pattern":"func TestProviderReviewedPublicationLostRepliesAndRestart"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem reviewed_commit_composes_with_original_recovery"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run producerSignatureCannotReplaceQualificationTest"},{"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn consistent_snapshot_rollback_can_replace_local_registered_artifact_counterexample"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceLateCommitReplyAfterRotationRemainsHistorical"},{"file":"crates/ledger/tests/unit/publication_review.rs","pattern":"fn reviewed_prefixes_match_an_independent_model"},{"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn stage_review_requirement_and_legacy_final_cas_have_one_serial_order"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_registration_recovery_composes_without_releasing_unknown"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run latchedReviewCannotUseLegacyPublicationTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run configurationImageCannotErasePersistentRevocationTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registryAppendBetweenReadAndCASRequiresRejoinTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRollbackLostReplyRetainsUnknownConsumption"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem registrar_binding_reaches_final_cas"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run revocationBetweenValidationAndFinalCASTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run delayedIssuanceDecisionCannotReactivateOldEpochTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateRotationRecoversLostReplyAndPending"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateConfigRollbackReacceptsOldKeyCounterexample"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_recovery_keeps_original_constraints"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem durable_review_binding_survives_final_cas"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registrationLostReplyCannotPublishUnrecoveredProjectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run oldRegistrarCannotPublishAlreadyRegisteredArtifactTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderStagingLostReplyRetainsConcurrentPendingAcrossRestart"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRoleCredentialIsNotRegistrarIncarnationEvidence"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem reviewed_publication_keeps_recovery_contract"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run substitutedArtifactGetsOriginalRejectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run crossStoreReviewRollbackCounterexampleTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderPendingCommandSubstitutionAndHistoricalRecovery"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn typed_publication_does_not_yet_require_delta_evidence"},{"file":"scheme/policy/func.ss","pattern":"project-policy profile"},{"file":"scheme/policy/assets.ss","pattern":"read-policy-assets profile"},{"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"}]},{"id":"CompiledSourceStartup","witnesses":[{"file":"scheme/gateway/compiled.ss","pattern":"weaver_governance_ready_v1"},{"file":"crates/governance-build/src/application.rs","pattern":"pub fn approved"},{"file":"build.ss","pattern":"approved application root mismatch"},{"file":"crates/governance/src/program/compiler.rs","pattern":"pub fn initialize"},{"file":"crates/governance/src/catalog/configuration.rs","pattern":"pub fn from_configuration"},{"file":"crates/server/src/governance_deployment.rs","pattern":"async fn start_compiler"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRequiresRealInstallation"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"metadataAsInitializationCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem graph_membership_cannot_replace_initialization"}]},{"id":"GovernorSourceHandoff","witnesses":[{"file":"scheme/gateway/types.ss","pattern":"def GatewayProgram"},{"file":"scheme/gateway/program.ss","pattern":"def \\(make-gateway-program"},{"file":"t/gateway-source-test.ss","pattern":"program installation and close follow an irreversible lifecycle"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"caughtReentryPoisonsOuterDeliveryTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem program_result_composes_with_registered_original"},{"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"},{"file":"go/internal/controlplane/deployment_source_test.go","pattern":"func FuzzDeploymentSourceHasOneOwner"},{"file":"go/internal/controlplane/producer_deployment_test.go","pattern":"func exerciseProducerDeployment"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"deploymentCannotFallBackToFileTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem producer_deployment_keeps_registered_original"},{"file":"crates/server/src/grpc.rs","pattern":"async fn compile_source"},{"file":"go/internal/controlplane/source_compile.go","pattern":"func BootstrapProducer"},{"file":"go/internal/controlplane/approved_source_rpc_test.go","pattern":"func TestApprovedSourceMTLSBootstrap"},{"file":"go/internal/config/freeze_test.go","pattern":"func FuzzFrozenSourceDoesNotFollowCallerMutation"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem compilation_reply_keeps_registered_original"},{"file":"crates/governance/src/catalog/admission.rs","pattern":"pub struct ProducerCatalog"},{"file":"crates/governance/src/catalog/client.rs","pattern":"pub fn submit"},{"file":"crates/governance/tests/unit/catalog.rs","pattern":"changed_source_observations_and_fresh_names_cannot_select_original"},{"file":"crates/server/src/governance_owner.rs","pattern":"pub fn publish_producers"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"oldCatalogObservationStillCannotPublishThroughNewFenceTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"producer_selection_keeps_all_original_fields"},{"file":"crates/server/src/governance_owner.rs","pattern":"pub async fn start_governance"},{"file":"crates/server/src/grpc.rs","pattern":"pub async fn serve_grpc_with_runtime"},{"file":"crates/server/tests/unit/governance_owner.rs","pattern":"shared_owner_schedules_preserve_cleanup_and_terminal_admission"},{"file":"crates/server/tests/integration/governance_owner.rs","pattern":"actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"lateFactoryActivationCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_owner_join_preserves_cleanup"},{"file":"crates/governance/src/scheme_input/records.rs","pattern":"pub fn root_source"},{"file":"crates/governance/src/scheme_input/values.rs","pattern":"fn bytes"},{"file":"crates/governance/src/host/client.rs","pattern":"pub fn source_lane"},{"file":"crates/governance/src/host/owner.rs","pattern":"pub fn run"},{"file":"crates/governance/tests/unit/host.rs","pattern":"cancelled_running_work_keeps_its_slot_until_natural_return"},{"file":"crates/governance/tests/unit/host.rs","pattern":"active_compiler_observes_both_request_and_owner_cancellation"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSourceCancellationDrainsSchemeOwner"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"checkThenSendCloseRaceCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_host_delivery_requires_open_gate"},{"file":"crates/governance/src/binding.rs","pattern":"pub struct SourceExpectation"},{"file":"crates/governance/tests/unit/binding.rs","pattern":"coherent_replacements_cannot_change_original_content"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"unsafeSelfConsistentReplacementWitness"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"coherent_replacement_cannot_redefine_original"},{"file":"crates/governance/build.rs","pattern":"run_package_main"},{"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeQualificationStaysWithPreparedSchemeOwner"},{"file":"t/gateway-source-test.ss","pattern":"SDK field symbols and identifier strings cannot be interchanged"},{"file":"crates/governance/src/scheme.rs","pattern":"pub fn materialize_source"},{"file":"crates/governance/tests/integration/scheme_vm.rs","pattern":"actual_aa_capture_materializes_owned_data_before_vm_cleanup"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run unsafeEncodedBlobWitness"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem encoded_blob_cannot_claim_typed_capture"},{"file":"scheme/gateway/capture.ss","pattern":"Gateway capture requires one source emission"},{"file":"scheme/gateway/func.ss","pattern":"def \\(capture-governed-gateway"},{"file":"t/gateway-source-test.ss","pattern":"native PBT requires one completed emission"},{"file":"t/gateway-source-test.ss","pattern":"a late inherited sink cannot replace an active next capture"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run ignoredCaptureFuseCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem caught_duplicate_cannot_clear_capture_fuse"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"},{"file":"scheme/governance/capture.ss","pattern":"def \\(governance-profile-snapshot"},{"file":"t/governance-test.ss","pattern":"native PBT preserves every original assessment binding"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_assessment_snapshot_cannot_reuse_boundary"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run coordinatedLiveProfileLabelsCannotReplaceOriginalCaptureTest"},{"file":"scheme/gateway/func.ss","pattern":"assq 'open-patterns"},{"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"},{"file":"scheme/governance/types.ss","pattern":"def GovernanceAssessmentContext"},{"file":"scheme/gateway/func.ss","pattern":"same-node-set?"},{"file":"t/gateway-source-test.ss","pattern":"a false Governance assessment cannot emit a source handoff"},{"file":"t/governance-test.ss","pattern":"a typed ready assessment cannot omit an original blocking threat"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityChangedCompiledSourceCannotRecoverTest"},{"file":"scheme/policy/func.ss","pattern":"project-policy profile"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"},{"file":"t/integration/governed-control-test.ss","pattern":"def governed-control-test"},{"file":"go/internal/config/bundle_test.go","pattern":"func TestBundleRejectsSelectionAndCommitmentSubstitution"}]},{"id":"SourceStartupObservation","witnesses":[{"file":"scheme/gateway/provider-program.ss","pattern":"call-with-module-source-operation-measurement"},{"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeVerificationUsesOnlyPublicPackageEntries"},{"file":"crates/governance-build/src/program.rs","pattern":"build_program_archive_with_contract"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run releaseTagCannotRebaseCapturedSourceCounterexampleTest"},{"file":"go/internal/devrunner/retention_test.go","pattern":"func TestSchemePreparationFailureKeepsOriginalCutWithoutAmbientReceipt"},{"file":"go/internal/devrunner/retention_test.go","pattern":"func TestLateCleanupFailureCannotRetainPassingReceipt"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_preparation_cut_cannot_rebase_boundary","declaration":"Weaver.PolicyBridge.changed_preparation_cut_cannot_rebase_boundary"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run changedPackageMetadataCannotRebaseSnapshotTest"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run stalePreparationReceiptCounterexampleTest"},{"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"},{"file":"go/internal/controlplane/deployment.go","pattern":"trace\\(\"authority-reconciled\"\\)"},{"file":"scheme/gateway/func.ss","pattern":"source-selection-loaded"},{"file":"scheme/gateway/func.ss","pattern":"source-module-view-loaded"},{"file":"scheme/gateway/func.ss","pattern":"source-contracts-checked"},{"file":"scheme/gateway/func.ss","pattern":"source-advisory-derived"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"status=failed drain_ns"},{"file":"crates/governance/src/host/owner.rs","pattern":"scheme-owner-drop-begin"},{"file":"t/fixtures/governed-control.ss","pattern":"fixture-module-ready"},{"file":"go/dev/provider_control_test.go","pattern":"These unauthenticated diagnostics never replace readiness or exit checks"},{"file":"crates/governance-build/src/tooling.rs","pattern":"fn bind_package_sources"},{"file":"crates/governance-build/tests/unit/package_sources.rs","pattern":"fn native_package_inputs_follow_the_selected_store_without_overwriting_sources"}]},{"id":"PolicyCAbiIsInert","witnesses":[{"file":"scheme/policy/func.ss","pattern":"def \\(validate-policy-projection!"},{"file":"scheme/gateway/func.ss","pattern":"validate-policy-projection! projection"},{"file":"t/policy-test.ss","pattern":"real Rust preflight refuses cross-document syntax assembly"},{"file":"t/policy-projection-test.ss","pattern":"every named document precedes aggregate validation"},{"file":"crates/policy-ffi/tests/unit/validation.rs","pattern":"fn aggregate_validity_does_not_establish_complete_source_documents"},{"file":"crates/policy/tests/unit/decisions.rs","pattern":"fn default_deny_forbid_and_evaluation_error_are_fail_closed"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem incomplete_policy_document_cannot_admit"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run aggregateOnlyPolicyValidationCounterexampleTest"},{"file":"scheme/policy/source-bytes.ss","pattern":"def \\(cedar-source-utf8"},{"file":"t/policy-test.ss","pattern":"native PBT checks Unicode source bounds before the C ABI"},{"file":"crates/policy-ffi/tests/unit/abi.rs","pattern":"fn unicode_byte_limits_apply_to_each_actual_abi_region"},{"file":"crates/policy-ffi/src/abi.rs","pattern":"pub unsafe extern \"C\" fn weaver_policy_validate_v1"},{"file":"scheme/policy/cedar-ffi.ss","pattern":"def-C-lambda policy-validate/raw"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authoritySourceCommitNeverSendsTest"}]},{"id":"ControlActivationAcknowledgment","witnesses":[{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsStagingReplyLossAndRestart"},{"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlPublicationReplyLossCannotActivateOrRebase"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityLostReplyCannotActivateTest"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"}]},{"id":"ControlStreamRecoveryBinding","witnesses":[{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPartialRequestAndRestart"},{"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlCompleteStreamsShareBudgetAndRejectSDKRetry"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem profile_recovery_retains_original_hold"}]},{"id":"WorkspaceBenchmarkCoverage","witnesses":[{"file":"go/internal/devrunner/benchmark_test.go","pattern":"func TestBenchmarkEvidenceRequiresEveryCase"},{"file":"go/dev/workspace_test.go","pattern":"func TestCargoWorkspaceAndDevelopmentGates"},{"file":"crates/broker/benches/gateway.rs","pattern":"fn guarded_provider"},{"file":"go/dev/provider_bench_test.go","pattern":"func BenchmarkGatewayInspect"}]},{"id":"DurableRangeProgressJoin","witnesses":[{"file":"crates/ledger/src/stream_progress.rs","pattern":"fn message"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_message_cursor_cannot_hide_consumed_range"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_progress_cannot_release_old_writer_or_connection"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run restoredUnknownProjectionBlocksAdmissionTest"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run unknownResetDuplicatesRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unresolved_tail_blocks_admission","declaration":"Weaver.StreamingExecution.RangeProgress.unresolved_tail_blocks_admission"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem changed_progress_cannot_execute","declaration":"Weaver.StreamingExecution.RangeProgress.changed_progress_cannot_execute"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem joined_execution_preserves_safety","declaration":"Weaver.StreamingExecution.RangeProgress.joined_execution_preserves_safety"}]},{"id":"TursoAdmissionAtomicity","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"pub fn begin"},{"file":"crates/ledger/src/exposure_manifest.rs","pattern":"fn verified_members"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn failed_commit_releases_writer_and_poisoned_session_cannot_reenter"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn duplicate_claim_members_cannot_be_normalized_out_of_recovery"},{"file":"go/dev/workspace_test.go","pattern":"func TestProjectArchitectureStorageUsesMRRDataTursoOnly"},{"file":"dev/proofs/quint/TursoAdmission.qnt","pattern":"run tornCommitRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem storage_step_retains_admission_safety","declaration":"Weaver.RuntimeAdmission.Persistence.storage_step_retains_admission_safety"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem committed_consume_survives_reply_loss_and_restart","declaration":"Weaver.RuntimeAdmission.Persistence.committed_consume_survives_reply_loss_and_restart"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem commit_itself_does_not_send","declaration":"Weaver.RuntimeAdmission.Persistence.commit_itself_does_not_send"}]},{"id":"BoundedAdvisoryDerivation","witnesses":[{"file":"scheme/gateway/derivation.ss","pattern":"def \\(make-gateway-derivation"},{"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-gateway"},{"file":"t/gateway-derivation-test.ss","pattern":"generated source replacements agree with graph traversal and fresh results"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run derivedAdviceCannotChangeImageOrSpendTest"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run adviceAsOriginalCounterexampleTest"}]},{"id":"SessionWorkflowFrontier","witnesses":[{"file":"scheme/gateway/program.ss","pattern":"def \\(hard-fact-affected"},{"file":"go/dev/provider_hard_fact_test.go","pattern":"func TestProviderControlHardFactWithdrawalRestartAndABA"},{"file":"scheme/gateway/func.ss","pattern":"def \\(session-workflow-path"},{"file":"crates/server/src/governance_deployment.rs","pattern":"admits_session_workflow"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"fn bind_winner"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn provider_workflow_rechecks_prepared_floor_and_frontier_before_one_reservation"},{"file":"crates/server/src/session_workflow.rs","pattern":"async fn run_session_workflow"},{"file":"crates/server/src/single_provider.rs","pattern":"SessionTopology::prepare"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionWorkflowAutomaticallyResumes"},{"file":"scheme/gateway/func.ss","pattern":"def \\(governor-ready-steps"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"pub fn observe_workflow"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_workflow_observation"},{"file":"crates/governance/src/host/owner.rs","pattern":"cut_sha256=.*ready_sha256="},{"file":"crates/governance/src/program/compiler.rs","pattern":"topology_binding"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn governor_indices_reject_stale_binding_and_foreign_node"},{"file":"crates/server/src/session_workflow.rs","pattern":"DerivationOutput::Indices"},{"file":"crates/server/src/single_provider.rs","pattern":"topology.preopen"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn pack_governor_facts"},{"file":"t/gateway-governor-retained-test.ss","pattern":"packed facts are complete and bounded by the live binding"},{"file":"t/gateway-governor-retained-test.ss","pattern":"a compact cut must name the current binding"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"Governor transport %d expected"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched inner-join cut_sha256="},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched outer-join cut_sha256="},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionDAGConcurrentJoinAndRecovery"},{"file":"crates/ledger/src/provider_workflow_choice.rs","pattern":"fn record_result"},{"file":"go/dev/provider_workflow_choice_test.go","pattern":"func TestProviderControlSessionChoiceFromReleasedResult"},{"file":"crates/ledger/src/provider_workflow_nested.rs","pattern":"fn load"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn nested_workflow_rejects_stale_decision_and_keeps_winner_after_reopen"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSessionNestedChoiceAndParallelRecovery"},{"file":"scheme/gateway/func.ss","pattern":"WEAVER_TEST_GOVERNOR_CHANGED_SOURCES"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"unexpected Governor source replacement"},{"file":"crates/governance/src/host/client.rs","pattern":"weaver-governor-roundtrip"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"Governor roundtrip phases do not cover the call"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider_metering_with_deployment"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"a new frontier transaction must read the current deployment"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"prepare\\(tx, &proposal.predecessors, plan, current\\)"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn rooted_governor_indices_preserve_full_width_binding_and_all_64_candidates"},{"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-retained-governor-program"},{"file":"t/gateway-governor-retained-test.ss","pattern":"prepared nested rules agree with full fresh snapshots under replacement"},{"file":"t/gateway-governor-retained-test.ss","pattern":"prepared nested rules preserve source budget rejection and recovery"}]}] diff --git a/docs/50-59-research-program/59-provider-rpc/59.00-index.org b/docs/50-59-research-program/59-provider-rpc/59.00-index.org index 4a61ff49..12485e2a 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.00-index.org +++ b/docs/50-59-research-program/59-provider-rpc/59.00-index.org @@ -5,9 +5,9 @@ #+TITLE: 59.00 Default gRPC Provider Gateway #+LANGUAGE: en -[[file:59.87-spec-upgrade-and-delivery-plan.org][Current SPEC upgrade and ordered delivery gates]] aligns Rust and Lean on -the retained owner review and prioritizes standard Scheme-to-provider acceptance -before optimization or broader protocol coverage. +[[file:59.87-spec-upgrade-and-delivery-plan.org][Local Rust, Go and Scheme delivery plan]] starts with Rust and Go +regression, then verifies the native provider path with prepared and +source-linked Scheme packages. It retains the release gates for later qualification. [[file:59.86-release-zero-trust-integration.org][Release closure and Gateway Zero Trust integration]] follows the released POO owners through standard Scheme qualification, the maintained SPEC dependency, diff --git a/docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.org b/docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.org index 8cb2015b..ec73e8d7 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.org +++ b/docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.org @@ -1781,6 +1781,152 @@ execution budget. The ordinary source RPC remains the explicitly trusted administrative profile; full semantic-adapter restrictions on that profile are not newly claimed by the startup mechanism. +** Deployment paths for Weaver's Scheme application + +The Weaver checkout supplies the initializer +=hardenedlinux/weaver/scheme/gateway/provider-program= in +=scheme/gateway/provider-program.ss=. Use Build Packages and the +=scheme-program= server feature with both application settings at build time: + +#+begin_src sh +export WEAVER_GOVERNANCE_APPLICATION=hardenedlinux/weaver/scheme/gateway/provider-program +export WEAVER_GOVERNANCE_APPLICATION_SOURCE="$PWD/scheme/gateway/provider-program.ss" +cargo build --locked --release -p weaver-server --bin weaver-server --features arrow,scheme-program +#+end_src + +Put generated qualification data under =.cache/weaver-deployment-qualification/=. +For a persistent local instance, use an explicit data directory such as +=.data/weaver/=. For a Linux service, =/var/lib/weaver/= is the recommended +default layout. An installation with an assigned persistent volume may +choose a different root. Keep the catalog and the ledger at separate paths +within that root and grant access to the service account. + +| Process | Existing setting | Example | +|---------+------------------+---------| +| Rust authority | =WEAVER_GOVERNANCE_CATALOG= | =/var/lib/weaver/governance/catalog.json= | +| Rust authority | =WEAVER_DB= | =/var/lib/weaver/weaver.db= | +| Go Control | =WEAVER_CONTROL_PRODUCER= | Exact =name= of a catalog entry | + +A deployment launcher can read its own =weaver.toml= and export these +settings. Weaver's two native entry points read the environment, and the +catalog itself uses the existing strict JSON decoder. The producer and +=WEAVER_CONTROL_CONFIG= selections are mutually exclusive. Retain the +existing TLS, authority credentials and listener settings for each role. + +Keep the Scheme package library from the same release build with the +server image. The linked C ABI provides the executable bindings, and +Yuanxu's runtime source Reader uses the Gerbil library interfaces to +resolve module imports during preparation. Set =GERBIL_PATH= to the +deployed Gerbil prefix, including its package source store. Put the +release's package library on the native =GERBIL_LOADPATH= before the +SDK library. This keeps source preparation bound to the deployed +release and its selected packages. + +The built-in provider program derives =init.ss= from the source path +recorded by Gerbil during compilation. Keep the selected Weaver source +tree available at that recorded path when deploying this entry point. + +** Development validation and release performance qualification + +The long repeated-cold-start campaign and its proposed fixed-shard replacement +are withdrawn from the active development plan. Retain the raw failed attempts +and their original verdicts. Withdrawal does not turn an incomplete or failed +cohort into acceptance. The dedicated shard entry and statistical CLI introduced +for that plan have been removed; the existing native Go integration entry remains. + +The primary Governor measurement starts after Control readiness. Repeating +whole-process cold preparation for every hot-path observation makes the dominant +execution cost unrelated to the intended contrast. The choice of 200 blocks was +not supported by an explicit effect-size, variance and confidence calculation. +Freezing that number did not establish that it was an appropriate design. +Distributing the same work across more runners would not correct this mismatch. + +Use three distinct scopes through the existing owners and public entry points: + +1. Cold preparation: build the release once through Build Packages and the linked + C ABI. Measure process startup, Reader preparation, source/version admission, + object preparation and activation separately. Diagnose one bounded original + request before repeating a campaign. Compilation is a separate build cost. +2. Prepared-owner performance: compare fresh and retained derivation over the same + exact source/fact snapshots inside an already prepared owner. Report queue, + conversion, FFI, ASCENT setup/run and ledger costs separately from preparation + and shutdown. Repeated requests are within-owner observations, not independent + process replicas; the final analysis must retain that clustering. +3. Native semantic regression: run the existing concurrent claim, complete release, + selected-branch join, restart, withdrawal, ABA and source/version refusal cases. + Keep four workers and the existing 12-second recovery / 15-second natural-exit + bounds. Preserve failures and natural-exit evidence. These cases establish + behavior; repeating each case hundreds of times is not a tail estimate. + +For a focused source-preparation diagnosis, the built-in provider can enable +=WEAVER_TEST_SOURCE_PROFILE=. It uses Core's existing +=call-with-module-source-operation-measurement= with stage accounting and +reports the private scalar table after capture returns or throws. It installs +no source observer or admission callback. The flag is disabled by default. +Nested stage spans are inclusive and must not be summed as disjoint costs. +The VM allocation account is signed runtime accounting, not physical allocation. +Instrumented output is diagnostic evidence, not an uninstrumented latency claim. + +Core's existing =GERBIL_BUILD_VERBOSE=2= trace separates compiler tool +imports, catalog traversal and source enrollment. The linked Weaver request +identified =building/build-projection= as the largest root import during +Reader bootstrap, even though the request performs no build. The candidate +scope is the runtime catalog only. The complete Core bootstrap spec and its +build product selection must retain all roots and native source checks. + +An isolated runtime catalog candidate passed the ordinary Core build and a +focused check that common entries retain the same native Context identities. +It did not pass the maintained publication gate: its test import exceeded +the existing idle limit before assertions, while the unmodified baseline +completed that gate. This is a refused candidate, not a source mutation +rejection or a measured speedup. Adoption still requires the original Core +resolution and projection gates, real downstream qualification, and the +linked Weaver native cases under their existing limits. + +First repair a reproducible defect using a focused bounded native case. A broader +performance campaign starts only after correctness and preparation are stable, +with a justified independent-replica count, within-owner request count, treatment, +minimum effect, confidence method and total execution budget preregistered. +Do not retry an unchanged failing image to obtain a favorable cohort. Do not use +small diagnostic samples as proof of a production p99 improvement. Record site +approval and deployment gaps separately from local Snake Oil validation. + +Freeze the measured join, offered arrival schedule, request mix, observation +window, maximum outstanding work, refusal rule and total campaign budget before +collecting comparison data. Separate first ASCENT open from subsequent decisions +within the prepared-owner window. Require matching Governor input and ready-node +digests at the measured join, alongside the existing source and release checks. +An incomplete wave or a mismatched cut remains in the run record and fails the +matching gate. Keep inner and outer join observations separate within each +owner block. + +For a fixed latency threshold, an exact one-sided 95% upper bound with zero +violations is =1 - 0.05^(1/n)= for =n= independent Bernoulli observations. +It takes at least 299 such observations to put that bound at or below 1%. +Correlated decisions in one owner cannot be substituted into that calculation +as independent observations. A paired p99 comparison instead needs a sample +size and interval justified for its owner and time-window clustering, observed +tail support, effect size, and allowed error. Use warm traffic to collect the +within-owner distribution and preserve owner/window boundaries in analysis. +Treat refusals, timeouts and shutdown failures as separate acceptance gates; +retain the corresponding attempted operations and do not drop them from the +cohort. If the frozen workload and time budget cannot support the selected +interval, report the observed tail as descriptive and leave the p99 gate open. + +The linked application currently defaults to fresh derivation on one Scheme +owner. Retained derivation remains a qualification setting pending the formal +gates. The sealed single-provider DAG prepares before activation, and a +subsequent authenticated source replay returns the prepared binding after a +current-authority check. Continue evaluating Actor or multi-VM execution when +owner traces show active preparation competing with derivation, or a repeated +queue or FFI bottleneck on the admitted workload. + +The pull request Scheme job runs one pass of the existing native correctness +suite with four Go test workers. Its selector explicitly skips +=TestProviderControlGovernorPerformance= even when the caller sets +=WEAVER_TEST_GOVERNOR_COHORT=. The original single-wave entry remains available +for reproducing historical diagnostics. + ** Governor release preregistration Protocol prepared. Site evidence, the execution selector and the statistical @@ -1859,6 +2005,30 @@ the site provides both. Freeze the numeric sample plan once those inputs support it. The default remains fresh derivation on one Scheme owner while qualification is pending. +** Catalog installation + +Agent Gateway provides an operator-facing example of explicit file selection +and read-only configuration mounts. Praxis uses the same validation path +for its offline check and startup, and builds a new pipeline before swapping +it in. [[https://agentgateway.dev/docs/standalone/latest/documentation/setup/update/][Agent Gateway configuration delivery]] +[[https://github.com/praxis-proxy/praxis/blob/70f900cbff41124c9ac22dab504d63a239e0d4cb/docs/operating/configuration.md][Praxis configuration]] + +Deliver each reviewed catalog version as a read-only file. Validate the +candidate through the native startup entry, then verify the source binding +and activation outcome through the existing authenticated Control entry. +A deployed source change still goes through Weaver's authority and ledger +fences. The catalog is a startup input, and changes on disk have no activation +effect until an explicit deployment operation consumes them. + +Generate a catalog from the existing approved =SourceData= for the site +and the matching source authority epoch and credential fingerprints. The +credential value and private key belong to the deployment's credential +configuration. Publish the exact catalog bytes reviewed for that instance. +Record the catalog digest, application module and source revision, SDK +revision, server image digest, and site approval and activation records +together. A catalog generated by the native integration entry binds its +test authority and loopback endpoints and can accompany that run's receipt. + ** Evidence and retained gaps The first graph attempts failed during metadata import: importing a module diff --git a/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org b/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org index ac1df10b..06e433df 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org +++ b/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org @@ -6,12 +6,2218 @@ #+LANGUAGE: en #+OPTIONS: toc:2 -* Active priority - -Deliver the Rust, Go and Cedar execution path first. Scheme reader/bootstrap and -prepared-scope optimization is being handled by its upstream owner; consume that -work only after it is ready. Keep current Scheme interfaces and dependency pins. -See the current Rust/Go/Cedar delivery section below for this implementation. +* Runtime checkpoint for architecture review + +This checkpoint submits the current Runtime improvements for review. It does +not qualify the submillisecond target or promote retained execution defaults. +Scheme/POO and ASCENT retain planning and inference; Rust retains deciding +authority, exact source/currentness checks, reservation and final effects. + +The prepared nested candidate reduced the fixed four-worker owner's P99 from +3.787--4.132 ms to 3.419--3.605 ms. The original target remains below 1 ms. +GC attribution and the topology-bound program specialization are recorded +below, alongside unfavorable controls and the unchanged eight-cell Gateway +gates. The module-native replacement property, source-budget rejection, +26 governance library tests, SysML checks and sequential restart/withdrawal/ +cancellation controls passed. Both four-way source readiness waves failed +before Governor derivation under the unchanged CompileSource deadline. + +Further performance work is deferred for architecture review. Existing +10-second CompileSource, 12-second recovery and 15-second drain limits remain. +Local qualification does not establish exact-head GitHub CI or production +approval. Generated execution evidence remains outside versioned source. + +Submission checks on the staged snapshot passed the controlplane race tests, +focused devrunner evidence/source-integrity controls and the architecture/ +requirement-trace checks. The complete devrunner race invocation exceeded its +90-second submission-check limit; it is not counted as a full-suite pass. + +* Runtime delivery plan + +** Execution from a published plan + +Prepare the immutable execution inputs at publication. Scheme and POO +own the declarative plan, source and profile projection, and ASCENT +owns derivation over Workflow topology and facts. Rust owns the +validated execution representation, transaction scheduling, Cedar +evaluation and effects. Publish owned Rust data through the current +typed boundary, keyed by the exact catalog version, source revision +and fence, reviewed Policy digest, profile digest and plan commitment. +Use the existing Go static and dynamic projections as ingress bindings. + +Today the broker has separate enqueue, consume and dispatch steps. +Consume loads and decodes the queued plan and then selects a route, +checks its authority and proves the original claim. The first runtime +candidate carries an immutable plan and commitment across the existing +enqueue-to-consume handoff. Reuse the exact encoding already produced +by enqueue. Consume checks both the queued digest and the stored bytes +inside its transaction, then joins current authority. The stable plan +digest excludes the observation revision and fence, so test a byte +mismatch with the same digest. A miss or restart uses the existing +durable decode path. Prepare and reuse parsed Policy and +immutable Cedar inputs with exact publication identity. Invoke Cedar +with live facts for each effect. Keep the current authority checks, +claim, shared exposure, revocation barrier, affine send and unknown +outcome handling in their deciding scopes. + +For Workflow, retain the topology and rule program in the existing +Governor owner. A wake applies the changed facts from the durable cut +and returns ready node identities with that cut. Rust joins the +identities to prepared plans and rechecks the frontier, claim and +reservation together. The retained owner can be reconstructed after +restart from the durable frontier. Measure complete-cut transfer before +replacing it with deltas, then compare identical cuts and ready sets +with the fresh path. Use the existing owner for that comparison. + +Qualify local execution phases and upstream elapsed time separately. +Use the existing ready-frame envelope in =ProviderEgressReadyBudget= +for local egress, and keep request-to-first-frame, throughput and the +registered eight-case limits for the complete path. Test the first +candidate with exact-source and stale-fence controls, duplicate claim, +withdrawal, unknown outcome, restart and bounded backpressure before +expanding the optimization to dispatch or release. Keep cold package +build and CompileSource measurements in the lifecycle record. + +** Measurement and current evidence + +Qualify steady-state execution on published objects. Reuse the maintained +=bench-execution= entries for direct Rust versus Go, admission overlap and +streaming. Record the optimized image, source state, four-worker workload, +host observations and complete receipts. Prepare the store, publish sources +and establish channels before timing requests. Keep CompileSource, recovery +and natural exit as separate lifecycle gates at 10, 12 and 15 seconds. + +Record request-to-first-frame, inter-frame and complete-stream latency +separately from the Rust queue-to-client interval. Compare shared and +independent domains and measure immediate and paced SSE separately before +changing batching. Attribute Rust admission and release to queueing, lock +wait, transaction hold and output backpressure. Compare Go's ordinary route +with the dynamic catalog path, including versioned catalog decode, selection +and task registration. Reuse immutable projections under exact identity and +retain fresh current-authority checks at the deciding transaction. + +The execution evidence reader records the current transaction timing fields. +WAL reports no MVCC scheduler grants. In MVCC, a provider transaction +records a domain grant and a publication transaction records a global +grant. Each deciding transaction retains its separate authority span. +The header-delay comparison requires all three released events and one +guarded first-frame callback for the committed response snapshot. The +scheduled encoding report counts delivery revalidation scopes and emits +their latency percentiles only when the run observes such scopes. + +Qualify Workflow separately on matched complete-release, hard-fact and DAG +inputs. Partition frontier observation, owner wait, rooted FFI, ASCENT +preparation and evaluation, and durable claim/reservation. Retained state +must preserve withdrawal, inactive-branch isolation and the one-time join. +Use the existing owner and compare mailbox costs on the actual workload +before changing its architecture. + +The local release diagnostic uses Weaver's linked provider program and the +existing nested Workflow entry. Run one four-owner A/A wave and one ABBA +fresh/retained wave, with the same Rust image and matched Governor cut and +ready-set digests at both joins. The owner trace distinguishes a Governor +FFI decision from hard-fact impact work on the same mailbox. Report the +first retained open separately from subsequent replacements. The local +retained comparison removes repeated rule construction at the measured +joins. Its observed owner queue is small relative to rule setup, frontier +observation and claim. Retain the existing mailbox and keep retained mode +available for the formal site gate in 59.64. The local sample has two +owners per treatment. Use it for phase attribution and run the original +withdrawal, restart and inactive-branch controls with both derivation modes. + +The current linked release completed one fresh A/A wave and one +fresh/retained ABBA wave with matching input and ready-set digests for +both joins, including across the two waves. The retained owner paid +the initial rule preparation on open and reused its session at the +measured joins. The observed owner wait was measured in microseconds, +while fresh rule preparation at the joins was measured in tens of +milliseconds. Use the bounded sample for phase attribution and keep +the same owner. On that same image, both derivation modes passed +hard-fact withdrawal and restart through A→B→A, nested recovery and +inactive-branch isolation, and source cancellation with owner drain. +The deployment-site statistical gate remains separate. + +*** From Scheme decisions to Rust execution + +The local release timings distinguish rule preparation from a live decision. +Fresh join rule setup took 74–77 ms. Retained joins took 0.61–0.79 ms in +the rooted FFI call, which includes the ASCENT evaluation. Owner queue +wait was 7–8 µs. On those joins the ledger frontier read took 4.60–5.61 ms +and the claim transaction 2.10–2.93 ms. The first retained open still +paid about 77.5 ms of setup. These timings describe Workflow joins on a +bounded matched cohort. Provider request-to-first-frame is a different +clock and includes upstream and transport work. + +Keep ordinary provider dispatch on the Rust projection path. The existing +first-frame traces put some hundred-millisecond excursions in Rust +enqueue or transaction preparation, with a large wall-time versus +thread-CPU gap. Separate scheduler wait, ledger begin and hold, and +provider transport for each ranked request. Move deterministic preparation +to publication, then compare the same immutable projection through +direct Rust and Go ingress. Keep live Cedar and durable admission in +their current authority scopes. The ordinary dispatch and response-frame +paths do not require a Workflow Governor round trip. + +*** Prepared Governor and Rust consumption + +The prepared-index release used the SDK revision pinned by Weaver and +the same four-owner release image in its fresh/retained wave. Across +the two owners per treatment and the two joins, fresh ASCENT setup +took 75.7–79.1 ms. The retained joins spent 0.74–1.01 ms in the rooted +call, 111–155 µs building the Scheme input, and 6–12 µs waiting for the +owner. The first retained open spent 82–85 ms in setup. This is local +phase attribution. The upper end of the retained call alone already +exceeds the sub-millisecond computation target. + +Use =ArchitectureEvolution::DerivePreparedGovernorCandidates= for the +next comparison. The existing single-provider =Prepared= object +already holds the Rust node and predecessor indexes. Before the first +live graph wake, prepare the matching Scheme topology and ASCENT +program on the existing owner. Bind them to the exact activated +publication and owner epoch. Keep the first-open cost in preparation +and record it separately. On wake, pass one coherent mutable cut +through the rooted ABI. The cut contains complete-release evidence, +availability, pending nodes and structured selector results and +decisions. Return candidate indices in the namespace of that +publication. Rust checks the binding, resolves the indices against +its prepared plans in compiled order and sends the candidates through +the existing transactional admission path. Claim and reserve still +depend on live authority and exact release, fact and frontier evidence. + +Compare the existing retained complete-cut call against the prepared +topology and full mutable cut on the same release. Match the semantic +cut, ready nodes and selected predecessors before comparing times. +Time coherent cut to resolved Rust candidates as a single interval, +including queue, marshalling, inference and resolution. Time release +to observation and release to committed reservation separately. +Record rejection of an old publication or owner binding alongside +withdrawal, restart, A→B→A, duplicate wake and one-time join controls. +Use a full current cut after rebind. Consider deltas only if this +comparison attributes meaningful cost to transfer or relation +replacement. + +The retained Scheme owner now projects the static node and selector +topology once per distinct graph. Every wake replaces the full set of +mutable relations. A changed graph or a failed derivation discards +the projection and session together. The retained compact transport +binds the topology from the activated Rust prepared object on its +first graph wake. Subsequent calls on that owner carry the binding +number and the complete mutable relations. The owner rejects a compact +call whose binding is missing or stale. Compact results echo the binding +and carry indices into the prepared Rust plans. Rust checks the binding +and bounds before resolving them in compiled order. Full-cut mode +retains named results. The opt-in activation preparation binds the +topology and opens one retained session with an empty cut after +matching the durable publication receipt. Source authority is checked +again after the wait. The first live decision still consumes the +complete current ledger cut. Separately, +reduce the ledger observation and reservation cost using their own +phase traces. The provider transport and frame release paths continue +to use their existing latency and throughput gates. + +The linked release passed the four-owner WAL A/A and fresh/retained +waves and the four-owner MVCC fresh/retained wave. Both join cuts and +ready sets matched the previous release. Both modes passed withdrawal, +A→B→A, nested restart, inactive-arm isolation and owner cancellation. +The observed maxima for CompileSource, nested scenario recovery and +wave drain were 8.79 s, 7.98 s and 1.55 s. Across the four retained +WAL join observations, the rooted call took 1.09–1.96 ms and input +construction took 201–281 µs. This release has no retained-without- +projection-cache arm. The result qualifies behavior and leaves the +sub-millisecond computation target open. + +The next WAL ABBA compared full and compact transport on one release, +with ASCENT retained in both arms. Each arm contributed two owners and +four matched join observations. FFI input construction median moved +from 170.3 to 68.3 µs. Rooted call median moved from 0.713 to 0.630 ms. +The two joins matched their semantic cut and candidate digests in +both arms. This cohort does not establish a P99. The separate MVCC +wave failed trace completeness when a shutdown write split an ASCENT +record. Preserve that failed wave and rerun the release gates after +the shutdown trace emits a complete record in one write. + +The repaired release passed all four-owner WAL and MVCC waves, +both modes' lifecycle controls, and the linear, parallel DAG and +conditional entries. All 16 instrumented trials retained complete +shutdown records. The observed WAL lifecycle maxima were 7.02 s for +CompileSource, 9.69 s for nested scenario recovery, and 1.20 s for +natural drain. In the repaired WAL ABBA, input construction median +moved from 126.9 to 69.7 µs and rooted call median moved from +0.789 to 0.803 ms. The repeated evidence supports a reduction in +input construction on the local workload. The compact arm's longest +join sample was 1.051 ms across owner wait, input, rooted call and +output, before Rust candidate resolution. Keep the local P99 target +open and measure direct candidate indices separately. + +The next WAL ABBA held compact input transport and retained ASCENT +constant and changed the result representation. Both joins matched +the original cut and named candidate digests. Across four join +observations per arm, observed-cut to resolved Rust steps median +moved from 1.061 to 0.957 ms. The longest indexed sample took +1.587 ms, including 1.354 ms in the rooted Scheme call and 7.5 µs +in output conversion. The sample supports direct, checked plan +indexing and leaves the sub-millisecond P99 target open. +WAL, MVCC, recovery, withdrawal and the linked Scheme binding +controls passed. The Rust package test reached its 180-second build +limit before running. A separate rustc control ran the same bounds +and binding validator in isolation. The later current-cut qualification ran +the original package Governor filter successfully. Its binding/index +negative control and owner capacity/shutdown control both passed. Preserve +the earlier build timeouts. + +The next compact indexed comparison moved the first ASCENT open to +verified activation. The two WAL control owners spent 80.68 and +138.00 ms on their first live resolution. The two preopened owners +spent 0.95 and 1.54 ms there, with 79.83 and 82.29 ms recorded +separately for activation preparation. Both joins matched their +cut and candidate digests in WAL and MVCC. The move isolates the +first-open cost from live resolution. Keep the mode opt-in while +the complete deployment gate remains open. + +The next compact comparison held activation preparation and indexed +results constant. On the hot path, the candidate sends the complete +seven-relation cut in one bounded bytevector using indices from the +active binding. The first bind still carries the full topology. The +named and packed arms matched the two join cuts and candidate +digests in WAL and MVCC. In the four WAL join observations per arm, +input construction median moved from 86.1 to 28.1 µs and cut-to-Rust +resolution median from 0.980 to 0.871 ms. The longest packed sample +took 1.772 ms, including 1.315 ms in the rooted Scheme call. Keep the +packed mode opt-in and the sub-millisecond P99 target open. The +retained ASCENT session accepts batches of changed source relations. +Compare a complete cut against a change-only replacement within the +same verified binding, including retractions, before choosing it. + +The following opt-in comparison uses the installed ASCENT session's +batch replacement and clean-result APIs. Both arms receive the complete +packed cut. The candidate compares all seven dynamic relations within +the retained binding, replaces changed relations, and reuses a completed +result for an identical input. The owner records its previous input only +after successful completion and clears it on binding replacement or an +exception. Effect admission still checks the current ledger. + +The four-owner WAL ABBA wave observed seven replacements per live +baseline decision. Candidate decisions replaced zero to four relations. +Two identical-input decisions reused the clean session. The two join +digests matched in WAL and MVCC. A/A, fresh/retained, withdrawal, +restart, A-to-B-to-A, owner cancellation, linear, parallel and conditional +Workflow controls and the two SysML checks passed on the same release. +The Scheme controls cover empty-relation retraction and duplicate cuts. + +In four WAL join observations per arm, complete-cut resolution median +was 5.267 ms for full replacement and 3.977 ms for changed replacement. +ASCENT run median was 1.415 and 1.189 ms. Maximum resolution was +7.530 and 14.120 ms. The longest candidate observation included 6.657 ms +of owner wait and 1.482 ms in the Scheme call. These small descriptive +samples leave the sub-millisecond tail gate open. Keep changed +replacement opt-in. Next attribute the remaining resolution time around +owner submission, response delivery and Tokio resumption before +choosing a scheduling change. + +The next release records continuous timestamps across capacity admission, +submission, owner queue, derivation, owner diagnostics and reply resumption. +Rust resolution also records preparation, the complete asynchronous call, +and candidate validation. Each returned call must have exactly matching +phase sums. Shutdown may cancel the final wake after owner derivation +finishes. Record derived, replied and resolved counts separately and check +the complete calls used by both admitted joins. + +The first local trace-count assertion incorrectly required these three +counts to match at shutdown. Preserve that failed wave. The corrected +four-owner A/A, fresh/retained and changed-source ABBA waves and MVCC +wave passed against the same release image. The source lane's ten unit +controls passed, including capacity, cancellation and terminal closure. +Reuse the same-image withdrawal, restart, owner drain and Workflow +controls with their origin and content digests. + +In four WAL join observations per arm, full replacement resolved in +0.892 ms median and 1.107 ms maximum. Changed replacement resolved in +0.791 ms median and 0.920 ms maximum. Its median owner queue was +14.625 µs, owner derivation 664.438 µs, owner diagnostics 29.333 µs, +and reply resumption 7.417 µs. Median input construction was 23.833 µs +and the rooted Scheme call 594.042 µs. Individual phase medians describe +different observations and must not be summed into an example call. + +The same candidate's frontier-read median was 1.979 ms and claim +transaction median 2.567 ms. Prioritize attribution and optimization of +those ledger operations while retaining the current source, receipt and +claim checks. Keep the changed-source mode opt-in. Four observations per +arm leave the P99 gate open. + +The next ledger candidate reads and decodes metering deployment once +within each Workflow observation transaction. It loads the value after +the first complete node proves its response release and also retains an +absent deployment for that transaction. Each complete node still checks +its own quota reservation and quote with the existing metering owner. +The value is discarded with the observation. The deciding admission +entry continues to read its deployment independently. + +The three focused Workflow ledger tests and both SysML checks passed. +The complete ledger integration suite passed all 136 tests with four +test threads in 20.27 seconds. Its first sandbox run passed 133 tests +and denied the three real TCP tests permission to open sockets. +Preserve that result alongside the full run with local network access. +The new fault control changes deployment after a successful observation, +requires the next observation to reject the damaged record, restores +deployment and requires observation to succeed again. The candidate +passed four-owner A/A and fresh/retained, both withdrawal and owner +cancellation modes, and linear, DAG and conditional native controls. + +The packed WAL and MVCC cohorts failed the original ten-second +CompileSource gate before reaching steady-state measurement. Module +view preparation took about 7.0–7.5 seconds wall time and 4.4–4.7 seconds +CPU time in the sampled owners. The twelve-core host's recorded +one-minute load average rose from 7.22 before the baseline waves to +31.07 afterwards. These observations leave attribution and full +qualification open. Preserve the failed cohorts and the original +budgets. Complete qualified runtime comparisons when source preparation +can pass that gate. A metering latency claim also requires an isolated +comparison against rereading deployment. + +The next admission candidate reuses the current hard-fact cut already +read by its deciding transaction. Admission previously read that cut to +classify a governed node, then progression preparation read and decoded +the same feed again. Both preparation entries now read their own current +cut and pass it into the private preparation routine. Admission compares +the resulting complete progression with the retained proposal before +reservation. Availability, source authority, released predecessor +responses, current decisions, domain exposure, Policy and budget checks +continue through their existing owners. + +The candidate release built and passed all 136 ledger integration tests +with four test threads in 26.81 seconds, including the existing stale +fact prefix, withdrawal, duplicate claim and restart controls. Both +SysML checks passed. The first build exposed an ownership error from +moving the cut in a Rust match guard. The corrected implementation +performs preparation in the match arm and retains the same conflict +result. Preserve the initial compiler diagnostic. + +During package qualification, the twelve-core host recorded one-minute +load averages of 38.20 during the build and 19.09 after the ledger suite. +At the subsequent native run its one-minute load was 6.85. The source +diff, input digests and staged release hash matched the built candidate. + +That release passed WAL four-owner A/A, fresh/retained and packed +changed-source ABBA, the four-owner MVCC wave, both modes of withdrawal, +A-to-B-to-A, restart and owner cancellation, and linear, parallel and +conditional Workflow controls. Both joins matched their reference cut +and candidate digests. The recorded WAL CompileSource maximum was +6.919 seconds, nested recovery maximum 10.338 seconds, and natural +drain maximum 1.213 seconds, within the original 10/12/15-second gates. +The two selected Rust Governor package tests also passed. + +The same-image changed-source arm resolved its four join observations +in 0.917 ms median and 1.097 ms maximum. Full replacement was +0.843 ms median and 1.187 ms maximum. Retain the changed-source +opt-in and the open sub-millisecond tail gate. The candidate's +frontier-read and claim-transaction medians were 1.938 and 2.450 ms. +These observations qualify behavior and describe this release. They +do not isolate the latency effect of metering reuse or the removed +feed reread. A causal latency claim requires a same-image read-strategy +comparison. + +1. Prepare the published Workflow once. Rust builds node-to-plan and + predecessor indexes with the compiled original and uses them after + exact publication activation. A Session wake borrows the prepared + plans for the ledger observation. It resolves returned candidate nodes + in compiled path order and copies only their plans and active + predecessors for admission. Bind the retained Scheme topology and + ASCENT program to the exact activated Workflow. Measure activation + and first open separately from steady-state wakes. +2. Shorten the durable observation. The batched family transaction reads + availability and receipts for the requested node set together with the + existing fact cut and branch decisions. It checks each completed node's + release and metering evidence and reconciles shared exposure and history + once in that transaction. Preserve exact + plan commitments, the fact floor and snapshot, and coherent branch decisions. + Measure database reads and transaction time separately from the + Rust projection and FFI. The admission transaction remains the + deciding check for current releases, facts, winner, claim and reserve. +3. Send changing relations to ASCENT once the observation is cheaper. + First compare a full set of mutable relations with the existing + complete-cut call. Introduce deltas only when measured transfer or + evaluation warrants them. A delta names its exact publication, + base and target cuts, including retractions. A stale base, owner + restart or publication change triggers a full coherent observation. + Compare selected arms and ready sets for equal cuts before comparing + timings. Reuse the existing mailbox and rooted ABI for this work. + +Keep the existing linked four-owner Workflow entry for the comparison. +Use one optimized image, a fixed nested Workflow and the same +release/fact sequence. Require matching cut and ready-set identities, +one-time joins and claims, no inactive-arm effects, and the original +withdrawal, restart and A→B→A controls. Report release-to-ready and +release-to-durable-claim separately. Evaluate sub-millisecond P99 +for the prepared local computation from an already observed cut to +Rust candidate resolution. The ledger observation, durable claim and +complete provider path each get their own measurements. The existing +ready-frame and provider acceptance budgets still apply to their +respective clocks. + +The first frontier batch kept both retained join cut and ready-set digests +equal to the archived linked Workflow reference. Four retained join frontier +observations ranged from 3.88 to 4.72 ms in the candidate, versus 4.60 to +5.61 ms in the archive. These are separate release images. Use them to +verify the observed sets and guide a same-image latency comparison. +The candidate passed the four-owner A/A and fresh/retained waves, both +derivation modes for withdrawal and A→B→A, nested recovery, inactive-arm +isolation and owner drain, and both SysML checks. The measured maxima for +CompileSource, nested scenario recovery and wave drain were 9.73 s, +7.85 s and 1.25 s respectively. + +The prepared Rust indexes passed the same four-owner waves with matching +cut and ready-set digests against the batched frontier reference. The +linear, parallel DAG and conditional Session entries passed on the +candidate image, including malformed structured-result rejection. +Both derivation modes passed withdrawal, A→B→A, nested restart, inactive +branch isolation and owner drain. CompileSource, nested scenario +recovery and wave drain peaked at 6.18 s, 7.69 s and 1.13 s on their +respective clocks. The SysML trace covers the preparation boundary. +The same-image diagnostic ran two four-owner ABBA waves with the original +HTTPS fixture and retained ASCENT in every arm. One wave changed only +the frontier read strategy. The other changed only post-FFI candidate +resolution. Both joins matched the cut, ready set and ordered selected +predecessors across all trials. Frontier median fell from 5.234 to +4.609 ms and candidate resolution median fell from 6.50 to 5.56 µs. +Each median uses four observations from the nine-node fixture. +Resolution timing starts after FFI and excludes the earlier plan +copies removed by preparation. Use the result to prioritize the +remaining ledger observation costs before changing the Scheme boundary. + +A four-owner retained wave split the observation transaction into +open, head, availability, branch reads, receipt lookup, winner proof, +release proof, exposure and commit. It matched both join cuts and ready +sets from the prepared-index release. The median observation was +3.89 ms at the inner join and 4.28 ms at the outer join. Per-node +exposure checks accounted for 1.27 and 1.58 ms respectively, the +largest measured phase at both joins. Complete nodes shared the same +authoritative domain view. The candidate checks exact release and +metering per node and reconciles shared exposure and history once +within the same transaction. The deciding admission scope retains +its existing validation. + +The four-owner same-image ABBA held ASCENT retained and matched the +two join cuts and ready sets in every trial. With two observations per +arm at each join, exposure median moved from 1.45 to 0.37 ms at the +inner join and from 1.82 to 0.36 ms at the outer join. Whole observation +medians moved from 4.36 to 3.54 ms and from 5.14 to 3.39 ms respectively. +This cohort locates the effect within the ledger and does not establish +a tail limit. The ledger negative control rejects a missing shared +history after restart and fact withdrawal. The candidate release passed +the four-owner A/A and fresh/retained waves with the prepared-index +join digests, both derivation modes for withdrawal and A→B→A, nested +restart and owner cancellation, and both SysML checks. The measured +maxima were 7.86 s for CompileSource, 8.27 s for nested recovery +and 1.54 s for natural drain. + +The next observation reuses one deployed fact feed and one origin +inside the frontier transaction for choice, nested reachability and +completed-node winner checks. Every governed complete node still +proves its exact committed transition, decision and release. The +ledger test completes a successor, removes its transition and checks +that frontier observation rejects the image. Four-owner A/A and +fresh/retained waves match the previous join digests. Linear, parallel +DAG, conditional and nested controls pass on the candidate image. +CompileSource, nested recovery and natural drain peaked at 7.94 s, +8.17 s and 1.08 s. The four candidate retained observations range from +2.52 to 2.83 ms. The preceding release provides a behavioral reference +on the same commit. + +The retained four-owner ABBA used one diagnostic image and changed +only the frontier observation implementation. Both joins matched +the candidate release's cut and ready-set digests. Inner observation +medians were 3.038 and 3.050 ms for reread and reuse. Outer medians +were 3.978 and 2.883 ms, with two observations per arm. The outer +reference included a 5.095 ms sample and a 2.862 ms sample, which +overlapped the reuse range of 2.822–2.944 ms. Keep the transaction-local +reuse for its reduced read count. This wave does not establish a +repeatable latency improvement or a P99 limit. The next attribution +should separate frontier scope acquisition from native transaction +open and branch evidence reads before considering a custody change. + +The retained four-owner WAL and MVCC waves used the same release +diagnostic image and matched both join digests from the candidate +release. In WAL the inner and outer native BEGIN medians were +0.822 and 0.919 ms. In MVCC they were 0.721 and 0.636 ms. The MVCC +domain-key discovery medians were 0.263 and 0.258 ms, while scheduler +grant wait was 0.167 µs at both joins. Closing authority took less +than 1 µs at the median. Nested branch reads took 0.296–0.447 ms +across the four journal and join combinations. Authority span +overlaps the observation and must be reported separately. These +waves measure phase costs on the local fixture. Keep the authority +scope and evaluate any change to transaction opening against the +full observation time, including the first read and cut currentness. + +The retained four-owner WAL ABBA used the same image and authority +closure for IMMEDIATE and DEFERRED observation. At the inner and +outer joins, open plus first fact read fell from 0.888 and 1.285 ms +to 0.131 and 0.206 ms. Whole observation medians fell from 2.790 +and 3.614 ms to 2.186 and 2.315 ms. Each arm contributes two +observations at each join. Both join digests matched the reference +release. The deferred diagnostic passed nested restart, hard-fact +withdrawal and A→B→A, and owner cancellation. The dedicated +WAL Workflow observation entry uses this deferred snapshot. +Admission, claim and reservation retain their existing transaction +behavior, and the MVCC family path continues to use CONCURRENT. +The candidate passed the original WAL waves and native controls, +the four-owner MVCC fresh/retained regression, and both SysML checks. +The ledger fault test observes the committed frontier during an +uncommitted transition deletion and rejects the next observation +after commit. Both journals matched the reference join digests. +WAL CompileSource, nested recovery and natural drain peaked at +7.09 s, 8.01 s and 1.21 s on their separate clocks. + +The first local release comparison uses =BenchmarkProviderGoControlPair= +and =BenchmarkProviderGoControlPacedPair= with the same Rust fixture image. +The paced input sends the same thirteen logical events with a requested +ten-millisecond spacing between writes. The first event is immediate, and +usage and completion share the final write. Receipt and invocation checks +cover every stream. The shared Protobuf cohort shows a larger first-frame +tail than the native queue-to-client tail in both paths. Join timings for +the same request before attributing that gap to Go, admission or dispatch. +Independent percentile estimates do not partition one request. + +The source-priority release completed the direct Rust and Go ingress +matrix on one frozen production image. Each case used 128 streams per +path in alternating four-request waves. All eight cases preserved +receipts, held budgets and exact HTTPS dispatch counts. Applying the +registered ratios to the path comparison, four met both limits. +Independent immediate Protobuf missed both with first-frame P99 +ratio 1.250 and throughput ratio 0.925. Independent paced Protobuf +and shared immediate Arrow and paced Protobuf missed first-frame +P99. The Rust and Go process CPU and combined benchmark-driver +allocations were captured separately from startup. + +The separate same-source observed image completed all eight cases. +Six met both ratios. In the two observed shared paced misses, the +ranked Go request's enqueue domain wait was 14.04 ms for Protobuf +and 13.04 ms for Arrow, compared with 2.65 ms and below 1 µs for +the respective ranked direct requests. Go-front time was 0.78 ms +for Protobuf and 9.10 ms for Arrow. These ranks are joined to +their own phase observations and characterize the observed image. +The production independent Protobuf misses still require attribution +on a comparable replay. The five slow-consumer controls cover +capacity wait, cancellation, revocation, recovery and the pending +range crash boundary. A same-source optimization still needs the +original both-order gate. + +The maintained Go control pair entries now consume the frozen production +image already staged and verified by TestMain when no specialized +diagnostic pair is selected. The production fixture launches its normal +CLI and records both Rust and Go control image hashes. Diagnostic pairs +retain the instrumented WIF owner. Production matrix reproduction uses +the normal benchmark entry directly. + +The first direct-entry production matrix completed all eight cells in +62.817 seconds on the qualified current-cut Rust release. Each path +completed 128 streams per cell in alternating four-request waves, +covering 2,048 total streams. Every cell passed its original receipt, +held budget, history, event count and exact HTTPS dispatch checks. +The wrong frozen-hash control failed before control activation and both +SysML checks passed. + +Five cells met the registered first-frame P99 ratio of at most 1.10 and +throughput ratio of at least 0.95. Independent immediate Protobuf missed +throughput at 0.935. Independent paced Protobuf missed first-frame P99 +at 1.396. Shared paced Protobuf missed first-frame P99 at 3.270, with +Go at 166.4 ms and direct Rust at 50.88 ms. All four Arrow cells met +both ratios. CPU and combined driver allocation metrics are retained +for every cell, with activation outside the request interval. + +Keep the three failing cells and the original limits. Attribute the +ranked shared paced Protobuf request through admission and first-frame +delivery before choosing another execution optimization. This matrix +uses a different image from the earlier source-priority matrix and +does not establish a cross-release speedup. + +The next focused replay applies the existing Go first-frame probe to +the shared paced Protobuf cell. It fixes the qualified Rust release +and uses the same diagnostic Go image with the probe disabled and +enabled. The diagnostic overlay is generated from the current Go +sources. Each mode completes 128 streams per path and retains original +receipt, budget and HTTPS invocation checks. + +All 128 probed Go requests joined their client and proxy timestamps by +family and node. At the probed Go P99 request, total first-frame time +was 66.590 ms. Client-to-Go was 0.421 ms, Go work before its Rust call +0.005 ms, waiting for the Rust-facing frame 65.784 ms, and forwarding +to client arrival 0.380 ms. The intervals belong to that same request +and sum to its total. The RPC wait includes Rust execution, local gRPC +and upstream transport. + +The plain diagnostic replay recorded direct/Go first-frame P99 at +78.023/132.847 ms. The probed replay recorded 83.682/66.590 ms, reversing +the path ordering. Keep the original production cell's 50.88/166.4 ms +and its failure. This replay locates the probed sample at the +Rust-facing boundary. Attribution of the earlier failed rank and +separation of Rust admission, store and transport remain open. + +The same-source Rust observation replay joined 128 requests and 3,712 +scopes for shared paced Protobuf. Its ranked request took 88.521 ms, +including 28.835 ms before worker entry, 26.667 ms at enqueue and +9.370 ms at consume. The enqueue scope reported 15.425 ms of domain +wait. Its upstream transport took 1.222 ms. + +The holder join exposed an observation boundary issue. A peer's scope +reported 9.308 ms of hold, while its pre-Drop releasing timestamp +covered 3.922 ms. That timestamp precedes the scheduler mutex and +lease removal. Preserve the sample and treat that endpoint as a +release request. + +The observed scope timeline now appends a versioned release extension +with requested, scheduler-locked, lease-removed, waiters-notified and +returned timestamps. Collection uses the existing commit-observer +feature and requested timeline. Removed is sampled under the scheduler +lock. Returned is sampled after unlocking and can include rescheduling. +The original fields remain available to existing decoders. + +The package ASP gate required provider scope obligations to have a +separate owner. RangeProgress, AdmissionRequest, OriginLifecycle and +their existing diagnostic controls moved into provider_scope.rs. +The provider facade retains the existing paths and provider-only token +construction. The library suite passed 61 tests with one existing +ignored test, the ledger integration suite passed all 136 tests, both +SysML checks passed, and the normal release built. + +The corrected-clock replay again joined 128 requests and 3,712 scopes. +Its ranked first-frame request took 75.573 ms, including 55.709 ms +at consume. The consume scheduler wait was 48.791 ms. Conflicting +admission leases overlapped 48.762 ms of that interval. One peer's +admission contributed 45.273 ms of overlap and recorded a 42.172 ms +commit. That commit completed in one poll with zero Pending returns. +Poll wall was 42.172 ms, thread CPU 0.140 ms and observed sync wall +0.068 ms. The remaining commit poll wall still requires I/O and +scheduling attribution. + +The largest release measurement gap in this replay was 32.333 µs. +It did not reproduce the earlier 5.387 ms gap. Preserve both captures. +Use the existing Turso Unix I/O spans to partition the long commit +poll before changing transaction or custody boundaries. These are +observation-profile results and leave the production matrix's three +misses open. + +** Runtime architecture priority + +The SDK mailbox benchmark establishes an available low-overhead owner +mechanism. It does not establish Weaver request latency: one message, +one rule evaluation, a durable reservation and a complete HTTPS stream +are different operations. Preserve separate clocks for cut-to-candidate, +release-to-durable-claim and request-to-first-frame. The existing target +below one millisecond applies to cut-to-candidate, including queueing, +ABI conversion, ASCENT and checked Rust result conversion. Neither +network pacing nor durable commit is covered by that target. + +| Boundary | Current implementation or evidence | Next change and acceptance boundary | +|----------+------------------------------------+-------------------------------------| +| Preparation to activation | Compiled Scheme, fixed owner and opt-in ASCENT preopen; first-live open moved from 80--138 ms to activation | Complete readiness before publishing the exact binding; compile remains outside the live decision clock | +| Preparation to live work | SourceInbox handles Compile and Derive in one blocking loop | Qualify isolation of preparation from the serving owner through the existing tracked-owner lifecycle; priority alone cannot preempt an executing compile | +| Rust to Scheme | Full packed seven-relation cut and checked candidate indices exist as opt-in modes | Retain the prepared topology and replace changed relations; require equal candidates and binding rejection controls before default adoption | +| Repeated decision | Retained ASCENT supports changed replacements and identical-input result reuse | Key reuse by active publication binding and the complete current input; clear on replacement, retraction and errors; ledger still checks current authority | +| Concurrent decisions | Bounded mailbox and thread-affine VM already exist | Partition independent sessions across assigned owners only when owner queueing dominates; preserve frontier/claim serialization and bounded capacity | +| Scheme result to effect | Rust validates candidates and claims with current facts in ledger transactions | Keep an index result as a proposal; stale results never authorize dispatch or release barriers | +| Shared admission | A measured tail waited on conflicting leases, including a long commit poll with little thread CPU | Attribute commit I/O and scheduling first; moving blocking work off Tokio does not release an authority lease, and unknown outcomes retain custody | +| Bulk data | Arrow C Data is an available batch boundary | Use for columnar workloads where ownership and conversion justify it; small indexed Workflow cuts do not need an Arrow conversion | + +This is an implementation order, not a claim that the target is met. +First remove first-use preparation from live execution, then eliminate +repeated input/result construction and relation replacement, then +address measured owner contention and lease-holding waits. Scheme/POO +continues to compose programs and object behavior; ASCENT derives from +current facts; Rust admits effects. Compiling all rules into a second +Rust policy implementation would duplicate these responsibilities. + +The preopen, packed and changed-replacement modes have correctness +evidence but remain opt-in. Four join observations per arm cannot +establish a sub-millisecond P99. Do not promote them from a mailbox +throughput number or broaden their acceptance claim to the three +failed production SSE cells. + +** Commit I/O attribution follow-up + +The existing commit-observer now captures Turso Unix spans during the +observed commit poll: pread, pwrite, pwritev, sync, size and truncate. +Record their interval union separately from per-kind intervals, with +wall time, current-thread CPU and span counts. Kind intervals may +overlap. These are instrumented spans on the polling thread, not a +system-wide syscall trace. An empty observation does not prove no I/O. + +The native control initializes the session and schema before enabling +observation, then commits a real insert. It caught static callsite +filter caching that hid previously encountered writes. A dynamic +filter fixes that observation error; the initial failed test remains +in local evidence. The corrected library suite passed 62 tests with +one existing ignored test, all 136 ledger integration tests passed, +and the default production release built with the same SHA256 as +before this observer-only change. + +One bounded four-worker replay completed in 53.854 seconds and joined +all 128 traced requests and 3,712 scopes. A 29.223 ms commit included +29.162 ms in observed Unix spans, predominantly a 29.126 ms sync span +with 0.050 ms thread CPU. A different 37.785 ms commit included only +4.588 ms of observed I/O. The latter's remaining wall time is still +unattributed; do not assign it to the filesystem or Scheme. + +The ranked request took 198.559 ms, including 29.850 ms of consume +domain wait, 92.657 ms outside measured upstream transport during +dispatch and 32.949 ms from headers to queue. This is a new observation +profile, not a reproduction or explanation of the original production +rank. It provides no basis to claim a universal fsync bottleneck or +completed performance optimization. Retain the production failures +and investigate the measured boundaries without weakening durability. + +** Review preflight program and cursor reuse + +The working candidate's production review preflight uses the existing native +prepared-statement transport for its legacy-profile predicate and +review projection. A prepared singleton read reaches Done before +dropping the cursor, rejects an unexpected second row, and creates a +fresh parameter-bound cursor on every use. Compatibility and program +invalidation remain Turso responsibilities. No policy result, row +snapshot or authority approval is cached by Weaver. + +The first native control rejected a simple API substitution: changing +only the projection to prepare_cached left three native preparation +calls on both cold and warm invocations. Keep that failed control. +With both fixed preflight queries reused and singleton cursors completed, +the same-connection control records three preparations cold and zero +warm. It verifies current candidates before and after a real replacement +publication, then rejects loss of the review-authority projection. +Additional native cases check fresh parameter binding, empty results +and multiple-row rejection. All 64 library tests and 136 ledger +integration tests passed; one pre-existing ignored test is unchanged. + +The deciding transaction still compares the exact review image, +publication request and receipt, schema, policy, key epochs, source +association and supplied revision/fence. Native program reuse does not +prove end-to-end performance or reuse across an incompatible connection +context. The normal fixed-release eight-cell matrix remains a separate +gate, including wrong-image rejection and the original direct/Go limits. + +The candidate's normal production matrix completed all eight cells and +2,048 streams in 65.365 seconds, with the same normal Go control image +as the prior production matrix. Both SysML checks and wrong-image +rejection passed. Five cells met both original ratios. Independent +immediate Protobuf and Arrow missed first-frame P99 at 1.127 and +1.291 times direct Rust; shared immediate Protobuf missed first-frame +P99 at 2.307 and throughput at 0.892. All four paced cells passed. +Keep these failures alongside the earlier production failures. Different +failed cells across runs do not prove that an earlier cause was fixed. + +On that exact candidate release, the original four-owner A/A, +fresh/retained and packed WAL waves matched the prior inner/outer +cut and candidate digests. Four packed MVCC trials matched them too. +Both derivation modes passed nested restart, hard-fact withdrawal, +A-to-B-to-A and source cancellation/drain. Across these wave samples, +CompileSource peaked at 7.020 s, scenario recovery at 7.941 s and +natural drain at 1.222 s, within the unchanged 10/12/15-second limits. + +Keep the change as a working candidate pending the original performance +gate and a matched-release A/B. The native zero-prepare result covers +immediate repeated preflight on one compatible connection. It does +not prove reuse survives the complete enqueue/receipt/consume path. +Inspect that consumer lifecycle and native compatibility invalidation +before another matrix; do not repeat the same matrix hoping for a pass. + +** Consumer cursor lifetime and frozen release A/B + +The native consumer control disproved extrapolation from immediately +repeated preflight. After actual enqueue and receipt, WAL needed three +new review preparations; after consumption it needed two. An independent +receipt read or an ordinary table scalar read caused three, while an +empty committed writer caused zero in that WAL probe. The exact failed +controls remain in the local packet. + +The candidate completes the existing original-task, task-publication, +publication-receipt and provider-receipt singleton reads through the SDK +prepared-query transport. Original-task preparation is now the default; +its existing diagnostic switch still selects the fresh reference. +Every cursor rebinds parameters and reads current rows. Publication +signatures, original commitments and deciding comparisons are unchanged. +The native consumer fixture binds a real committed birth publication, +executes enqueue and consume, and checks that a subsequent exact Policy +projection change is rejected with the original hold still present. + +WAL then records zero review preparations after both actual phases. +MVCC still records two after each. The original hypothesis of zero +after both journals is false; do not bypass SDK compatibility or claim +MVCC reuse from the WAL result. The regression enforces WAL reuse and +currentness on both journals. All 65 library and 136 integration tests +passed, with one existing ignored library test unchanged. + +For remaining planning work, only the preflight projection uses a +fixed CROSS JOIN order over the existing singleton and indexed keys. +The shared predicate macro keeps every original join condition, +JSON check and epoch bound. The deciding exact-image comparison and +general reviewed-head requirement keep their original predicates. + +The existing production benchmark accepts an optional frozen Rust +baseline image and digest. It stages and verifies that image before +activation; its two arms use the same normal Go forwarding binary. +The default benchmark still compares Go with direct Rust. Both modes +retain the original eight cells, four concurrent requests, 128 streams +per arm per cell, alternating arm order, exact receipts, 13 events and +one real HTTPS invocation per stream. Both wrong-image controls passed. + +In the frozen Rust release A/B, all eight cells met the unchanged +P99 ratio ceiling 1.10 and throughput floor 0.95. Rust CPU per stream +fell in every cell, by 11.1--30.0%; throughput rose by 4.5--44.9%. +First-frame P99 ratios ranged from 0.485 to 1.066. These are observed +cohort results for the combined cursor and planning changes, not an +attribution of each gain or a population P99 guarantee. + +The separate original Go-versus-direct gate passed correctness in all +eight cells but met both performance limits in only three. The five +misses remain: independent immediate Arrow, shared immediate Protobuf +and Arrow, and independent/shared paced Arrow. A passing Rust A/B does +not close the forwarding comparison. + +The same-release four-owner A/A failed its original ten-second +CompileSource deadline: native owner calls took 10.409--10.436 s and +readiness reported cancellation. Its source-module view phase consumed +most of the preparation interval. No replacement wave was run. The +fresh/retained comparison, both derivation modes for withdrawal, +nested restart, A-to-B-to-A and cancellation, and packed WAL/MVCC +waves passed. The all-groups lifecycle verifier correctly refused to +issue a passing receipt because A/A failed. Keep this preparation +failure separate from steady Runtime and preserve 10/12/15-second +limits. The candidate remains unqualified for overall promotion. + +** Arrow forwarding attribution and domain discovery cursor + +Two focused Arrow cases kept the production Rust image fixed and +compared plain/probed Go builds from one observation image: independent +immediate output and shared paced output, four concurrent requests and +128 streams per path per case. All 1,024 streams completed with the +original receipts and real HTTPS calls. Post-measurement logs joined +client start/receive with Go ingress, RPC submission, first receive, +send start and send return. Send return is an overlapping observation; +it is not required to precede client receipt. + +First-send wall P99 was 22 and 44 microseconds in the two probed cases. +Their Go P99-ranked requests took 31.630 and 69.722 ms. Most time was +between submitting the Rust RPC and receiving its first frame. The +relative direct/Go tail ordering changed between plain and probed +waves, so these captures do not explain an earlier failed rank. + +A second Go observation split RPC creation/submission from the first +Recv wait. RPC setup at the ranked requests was 37 and 28 microseconds; +first-receive waits were 19.007 and 202.668 ms. This interval includes +remote execution, gRPC transport, local decoding and scheduling. It is +not a measurement of Rust execution alone. There is no measured basis +here for replacing Go serialization or its send path. + +The existing Rust observation entry then joined 128 shared paced Arrow +requests and 1,408 scopes, with the same current Rust source but a +separate optimized test/commit-observer image. Its ranked request took +163.943 ms: enqueue 48.625, consume 16.580, guarded dispatch outside +transport 25.276, upstream transport 22.968 and headers-to-first-batch +46.136 ms. The two domain waits totaled 45.675 ms. Conflicting active +leases covered 35.514 ms; one peer admission recorded a 9.700 ms commit, +including 7.707 ms of observed Unix I/O spans. Keep interval overlap, +per-thread I/O coverage and the four-row pacing boundary explicit. +Observed Rust CPU was 57.66 ms/stream with tracing versus 38.12 without; +do not transfer these instrumented durations to the production failure. + +Following the admission path exposed another abandoned singleton read: +MVCC lock-key discovery used the general first-row domain-view reader. +It discarded the cursor after its first row, invalidating compatible +prepared programs despite the existing prewarm. The domain-view and +provider-view readers now reuse the existing complete singleton +transport. Query predicates, fresh parameters and row decoding are +unchanged. Scheduler generation remains captured before the discovery +query; root and generation checks remain inside the deciding protocol. + +The published-task consumer control now records zero review +preparations after enqueue and consume on both WAL and MVCC. The +previous MVCC two-prepare result was an unresolved observation, not +proof that engine compatibility required those two compilations. +This change removes that consumer-side invalidation without bypassing +the SDK's genuine compatibility checks. All 65 library tests and 136 +ledger integration tests passed, with one existing ignored test. + +On the new frozen release, the single-change Rust A/B met both original +ratios in seven of eight cells. Independent paced Arrow missed +first-frame P99 at 1.139 times reference; its throughput ratio was +0.999. CPU per stream decreased in seven cells and increased 1.3% in +shared immediate Protobuf. The separate original Go/direct gate met +both limits in four of eight cells. Preserve every miss and keep the +candidate pending overall performance qualification. + +The same-release four-owner A/A, fresh/retained, packed WAL/MVCC, +withdrawal, nested restart, A-to-B-to-A and source cancellation/drain +checks passed with the prior join identities. The WAL wave maximum +CompileSource was 8.780 s, scenario recovery 7.852 s and natural drain +1.149 s, within unchanged budgets. This new-head pass does not erase +the preceding 10.409--10.436 s preparation failures or establish that +a Rust query change repaired Scheme preparation variability. + +** Prepared nested rule specialization + +The retained program now partially applies the existing canonical rule +objects to an immutable wholly nested topology. Selection requires retained +execution, nonempty nested-node coverage of every node and empty flat arm/join +projections. Other topologies and the full fresh oracle keep their original +program. The specialization removes the three empty private flat relations +=choice-made=, =skip= and =missing=, their rules, and the flat-ready rule whose +negative nested-node guard cannot hold. It reconstructs the program through +ASCENT's public =gerbil-ascent-program= constructor, not a second evaluator or +unchecked mutation of an admitted session. + +All source-bearing declarations and seven mutable input groups remain. +Input/derived/output limits remain 640/768/1408. Empty private declarations +contribute no source rows. Retained topology replacement still resets the +session, and ASCENT still prepares, checks and atomically publishes source +replacements. Preparation selects 21 relations/14 rules instead of 24/21. +There is no new mode switch or production-default change. + +The module-native suite passed. A seeded property checks 32 sequences of eight +snapshot replacements against eight cached full-fresh results, including +branch choices, parallel/join cuts, deletion and restored availability. The +original source-budget rejection message also matches fresh evaluation, and a +subsequent valid cut succeeds. Existing topology/binding replacement, packed +bounds and withdrawal/A-to-B-to-A cases remain part of that suite. These are +finite witnesses, not an exhaustive equivalence proof. + +Two frozen optimized benchmark images ran baseline/candidate/candidate/baseline +through the unchanged quiet four-worker owner profile, 128 calls per arm. +Each native image had matching expected candidates. Baseline P50 was +1.067--1.092 ms and candidate P50 0.909--0.910 ms. Baseline P99 was +3.787--4.132 ms and candidate P99 3.419--3.605 ms. Both candidate P99 values +still fail the unchanged 1 ms target. The added baseline/candidate usage arms +recorded 8/7 calls with collection; one pair does not establish a general +allocation-rate reduction. The baseline usage arm also had slow no-GC calls, +so preserve it and do not generalize the previous cohort's GC-only attribution. +Whole-process CPU includes preparation and is not a hot CPU comparison. + +This is a bounded consumer-side reduction of prepared program work. It does +not isolate the source reader's VM heap, remove all update allocation, qualify +Gateway latency, or close the original eight-cell end-to-end gates. The native +release built in 1 minute 42 seconds; the benchmark image built in 1 minute +27 seconds, both inside the unchanged build budget. All 26 governance library +tests, the ASP gate and SysML/requirement-trace checks passed. + +The same frozen native release passed hard-fact withdrawal/restart/A-to-B-to-A, +both nested-recovery/skip scenarios and active source-cancellation drain. +However, both preregistered four-way fresh/retained and changed-source waves +failed readiness during CompileSource. All eight owners reached source +selection but were canceled before module-view admission and Governor +derivation under the unchanged 10-second request deadline. Preserve both +failed waves; do not rerun until a pass or treat the sequential controls as +their substitute. This batch is not a complete native qualification. + +The failure location precedes the prepared rule factory. It does not by itself +prove the new source text/import had no preparation cost, and host load alone +is not an explanation. Reuse the existing private reader stage measurements +and package-owned source mechanisms for a source-path audit before another +four-way startup run. Compilation, reader preparation and live derivation +remain distinct costs, with their original budgets and failed evidence. + +** Owner GC attribution through the existing SDK + +The pinned SDK's public =gerbil_scheme_rust_objects_usage= C ABI already +provides four GC and four OS counters; its objects benchmark uses the same +entry. The Weaver owner benchmark now reuses that interface on the live affine +owner, with a small benchmark-only FFI leaf. It adds no Scheme export, runtime +callback, SDK change, Gambit change, forced collection or heap setting. +=WEAVER_TEST_GOVERNOR_USAGE=1= samples before/after each evaluation. Both +snapshots are outside the derive interval, and their overhead remains inside +request/reply/queue latency. The diagnostic remains disabled by default. + +One frozen image ran quiet-before, usage-1, usage-2 and quiet-after: the same +32 four-way waves and 128 calls per arm as the preceding warm profile. All +512 expected-result checks, interval joins and natural exits passed. + +| Arm | Submission-to-owned-result P99 | Calls with GC | Calls over 1 ms inside owner | +|-----+--------------------------------+---------------+------------------------------| +| quiet-before | 3.722 ms | not observed | not attributed | +| usage-1 | 3.747 ms | 8 of 128 | 8, all with GC | +| usage-2 | 3.692 ms | 8 of 128 | 8, all with GC | +| quiet-after | 3.847 ms | not observed | not attributed | + +Across the two diagnostic arms, every owner interval over 1 ms contained one +collection. GC wall time was 1.799--2.165 ms and accounted for 78.0--81.5% of +each associated slow owner interval. No-GC owner maxima were 0.561/0.494 ms. +This attributes most measured slow-call time to collection in this cohort; +it does not identify the allocating constructor or establish every production +tail's cause. The collector may run during input conversion, Scheme inference +or result conversion inside the measured evaluation. + +Observed Scheme heap capacity was 20,146,464--21,195,040 bytes. That is capacity, +not live data, per-call allocation or retained program size. OS CPU and context +switch counters cover the whole process, not only the VM thread. RSS is an +absolute high-water mark. Do not substitute any of these for physical +allocation accounting. Quiet controls still miss the unchanged 1 ms target; +neither diagnostics nor the earlier finite P99 ratios promote a default. + +The next consumer-side optimization should reduce work/objects using the +prepared immutable topology and the existing Scheme relational composition +API. The current nested topology projection marks every node as nested, making +the flat-ready rule inactive; the combined program nevertheless declares both +flat and nested rule families. Audit a prepared specialization against the +original full program, including original input/derived/output bounds, +deletions and failure behavior, before changing it. Keep ASCENT's prospective +snapshot, completed-result admission and atomic engine publication intact. + +There is also a distinct architecture seam. Weaver's =SchemeCompiler= uses +=GerbilRuntime::initialize_program=, and its existing source lane runs capture +and inference on that same owner. The SDK's =InstancePool= uses explicit private +images and claims a different process backend. =claim_linked= and =claim_images= +are mutually exclusive. Adding a pool beside the existing linked VM is not a +supported isolation design. If prepared specialization is insufficient, assess +a whole-backend migration using SDK image/Build Package APIs, with separate +source and bounded execution image roots. Reuse native conversion capabilities +and preserve publication/owner binding and ledger rechecks; do not add another +loader, serialization service or consumer-owned VM implementation. This is a +design option, not an implemented migration or a proven GC improvement. + +** Quiet resident-owner benchmark + +The existing =scheme_conversion= target now includes a finite owner profile, +selected with =WEAVER_TEST_GOVERNOR_OWNER_BENCH=1=. Its required feature is +=scheme-program=, allowing the actual approved Weaver application. The old +=scheme-qualification= feature still implies that feature for the original +conversion profile. Qualification and an explicit approved application remain +mutually exclusive; the initial rejected build is retained as evidence of that +guard. No build-manager or SDK admission rule is relaxed. + +The profile uses the existing =source_lane= and cancellable Governor owner +loop on one tracked Tokio blocking job, with four Tokio workers and capacity +four. One VM is prepared per process. It reuses the nine-node nested/parallel +topology from =runNestedSession=, then performs 32 waves of four snapshots: +parallel fork, inner join, outer join and withdrawal of a parent availability +fact. Every reply must match its exact expected candidates. Source capture, +ledger authority, reservation, provider traffic and network are excluded. +Preparation and natural owner drain have their own clocks and deadlines. + +The measured path disables verbose per-request timers and logs in both arms. +Owner records use a preallocated Rust vector. Unique snapshot identity and +wave join each submission and reply to its owner start/finish, and interval +nesting is checked. Queue includes admission and dispatch; owner derivation +includes Rust input construction, Scheme evaluation and Rust output conversion; +reply includes return scheduling. Do not add independent percentile values. + +One frozen optimized benchmark image ran the complete A1/B1/B2/A2 order, +128 measured calls each. A is fresh/full/named and B is +retained/packed/indexed/changed-relations. All 512 expected-result checks and +natural exits passed. This compares composite execution paths; it does not +attribute the entire improvement solely to ASCENT or solely to transport. + +| Arm | Submission-to-owned-result P50 | P99 | Owner derivation P99 | Queue P99 | +|-----+--------------------------------+-----+----------------------+-----------| +| A1 | 276.175 ms | 527.363 ms | 231.693 ms | 372.017 ms | +| B1 | 1.038 ms | 4.047 ms | 2.878 ms | 3.324 ms | +| B2 | 1.091 ms | 3.809 ms | 2.580 ms | 3.427 ms | +| A2 | 285.803 ms | 518.579 ms | 227.353 ms | 405.926 ms | + +These are nearest-rank percentiles over fixed finite samples. The fresh and +retained repeated-arm P99 max/min ratios were 1.017 and 1.063, respectively; +they do not establish repeatability for the original eight Gateway cells. +The prepared retained path improves this local latency profile substantially +but fails the unchanged submillisecond hot-decision target in both B arms. +No production default or broad performance acceptance is promoted. + +Preparation was 145--182 ms and owner drain 0.075--0.108 ms in this profile. +Process CPU receipts include preparation and drain and are not per-decision +CPU measurements. The complete four-process experiment took about 29 seconds; +these are 512 warm decisions, not 512 VM or source cold starts. + +Retained slow owner samples occurred about every four waves, across several +snapshot types. Their periodicity suggests an allocation/GC hypothesis, not +a measured GC attribution. Inspect supported Scheme statistics and replacement +allocation before changing heap policy or adding VM shards. The installed +ASCENT replacement path prepares a prospective source snapshot and an updated +engine before publishing accepted state. Preserve that failure-atomic boundary; +do not bypass it to reduce the observed latency. + +Build once through the existing target, freeze the resulting binary, and set +the three mode variables consistently for each preregistered arm: + +#+begin_src sh +WEAVER_TEST_GOVERNOR_OWNER_BENCH=1 \ +WEAVER_TEST_GOVERNOR_RETAINED=1 \ +WEAVER_TEST_GOVERNOR_PACKED_FACTS=1 \ +WEAVER_TEST_GOVERNOR_CHANGED_SOURCES=1 \ +cargo bench --locked --offline -p weaver-governance \ + --features scheme-program --bench scheme_conversion +#+end_src + +Use the existing approved-application/SDK environment; leave verbose Governor +timing unset. A uses zero for the three mode variables. Each invocation emits +one JSON sample set after natural owner cleanup. Original Criterion conversion +groups remain the default when the owner profile selector is absent. + +All 26 governance library tests and the ASP gate passed with this addition. +The preceding same-core release's Workflow, withdrawal/restart/A-to-B-to-A and +cancellation controls remain separate evidence; no extra cold-source matrix +was run for this benchmark-only addition. + +** Bound Governor index consumption + +The indexed reply is one exact owner-generation binding followed by at most +64 node indices. The previous general source deserializer limited every +vector to 64 entries, rejecting the full 65-entry binding-prefixed reply. +It also rooted each index and copied a general integer magnitude before +converting an intermediate unsigned vector to indices. + +The consumer now borrows elements from the SDK's rooted collection snapshot. +It checks the exact full-width generation once, reads bounded fixnum indices +without per-element roots or general integer buffers, and produces owned +Rust indices before dropping the snapshot. Count, type and foreign-index +checks remain mandatory. Repeated candidates retain the existing downstream +sort/deduplicate contract; current frontier, authority and reservation checks +remain in the deciding transaction. This does not change the Scheme ABI, +retained-mode defaults, SDK revision or Gambit sources. + +The native same-owner control covers empty and full result sets, reversed +order, repeated candidates, the complete unsigned generation range, stale +bindings, wrong scalar/collection shapes, oversized integers and counts, +and successful use after rejection. The former general decoder remains an +explicit negative reference for the 65-entry case. All 26 governance library +tests pass, including this real linked-VM control and the existing ASP gate. +The production release build completed in 2 minutes 25 seconds within its +unchanged build budget. The same frozen release passed the existing four-way +changed-source Workflow wave and the retained/packed nested-recovery, +hard-fact withdrawal/restart/A-to-B-to-A and cancellation controls. The SysML +architecture and requirement-trace checks also passed. These are separate +correctness and lifecycle checks, not an output-latency or end-to-end win. + +The four-way wave still observed 10.4--13.6 ms complete predecessor-to-join +intervals. Its 32 compact observations recorded 1.55--5.55 ms ledger +observation spans and 5.1--19.4 microseconds output processing. Optional +diagnostic work before owner reply reached 2 ms. These are individual phase +ranges under unrelated host load; do not add their maxima or treat them as +production percentiles. They locate remaining work beyond result decoding. +Retain the previous failed end-to-end matrices and equal-image tail control; +no performance gate is promoted by this batch. + +The derivation implementation is separated into bounded fact projection, +topology projection, binding transition, rooted invocation and result +acceptance. Topology fields use a fixed array rather than introducing a new +heap allocation. Detailed clocks remain optional, and no new Actor layer, +transport service, authorization cache or Runtime result cache is introduced. + +** Member-set program reuse and equal-image control + +Repeated retained-member verification still compiled both fixed +manifest queries inside the deciding transaction. The native before +control recorded three preparations: committed members, projected +members and an independent metering read. The candidate reuses the +existing manifest query transport and SDK prepared programs, including +preparation before provider admission. The production and observed +default now agree; the existing diagnostic switch still selects the +fresh reference. Compatibility remains SDK-owned and failed prewarming +does not waive the subsequent deciding read. + +Each verification binds its current family and consumes the complete +row sets. Exact retained/projected member bijection, duplicate rejection, +original ceilings, applied release and held-budget conservation remain +unchanged. The native test switches to a registered empty peer family, +then corrupts the current provider reservation and requires rejection. +Rollback retains the original hold. On WAL and MVCC, repeated +verification now records one preparation, solely the metering read; +the two manifest preparations are gone. All 66 library and 136 ledger +integration tests passed, with one existing ignored library test. + +The frozen Rust release A/B retained all eight original cells and +2,048 streams through identical Go forwarding. Rust CPU per stream +decreased in all eight cells, by 0.7--9.5%, but only five met both +original end-to-end ratios. Independent immediate Protobuf/Arrow +missed first-frame P99 at 1.782/1.166 times reference; shared paced +Protobuf missed at 1.434. Throughput met the floor in all eight. +The separate original Go/direct comparison met both limits in two +of eight cells. These are failed performance gates, not permission +to promote a native compilation-count improvement. + +One additional finite control used the identical frozen Rust binary +and identical Go forwarding in both arms for shared immediate Protobuf. +Both image digests were verified before activation, and each arm ran +the original 128 streams with four concurrent requests. P99 was +52.77/59.16 ms: ratio 1.121, exceeding the unchanged 1.10 ceiling. +Throughput ratio was 0.996 and Rust CPU ratio 0.973. The equal-image +control itself fails the tail gate. This identifies a repeatability +limitation for that cell; it neither explains every failed A/B rank +nor establishes noise bounds for all eight cells. Keep the original +gates and the failed control. Do not rerun until a pass or infer a +code regression solely from an unmatched tail ratio. + +The same-head Scheme fresh/retained comparison, retained cancellation, +withdrawal/restart/A-to-B-to-A and packed WAL/MVCC groups passed. The +four-owner A/A and fresh nested-recovery readiness failed during +source compilation under the original deadline. The all-groups +lifecycle verifier refused a passing receipt. Preserve these failures +separately from the Runtime improvement and keep 10/12/15-second limits. + +The upstream check read PR 18's remote head and found it equal to the +consumer pin bfe803f597a15a3654b70a64c3a039980c31da8a. The dirty local +SDK checkout and its branches were preserved. This batch changes no +SDK or Gambit sources. Before another performance candidate, qualify +measurement repeatability and inspect the expensive source module-view +phase through the existing Module System interface. +[[https://github.com/tao3k/gerbil-scheme-rust/pull/18][Scheme SDK PR 18]] + +The focused independent Protobuf replay kept the production Rust +image fixed. The Go probe joined 128 completed streams per path +and pacing case by original family and node using the host monotonic +clock. At the Go P99-ranked request, waiting for the Rust gRPC +frame accounted for 30.678 of 30.998 ms in the immediate case and +27.788 of 28.181 ms in the paced case. The Go handler's work +before its Rust RPC was 3–4 µs at those ranks. Plain and probed +waves reversed the relative direct and Go P99 ordering. The join +locates time at the Rust-facing boundary. It does not attribute the +prior gap to the proxy or distinguish Rust execution from its local +gRPC and upstream transport. Keep the earlier matrix failures. + +A separate process-allocation replay instrumented both paths while +retaining the same production Rust image. In the independent +Protobuf immediate case, the Rust allocator received about 180,000 +calls and 38.3 MB of requested bytes per stream on either path. +Paced streams recorded about 291,000 calls and 61.1 MB requested. +The Go proxy recorded 247 objects and 14.2 KB per immediate stream, +and 319 objects and 22.4 KB per paced stream. These are allocation +counters over the measured window, not resident memory or a latency +gate. The comparable Rust counts and the first-frame join prioritize +Rust work on this fixture. Keep the other matrix cases separate. + +The focused release-program comparison used one observed release +image and Go forwarding in both arms. It varied only cached +preparation of the exact release lookup and mark statements. +Four Protobuf cases ran in both orders, with 128 streams per arm +per case and fresh bindings in each deciding transaction. +Seven of eight cases used less Rust CPU per stream, and all +met the throughput ratio. The reverse-order independent immediate +and paced cases missed the first-frame ratio at 1.134 and 1.327. +The immediate ranked sample added 2.14 ms at enqueue. The paced +sample added 8.67 ms in upstream transport, of which 4.86 ms +was TCP connection time. Keep the optimization diagnostic. +The five slow-consumer controls passed with cached programs. +The focused Protobuf run leaves the Arrow and full promotion +gates open. + +The same-image upstream TLS comparison let one Snake Oil peer +issue session tickets and disabled tickets on the other. The +existing database-connection reuse diagnostic is a separate +mechanism. Both HTTPS arms opened a new TCP socket for every +request. The default Rust TLS configuration resumed 124–125 of +128 sessions in each of the eight Protobuf pairs, and the +ticket-disabled peer observed zero resumptions. TLS P50 fell by +24–37 percent with tickets. TCP connect P50 remained in the +0.145–0.187 ms range across both arms. End-to-end first-frame +and throughput met both ratios in only three pairs, with the +largest added ranked phases distributed across enqueue, consume, +upstream transport and headers-to-queue. The local TLS saving +does not explain the first-frame tail. Preserve the existing +fresh-socket guard, and keep TLS tickets distinct from any future +HTTP connection reuse design. The original no-retry and +partial-request restart controls passed. + +The local first-frame diagnostic joins the existing Rust handoff and transport +observations to the client by family and original node. It checks complete, +unique and ordered observations, then reports the phase times of the actual +request at the first-frame P99 rank. In the shared paced Protobuf replay the +largest phase for both paths is the broker interval remaining after the +observed TCP, TLS, write and response-header timers. This residual contains +admission, consumption, request preparation, guarded dispatch and untimed +work. Measure those boundaries before selecting a change. Different host +loads and diagnostic builds remain separate observations. + +Monotonic native stage timings now split the first-frame observation into +enqueue, consume, request preparation and guarded dispatch. TCP, TLS and +request-write timers are removed from the dispatch interval before joining +the phases. A wall-clock diagnostic with an overlapping interval failed and +is retained. The corrected shared paced replay identifies enqueue and +consume as the two largest local phases on both sampled P99 requests. + +The same-image control with both arms through Go tested omitting the +post-commit receipt read that the broker discards. Both arms retained the +same send counts, complete streams and durable holds. The candidate showed +slower admission and first-frame tails in this run. Preserve the experiment +and retain the existing broker path while inspecting the work inside +admission and consumption. + +The enqueue and consume observations now retain deltas from their own +ledger session. Domain wait, native transaction begin and transaction +hold are separate counters. Cedar and preparation counters can nest +inside broader intervals and must not be added to them. In the observed +Go-routed first-frame P99 request, native begin dominates enqueue and +domain wait dominates consume. Keep the deciding scheduler and authority +order while investigating the native begin path. This sample does not +attribute the whole native begin interval to a Turso lock. + +The follow-up observer wraps the same Turso transaction future and counts +polls and Pending returns. The four Protobuf cases use shared and independent +domains with immediate and paced responses. Each accepted enqueue and +consume has one matching BEGIN observation. The measured slow begins +complete in one poll, with little time outside it. The next diagnostic +must separate synchronous driver work, engine contention and OS +descheduling inside that poll. Keep MVCC snapshot creation under the +existing scheduler and authority barriers. + +Thread CPU accounting on the same observed poll separates two costs. The +longest wall-clock BEGIN in the four-cohort replay used little CPU on its +own thread. Most BEGIN calls above the one-millisecond floor still spent +at least half their time on that thread. Enqueue has a higher CPU median +than consume in every cohort. Both use the same connection for a given +request, with enqueue first. Measure connection initialization, SQL +preparation and first-write execution separately before choosing a +reuse boundary. Time outside the thread's CPU can include synchronous +blocking and OS scheduling. The clock alone cannot identify a lock. + +The observed release follows Turso 0.8.3's own SQL preparation span +inside the transaction future. Join one span per BEGIN, and record +Ledger open separately. The larger part of the first BEGIN CPU remains +after preparation. In this Turso version the transaction opcode opens +the connection-local TEMP pager on first use. Test that cause with +disposable connections under the existing writer scope. A read of the +TEMP schema before the grant keeps the file spill policy. The isolated +memory-mode control also changes sort and hash spill behavior, so keep +its results separate from a candidate for provider execution. + +The native TEMP pager probe compares the first and second BEGIN on each +disposable connection. A read of the empty TEMP schema moves most of +the first-BEGIN work before the domain grant, with additional total +work in this isolated probe. Treat prewarming as a lock-hold candidate. +Require a paired HTTPS test for shared and independent domains before +changing the runtime default. Keep the existing journal, FULL synchronous +mode, foreign-key enforcement and bounded file spill policy. + +The same-image A/B ran both arms through Go and measured file-backed TEMP +prewarming before the writer grant. It lowered BEGIN CPU across all four +cases. Both shared cases missed the hold target. Immediate shared SSE +missed the queue target, and paced shared SSE missed the first-frame +target. The prewarming candidate was removed. The deciding transaction +continues to initialize TEMP on first use. The MRR Data reusable writer +design in 59.66 owns an opaque metadata transaction API. Its private +physical lease cannot directly host Weaver's deciding SQL scopes. Use +the lifecycle obligations in 59.66 to assess reuse of physical custody +under Weaver's existing execution permits. + +Bound the candidate to the provider execution lane and tie the total of +active and idle connections to its existing permit count. Each checkout +must build a fresh logical Ledger session with a new dispatch identity, +fresh cancellation and no retained request evidence. The physical +connection is eligible for return only after a completed provider stream +and verified autocommit. Discard on any error, cancellation, unknown +commit or unwinding. Stop checkout on runtime close and release idle +connections after tracked workers drain. Test stale dispatch identity +and unknown-commit discard before the paired HTTPS measurement. + +The local physical-reuse candidate runs under the provider execution +permit in the observed server. It clears request custody before parking +and constructs a new logical Ledger on checkout. Native controls deny +an old dispatch after checkout and refuse to park an applied but +unacknowledged commit. The first same-image comparison met the reuse +and BEGIN CPU thresholds. Independent immediate SSE missed both +first-frame and throughput thresholds. The matched first-frame tail +was spent mainly inside the admission commit on the reused connection. +Keep reuse confined to qualification. Measure that commit separately +from BEGIN and require the full original performance gate before +adoption. + +The focused immediate-SSE replay observes the native COMMIT future and +the Unix sync span in the same request. Record poll wall, thread CPU, +Pending returns and sync spans separately. Pending can represent a +coordinator yield. Sync spans count calls on the observed thread and +do not enumerate the physical files. The previous independent-domain +long commit did not recur in the focused run. Its result remains in +the adoption record. A focused replay leaves paced coverage and the +full reuse gate pending. + +The release-buffer candidate reused only the bounded event vectors +after encoding, guarded release and Workflow result capture. A partial +next range retained its contents, and Protobuf and Arrow owned the +encoded payloads independently of the vectors. The same-image +comparison reduced explicit vector allocations in the observed cases. +Several cases exceeded the first-frame gate, and one lacked the +required native preparation span. Preserve those outcomes and the +partial receipt. The candidate was removed. The observed first-frame +tails included work before the first reusable group, so the recorded +ratios alone do not attribute that regression to vector reuse. + +The driver observer uses a single dispatcher for the prepare and Unix +sync callsites. Each thread selects the expected span inside the +transaction measurement. The process accounting mode snapshots the +same Rust and Go child PIDs after readiness and after the offered work. +The four Go control processes are summed per arm. The benchmark driver's +Go heap deltas cover both arms and the local HTTPS fixture, so they +describe the harness window. Keep these separate from component +allocation benchmarks and from the unmeasured Rust and Go child heaps. + +The Go child heap diagnostic runs the existing control executable +entry in a test image and reads native cumulative allocation +counters through private process pipes. Read each child after +readiness and again before shutdown. Four idle controls per arm and +the direct Rust arm recorded zero Go child heap allocation during +their respective windows. The Go forwarding arm allocated 13.7 to +15.9 kB and 125 to 297 objects per completed stream across the eight +cases. Those counts include the whole Go forwarding process and do +not identify the allocating call sites. The Rust child heap remains +unmeasured. The production control image continues to build through +its ordinary entry. + +The wire-binding experiment compared the Protobuf request directly +with the admitted static plan before forwarding. Its isolated +binding allocated zero objects for both tested request sizes. +Whole-process allocation varied across the eight native cases. +Shared paced Protobuf exceeded its allocation limit, three cases +missed first-frame limits, and one also missed throughput. The exact +binding, race and native controls passed. Preserve the two Go +images and comparison while retaining the existing runtime entry. +Use process-level allocation call sites to select the next +forwarding change. + +The Go allocation profile uses a separate intrusive run. Capture +native allocs profiles before and after the steady workload in each +child and retain the direct Rust arm as an idle Go control. Subtract +the baseline profile per arm and exclude stacks rooted in the +profile writer. Profile sampling and forced collection change the +allocation totals, so use these deltas for call-site attribution. +In both shared paced encodings, reconstructing the outbound +Protobuf plan accounted for exactly seven objects and 656 bytes +per stream. The receive stack accounted for about 4.4 kB per +Protobuf stream and 7.2 kB per Arrow stream. These cumulative +stacks can overlap. Evaluate retaining the already approved outbound +plan at publication before changing the gRPC decoding boundary. + +The published outbound comparison built both Go images with the +same counter-only observer and used the same Rust release. The +candidate retained one owned Protobuf plan per static operation +and allocated a separate envelope per request. Shared paced +Protobuf fell from 302.1 to 274.4 Go heap objects per stream, but +independent immediate Arrow missed both tail and throughput +limits and independent paced Protobuf missed its tail limit. +Exact matching, concurrent marshaling under race detection, +and native negative controls passed after adapting the bootstrap +microbenchmark to the candidate's message type. Retain the +existing runtime entry and archive the candidate. + +The Darwin allocator diagnostic attached a test-only counter to +the same Rust release image. It counted successful calls and +requested bytes at four imported libc allocation entrypoints. +All idle deltas were zero. Across four paced cases it observed +about 161,000 to 526,000 calls and 34.5 to 109.1 MB requested +per stream. These are cumulative requests, including realloc +requests. Internal allocator calls and other allocators are outside +this scope. The counter increased Rust CPU by 56 to 64 percent. +Keep the plain arm for latency and throughput. Attribute the +allocation sites before choosing changes to Turso or frame handling. + +The same-image stack sample attributes allocation calls rather +than CPU time. Across the two shared paced cases, approximately +90 percent of sampled calls had a Turso frame and 62 to 67 percent +were in statement preparation. Nearly all preparation samples +included a parser or translator frame. The largest named callers +through the currentness helper were original task reconciliation +and member manifest reads. Keep the deciding reads and their exact +checks. Evaluate fixed-program preparation at those callers before +changing frame encoding or widening reuse. The first symbolization +used the interposer's image address and was discarded. The repeat +identified the executable by its Mach-O type and verified that +selection with a separate four-allocation probe. + +The published DataFusion Parquet point-read study attributes about +12 percent of CPU to logical planning and 50 percent to physical +planning in its measured configuration. Its custom physical plan +reuse improves the sampled lookup workload. DuckDB separately +documents direct Arrow analysis and vectorized execution. Use that +published evidence if a separate analytical workload is requested. +The default Gateway deployment has one Turso store. It uses compatible +prepared programs with fresh bindings. Arrow is an output and +interchange format. Exports can feed a consumer through the existing +boundary when it needs them. +[[https://datafusion.apache.org/blog/2026/10/24/point-queries/#prepared-statements][DataFusion point reads]] · [[https://duckdb.org/2021/12/03/duck-arrow][DuckDB Arrow integration]] + +The combined original-task and manifest preparation diagnostic +rebinds the same three fixed statements to current transactions. +In shared paced Protobuf, original-task P50 fell from 0.519 to +0.271 ms and process CPU from 91.17 to 75.23 ms per stream. +With the same allocator counter loaded in both arms, observed calls +fell by 24 percent for Protobuf and 19 percent for Arrow. Use the +plain arms for the latency gates. Three cases still missed first +frame and one also missed throughput. Keep this mode diagnostic. + +The first-use manifest experiment compared eager and lazy preparation +with original-task programs prepared in both arms. In four independent +cases the preflight P50 fell by 12 to 20 percent. Both Arrow cases +exceeded the existing first-frame limit, and three cases increased +median domain hold. Keep the existing diagnostic modes and retain +this comparison as evidence of work moved into the first deciding read. + +The paced HTTPS diagnostic pairs light and traced Rust workers on the +same release image, with Go forwarding in both arms. Process CPU is +similar in the four cases even though their first-frame tails vary. +Shared Protobuf remains the most CPU-intensive case with tracing off. +A separate intrusive stack sample observes allocation, Turso SQL +translation, currentness queries and MVCC access. Use the existing +physical SQL-program comparison to isolate repeat preparation. Every +guard must still bind its parameters and read the current transaction. +Wall-clock stack samples include sleeping threads. Keep their counts +separate from CPU shares and from allocation totals. + +The fixed SQL-program comparison uses the same release worker, new +bindings and current transaction rows in both arms. Across eight +four-way HTTPS cases, the cache lowered Rust CPU per stream in each +case. Shared paced Protobuf fell from 96.17 to 69.61 ms per stream at +the same throughput. Two Arrow cases exceeded the first-frame P99 +limit. The shared immediate tail included longer enqueue and consume +spans on the affected request. This observation does not isolate the +cause of the tail. The measured native chain also hit its existing +operation-channel startup deadline in the independent domain. Keep +the SQL cache comparison diagnostic and track startup separately. + +The focused Arrow repeat uses the same optimized image and the same +first-frame and throughput limits. The shared immediate tail did not +recur. The shared paced case exceeded its first-frame limit. On that +P99 request the largest added span was enqueue domain wait, while +headers-to-queue was slightly shorter. The two runs support tracking +the lock holder and its transaction stage alongside the waiter before +changing shared-domain scheduling. The measured Go control chain now +uses the benchmark's optimized WIF image. Both settings passed its +existing startup and exit gates on that image. The earlier debug-image +startup failure remains in the original receipt. + +The shared paced Arrow diagnostic joins each request's scope records +by scheduler ordinal and uses one monotonic clock per release worker. +The sample immediately before grant release gives a conservative +measure of conflicting holder overlap. The five longest enqueue +waits per arm were covered primarily by earlier admission scopes. +The longest wait in each arm overlapped three earlier admissions. +Their transaction holds were longer than their commits. This run +passed the focused first-frame and throughput limits and did not +reproduce the previous long tail. Preserve the earlier failure and +use the holder spans to investigate work inside the admission +transaction before changing the scheduler. + +The history comparison experiment matched each current history row +directly against the verified original member map for its origin. +Both arms read the same rows and checked the exact origin, node, +member, event and digest. The experiment avoided flattening the two +maps. The eight-case same-image run missed its enqueue hold target +and exceeded first-frame or throughput limits in multiple cases. +The host had elevated load during the run. Preserve those receipts +and keep the existing comparison. Investigate the original member +projection and reservation statements separately inside the deciding +transaction. + +The admission timeline splits the exact domain view into original +task verification, member manifest comparison and history comparison. +It records reservation writes separately. In both shared paced +encodings and both SQL-program settings, the manifest span grew +from the first eight waves to the last eight. Reservation medians +stayed within 0.32 to 0.37 ms. The manifest was the largest measured +part of the exact view. Keep comparing exact original identities, +digests, ceilings and settled exposure from current rows. Target the +intermediate projected manifest and its repeated decoding before +changing the reservation writes or shared-domain custody. + +The streamed projection experiment reused the original member map +and marked each live projected member once. It retained the same +SQL projection, digest and ceiling decoding, settlement subtraction, +and exact history comparison. Removing the intermediate row vector +and second map did not lower shared paced Protobuf manifest P50. +Two immediate independent cases missed the first-frame limit and +one missed the throughput limit. Preserve the receipts and retain +the existing projection. The manifest corruption controls passed. +The separate shared-budget control hit its existing startup deadline +before making a provider call. The next comparison should target the +number of live statements per shared domain, keeping the exact +per-origin member and history checks. + +The shared-domain batch reads the original and projected member +rows with two live statements selected by the current budget or +history root. It preserves individual origin, settlement, and +history checks. Shared paced Protobuf manifest P50 increased from +0.743 to 0.852 ms. Shared immediate Arrow also missed both +the first-frame and throughput limits. Turso selected the budget and +history indexes and the three family indexes. It expanded the root +selection in each branch of the union, so the SQL statement count +understates the lookup work. The budget-only and history-only +sibling substitution controls passed. Keep the per-origin statements +for the deciding path. + +The fixed manifest-program experiment warms two compatible Turso +programs on the request connection before acquiring domain custody. +It rebinds each origin and reads current rows inside the deciding +transaction. All eight cases lowered manifest P50. Shared paced +Protobuf lowered manifest P50 from 0.769 to 0.551 ms and Rust +CPU from 84.45 to 79.14 ms per stream at unchanged throughput. +Both paced Arrow cases missed the first-frame limit. Keep the +comparison diagnostic and reproduce the Arrow tails against a +same-setting control before promoting it. + +The paced Arrow follow-up used the identical optimized image. In +the fresh/fresh control the two arms differed by 4.6 percent at +independent first-frame P99 and 8.5 percent at shared first-frame +P99. Both were within the registered limit. In the new fresh/prepared +pair both paced Arrow cases passed first-frame and throughput limits. +Keep the original eight-case failure. The focused repeat supports a +full matrix repeat under the same controls before changing the runtime +default. + +The independent full-matrix repeat lowered manifest P50 in all eight +cases, including shared paced Protobuf from 0.772 to 0.580 ms. +Three cases missed the first-frame limit and independent immediate +Arrow also missed throughput. The matched shared paced Arrow tail +spent 49.42 ms in upstream transport compared with 0.70 ms in the +reference tail, while enqueue was shorter. The matched independent +immediate Arrow tail added time before Rust worker admission. +Keep preparation diagnostic. Extend the matched request breakdown to +separate connection establishment, TLS, write and response headers. + +The first-frame receipt now verifies that the four transport durations +sum to the matching request's upstream interval. The Arrow diagnostic +did not reproduce the earlier 49 ms transport sample. The shared paced +prepared tail spent 15.58 ms upstream, including 9.07 ms awaiting +headers and 4.86 ms in TLS. Its consume stage also grew. The independent +paced tail grew while its upstream time fell. Retain the four-case +receipt and its three first-frame failures. Connect, TLS and the +write/seal remain inside the modeled guard. Header wait stays after +commit and carries no authority. + +Static Go dispatch keeps the exact independently owned plan admitted at +publication. Each request compares its original key, profile, commitment, +model, ceiling, ordered routes and body against that plan. The forwarded +revision and fence come from publication. The separately maintained +configuration validator still checks the entire plan before ownership +transfer, and Rust applies current authority at execution. The Go binding +microbenchmark compares the previous request projection with this exact +match using distinct body storage. Its timing covers the binding step. +Native controls cover restart, revocation, shared budget and publication +outcomes through the actual service. + +Dynamic Go dispatch reads the authenticated catalog on each request and +registers the resulting original task against its publication before forwarding. +It retains one immutable local projection for an exact catalog version and +identical record bytes. A version or byte change takes the existing projection +path, and a failed read or invalid projection refuses routing. Rust still +checks the catalog version in admission. The projection comparison uses +separate input and retained buffers, and covers a single entry and the same +entry with 64 KiB of padding. The native comparison holds the Rust release +image fixed and races four requests against one original in each of the +complete, partial and Cedar-denied cases. It checks source withdrawal and +restart through the existing HTTPS integration fixture. + +Concurrent misses recheck the retained version and bytes after acquiring +projection custody. One request builds the projection for an identical +snapshot. A hit stays on the atomic read path. The custody applies to local +projection only, after the source RPC and before registration. + +The Go projection also owns the Protobuf task registration request +for its exact catalog record and publication. Hot requests reuse the +read-only wire object. They still inspect the authenticated catalog, +match the exact version and bytes, issue registration, and forward the +current catalog version to Rust admission. The dual-order local +binding comparison reduced 667–694 ns to 177–210 ns and 23 to 9 +allocations per call. It measures work before transport. Both Go +variants passed the same release HTTPS control with four contenders +for complete, partial and denied outcomes. The race and SysML checks +passed, and the Go hot-path change is in the working tree. + +A follow-up timed the existing four-contender HTTPS waves after +catalog activation. In each of the complete, partial and Cedar-denied +cases, three contenders stopped at catalog inspection before +projection, and one reached the Rust operation RPC. The three +forwarded requests spent 0.77–1.95 ms in catalog inspection, +0.16–0.21 ms in local projection and 2.34–3.63 ms in task registration. +This was the first projection after activation, not the earlier hot +binding benchmark. The Go timings include both RPCs' transport and +server work. They do not record the original inspect status or prove +that all nine refusals had the same cause. Reuse the source owner's +existing custody in the next timing comparison to separate admission, +transaction execution and reply before changing the command lane. + +The source-owner observation retained the original gRPC status and +matched the Go waves to the Rust command trace. Seven of twelve +requests were refused at inspection with =ResourceExhausted= and +the exact source-lane-full reason. Two other contenders completed +inspection but stopped at registration without a registration +command executing. One reached the operation RPC in each case. +The register failure status was not retained in this sample. + +In the complete and partial cases, the admitted registration commands +spent 1.85–2.03 ms executing, including 1.72–1.83 ms holding the +transaction and 57–61 µs committing. In the denied case the command +spent 9.01 ms from submission to owner dequeue and 4.05 ms executing. +The paired inspection also spent 4.37 ms before dequeue. Answering +took under 5 µs in all six admitted inspections and registrations +of the forwarded paths. Separate the accepted command's scheduler +delay from the rejection at capacity. These single-original waves +do not establish the behavior of four independent dynamic operations. +Test that workload before changing admission behavior or adding +source command capacity. + +The independent-operation follow-up used four Go owners and four +original family/node keys on the same Rust source owner. The two +arms used the same release image and equivalent fixture inputs. +They used separate API quota keys with sufficient shared user and +tenant capacity. The serial arm completed all four. With simultaneous +starts, one completed and three received the exact source-lane-full +inspection refusal. The refused requests emitted no frames and had +no provider claim. Both arms verified the upstream invocation count. +Serial first frames arrived in 19.30–21.85 ms, and the sole concurrent +completion had a 21.57 ms first frame. This distinguishes rejection +under contention from slower service for the accepted request in +this sample. + +The fixture also confirmed that the management connection and four +dynamic Go owners cannot occupy the four-connection source listener +together. Publish and register the review before closing the +management connection, then start the four owners with separately +owned configurations. Keep the connection cap distinct from the +command capacity in the next comparison. The original setup +failures remain separate from measured requests. + +The bounded-wait experiment kept one executing source command +and allowed at most three waiting catalog inspections or published +task registrations for up to 50 ms. Both orders ran on one release +image. The reference completed one of four independent operations +in each order. The candidate completed all four in both orders. +Candidate first frames took 41.65–57.32 ms compared with 22.59 and +36.32 ms for the only two reference completions. The measured +candidate source path took 5.53–31.56 ms. Compare completion counts +and accepted latency separately. + +The cancellation control drops a waiting future and observes the +return of its waiting permit while the active permit stays held. +The same-original HTTPS controls still enforce exactly one +invocation, retain partial exposure, and deny a forbidden provider. +Keep the experiment isolated. The semaphore's waiter handoff can +deny an immediate publication or withdrawal attempt before the +next waiting read executes. Qualify mutation progress under +continuous catalog arrivals before considering adoption. + +The reserved-handoff candidate retains one executing command, three +catalog waiters, and one separate mutation reservation. A catalog +waiter yields a handed-off permit while that reservation is present. +The first implementation made waiters compete for the reservation +mutex after release and could expire healthy readers. Keep that +failure receipt. The revised reservation has a single mutation +owner and notifies readers on release. Waiting or cancelling still +creates no source command until the active permit is obtained. + +The deterministic control reproduced FIFO refusal while a catalog +waiter held the next handoff. The revised mode gave that turn to +the reserved mutation. In three real owner rotations, each with +three queued catalog reads, the rotation committed first. All nine +reads from retired identities were denied, and each new identity +could read. The owner drained naturally. Both modes completed all +four independent HTTPS operations on the same release image. The +candidate also passed the complete, partial and denied same-original +cases. Nine source owner checks and two SysML checks passed. +The next ABBA used a single release diagnostic image and three authenticated +catalog readers. Each reader had completed four inspections and all three +had a call in flight when the catalog withdrawal began. Both FIFO attempts +returned ResourceExhausted. Both reserved-handoff attempts committed in +0.58–0.69 ms. All 144 inspections completed in each wave. The successful +withdrawals denied both direct execution with the previously registered +original and old catalog version and dynamic Go routing. No provider +invocation occurred until restoration and the original completion +control. + +A linked Scheme release then compared FIFO, mutation priority, and +priority that also covers the authenticated read that prepares a +hard-fact resolution. Three readers repeatedly inspected the catalog +head on the same source lane. The hard-fact fixture has no published +catalog, so the inspection exercises current-row and authority reads. +The published catalog projection is covered by the preceding test. +After each reader had completed four calls, the experiment staged +withdrawal under pressure, restarted, and resolved it under renewed +pressure. FIFO refused both first attempts in both waves. Mutation +priority admitted staging and refused both resolution calls at the +source lane. Covering the preparation read admitted both operations +in both waves, with staging at 0.88–1.11 ms and resolution at +6.67–7.05 ms. All 144 inspections succeeded in each pressure window. +Both successful phases denied execution before the readers drained, +and the original A→B→A control restored exactly one dispatch. Reference +refusals were retried after the readers drained solely to verify +recovery. Keep source-slot custody separate from Scheme derivation. + +The linked runtime enables the bounded handoff at the existing source +owner. Catalog inspection and published registration can wait in +three slots. One separate priority reservation covers the tested +publication and rotation commands and hard-fact prepare, stage and +resolve. A wait expires at 50 ms and has no command before the grant. +The fact preparation command returns its permit before Scheme +derivation. The final resolution takes a separate slot and rechecks +the exact durable barrier. The source-owner tests cover cancelled +and expired waits and identity rotation ahead of queued readers. + +The release regression reused the original Go ingress and HTTPS +fixture. Four independent dynamic operations completed with five +frames each and retained their exact claims. Catalog withdrawal +committed at 0.66 ms, and hard-fact stage and resolution committed at +0.83 and 12.21 ms, on the first attempts under the bounded reader +load. All 144 inspections completed in each of the three pressure +windows. The original partial response, Cedar denial and source +ingress credential controls passed. This sample verifies bounded +progress and custody and does not establish a latency percentile. +On that image the original four-owner WAL A/A and fresh/retained +waves matched the deferred-observation reference join digests. +Both modes passed the withdrawal, nested restart and owner drain +controls. CompileSource, nested recovery and natural exit peaked +at 6.59 s, 7.70 s and 1.37 s respectively. + +The Rust source owner retains one verified canonical catalog response. +Each inspection still authenticates the source and reads the current row. +The owner can return that row's bytes directly on an exact version and +byte match. A changed record goes through typed decoding, digest +verification and canonical serialization. An older noncanonical record +still returns canonical bytes. The typed reads in deciding admission and +Workflow use the existing verification path. + +In the fixed-release catalog comparison, the 64-entry response had +23,001 bytes. Single-caller inspection P50 fell in both candidate runs, +while the observed single-caller P99 rose. Under four simultaneous +readers the one-slot source lane admitted 32 of 128 requests in each +run and refused the other 96. Accepted-request P50 and P99 fell in both +candidate runs. Keep these inspection samples separate from provider +stream first-frame and release qualification. + +The admission-overlap control retains the existing pressure worker and +separates the admission barrier from the authority span. Its selected turn +shortens the measured barrier, while pressure still raises queue-to-Go +latency. The immediate Arrow ABBA control measures a lower median send +interval with coalescing. Keep both results scoped to their workloads and +retain the paced observations before changing the batching default. + +The follow-up shared-domain overlap used the original four-owner, +64-range entry and 128 streams per arm. Without the pressure worker, +selected closure moved admission-barrier P99 from 21.14 to 9.40 ms +while authority-span P99 moved from 29.99 to 43.25 ms and completion +throughput moved from 16.29 to 14.67 streams/s. With pressure, +barrier P99 moved from 19.90 to 15.32 ms and queue-to-Go P99 moved +from 9.62 to 5.86 ms. These are separate local workload observations. + +The shared paced Arrow trace joined 256 requests to 2,816 scopes +on the same observed release. The two longest selected-closure +admission waits were 48.24 and 44.71 ms. Both overlapped the same +41.56 ms exclusive admission holder for 41.55 ms. That holder spent +38.93 ms opening the native transaction and 2.63 ms after opening. +This identifies a shared blocker for those requests. The next +diagnostic should join driver preparation, poll CPU and pending +time to the specific native BEGIN outlier before changing lock +custody. Retain exact current authority at the deciding scope. + +The next observed release added those counters to each existing +scope timeline. The same shared paced Arrow entry recorded 128 +admissions per arm. Median BEGIN was 1.43 ms in both arms. Four +observations exceeded 10 ms across the two arms. Every admission +BEGIN completed on one poll without Pending. The four outliers +spent 11.19–20.19 ms in BEGIN, with 0.82–1.76 ms of thread CPU and +0.14–1.00 ms in Turso preparation. At the longest selected-closure +wait of 59.72 ms, two exclusive admissions with long BEGINs held +the overlapping scope for 22.58 and 14.68 ms. This locates most of +the outlier time inside a synchronous poll outside SQL preparation. +Distinguish synchronous waits from OS preemption with a thread +state trace on the same workload before choosing an optimization. + +An Instruments capture on the same observed image joined all 256 +scope and timeline log writes from the traced arm to their kernel +thread. Its one admission BEGIN above 10 ms took 17.04 ms. Across +the 17.03 ms interval common to the timing bounds, the thread was +blocked for 16.10 ms and preempted for 8.3 µs. A 16.25 ms mkdir +call ran in Turso's ensure_temp_database path through the transaction +opcode and tempfile directory creation. The capture locates one +tail event. + +The follow-up tested that connection-local initialization before the +grant on the same observed image. Both arms used selected closure, +four owners and 128 shared paced Arrow streams. The candidate +initialized TEMP in all 128 admissions with the same spill policy +and FULL durability. BEGIN P99 fell from 1.91 to 0.32 ms. Exclusive +hold P99 rose from 5.81 to 7.29 ms and enqueue P99 rose from 21.32 +to 25.23 ms. First-frame P99 moved from 76.22 to 82.81 ms and +throughput from 26.44 to 26.42 streams/s, within the original +first-frame and throughput limits for this one case. The two +longest candidate holds spent 6.97 and 7.22 ms after BEGIN, +including 3.94 and 4.22 ms in current-claim checks. Neither arm +reproduced the earlier long BEGIN. Native authority controls passed. +Archive the experiment and retire the diagnostic switch. Further +work on these ranked holds should split current-claim reads from +validation inside the deciding transaction. + +The next four-owner shared paced Arrow comparison measured membership +lookup and both manifest reads separately inside the claim check. +An indexed UNION ALL membership query included overlapping origins +once and preserved disjoint budget and history membership. It met +the case's first-frame and throughput limits. Membership median +rose from 43 to 51 µs and claim P99 was 4.48 versus 4.50 ms. +The first-frame and admission-hold improvements in this cohort are +larger than the membership interval. Keep the separate indexed +membership reads and retain the timing split. In the reference, +the manifest median was 0.669 ms, including 0.571 ms in the two +reads. The median per-request remainder was 0.096 ms, including +validation and metering settlement checks. This selects manifest +read execution for the next attribution on the admission path. + +The admission driver split recorded 512 committed and 512 projected +reads per arm across 128 shared paced Arrow streams. No read returned +Pending. Fresh preparation medians were 44 µs for the four committed +reads and 151 µs for the four projected reads. The existing prepared +program mode moved both medians to zero inside the transaction. +Poll wall outside preparation remained close, from 157 to 153 µs +for committed and 211 to 208 µs for projected. Total manifest read +median fell from 0.566 to 0.366 ms. The same-image first-frame P99 +and throughput ratios were 0.778 and 1.040 in this focused cell. +The longest fresh projected read group spent 6.13 ms in polls with +0.49 ms of thread CPU, including only 0.15 ms in preparation. +Preparation reuse reduces the median cost. The long poll gap still +requires separate attribution. + +The same prepared-program image then ran the full eight-case matrix +in both orders, with 128 streams per arm per case. All eight passed +in the first order and four passed in reverse. Reverse independent +immediate Protobuf missed both limits. Independent immediate Arrow +missed throughput, and shared immediate Arrow and independent paced +Protobuf missed first-frame P99. Both shared paced encodings passed +in both orders. Keep the existing opt-in mode and preserve the full +matrix. The driver split supports the preparation saving on the +focused workload while the two-order result leaves adoption open. + +* Local Rust, Go and Scheme integration baseline + +Develop and qualify the Rust and Go execution path locally while ASCENT is being +refactored. Use the existing Scheme application through the native SDK and keep +its local source path available for integration work. CI, dependency cold +preparation and ASCENT optimization are outside this delivery sequence. The +release and approved site replay gates below apply when release qualification +resumes. + +** 1. Establish the local Rust and Go baseline + +Start with the Rust contract, Cedar policy, ledger and broker libraries. Use +their existing unit and property tests with the locked Cargo graph. Run the Go +control plane, gateway client, routing and stream packages under the race +detector. Use four test workers and the configured Go toolchain. Keep each +failure with its exact command and host, and resolve it at the owning layer +before broadening the run. The existing =check-rust= and =check-go= entries are +the broader local regression gates after a focused change passes. + +#+begin_src sh +cargo test --locked --offline -j 4 -p weaver-contracts -p weaver-policy \ + -p weaver-ledger -p weaver-broker --lib -- --test-threads=4 +go -C go test -parallel=4 -count=1 -race ./internal/controlplane \ + ./internal/gatewayclient ./internal/routing ./internal/streaming +#+end_src + +The first vertical slice is source withdrawal and nested Session recovery. +[[file:../../../dev/sysml/ControllerObjectLifecycle.sysml][ControllerObjectLifecycle]] +owns source identity and preparation. [[file:../../../dev/sysml/ControlActivation.sysml][ControlActivation]] +owns activation boundaries. [[file:../../../dev/sysml/StreamingExecution.sysml][StreamingExecution]] +allocates the release path. Use the existing tests to verify that Go preserves +the release receipt, Rust checks the frontier, claim and reservation, and the +Scheme Governor selects only branches enabled by the current facts. Exercise the +real gRPC and provider path for withdrawal, restart and a join that runs once. + +** 2. Connect local Scheme sources through the existing owners + +Keep an already prepared =GERBIL_PATH= as the reference environment. For an +edited dependency, use a separate development package prefix under the ignored +verification cache. Reuse prepared inputs for the other dependencies and use +=gerbil pkg link --global-env = in that prefix. Gerbil +requires the destination package slot to be free before linking it. Record the +resolved path, revision and worktree state of each linked source in the local +receipt. Read local checkout paths from the developer environment. + +Linking selects the package source. Build the affected modules through the +package's native entry and let SDK Build Packages stage the application library +for the Rust test. Use that library in =GERBIL_LOADPATH= before the rest of the +prepared libraries. Check the selected module and loaded product in the actual +consumer so a stale compiled dependency cannot masquerade as the linked +candidate. Start with the current package interface for Rust and Go work. +Exercise the refactored ASCENT checkout as a candidate when its interface +builds. Attribute source-linked results to that checkout and keep release-pin +qualification separate. + +** 3. Verify Rust and Scheme integration and measure the affected path + +Use the existing SDK owner tests followed by the focused Go test +=TestProviderControlSessionNestedChoiceAndParallelRecovery=. Pair it with +=TestProviderControlHardFactWithdrawalRestartAndABA= when touching source or +ledger authority. Set up the [[file:../../../crates/governance/README.org][Gerbil Scheme SDK environment]] +and reuse the prepared policy pkg-config metadata before invoking the Go +fixture: + +#+begin_src sh +go -C go test -parallel=4 -json -count=1 -race -tags=integration,schemeintegration \ + -timeout=10m ./dev -run '^TestProviderControl(SessionNestedChoiceAndParallelRecovery|HardFactWithdrawalRestartAndABA)$' +#+end_src + +Keep the existing 12-second recovery and 15-second natural exit bounds. Run the +affected native suite once after focused correctness passes. For performance +changes, define the sample count, comparison and pass criteria before running. +Use the same local workload on a fixed host and record preparation, native +compile, first load, steady-state execution and restart separately. Keep the +generated receipts and failed samples under the verification cache. A cold +dependency installation is needed only to qualify that installation path. + +The first open checkpoint is the registered =CompileSource= RPC after the +authenticated source channel connects. The startup trace distinguishes +compilation and response validation from publication inspection, task +registration and finalization. On the prepared reference image the startup +failure reproduces at the Rust server's existing 10-second RPC deadline, +before publication. Use the existing Reader metrics to compare import and +bootstrap wall time with CPU time under a measured host load. Keep the same +reference image and the original failure receipts when assessing a candidate. +Control readiness precedes the nested workflow's own recovery clock. + +The next candidate uses the Core Reader's narrower runtime context catalog +and its declared POO revision in an isolated package prefix. Qualify the +producer's existing Reader and compiler Context tests first. They check that +the Reader captures its own Context, excludes build entry roots, and still +rejects changed source inputs. Then rebuild the affected downstream package +products and compare the same Weaver fixture and startup phases with the +prepared reference. Attribute the comparison to the complete Core and POO +candidate pair. Record host load with each sample and retain the original +startup, recovery and shutdown limits. + +The candidate Core is the source revision named by the prepared Lab checkout's +Core gitlink. Its declared POO revision and the existing ASCENT revision were +built in the candidate prefix, and the SDK manifest confirms use of that prefix +for the native modules. The local functional suite and native owner tests pass. +The fixed-load startup comparison shows fewer Reader role imports on the +candidate. Both builds met the RPC deadline in that comparison, with different +background host loads. Keep the earlier timeout evidence and treat the +comparison as a bounded local check. The ASCENT refactor has a separate Core +dependency selection. An isolated build of its committed refactor stopped at +Module publication admission. Its relations, inference and evidence roles +declare the earlier Yuanxu contract object, while the Lab-selected Core +requires a native POO Type for a scope contract. The local Weaver candidate +therefore uses the previously qualified ASCENT package. Admit the refactor +after its owner supplies compatible role declarations and the native consumer +passes the same session and withdrawal controls. + +The existing CPU pressure fixture did not reproduce the reference timeout. +Samples taken during the original source compilation path identified phase +modules entering Gambit's dynamic loader. Module identity and the generated +code explain the bypass: the SDK installs its redirect in the VM's value +binding for =load=, while the compiled Gerbil loader calls the primitive +binding directly. The native two-module control exercises both bindings and +checks that unrelated carriers still load normally. + +Qualify the loader candidate in a private SDK copy using the same package +sources, Weaver fixture and deadlines. Compare the actual loaded module +identities and record uninstrumented timing separately from the process +samples. Verify publication, the nested selection controls and natural exit +before running the affected suite. The installed SDK remains the reference +until the candidate is validated in the consumer. Keep the VM-local binding +and normal fallback semantics in any SDK implementation. + +The first private SDK build passes the affected four-worker Go suite, +including source withdrawal and A→B→A, nested choice recovery and a single +join. Rust tests from the same build pass the owner cleanup and owned VM +capture checks. + +The source qualification uses Gerbil's =src/gerbil/runtime/loader.ss= from +the prepared SDK revision. At the carrier load inside =load-module=, evaluate +=((##global-var-ref 'load) path)= to honor the SDK's VM-local binding. Use +Gerbil's optimizing compiler to emit static Scheme, then the SDK's matching +Gambit compiler to emit C and the object. Compare exported symbols and inspect +the generated binding. Stage that source and those products in the private +SDK, and let the existing Weaver Build Packages entry link the provider. + +Both source-built variants pass the focused native gRPC control with the same +Core, POO and ASCENT. The link-input digests differ at the loader and the +compiler timestamps of two rebuilt fixtures. The diagnostic snapshots show +the candidate uses fewer dynamic carriers and retains the fallback. Keep +process samples separate from the uninstrumented RPC timings. The paired runs +verify the loading mechanism under the observed host conditions. They do not +estimate startup tail latency. + +The source-built candidate's full run with Reader stage accounting still +misses the existing =CompileSource= deadline on several cases. The affected +cases fail during readiness, before the scenario recovery clock starts. +Preserve the failing image, host observations and timing receipt. The +partial-request case passes a separate same-image diagnostic replay with +fewer dynamic carriers and continued expander and POO work. With accounting +disabled, the same image passes the default four-worker integration entry, +including restart, withdrawal and the nested join. The Rust owner and VM +checks pass on binaries from that same build. The runs encounter different +host loads, so they cannot isolate accounting overhead. Keep the deadline +failure receipts as the reference for the next candidate. Attribute the +Reader's remaining compiler Context imports and role expansion while +retaining source and authority checks. + +On the same image, a default/stage/stage/default sequence of the original +partial-request restart case passes all four runs. The first compile and the +restart overlap in timing across both settings. Treat this as a bounded +accounting control with the host observations, separate from the earlier +failed full run. For the next candidate, follow the Lab-selected Core's +separation of role-initializer and published Scope support. Its native +controls must retain currentness for mutated or missing initialization inputs +before the actual Weaver consumer can use the candidate. + +The Lab-selected initialization-support Core passes the 17 native Reader +and compiler controls. The consumer uses that isolated Core and Lab, the +same POO artifacts, and the established ASCENT source rebuilt against the +candidate. The native plan and test-owned image confirm the candidate +Reader and linked dependency inputs. The focused provider run and the +same-image default regression pass, including partial request recovery, +withdrawal, A→B→A and the nested one-time join. The linked Rust owner and VM +tests and existing OpenSysML requirement trace also pass. Candidate results +cover the observed local conditions. The earlier stage-accounting timeouts +remain separate evidence for the readiness tail. + +The same candidate image passes all four previously failing scenarios with +stage accounting enabled, then passes the complete affected suite with the +same accounting configuration. The replay partitions the six startup traces +into the authenticated compile RPC, bundle decode, publication and authority +reconciliation. It also retains the subsequent Governor owner calls and +restart traces separately. The Go workspace race suite passes. These runs +qualify the local source-linked candidate under the existing deadlines. The +earlier run encountered different host load and remains a failed receipt. +Release distribution and matched site performance qualification retain +their separate gates. + +The later locally available ASCENT refactor also refuses at native +=module/publication= scope admission when linked against the qualified Core +and POO. Keep the established ASCENT source in the local candidate. Admission +of the refactored package and its upstream performance work remain separate +from the completed local consumer gate. + +The SDK =bfe803f= debug owner test linked even though the separate +server binary hit a Darwin linker bus error. Its first direct run +rejected the original during source selection. With its own staged +package library restored to the runtime load path, the same test +binary captured both authenticated source results. Each Scheme +capture took about 3.52 seconds. The deployment frontend still +missed its existing three-second activation dial because the second +capture completed after that deadline. The two failures belong to +lifecycle qualification. Preserve the original 10-second +=CompileSource=, 12-second recovery and 15-second natural-exit gates. + +A bounded replay reused the exact SDK =bfe803f= debug owner image +and its staged Scheme load path. The original owner integration +passed, including authenticated Go bootstrap and deployment, +source rotation during an in-flight compile, refusal of the late +artifact and natural owner drain. The two successful captures +before rotation took 1.70 and 1.67 seconds, with 1.60 and 1.50 +seconds elapsed at module-view resolution. The intentionally +declined warm-up and the post-rotation capture are separate +observations. The earlier three-second dial failure remains on +record. This one replay does not establish a startup tail bound. +The archived four-owner Workflow release used SDK =9aa4de6=. +Qualify the 12-second recovery on the current pin's own release. + +The =bfe803f= release then completed the original four-owner +A/A and fresh/retained waves, and both derivation modes passed the +hard-fact withdrawal, restart and A→B→A control, nested choice +and join controls, inactive-branch isolation and cancellation +with natural owner drain. Both joins matched their cut and ready +digests across all eight trials. Wave CompileSource peaked at +6.65 seconds and measured drain at 1.12 seconds. The two nested +restart scenarios ended at 7.98 and 7.53 seconds on the scenario +clock, within 12 seconds. The preceding release build took +5 minutes 42 seconds and is separate from those clocks. Both +SysML checks passed. + +In the fresh/retained wave, the retained owner paid about 77.5 ms +of setup at open. Join setup was zero thereafter, versus 74–77 ms +in the fresh arms. Retained join FFI calls took 0.61–0.79 ms, +frontier reads 4.60–5.61 ms, and claim transactions 2.10–2.93 ms. +Retained owner waits at the joins were 7–8 µs. Keep the current +owner mechanism and scope the timing result to this bounded local +wave. Site performance and the provider promotion matrix retain +their independent gates. * Maintained baseline @@ -27,7 +2233,7 @@ The Rust SDK selection now follows the inspected package operations, tool environment and archive contract replace downstream tool preparation. The already selected Agentic AI Lab cohort is now declared in the single root Scheme dependency instead of separate Go checkout arguments. -Continue delivery in [[https://github.com/hardenedlinux/weaver/pull/1][Weaver PR 1]]; do not open another integration PR. +[[https://github.com/hardenedlinux/weaver/pull/1][Weaver PR 1]] records that integration baseline. Compared with Weaver's previous SPEC selection, this revision changes typed SDK preparation, source-body correspondence, literal-context construction @@ -90,7 +2296,7 @@ package failure or a killed test is FAIL. Keep the existing runtime and lifecycle gates, all generated cases and host-derived core count. Do not use forced exit, package uninstall or a changed dependency pin as a retry. -*** Producer-owned native link inputs +*** SDK package link inputs The observed missing-libcrypto failure originates in a low-level SDK staging path that omitted the package owner's pkg-config declaration and retained an @@ -331,7 +2537,7 @@ declare Scheme end-to-end acceptance or stable performance improvement. #+CAPTION: The imported Zero Trust contract constrains actual Gateway use. [[file:../../architecture/diagrams/00d-zero-trust-overview.svg]] -* Native Runtime measurements +* Scheme owner string encoding measurements Two complete runs each contain fourteen cases and thirty samples per case. External Rust dependencies use opt-level 3; the qualification application retains @@ -580,12 +2786,11 @@ behavior, units and complete sample inventory. A PASS is not performance admission against a throughput, percentile or non-regression threshold. The existing higher performance-qualification contract remains separate. -* Current delivery priority: Rust, Go and Cedar +* Rust, Go and Cedar delivery record -Scheme reader/bootstrap and prepared-scope optimization is upstream owner work -and is deferred from this change. Keep its current source interface and package -selection. No Scheme source or dependency pin is changed. Rust/Go execution must -remain independently testable while that upstream work proceeds. +This delivery batch used the existing Scheme source interface and package +selection while the upstream owner handled reader and prepared-scope work. +The local delivery sequence above specifies how to test linked candidates. ** Typed Cedar facts on the execution path @@ -765,6 +2970,980 @@ change adds neither parallel source publication nor automatic transaction retry. Future contention work must measure those waits and preserve their shared-domain linearization instead of splitting shared constraints for throughput. +** Provider terminal retention + +The queued run holds the bound request for dispatch. An unresolved run +retains its plan and dispatch state. Completion replaces the plan with its +original ceiling in the same transaction as terminal state and any typed +result or usage. The historical exposure projection still compares the +ceiling and plan digest with the independent committed claim. Existing +terminal rows with full plans follow the same projection. + +Use the shared-domain Arrow case of =BenchmarkProviderGoControlPair= to +measure terminal plan bytes separately from the main database and MVCC +journal. Capture both direct and proxy arms after verified completion and +natural shutdown. Open a copy through the native ledger session for the +logical inventory. + +For runtime qualification, build both versions from the same source +snapshot with only the terminal update changed. Run both through the same +Go forwarding path and alternate which arm starts each four-request wave. +The first eight-case matrix completed seven cases within the existing +first-frame and throughput limits. Shared immediate Protobuf failed the +native observation check because a completed BEGIN poll had no recorded +prepare span. Treat that case as incomplete and retain the original +failure. The logical storage result and the runtime qualification have +separate acceptance criteria. + +The regression test opens a Turso session outside the observer after +registering its scoped tracing dispatcher. When that is the only registered +dispatcher, tracing can cache the unobserved callsite's interest as disabled. +Keeping a silent dispatcher registered makes the callsite consider both +dispatchers. The scoped observer still records only the requested driver span. +The rerun completed all eight cases with complete observations. Independent +immediate Protobuf exceeded the first-frame limit. Its ranked request spent +more time in admission and upstream transport. The complete run still +failed the runtime gate. + +The same-image follow-up switches only the terminal write in an observed +release. The compact/compact controls stayed within the original limits +in independent immediate Protobuf and shared immediate Arrow. All eight +full/compact cases produced receipts and met the throughput limit, while +four missed first-frame P99. The measured tail changes include upstream +transport, worker scheduling and consumption. The largest stage differs +by case. The shared Arrow storage copy confirmed the intended terminal +record in both arms. Keep the failed performance decision separate from +the verified logical storage reduction. + +The bounded same-image and reverse-order controls did not reproduce the +independent immediate Protobuf first-frame miss. Shared immediate Arrow +reproduced the gap increase in reverse order, while a later handoff join +showed similar client gap P99 in both arms. In that joined run the two +longest client gaps of each arm accrued before Rust handoff. Use the +per-frame join and shared-domain wait to investigate the release path. +These focused observations do not replace the eight-case runtime gate. + +The paced SSE calibration used the same compact write in both positions. +Three of the four cells differed by more than 10% in first-frame P99. +The later position was faster in all four cells even though the first +position of each four-request wave alternated. Swapping the two write +treatments in the same release left only shared paced Protobuf above +the original first-frame limit. Its compact/full ratio was 1.118, +compared with 1.279 in the original order. Throughput passed in every +paced cell in both orders. In shared paced Protobuf, worker wait was +the largest phase difference in the original order, while admission +was largest in the reverse order. Keep the original failed matrix and +use the ranked stream's lock timeline to test the shared-domain lead. + +The shared paced Protobuf timeline reproduced the miss. The compact +arm's ranked request waited 7.49 ms for admission and 8.72 ms for +consumption. Conflicting admission holds overlapped 6.90 ms and +3.16 ms of those waits, respectively. The same request also spent +14.32 ms committing its first range preparation, compared with +0.14 ms in the full arm's ranked request. Consumption commit itself +took less than 0.10 ms in both arms. The next commit observation must +separate driver polling, thread CPU and sync time at first-range +preparation before changing the write or custody boundary. + +The follow-up observed 128 first-range commits per arm. Medians were +0.078 and 0.076 ms for compact and full. The slowest compact commit +took 8.40 ms, with 0.116 ms in polls, two Pending returns and no +observed sync on that thread. A different compact commit took 1.79 ms, +including 1.63 ms in a sync span. These are distinct sources of +commit wall time. The first-range commits of the ranked first-frame +requests were below 0.10 ms in both arms. The compact request waited +14.12 ms for admission, with 12.78 ms overlapping earlier admission +custody from one peer, and spent 9.98 ms waiting for its worker. The +peer spent 4.18 ms opening its transaction and held it for 8.60 ms. +The observed claim and manifest intervals were 6.29 ms and 3.32 ms +within that hold and overlap. Continue attribution on those two +queues while preserving the durable first-range cut. + +One same-image experiment combined the original and live manifest +reads for each family into a single tagged =UNION ALL= statement. +Both arms used compact terminal writes, the same deciding transaction +and the same digest, ceiling, settlement and history checks. Shared +paced Protobuf manifest P50 stayed effectively flat. Independent +manifest P50 increased by 8.1%, and first-frame P99 exceeded the +existing gate in both cells. The duplicate-member and corrupted +projection controls passed. Keep the combined read isolated and +retain the two existing reads. + +The worker-dispatch calibration separately timed the runtime gate, +the interval from Tokio submission to closure entry, and the Ledger +admission wait. The eight arms each completed 128 paced streams. +Runtime gate P99 reached 8.44 ms. Every submission-to-entry sample +above 1 ms ran on a thread that had already executed tracked jobs. +This interval includes both Tokio wake-up and host scheduling. + +The tracked-submit candidate registers a =TaskTracker= token under +the gate and releases the gate before calling Tokio. Shutdown, +executor custody and output backpressure controls passed. Across +both treatment orders, gate P99 fell from 0.53–8.42 ms to at most +7 microseconds. Independent Protobuf and shared Arrow missed +first-frame P99 in one order. All four paced cells passed in the +reverse order and throughput passed in both. Retain the failed +cohorts and keep the candidate isolated pending order-balanced +first-frame qualification. + +The full eight-cell follow-up ran with each treatment position once +on the same image. The candidate passed four cells when first and five +when second. Runtime gate P99 was at most 13 microseconds in the +candidate, while independent paced Arrow exceeded first-frame P99 +in both orders. Its ranked candidate requests spent 203.22 and +15.29 ms from Tokio submission to closure entry on previously used +threads. Their Ledger admission waits were below 2 microseconds. +Host load was elevated and the original limits still apply. Keep +the candidate isolated. A separate shutdown control paused after +the tracking token was registered and before Tokio submission. +Drain stayed pending with the execution slot held. Resuming +submission after cancellation skipped the callback, returned the +slot and allowed drain to finish. + +The independent paced Arrow diagnostic used an isolated Tokio 1.53.1 +build to join each request to the blocking pool's submission lock, +enqueue, dequeue and closure entry. Across both treatment orders and +arms, submission-lock P99 was 8.88–13.93 ms, queue residence P99 +was 6.85–17.21 ms, and dequeue-to-closure P99 was at most 23 +microseconds. Each arm's slowest handoff saw an empty queue and two +or three idle workers when the submitter obtained the pool lock. +The pool had nine threads against a cap of 516. These observations +direct further work toward lock-holder and worker wake timing. +The candidate-first run missed both runtime limits and the reverse +run passed. The diagnostic leaves the original performance decision +in force. + +The follow-up linked submission waits to the last recorded pool lock +holder and recorded the condition-variable return on the dequeuing +worker. The four longest submission-lock waits across the two arms +and orders were 10.07–20.93 ms. In each case the last recorded holder +was a dequeue and overlapped less than 0.34 microseconds of the wait. +This lower bound leaves earlier holders and submitter scheduling open. +In the candidate's longest queued samples, the submitter released +the lock within 0.25 microseconds of notification, and the dequeuing +worker reacquired it about 9.14 and 12.78 ms after notification. The +common condition variable permits only a timing association. The +candidate-first cell again missed first-frame P99, the reverse cell +passed, and both throughput ratios passed. Shortening the observed +notify-to-unlock interval alone has little room to reduce these tails. + +The Provider scheduling comparison registered the same tracking token +and released the same gate in both arms. One arm used the blocking +pool directly. The other queued a Tokio task that entered +=block_in_place= before running the same closure. In the two-case +diagnostic, both treatment orders passed independent paced Arrow and +shared paced Protobuf. Independent paced Arrow first-frame P99 was +47–49% lower in the candidate. The original eight-cell matrix then +passed four cells with the candidate first and six with it second. +Shared immediate Protobuf missed throughput in both orders, and +independent paced Protobuf missed first-frame P99 in both. The latter +ranked requests spent less time waiting for their worker in both +orders, with the largest increases after worker entry. Shared +immediate Protobuf's admission hold median and Rust CPU per stream +were similar in both arms. Keep the scheduling candidate isolated. +The tracked-but-not-submitted shutdown and backpressure controls +passed on the comparison image. + +The range-digest experiment reused a request-local JSON buffer. It +kept the exact serialized bytes, SHA-256 and release ordering. The +digest equality test covered a large escaped Unicode payload followed +by smaller ranges using the same buffer. Backpressure controls passed. +Shared immediate Protobuf met both limits in both treatment orders. +Independent paced Protobuf missed the first-frame limit with the +candidate first and met it in reverse. In the miss, the ranked +request spent most of the added time before frame preparation, +particularly in admission and upstream transport. Process CPU +did not improve consistently. Retain the focused comparison and +keep the buffer candidate isolated. + +The Provider claim insert experiment removed the separate occupied-key +read. The existing =(family,node)= primary key rejected a conflicting +insert before any budget or history update. WAL and MVCC controls +verified that occupied request, stream and provider claims kept their +original contents, budget and history. Reservation P50 fell in all four +focused cohorts by 0.6–11.6%, and Rust CPU per stream fell by 1.6–3.5%. +All first-frame ratios passed. Shared immediate Protobuf missed +throughput in the reverse order at 0.919 of baseline, with an inter-frame +P99 ratio of 1.860. Keep the candidate isolated and attribute that +frame gap before widening the comparison. + +The same-image frame-gap replay joined all 1,536 consecutive gaps per +arm to the Rust handoff, receipt acknowledgment, receiver acceptance +and Go receipt. Inter-frame P99 was 0.821 and 0.800 of baseline in the +two orders, so the earlier increase did not recur. Most of each +candidate ranked gap accrued between Rust handoffs. In this replay +the first-frame limit failed in both orders. The largest added +interval on the ranked request was consumption with the candidate +first and admission with the candidate second. Keep both observations +and the original failed throughput cohort. The wall-clock join +measures handoff and transit deltas, while the per-request scope totals +remain separate from exact scope overlap with a frame gap. + +The queued-row reuse experiment selected the plan, digest and reservation +in one read inside consumption. It checked the requested family and node +against the plan, then compared the selected digest and reservation against +the committed claim. The three substitution controls rejected each mismatch +and preserved the queued rows and hold. The first control setup was retained +after policy rejected its test node. The corrected control used a permitted +second node. + +With one release image and 128 streams per arm per cohort, three of four +cohorts met the first-frame and throughput limits. In the reverse-order +independent paced Protobuf cohort, first-frame P99 rose from 56.19 to +121.30 ms and throughput fell from 26.73 to 25.15 streams/s. Claim P50 +fell from 0.607 to 0.544 ms in that cohort, while consumption transaction +P99 rose from 6.20 to 13.89 ms. On the two requests ranked at first-frame +P99, the 41.14 ms consumption increase included 21.37 ms more publication +preparation before the transaction and 3.85 ms more transaction hold. +Keep the candidate isolated and the full matrix gated. Split review-head +and task-birth preparation on the existing path before selecting the next +change. The ranked requests identify where time accrued in the failed +sample. They do not establish the cause of the publication preparation tail. + +The split preparation replay used the existing two-read consumption in both +arms of the same release. All 512 measured preparation spans had a reviewed +head and a bound birth receipt. Across the two orders, consumption review +preparation P50 was 3.61–3.65 ms wall and 3.50–3.54 ms thread CPU. Birth +preparation P50 was 0.047–0.049 ms wall. The review stage accounted for +most preparation time in both ranked first-frame requests from the +observed arm. The extra observation arm missed the first-frame limit in one +order and the throughput limit in the other. Use these timings for phase +attribution and retain both failures. This replay did not reproduce the +25.45 ms preparation span from the queued-row candidate. + +Admission and consumption already share one Ledger connection for a Provider +request. The review preflight runs the same fixed SQL through fresh query +preparation in both phases. Compare reusing only the connection's compiled +review query, with a fresh cursor and current rows in each phase. Keep the +existing exact review, birth, authority and fence comparisons in the deciding +transaction. The phase replay identifies review preparation as the next +target. It does not distinguish SQL compilation from query execution. + +The compiled review query candidate passed the repeated-read mutation check +and the task-birth controls. Its four targeted cohorts met the first-frame +and throughput limits. The full matrix on the same image kept one +unjoinable observation failure in the first order. Of the 15 cohorts with +complete measurements, 11 met both limits. The four misses were in +immediate SSE and all missed the first-frame limit. Independent immediate +Arrow missed in both orders at 1.607 and 1.439 times the reference. +The larger increase on the ranked request was enqueue in the first order +and consumption in the second. The candidate stays isolated. Separate +missing trace observations from ordering failures in subsequent diagnostics +and use the retained immediate cohorts to investigate the two outer stages. + +Joining the ranked requests to their scheduler grants separates several +sources of delay. For independent immediate Arrow in the first order, +the 30.24 ms increase in enqueue included 19.34 ms more commit wall time +and 0.11 ms more commit thread CPU. In the reverse order, headers to +first queue contributed the largest increase in both Arrow misses +(25.33 ms independent and 42.52 ms shared). The independent Protobuf miss +spent 37.55 ms more in publication preparation before the enqueue +transaction. These intervals describe the ranked requests. They do not +identify a single cause across the failed cohorts. + +An immediate Arrow diagnostic then measured response headers, first +queue and scheduler scopes on one monotonic clock. It joined all 512 +requests across the two domains and two same-path arms. The median +headers-to-queue interval was 3.42–3.65 ms for independent domains and +6.52–6.63 ms for a shared domain. The median time before the first +release scope was under 0.07 ms in all four arms. Preparation and final +queue hold accounted for most of the interval, including the requests +ranked by first-frame P99. The independent same-path pair exceeded the +first-frame ratio limit at 1.190. Retain that result as diagnostic +variation. The next candidate compares ordered projected rows directly +with the exact retained claim map to avoid building a second tree in +each deciding transaction. It retains the separate prepare and final +queue guards, duplicate rejection, checked totals and settlement checks. + +The ordered member comparison passed all 24 exposure controls. Three of +four immediate Arrow cohorts met the existing limits. In the first-order +independent cohort, throughput fell from 55.08 to 51.38 streams/s +(0.933 of reference). The first final queue transaction P50 increased +27.5%, and Rust CPU per stream increased 3.5%. Manifest medians moved in +both directions across orders and stages. Keep the candidate isolated. +Read completed worker traces after the fixture's natural exit, outside +the measured interval. The exact-window diagnostic and the member +comparison both used this order and retained complete traces. + +The next phase diagnostic retained the exact manifest and separated +the two SQL reads, committed-member decoding, projected-map construction, +settlement and final comparison. In the independent immediate Arrow +cohort, the median per-request share of measured thread CPU in the SQL +reads was 85.2% in both first-frame transactions. Map construction, +committed decoding and exact comparison together accounted for 4.3–4.4%. +The shared cohort failed the first-frame trace join. Its projected +response-header wall timestamp was 3.157 ms later than the sampled +queue wall timestamp. Preserve that failure and join the Rust and Go +first-frame events on a shared host monotonic clock. + +With the shared clock, the fixed-release diagnostic joined all 512 +requests. Across independent and shared Arrow, the two reads accounted +for 85.5–86.1% of measured CPU at the first prepare and queue +transactions. The projected read used the most CPU in all four +comparisons. In shared Arrow its P50 was 0.836 ms in prepare and +0.477 ms in queue. Retain the exact comparison and measure driver SQL +preparation separately from row execution and decoding. The clock +change applies to request-to-first-frame attribution in the test entry. +The diagnostic's arm ratios measure variation with the extra clocks. + +The next same-image diagnostic used Turso's preparation span to split +the projected read for the first prepare and queue scopes. It matched +one preparation per independent domain and four per shared domain in +each observed scope. Across the four scope/domain combinations, the +median per-request CPU shares were 39.2–39.8% for SQL preparation, +5.5–6.6% for typed row decoding, and 52.8–54.8% for the remaining +cursor work and observation overhead. The instrumented arm missed +independent first-frame and shared throughput limits. Keep both +measurements as diagnostics. The next comparison prepares only the +projected query on first use of the existing connection, with no +extra preparation before the deciding scope. Each use binds the +current family and opens a fresh cursor. + +In the same shared Arrow diagnostic, the remaining cursor-and-observer +CPU increased between the first and last eight waves from 0.169 to +0.609 ms in prepare and from 0.138 to 0.496 ms in queue. Preparation +CPU decreased slightly in both comparisons. Keep request ordinal as a +workload grouping and measure live row counts before assigning the +growth to a specific operator. + +Preparing only the projected query on first use passed 25 correctness +controls and reduced the manifest P50 in every measured first prepare +and queue scope. The reduction ranged from 6.0% to 34.6%. Both first-order +cohorts met the existing limits. In reverse order, independent and +shared first-frame P99 reached 2.058 and 1.579 times reference, and +shared throughput fell to 0.874. Keep the candidate isolated. +The independent ranked request held its first preparation scope for +169.80 ms, with 0.22 ms attributed to the manifest and 0.13 ms to commit. +The shared ranked request waited 173.66 ms for admission. Peer grants +overlapped 129.99 ms of that wait, with 43.67 ms outside those observed +scopes. Split the outstanding preparation wall time from thread CPU +and instrument the range staging statements. The peer overlap is a +timing bound and does not assign the residual to a specific lock. + +The next diagnostic measured transaction wall and thread CPU alongside +progress reads, the live Policy guard, range inserts and cursor update. +It did not reproduce the 169.80 ms hold. The longest independent first +preparation took 16.51 ms wall and 3.03 ms thread CPU, including a +13.20 ms Policy guard with 1.79 ms CPU. The longest shared preparation +took 20.84 ms wall and 7.40 ms CPU, including 13.71 ms in claim +verification. Median range inserts and cursor updates each stayed +below 0.16 ms. The shared instrumented arm missed the first-frame +limit. Preserve that result and target the repeated Cedar inputs, +keeping a fresh context and an error-free allow for each actual row. + +The shared Cedar-input candidate passed 56 correctness checks, +including comparison with the original per-row evaluations and the +grouped rollback, withdrawal and recovery paths. Cedar P50 decreased +in six of eight first preparation and queue measurements, stayed flat +in one, and increased 9.0% in the other. Only one of the four HTTPS +cohorts met both original limits. The first-order independent cohort +missed both, with first-frame P99 at 2.158 times reference and +throughput at 0.765. The ranked request added 114.93 ms in enqueue, +including 81.98 ms in publication preparation and 41.56 ms in +transaction begin. The added BEGIN thread CPU was 0.69 ms. In the +reverse shared cohort the ranked request's first preparation hold +increased from 23.15 to 49.16 ms. Keep the candidate isolated and +preserve the separate stage observations. + +The admission replay joined publication preparation and BEGIN on the same +1,024 requests across ordinary and controlled pressure runs. The longest +ordinary review preparation took 137.61 ms wall and 8.07 ms thread CPU. +The longest ordinary BEGIN took 20.24 ms wall and 1.57 ms CPU. The +longest BEGIN in every arm completed in one poll without Pending. +The four pressure workers actually used 1.62–1.66 CPU cores. They did +not reproduce a larger maximum than ordinary load. Both paths retain +substantial off-CPU intervals. Poll timing alone does not distinguish +synchronous engine waits from host scheduling. Use the exact review +query plan to select work that can be removed in the common case. + +On the reviewed-head control, Turso labels the MAX epoch predicate +as a scan. The bytecode shows that it positions at the last key and +jumps directly to aggregate finalization, skipping the reverse-iteration +opcode. The descending LIMIT 1 form also stops after that key. +The alternate upper-bound absence probe adds a correlated lookup. + +The correlated upper-bound probe passed ten controls, including 32 +retained key epochs and rejection after rotation. It missed both +performance limits in all four Arrow cohorts. Throughput was +0.689–0.827 of reference, and Rust CPU per stream increased 24–45%. +Publication preparation also took longer on each ranked request. +Keep the aggregate path. The indexed-probe label does not predict the +cost of the full query, and the bytecode rules out retained-key traversal +as the common-case cause. Split compilation and execution of the +complete review projection before changing its joins. + +The split on the current projection joined 512 Arrow requests and +checked one Turso preparation per observed admission or consumption. +Across both domains and arms, median per-request compilation accounted +for 95.6–96.7% of the projection's thread CPU. Typed row decoding +accounted for about 0.1–0.2%. The shared diagnostic pair exceeded the +first-frame limit. Keep that observation separate from optimization +acceptance. The next comparison constrains the order of the +singleton and key-bound joins while preserving the same SQL +predicates, snapshot and deciding-scope comparisons. + +The constrained-order candidate passed nine review and birth +controls. The reviewed-head fixture retained indexed lookup for the +singleton, publication, review, delta and key tables. The original +and constrained projections returned the same Policy on the current +fixture and agreed after each injected row change. In four targeted +immediate Arrow cohorts, median compilation CPU fell from +2.11–4.51 ms to 0.28–0.65 ms. All four cohorts met both original +limits. The full eight-case comparison uses the same image and +the same two orders. + +The full comparison completed all 16 cohorts with matched traces. +Compilation CPU P50 decreased in all 32 admission and consumption +groups, by 82.1–90.7%. Rust CPU per stream decreased in all 16 +cohorts, by 2.4–22.8%. Ten cohorts passed both end-to-end limits. +Shared paced Protobuf missed throughput in both orders, and five +cohorts missed first-frame P99. Keep the candidate isolated. Among +the ranked misses, the largest added interval was worker setup in +one, consumption in two, and headers to queue in three. The +largest was 157.01 ms of worker setup in shared paced Arrow, while +both publication-preparation stages on that request were shorter. +Retain these matched requests when separating worker setup, +consumption and release tails from the compilation improvement. + +The worker setup diagnostic used the fixed reviewed-head query in both +arms and joined 512 paced Arrow requests. Setup P50 was 0.282–0.295 ms. +The Ledger open interval including cancellation setup accounted for +0.198–0.213 ms, principal and observer setup accounted for +0.064–0.067 ms, and remaining setup accounted for 0.006–0.007 ms. +The longest setup was 2.80 ms with 0.43 ms of thread CPU. +The 157.01 ms difference from the full matrix did not recur. Both +same-path pairs met the registered limits. Preserve the original +failure and investigate the repeated shared paced Protobuf throughput +miss with the per-frame clock and scope intervals. + +The two-order shared paced Protobuf replay joined 512 requests and +6,144 consecutive frame gaps. The throughput ratios were 1.013 and +1.125, so the prior throughput misses did not recur. In three of the +four requests ranked at inter-frame P99, the prepare and final queue +holds covered at least 98% of the Rust handoff interval. The other +ranked gap included 9.74 ms outside its own scopes and a 5.43 ms +increase in handoff-to-client transit. Keep the original complete +matrix as the promotion gate. The Go benchmark measures consecutive +client receives with its monotonic clock, and retains the original +cross-process observations for handoff attribution. + +The largest individual gap in the first candidate arm had a +104.43 ms Rust handoff interval, including 95.07 ms in preparation +hold. In the reverse order, the largest candidate client gap was +80.50 ms with a 15.56 ms handoff interval and a 64.94 ms increase +in transit. Measure preparation CPU and delivery acknowledgment +separately in subsequent attribution. + +The acknowledgment replay joined 6,656 frames across both orders on +the same host monotonic clock. Across the four arms, P99 ranged from +0.55–1.52 ms for queue to acknowledgment, 0.59–2.10 ms for +acknowledgment to receiver acceptance, and 1.66–5.39 ms for receiver +to Go. Receiver lock wait P99 was below 0.42 µs. The longest reverse +candidate gap included a preparation transaction of 69.22 ms wall +and 3.43 ms thread CPU. Claim verification accounted for 46.19 ms +wall, including 40.24 ms in the manifest. Within the manifest, the +current projected read accounted for 39.63 ms wall and 0.52 ms +thread CPU. Transit was shorter than for the preceding frame. +The reverse pair missed first-frame P99 at 1.373 of reference. +Both throughput ratios met the diagnostic +limit. Keep the complete matrix as the acceptance gate. Separate +manifest execution and off-CPU time in the next preparation trace. + +The projected-read poll trace joined all 512 requests and 6,656 frames +across both orders. Its longest projected read was 6.73 ms. SQL +preparation accounted for 6.49 ms wall and 0.51 ms thread CPU. All four +polls in that read returned ready, with 5 µs outside the polls. The +39.63 ms read did not recur. The timing locates the measured delay +within preparation and leaves the cause of its off-CPU time unresolved. +Throughput met the gate in both orders. Reverse first-frame P99 again +missed, at 1.455 of reference. + +The next same-image pair used fixed review joins in both arms and +reused only the projected-members SQL program in the candidate. Each +execution bound the current family and read rows in the deciding +transaction. In each order, 1,408 preparation scopes per arm overlapped +an observed frame interval. Their median projected read fell from +0.529 to 0.299 ms and from 0.511 to 0.308 ms. Candidate preparation +P99 recorded no SQL compilation, while one candidate read still took +19.14 ms with no compilation and four ready polls. All 24 exposure +controls, four backpressure controls, and two SysML checks passed. + +Throughput ratios were 0.990 and 1.020. First-frame P99 ratios were +4.600 and 0.796. Keep the candidate isolated. For the first-order +candidate at P99, 149.34 ms elapsed before handoff and 8.35 ms after. +Its 56.94 ms from response headers to queue included 47.95 ms in the +first preparation hold and 8.24 ms in the final queue hold. The +preparation transaction used 6.53 ms thread CPU across 47.32 ms wall. +Its claim check included 17.55 ms in history verification and 0.93 ms +in the current projected read. Before changing the history query, +separate its expected-map construction, current SQL preparation and +cursor polls, and row comparison at the first-range transaction. +Preserve the full-matrix failure and both focused orders. + +The history trace used the same SQL and release path in both A/A +arms. It observed 512 first-range preparations and 6,144 preparation +scopes in total. Across the four arms, median first-range history +verification took 0.267–0.293 ms. The current row read took +0.245–0.265 ms, expected-map construction took 6.7–7.9 µs, and row +comparison took 8.3–9.3 µs. No history-read poll returned Pending. +The longest history check took 47.10 ms. One ready poll accounted +for 47.03 ms wall and 1.08 ms thread CPU, including 17.50 ms wall +and 0.147 ms thread CPU in SQL preparation. This locates the delay +inside the synchronous part of the driver poll. Distinguishing +thread scheduling from blocking inside that poll requires additional +evidence. + +The longest history check belonged to a different request than the +reverse-order first-frame P99. The ranked request spent only +0.443 ms in its own first-range history check. Even with the same +path in both arms, reverse-order first-frame P99 was 76.01 versus +194.40 ms and throughput stayed within 2%. Use the original +eight-case matrix to characterize same-path variation before +interpreting the next SQL candidate's end-to-end effect. Keep the +registered acceptance limits for candidate promotion. + +The same-path matrix completed all eight cases in both orders, using +one image and 128 streams per arm per case. Across the 16 pairs, +swapping the slower and faster labels as needed to measure spread, +12 exceeded the first-frame limit and three exceeded the throughput +limit. The largest first-frame ratio was 3.80 and the lowest +slow-to-fast throughput ratio was 0.848, both in independent +immediate Protobuf in the reverse order. This records variation under +the observed host load. Candidate acceptance still requires the +original one-direction limits in both orders. + +The first-frame trace joined the enqueue and consume transactions for +all 32 ranked requests in the same-path matrix. Among the 12 pairs +with excess first-frame spread, the largest added phase was enqueue +in three, consume in three, upstream transport in two, queue to client +in two, worker setup in one, and dispatch outside transport in one. +In the largest spread, consume accounted for 54.72 ms of the +82.91 ms difference. The slow consume transaction held for 51.91 ms +with 3.46 ms of thread CPU. BEGIN and COMMIT each took less than +0.08 ms. Cedar accounted for 12.02 ms wall time, and the claim check +took 0.43 ms. Preserve these matched observations when attributing +wall time in the consume transaction. Its thread CPU and hold time +are distinct measurements. + +The focused consume trace joined 512 independent immediate Protobuf +requests across two same-path orders. Median consume hold was +3.69–4.69 ms. Median queued-plan read and decode was 36–38 µs, +route selection was 1.50–2.65 ms, and Cedar within route selection +was 0.065–0.121 ms. The longest transaction held for 58.96 ms and +used 4.14 ms of thread CPU. Its claim check took 53.62 ms wall +and 1.25 ms thread CPU. Treat the prepared-plan handoff as a bounded +CPU optimization. Continue investigating the longer route and claim +holds with the existing currentness checks enabled. + +The prepared-plan candidate joins exact queued bytes and the durable +digest before borrowing the enqueue plan. A mismatch takes the normal +decode path under current authority. A changed fence with an unchanged +digest was rejected, preserving the queued receipt and original hold. +Restoring the original bytes allowed one consumption. All 29 Rust +controls and two SysML checks passed. The focused two-order A/B reduced +the median queued-read CPU by 3.2–3.7 µs and the median digest and +winner phase CPU by 6.9–7.4 µs. Total median consume CPU increased +by 25–32 µs. Both first-frame and throughput ratios met the +registered limits in the focused cell. This result leaves the +candidate isolated for the full matrix. + +The full prepared-plan matrix completed both orders and all eight +cases. Nine of 16 cohorts met both limits. Six exceeded first-frame +P99 and four missed throughput. Plan-read CPU P50 fell in all 16 +cohorts by 1.3–6.5 µs, and digest and winner CPU fell by 5.8–8.2 µs. +Total consume CPU P50 fell in ten cohorts. Keep the candidate isolated. +The largest added first-frame phase in the seven misses was consume +in three, enqueue in two and upstream transport in two. In the three +consume cases, the ranked candidate requests spent at most 0.081 ms +reading the plan and 9.02–12.90 ms holding the transaction. Route +selection and claim verification accounted for most of that hold. +Keep the archived same-path variation and currentness controls when +testing the next reduction in repeated authority preparation. + +The route trace joined 1,024 immediate Protobuf requests across +independent and shared domains in two same-path orders. Median route +CPU was 1.45–1.69 ms. Current publication and task birth used +0.356–0.401 ms, the domain view used 0.307–0.396 ms, and the profile +and task floor used 0.330–0.359 ms. Task decode and Cedar binding +used 0.102–0.111 ms, and Cedar itself used 0.069–0.083 ms. +The same-path pairs missed the throughput limit twice and the +first-frame limit once. Separate profile SQL preparation, row +execution and typed decode before deciding whether to reuse the +profile preparation or its SQL program. The transaction must still +match the exact registry record and verify the current task floor. + +The profile SQL comparison completed 1,024 immediate Protobuf +requests across both orders and domain shapes. Median profile CPU +fell from 390–451 µs to 237–270 µs. Floor-query preparation used +283–332 µs in the reference and 151–169 µs in the candidate. Typed +profile decode and digest used 9–12 µs in both arms. Every consume +scope still recorded driver preparation for both statements. The +observed reduction therefore does not establish a compilation-free +hit. Check the prepare count and statement context across admission +and consumption before choosing the next reuse boundary. +Only one of four cohorts met both registered end-to-end limits. +Keep this candidate isolated. All 37 Rust controls and both SysML +checks passed. + +The prepare counters matched both scopes for all 1,024 requests. +For each profile statement, enqueue prepared once in both arms. +Consume prepared twice in the ordinary arm and once in the cached +arm. All observed root prepares happened before reading rows, with +zero execution-time reprepare spans. The ordered fixture tries a +Cedar-denied route before its allowed primary on consume. The +cache removes the second compilation within consume while the +common reads still repeat. The next candidate retains a successful +publication, profile and task read only within that same transaction, +then evaluates each eligible route with its own Cedar request. A +failed common read is retried for the next eligible route as before. +The comparison uses ordinary SQL in both arms to isolate this change. + +The route-input candidate completed 1,024 requests with the ordered +denial and one successful primary invocation per request. Both +profile statements prepared once per consume in the candidate and +twice in the reference. Median route CPU fell by 0.304–0.775 ms +and median consume CPU fell by 0.363–1.254 ms across the four +cohorts. Both independent pairs met both end-to-end limits. Both +shared pairs missed throughput at 0.916 and 0.943 of reference, +and the candidate-first shared pair also missed first-frame P99. +Keep the candidate isolated at the focused gate. All 37 Rust +controls and both SysML checks passed. + +Rejoining the archived shared paced Protobuf trace gives 6,656 +monotonic frame observations. None required receiver refresh. +Queue-to-Tonic P99 was 1.076–2.572 ms across the four arms, and +acknowledgment-to-Tonic P99 was 0.535–1.840 ms. The receiver's +measured turn P99 was 9.6–12.1 µs. This interval starts after +frame preparation and includes the queue-to-acknowledgment wait. +The ready-frame envelope needs a separate eligibility timestamp +after credit and current authority are available. Record that +timestamp alongside scheduling and receiver acceptance before +qualifying the 1 ms target. + +Two shared paced Protobuf A/A orders on the same image joined 6,656 +frames from the ledger acknowledgment through Tonic acceptance. Of +these, 5,065 were polled at least once before acknowledgment. No +closed-authority polls or receiver refreshes were observed. Across +the four arms, P99 from the later of acknowledgment and the preceding +frame's acceptance to the accepting poll was 1.343–2.793 ms. P99 from +that poll to Tonic acceptance was 13–14 µs. The earlier timestamp is +a lower bound on eligibility for a frame with reserved capacity. +These measurements exclude frame preparation and do not establish +continuous authority or qualify the 1 ms envelope. + +Compare a producer-held inert frame and reserved permit against the +current pre-commit channel publication. Keep staging inside the +existing transaction and make the frame visible to the receiver only +after the commit outcome is known and acknowledgment succeeds. +Preserve the final authority check, cancellation and unknown-outcome +handling, and the existing capacity bound. Time staging, acknowledgment, +channel visibility, and receiver acceptance separately. Use both run +orders to test whether one publication per deliverable frame reduces +receiver wakeups and the delivery tail. + +The isolated candidate passed both orders of the four-worker shared +paced Protobuf pair. The same release image ran both arms with 128 +streams and 1,664 frames per arm in each order. Pre-acknowledgment +polls affected 1,242 and 1,309 reference frames and zero candidate +frames. Acknowledgment-to-Tonic P99 fell from 3.177 to 2.120 ms and +from 4.260 to 3.747 ms. One candidate frame in the second order +encountered closed authority. First-frame P99 was 1.000 and 0.850 +of reference and throughput was 0.979 and 1.043 of reference. +Client inter-frame P99 moved in both directions, from 20.26 to +21.36 ms and from 40.33 to 36.73 ms. + +The original backpressure properties passed in the reference arm. +In the candidate, the same property faults left the channel empty +before acknowledgment, with an acknowledged frame observable after +the successful outcome. The five slow-consumer scenarios and both +SysML checks passed on the local qualification path. The injected +crash for the candidate occurs after private staging and before commit. +The held permit is discarded before sending a terminal status on +producer failure. Keep the candidate isolated pending the eight-case +both-order gate. The measurements leave the 1 ms delivery target open. + +The eight-case matrix completed both orders on that release image. +The frame join covered 34,816 observations across both arms. The +reference polled 9,805 frames before acknowledgment, and the +candidate polled zero. Acknowledgment-to-Tonic P99 fell in 13 of +16 pairs. Ten pairs met both original end-to-end limits. Six missed +first-frame P99, and two of those also missed throughput. The largest +first-frame ratio was 2.491, with throughput at 0.832 of reference, +in independent immediate Arrow in the second order. Keep confirmed +publication isolated. + +Consume accounted for the largest added phase in four of the six +ranked first-frame misses. In the two shared paced Arrow misses, +candidate owner-gate waits were 32.23 and 63.57 ms against 5.46 and +0.0003 ms in the corresponding reference requests. In the two +independent Arrow misses dominated by consume, the candidate +transaction held for 17.18 and 24.22 ms with 5.33 and 4.08 ms of +thread CPU. These ranked comparisons use different request +identities in each arm. They locate the observed tail without +establishing that the publication change caused it. For the next +candidate, separate owner-gate delay from transaction hold and +identify which work occupied the gate before changing scheduling. + +The archived shared paced Arrow cases joined 5,632 scopes from 512 +requests by scheduler ordinal. In the two ranked candidate consume +waits, observed conflicting grants covered 22.94 of 32.23 ms and +54.47 of 63.57 ms. All five observed holders were peer enqueue +admissions with exclusive custody. Earlier conflicting tickets were +visible without a traced active conflict for another 5.28 and +6.15 ms. The remaining 4.02 and 2.95 ms were uncovered by the trace. +Compatible origin-write scopes from other families were excluded, +even when they overlapped the wait. + +The five holders took 10.64–16.66 ms of transaction wall time, +5.15–6.66 ms of transaction thread CPU, and 1.01–7.88 ms to begin. +Commit ranged from 0.24 to 4.03 ms. This prioritizes the complete +enqueue custody interval, including BEGIN, for the next comparison. +Keep FIFO order and the exclusive shared reservation boundary. +Compare work that can be moved before custody only when the deciding +transaction can rejoin the exact authoritative inputs. Distinguish +elapsed time outside thread CPU from measured engine waits before +selecting a scheduling change. + +The enqueue task-reuse candidate retains the decoded task already +verified by original-task preparation. The Cedar binding may use it +only when the record reread in the deciding transaction matches the +prepared bytes. A mismatch or unavailable preparation falls back to +current-record decoding. The guard still builds its binding for the +actual route and evaluates current Cedar, and original-task, claim +and reservation checks retain their existing custody. + +Both orders of the independent and shared paced Arrow pair completed +on one release image. The enqueue hold P99 fell by 16.8–28.1% in the +four pairs. All four passed throughput. Three passed first-frame P99, +and shared Arrow in the second order rose from 202.0 to 224.3 ms +against the 1.10 limit. The ranked candidate's headers-to-first-queue +interval was 100.64 ms against 42.49 ms. The first prepare hold was +67.52 ms against 9.61 ms, including a candidate prepare commit of +61.45 ms against 0.40 ms. These are different ranked requests. +The result leaves the candidate isolated and the exact prepare-commit +wait unattributed. All 136 ledger controls, four server backpressure +checks and two SysML checks passed. + +The first-prepare follow-up joined 512 commits to the existing Turso +poll and Unix sync counters on one observed release image. The earlier +61.45 ms commit did not recur. The largest was 3.28 ms, almost all +inside one poll, with 0.078 ms of thread CPU and 0.030 ms in the +observed sync span. Other commits spent 2.71 ms in sync or 3.10 ms +between polls after Pending. These counters distinguish the measured +shapes without assigning unsampled time to a specific engine lock. + +The reverse-order first-frame miss recurred at 118.2 versus 99.6 ms. +Both ranked first prepare commits stayed below 0.10 ms. The larger +interval was dispatch outside upstream transport, at 55.41 versus +8.66 ms. The ranked candidate's guarded-send scope held for 49.92 ms +with 5.55 ms of transaction thread CPU and a 0.55 ms commit. Its +scheduler wait was below 1 µs. Attribute the remaining guarded-send +span before altering either the send seal or range durability. +This run is a diagnostic and leaves the task-reuse candidate isolated. +Four backpressure checks and two SysML checks passed on the image. + +The guarded-send follow-up reused both shared paced Arrow orders and +joined 512 transactions to live guard, request callback, callback +record and commit measurements. The 49.92 ms hold did not recur. +The longest hold was 25.46 ms, with 17.27 ms in the callback and +0.34 ms of callback thread CPU. Its claim check took 3.72 ms and +its commit took 3.56 ms. Among the other three arm maxima, the claim +check was the largest measured part, at 7.53, 2.49 and 5.80 ms. +The callback does include existing connection and write stages. +The current join does not partition its longest off-CPU interval +among those stages. The separate thread CPU clock brackets the wall +measurement and exceeded it by up to 4 µs on short substeps. + +Both focused orders met the original end-to-end limits under this +observer. Keep the earlier failures and keep task reuse isolated. +Use the exact live claim reconciliation and the callback's existing +connect, TLS, write and seal boundaries for separate follow-ups. +Do not move application writes or their seal outside current authority. + +The callback follow-up retained the existing Rust transport trace in +the Go benchmark output after measurement. It used the same release +image and joined all 512 callback, transport and claim observations. +Of 28 callbacks lasting at least 2 ms, 27 spent at least 90% of their +wall time in TCP connect plus TLS. In the 11.73 ms maximum, connect +took 6.23 ms, TLS 5.42 ms, and write through seal 0.021 ms. The +largest callback interval outside the measured transport stages was +0.41 ms. Keep connect, TLS and write under the invocation guard as +specified. The measurement supplies no basis for optimizing seal +CPU or moving a network effect across that boundary. + +Among the 20 longest claim checks, the manifest was the largest +observed component in 18, and the two manifest SQL reads exceeded +decode in 19. The longest claim spent 6.87 ms in the committed read +and 4.27 ms in the history check. This selects SQL read execution +and waiting for the next claim comparison. Prior prepared-program +and combined-query failures remain relevant. The first-order +first-frame ratio was 1.248 and failed the existing limit. The +second order passed both limits. This remains diagnostic. + +The manifest driver follow-up paired 512 guarded sends and all four +family reads per query in each send. Neither query returned Pending +across the 4,096 observed reads. The largest interval outside polls +was 73 µs. The longest projected read was 9.56 ms, including 7.81 ms +inside the SQL preparation span. Its preparation thread CPU was +0.43 ms. A 5.06 ms committed read spent 5.01 ms inside the driver +polls outside the preparation span. These are different tail shapes. +The poll and preparation clocks do not distinguish preemption from +synchronous engine blocking. + +Median poll thread CPU was 0.355 ms for the four committed reads and +0.521 ms for the four projected reads. Median per-request preparation +shares were 21% and 41%, respectively. Test reducing the repeated +per-family driver calls separately from prepared-program reuse. +Keep the live rows, original digests, duplicate checks, and full +budget/history membership as the deciding inputs. Both first-frame +ratios missed the original limit under elevated host load. The first +order also missed throughput. Keep the diagnostic isolated and do +not use these ratios for promotion. + +The bounded committed-manifest candidate reads the two to four +families already selected by the live budget root in one query. +It keeps separate projected, settlement and history checks and +rejects a missing peer claim without releasing either hold. +Both shared paced Arrow orders verified one committed read per +guarded send in the candidate and four in the reference. Median +preparation CPU fell from 58–61 to 16–17 µs, but median poll CPU +outside preparation rose from 213–217 to 534–546 µs. The first +order missed first-frame and throughput at 1.183 and 0.922 of +reference. The second order passed both limits. Keep the candidate +isolated. All 137 ledger checks, four backpressure checks and +two SysML checks passed. + +On the pinned Turso driver and the same composite primary key, +both plans report an indexed search. Bytecode for the batch +=IN= form builds an ephemeral index with four inserts before +the family seeks. A four-branch =UNION ALL= plan showed four +direct seeks and no ephemeral index. This is plan evidence only. +Compare its live execution and compilation cost before selecting +a batched shape. + +The indexed UNION ALL candidate kept one committed read per shared +guarded send. In the focused paced Arrow comparison its median +committed poll CPU was 230 and 239 µs against 287 and 249 µs. +Median preparation CPU also fell in both orders. Committed read +wall P99 rose from 0.70 to 1.03 ms and from 0.54 to 1.60 ms. +Both original end-to-end limits passed in both focused orders. +All 137 ledger checks, including the missing peer claim control, +four backpressure checks and two SysML checks passed. Use that +exact image for the full matrix before deciding promotion. + +The full matrix completed all 16 pairs on that image. Eleven +passed both original limits. Five missed first-frame P99, and two +of those also missed throughput. The shared candidate made 1,024 +committed reads against 4,096 in its reference and reduced median +committed poll CPU in six of eight shared pairs. Both shared +misses were Protobuf in the first order. For their ranked requests, +dispatch outside measured transport had the largest added interval, +at 3.25 and 19.48 ms. Three independent pairs missed with the same +single-family SQL in both arms. Keep the candidate isolated. +The focused and full samples establish a local SQL benefit in +several cases, with insufficient evidence for end-to-end promotion. + +Keep the Governor and the frame delivery loop on separate schedules. +The existing Scheme/POO owner retains the compiled topology and ASCENT +rules. On complete release, activation or fact resolution it derives +the ready node identities and the evidence used for the decision. +Rust consumes that result through the existing owner boundary and +checks its fact version and receipts when committing the claim and +reservation. Frame delivery uses the established Rust credit and +authority path. Measure warm Governor derivation and its Rust +consumption separately from the acknowledged-frame tail. An upstream +mailbox throughput measurement establishes only the transport result +for its own workload. + +The shared immediate Arrow follow-up joined each handoff and scheduler +scope on a single monotonic clock. Several first-to-second frame gaps +in both arms spent nearly all their time inside their own range +preparation and final queue transactions. Observed scheduler wait was +small, including the overlap with peer completions. Original claim +and manifest reads occupied most of the measured claim verification +interval. Optimize that work inside each current transaction first. +Preparation and final queue remain separate authority checks across +the intervening output preparation boundary. + +The bounded peer precheck decodes and hashes up to three peer originals +before consumption. Each deciding transaction still reads the current +peer row and uses the prepared digest verification only on exact record +equality. In the shared immediate Arrow comparison, original verification +P50 fell by about a third in both range phases. First-frame P99 exceeded +the existing limit, and the original preflight for that ranked request +took longer. Keep this candidate isolated. Combine the preflight reads +before testing whether the lock-hold saving survives end to end. + +A follow-up uses one bounded preflight query for the current task and +the peer originals. The shared immediate Arrow trace still shortened +the deciding original verification. Preflight P50 rose from 0.17 to +2.26 ms. In the separate eight-case matrix, four cases met the +registered limits, three missed first-frame limits, and one failed the +existing operation-channel startup deadline before measurement. Keep +the candidate isolated. The current deciding read and exact record +comparison remain the authority boundary. + +The request-local variant retains peer verification only after a +successful current read. It adds no preflight statement. The shared +Arrow comparison reduced original verification P50 in both range +transactions while preflight P50 was effectively unchanged. First-frame +P99 still exceeded the limit. The ranked request spent more time in +dispatch outside measured transport, while the two arms had different +worker wait and transport intervals. Keep this candidate isolated and +retain the joined request trace for dispatch attribution. + +The dispatch follow-up joined the original burn and guarded send scopes +to each request. The longest dispatch observations included both active +transaction holds and scheduler wait. Much of the observed conflicting +hold during those waits came from an exclusive admission in the same +shared domain. The candidate first-frame P99 request in this run spent +most of its time in consumption, including both a long wait and a long +current-read transaction. Its commit was short. Use same-thread CPU +observations to separate the long transaction wall interval from CPU +work before changing the scheduler or the affine dispatch boundary. + +The same-image shared Arrow controls now pair transaction wall time with +the current thread's CPU clock. Without added pressure, the longest +consume transactions spent almost all of their wall interval on the +calling thread. Four existing pressure workers increased some off-CPU +intervals, but the longest consume in each arm was still mostly CPU. +The longest guarded send in that run included a measured transport write +comparable to its off-CPU interval. The earlier 128 ms consume outlier +did not recur. Keep the controls separate from the acceptance matrix and +prioritize the current-read CPU work that the controls actually observed. + +The settlement-read variant adds applied metering rows to the current +per-family reservation projection. It still verifies each settlement +against the original usage and subtracts only its validated release. +The shared immediate Arrow comparison removed one SQL statement per +family. Manifest medians changed little, Rust CPU per stream rose, and +the observed inter-frame tail increased. Keep this query shape isolated. +One focused first-frame and throughput comparison is insufficient to +qualify the change. + +The indexed-existence follow-up reads settlement presence with each +current budget or history membership row. When present, the original +settlement verification still runs. In shared immediate Arrow, manifest +medians fell modestly, while transaction medians stayed similar or rose. +First-frame P99 and completion rate improved in that wave, but Rust CPU +per request and the frame-gap P99 rose. Keep the candidate isolated +and retain the separate budget-only and history-only negative controls. +Turso selected both root indexes and the existing covering settlement +index. The negative controls rejected orphan settlement rows in both +root memberships, including when only one root was shared. + +The startup follow-up froze the same observed server image and used the +existing fresh-image and restart test. Across the unprofiled controls, +process spawn returned in about two milliseconds, while first runtime +entry on a fresh copy took roughly 0.75 to 0.93 seconds. Listener binding +took about one millisecond after runtime entry. Same-file restart entered +the runtime in about ten milliseconds. The ABBA copy and clone attempt +comparison did not eliminate the first-execution interval. A separate +sample observed the main thread at dyld entry and during image preparation +before Rust main. This locates the sampled delay before the Gateway +runtime. The original three-second failure remains unqualified because +the sample did not reproduce that failure. + ** Executable correspondence and acceptance The added 48-case Rust Proptest property uses actual WAL and MVCC stores, row @@ -1088,7 +4267,7 @@ commits, then asserts zero stale rows across both streams (or ten current rows without revoke), unchanged holds and no recovery replay. Waiting for response headers is not a valid premise for publication exclusion after request sealing. -** Native commit acknowledgment and process-crash refinement +** Ledger commit acknowledgment and crash recovery The former post-callback deciding transaction was read-only. It now records =provider_runs.dispatched=2= before the native commit; =1= remains the earlier diff --git a/go/cmd/weaver-control/heap_observer_test.go b/go/cmd/weaver-control/heap_observer_test.go new file mode 100644 index 00000000..3bcfcb22 --- /dev/null +++ b/go/cmd/weaver-control/heap_observer_test.go @@ -0,0 +1,74 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build integration && !windows + +package main + +import ( + "encoding/binary" + "io" + "os" + "path/filepath" + "runtime" + "runtime/metrics" + "runtime/pprof" + "testing" +) + +func TestMain(m *testing.M) { + if os.Getenv("WEAVER_TEST_CONTROL_HEAP") != "1" { + os.Exit(m.Run()) + } + profileDir := os.Getenv("WEAVER_TEST_CONTROL_PROFILE_DIR") + if profileDir != "" { + runtime.MemProfileRate = 1 + } + go observeHeap(profileDir) + main() +} + +func observeHeap(profileDir string) { + samples := []metrics.Sample{ + {Name: "/gc/heap/allocs:bytes"}, + {Name: "/gc/heap/allocs:objects"}, + } + var command [1]byte + var response [16]byte + for { + if _, err := io.ReadFull(os.Stdin, command[:]); err != nil { + return + } + switch command[0] { + case 1: + case 2, 3: + if profileDir == "" { + return + } + name := "before.pprof" + if command[0] == 3 { + name = "after.pprof" + } + runtime.GC() + runtime.GC() + file, err := os.OpenFile(filepath.Join(profileDir, name), os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0600) + if err != nil { + return + } + writeErr := pprof.Lookup("allocs").WriteTo(file, 0) + if closeErr := file.Close(); writeErr != nil || closeErr != nil { + return + } + default: + return + } + metrics.Read(samples) + for i, sample := range samples { + binary.LittleEndian.PutUint64(response[i*8:], sample.Value.Uint64()) + } + if _, err := os.Stdout.Write(response[:]); err != nil { + return + } + } +} diff --git a/go/dev/contention_test.go b/go/dev/contention_test.go index dcc90ee2..6c1ec36c 100644 --- a/go/dev/contention_test.go +++ b/go/dev/contention_test.go @@ -41,10 +41,9 @@ func TestContentionPairs(t *testing.T) { var output bytes.Buffer fmt.Fprintf(&output, "weaver-contention-image sha256=%s profile=release\n", digest) output.Write(data) - evidence, err := devrunner.ReadContentionEvidence(&output) - if err != nil { + t.Logf("weaver-contention-image sha256=%s profile=release", digest) + t.Log(string(data)) + if _, err := devrunner.ReadContentionEvidence(&output); err != nil { t.Fatal(err) } - t.Logf("weaver-contention-image sha256=%s profile=release", evidence.ImageSHA256) - t.Log(string(data)) } diff --git a/go/dev/header_seal_bench_test.go b/go/dev/header_seal_bench_test.go index 87483842..ffc7050a 100644 --- a/go/dev/header_seal_bench_test.go +++ b/go/dev/header_seal_bench_test.go @@ -56,9 +56,9 @@ func TestHeaderSealPairs(t *testing.T) { fmt.Fprintf(&output, "weaver-header-seal-image sha256=%s profile=release\n", digest) output.Write(data) + t.Logf("weaver-header-seal-image sha256=%s profile=release", digest) + t.Log(string(data)) if _, err := devrunner.ReadHeaderSealEvidence(&output, runtime.NumCPU()); err != nil { t.Fatal(err) } - t.Logf("weaver-header-seal-image sha256=%s profile=release", digest) - t.Log(string(data)) } diff --git a/go/dev/provider_control_bench_test.go b/go/dev/provider_control_bench_test.go index 739381c8..eda7cfd7 100644 --- a/go/dev/provider_control_bench_test.go +++ b/go/dev/provider_control_bench_test.go @@ -7,10 +7,15 @@ package dev import ( + "cmp" "context" "fmt" + "net/http" "os" "path/filepath" + "runtime" + "slices" + "strconv" "strings" "testing" "time" @@ -18,12 +23,16 @@ import ( pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" v1 "github.com/HardenedLinux/weaver/go/api/v1" "github.com/HardenedLinux/weaver/go/internal/config" + "golang.org/x/sys/unix" ) type controlFrameSample struct { - family string - wave int - received map[uint64]int64 + family string + node string + wave int + started, first int64 + received map[uint64]int64 + frameGaps []time.Duration } type controlBenchArm struct { frames []controlFrameSample @@ -36,11 +45,130 @@ type controlBenchArm struct { wall time.Duration } +func providerObservationNanos() int64 { + var stamp unix.Timespec + if err := unix.ClockGettime(unix.CLOCK_MONOTONIC, &stamp); err != nil { + panic(err) + } + return stamp.Nano() +} + // Four independently bootstrapped task owners each expose 32 distinct original // nodes. Both arms activate through Go; only the measured request path differs. // Cold activation stays separate from the 128 warm, exactly-once operations. func BenchmarkProviderGoControlPair(b *testing.B) { - image := wifImage(b, true) + benchmarkProviderGoControlPair(b, burstProviderSSE(13)) +} + +func BenchmarkProviderGoControlPacedPair(b *testing.B) { + benchmarkProviderGoControlPair(b, pacedControlSSE) +} + +func pacedControlSSE(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/event-stream") + tick := time.NewTicker(10 * time.Millisecond) + defer tick.Stop() + for event := range 12 { + if event != 0 { + select { + case <-r.Context().Done(): + return + case <-tick.C: + } + } + switch { + case event < 10: + emitChunk(w, "delta", false) + case event == 10: + emitChunk(w, "", true) + default: + fmt.Fprint(w, providerUsageAndDone) + } + } +} + +func benchmarkProviderGoControlPair(b *testing.B, handler http.HandlerFunc) { + reusePair := os.Getenv("WEAVER_TEST_PROVIDER_CONNECTION_PAIR") == "1" + tracePair := os.Getenv("WEAVER_TEST_PROVIDER_TRACE_PAIR") == "1" + plansPair := os.Getenv("WEAVER_TEST_PROVIDER_CURRENTNESS_PAIR") == "1" + manifestMode := os.Getenv("WEAVER_TEST_PROVIDER_MANIFEST_PAIR") + manifestAA := manifestMode == "aa" + evidencePair := manifestMode == "evidence" + manifestPair := manifestMode == "1" || manifestAA || evidencePair + baseline, bindingPair := os.LookupEnv("WEAVER_TEST_CONTROL_BASELINE_IMAGE") + providerBaseline, providerPair := os.LookupEnv("WEAVER_TEST_PROVIDER_BASELINE_IMAGE") + rustHeapPair := os.Getenv("WEAVER_TEST_RUST_HEAP_LIBRARY") != "" + if rustHeapPair && (reusePair || tracePair || plansPair || (manifestPair && !evidencePair) || bindingPair) { + b.Fatal("Rust heap comparison requires exclusive custody of the diagnostic arm") + } + if bindingPair && (reusePair || tracePair || plansPair || manifestPair || !filepath.IsAbs(baseline)) { + b.Fatal("binding comparison requires an exclusive absolute baseline image") + } + if tracePair && (reusePair || os.Getenv("WEAVER_TEST_PROVIDER_SCOPE_TRACE") != "") { + b.Fatal("trace comparison requires exclusive custody of the trace setting") + } + if plansPair && (reusePair || tracePair || os.Getenv("WEAVER_TEST_CACHE_CURRENTNESS_PLANS") != "") { + b.Fatal("currentness comparison requires exclusive custody of the SQL cache setting") + } + if manifestPair && (reusePair || tracePair || plansPair || os.Getenv("WEAVER_TEST_PREPARED_MANIFEST_PROGRAMS") != "" || os.Getenv("WEAVER_TEST_CACHE_CURRENTNESS_PLANS") != "") { + b.Fatal("manifest comparison requires exclusive custody of program preparation") + } + if evidencePair && os.Getenv("WEAVER_TEST_PREPARED_ORIGINAL_PROGRAM") != "" { + b.Fatal("evidence comparison requires exclusive custody of original program preparation") + } + // TestMain stages and verifies the frozen production image before benchmarks. + production := os.Getenv("WEAVER_TEST_PREBUILT_PROVIDER_IMAGE") != "" && + !(reusePair || tracePair || plansPair || manifestPair || bindingPair || rustHeapPair) + if providerPair && (!production || !filepath.IsAbs(providerBaseline)) { + b.Fatal("Rust release comparison requires a frozen production image and an absolute baseline image") + } + image := serverBinary + if !production { + image = wifImage(b, true) + } + labels := [2]string{"direct-rust", "go-control"} + if reusePair { + labels = [2]string{"fresh", "reuse"} + } + if tracePair { + labels = [2]string{"light", "traced"} + } + if plansPair { + labels = [2]string{"fresh-plans", "cached-plans"} + } + if manifestPair { + labels = [2]string{"fresh-manifest", "prepared-manifest"} + } + if manifestAA { + labels = [2]string{"fresh-manifest-a", "fresh-manifest-b"} + } + if rustHeapPair && !evidencePair { + labels = [2]string{"without-heap-counters", "with-heap-counters"} + } + controlImages := [2]string{controlBinary, controlBinary} + providerImages := [2]string{image, image} + if providerPair { + providerImages[0] = filepath.Join(b.TempDir(), "weaver-server-baseline") + digest, err := publishProviderImage(providerBaseline, providerImages[0]) + if err != nil || digest != os.Getenv("WEAVER_TEST_PROVIDER_BASELINE_SHA256") { + b.Fatalf("Rust baseline image does not match the frozen digest: %s %v", digest, err) + } + b.Logf("Rust baseline image sha256=%s; both arms use Go forwarding", digest) + labels = [2]string{"baseline-rust", "candidate-rust"} + } + if bindingPair { + controlImages[0] = filepath.Join(b.TempDir(), "weaver-control-baseline") + digest, err := publishProviderImage(baseline, controlImages[0]) + if err != nil || digest != os.Getenv("WEAVER_TEST_CONTROL_BASELINE_SHA256") { + b.Fatalf("control baseline image does not match the frozen digest: %s %v", digest, err) + } + b.Logf("Go control baseline image sha256=%s", digest) + labels = [2]string{"projected-binding", "wire-binding"} + } + trace := [2]bool{!tracePair, true} + if production { + trace = [2]bool{} + } for _, shared := range []bool{false, true} { for _, encoding := range []pb.Encoding{pb.Encoding_PROTOBUF, pb.Encoding_ARROW_IPC} { rows := uint32(1) @@ -51,7 +179,34 @@ func BenchmarkProviderGoControlPair(b *testing.B) { b.StopTimer() var arms [2]*controlBenchArm for i := range arms { - arms[i] = newControlBenchArm(b, image, 32*b.N, shared) + var env []string + if reusePair && i == 1 { + env = append(env, "WEAVER_TEST_REUSE_PROVIDER_CONNECTION=1") + } + if rustHeapPair && (i == 1 || evidencePair) { + env = append(env, "WEAVER_TEST_RUST_HEAP_ARM=1") + } + if plansPair { + env = append(env, fmt.Sprintf("WEAVER_TEST_CACHE_CURRENTNESS_PLANS=%d", i)) + } + if manifestPair { + prepared := i == 1 && !manifestAA + if prepared { + env = append(env, "WEAVER_TEST_PREPARED_MANIFEST_PROGRAMS=1") + } else { + env = append(env, "WEAVER_TEST_PREPARED_MANIFEST_PROGRAMS=0") + } + } + if evidencePair { + env = append(env, fmt.Sprintf("WEAVER_TEST_PREPARED_ORIGINAL_PROGRAM=%d", i)) + } + arms[i] = newControlBenchArm(b, providerImages[i], controlImages[i], 32*b.N, shared, trace[i], production, handler, env...) + } + account := providerPair || tracePair || plansPair || manifestPair || rustHeapPair || + os.Getenv("WEAVER_TEST_PROVIDER_PROCESS_ACCOUNTING") == "1" || os.Getenv("WEAVER_TEST_CONTROL_HEAP") == "1" + var accounting controlAccounting + if account { + accounting = startControlAccounting(b, arms) } b.StartTimer() for wave := range 32 * b.N { @@ -63,6 +218,7 @@ func BenchmarkProviderGoControlPair(b *testing.B) { events int transport domainStreamTransport latency time.Duration + started int64 err error } results := make(chan result, 4) @@ -70,15 +226,16 @@ func BenchmarkProviderGoControlPair(b *testing.B) { for owner := range 4 { go func() { client := arm.f.client - if i == 1 { + if i == 1 || providerPair || reusePair || tracePair || plansPair || manifestPair || bindingPair || rustHeapPair { client = arm.control[owner].client } ctx, cancel := context.WithTimeout(b.Context(), 12*time.Second) defer cancel() <-start at := time.Now() - n, timing, err := readDomainProgramStreamWithClient(ctx, client, arm.plans[owner][wave], encoding, rows) - results <- result{owner, n, timing, time.Since(at), err} + started := providerObservationNanos() + n, timing, err := readDomainProgramStreamTimed(ctx, client, arm.plans[owner][wave], encoding, rows, nil, providerObservationNanos) + results <- result{owner, n, timing, time.Since(at), started, err} }() } close(start) @@ -87,7 +244,8 @@ func BenchmarkProviderGoControlPair(b *testing.B) { if r.err != nil || r.events != 13 || r.transport.frames != (13+int(rows)-1)/int(rows) { b.Fatalf("control stream completion: %+v", r) } - arm.frames = append(arm.frames, controlFrameSample{arm.plans[r.owner][wave].Family, wave, r.transport.received}) + plan := arm.plans[r.owner][wave] + arm.frames = append(arm.frames, controlFrameSample{plan.Family, plan.Node, wave, r.started, r.transport.firstTick, r.transport.received, r.transport.frameGaps}) arm.latency = append(arm.latency, r.latency) arm.recv = append(arm.recv, r.transport.recv) arm.decode = append(arm.decode, r.transport.decode) @@ -96,34 +254,55 @@ func BenchmarkProviderGoControlPair(b *testing.B) { } } b.StopTimer() + if account { + accounting.finish(b, arms, labels, 32*b.N*4) + } b.ReportMetric(0, "ns/op") - for i, label := range []string{"direct-rust", "go-control"} { + for i, label := range labels { arm := arms[i] verifyControlBenchArm(b, arm, shared) + for _, owner := range arm.control { + owner.stop(b) + } + // The server writes observations when workers finish. Read + // them after natural exit, outside the timed section. + arm.f.stop(b) b.ReportMetric(float64(len(arm.latency))/arm.wall.Seconds(), label+"-complete/s") b.ReportMetric(tailMillis(arm.latency, 99), label+"-stream-p99-ms") - b.ReportMetric(tailMillis(controlFrameLatencies(b, arm), 99), label+"-rust-queue-to-client-p99-ms/frame") + if trace[i] { + b.ReportMetric(tailMillis(controlFrameLatencies(b, arm), 99), label+"-rust-queue-to-client-p99-ms/frame") + reportControlFirstFrame(b, arm, label) + } else { + assertNoControlTrace(b, arm) + } + first, gaps := controlArrivalLatencies(b, arm) + b.ReportMetric(tailMillis(first, 99), label+"-first-frame-p99-ms/stream") + b.ReportMetric(tailMillis(gaps, 99), label+"-inter-frame-p99-ms/frame") b.ReportMetric(tailMillis(arm.recv, 99), label+"-grpc-recv-p99-ms/stream") b.ReportMetric(tailMillis(arm.decode, 99), label+"-decode-p99-ms/stream") for j, duration := range arm.activation { b.ReportMetric(float64(duration.Nanoseconds())/1e6, fmt.Sprintf("%s-cold-owner%d-ms", label, j)) } - for _, owner := range arm.control { - owner.stop(b) - } - arm.f.stop(b) } }) } } } -func newControlBenchArm(t testing.TB, image string, nodes int, shared bool) *controlBenchArm { +func newControlBenchArm(t testing.TB, image, controlImage string, nodes int, shared, trace, production bool, handler http.HandlerFunc, extraEnv ...string) *controlBenchArm { t.Helper() if nodes > 64 { t.Fatal("frozen control benchmark supports at most 64 nodes per task; use -benchtime=1x") } - f := providerFixture(t, burstProviderSSE(13), false, image, []string{"--exact", "grpc_config::serve_wif_gateway", "--ignored", "--nocapture"}, []string{"WEAVER_STORAGE_JOURNAL=mvcc", "WEAVER_TEST_PROVIDER_SCOPE_TRACE=1"}, providerProfile(), nil, nil) + env := append([]string{"WEAVER_STORAGE_JOURNAL=mvcc"}, extraEnv...) + if trace { + env = append(env, "WEAVER_TEST_PROVIDER_SCOPE_TRACE=1") + } + arguments := []string{"--exact", "grpc_config::serve_wif_gateway", "--ignored", "--nocapture"} + if production { + arguments = nil + } + f := providerFixture(t, handler, false, image, arguments, env, providerProfile(), nil, nil) arm := &controlBenchArm{f: f} families := []string{"controlbench-0", "controlbench-1", "controlbench-2", "controlbench-3"} parent := uint64(0) @@ -156,6 +335,7 @@ when { ["controlbench-0","controlbench-1","controlbench-2","controlbench-3"].con } path := writeControlBundle(t, f, bundle, "json") owner := newControlProcess(t, f, path) + owner.image = controlImage at := time.Now() owner.start(t) startupLog, err := os.ReadFile(filepath.Join(owner.directory, "control.log")) @@ -183,6 +363,18 @@ when { ["controlbench-0","controlbench-1","controlbench-2","controlbench-3"].con } return arm } + +func assertNoControlTrace(b *testing.B, arm *controlBenchArm) { + b.Helper() + log, err := os.ReadFile(filepath.Join(arm.f.directory, "server.log")) + if err != nil { + b.Fatal(err) + } + if strings.Contains(string(log), "weaver-provider-first-frame ") || + strings.Contains(string(log), "weaver-provider-scope ") { + b.Fatal("light accounting arm emitted fine-grained Rust traces") + } +} func verifyControlBenchArm(t testing.TB, arm *controlBenchArm, shared bool) { t.Helper() ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second) @@ -212,18 +404,18 @@ func verifyControlBenchArm(t testing.TB, arm *controlBenchArm, shared bool) { } func TestProviderGoControlMeasuredChain(t *testing.T) { - image := filepath.Join(t.TempDir(), "weaver-control-chain") - if _, err := publishProviderImage(observedServer(t), image); err != nil { - t.Fatal(err) - } + // Exercise the same optimized WIF entrypoint as the paired benchmarks. + image := wifImage(t, true) for _, shared := range []bool{false, true} { t.Run(fmt.Sprintf("shared=%t", shared), func(t *testing.T) { - arm := newControlBenchArm(t, image, 2, shared) + arm := newControlBenchArm(t, image, controlBinary, 2, shared, true, false, burstProviderSSE(13)) for wave := range 2 { for owner := range 4 { ctx, cancel := context.WithTimeout(t.Context(), 12*time.Second) - n, timing, err := readDomainProgramStreamWithClient(ctx, arm.control[owner].client, arm.plans[owner][wave], pb.Encoding_ARROW_IPC, 4) - arm.frames = append(arm.frames, controlFrameSample{arm.plans[owner][wave].Family, wave, timing.received}) + started := providerObservationNanos() + n, timing, err := readDomainProgramStreamTimed(ctx, arm.control[owner].client, arm.plans[owner][wave], pb.Encoding_ARROW_IPC, 4, nil, providerObservationNanos) + plan := arm.plans[owner][wave] + arm.frames = append(arm.frames, controlFrameSample{plan.Family, plan.Node, wave, started, timing.firstTick, timing.received, timing.frameGaps}) cancel() if err != nil || n != 13 || timing.frames != 4 { t.Fatal("real Go routing / Rust streaming chain", n, timing, err) @@ -232,6 +424,11 @@ func TestProviderGoControlMeasuredChain(t *testing.T) { } verifyControlBenchArm(t, arm, shared) controlFrameLatencies(t, arm) + first, gaps := controlArrivalLatencies(t, arm) + controlFirstFramePhases(t, arm) + if len(first) != 8 || len(gaps) != 24 { + t.Fatal("incomplete arrival observations", len(first), len(gaps)) + } for _, owner := range arm.control { owner.stop(t) } @@ -240,16 +437,324 @@ func TestProviderGoControlMeasuredChain(t *testing.T) { } } +var controlFirstFramePhaseNames = [...]string{ + "front", "worker-wait", "worker-setup", "enqueue", "consume", "request-prepare", + "dispatch-outside-transport", "broker-remainder", "upstream-transport", "headers-to-queue", "queue-to-client", +} + +var controlTransportPhaseNames = [...]string{"connect", "tls", "write", "response-head"} + +var controlLedgerPhaseNames = [...]string{ + "owner-gate-wait", "domain-wait", "transaction-begin", "domain-hold", "transaction-hold", + "commit", "cedar", "publication-prepare", "original-prepare", "domain-prepare", "begin-poll", "begin-thread-cpu", + "begin-sql-prepare", "begin-sql-prepare-cpu", + "commit-poll", "commit-thread-cpu", "commit-sync", +} + +const ( + controlBeginWall = 2 + controlCommitWall = 5 + controlDomainPrepare = 9 + controlBeginPollWall = len(controlLedgerPhaseNames) - 7 + controlBeginCPUWall = len(controlLedgerPhaseNames) - 6 + controlPrepareWall = len(controlLedgerPhaseNames) - 5 + controlPrepareCPU = len(controlLedgerPhaseNames) - 4 + controlCommitPoll = len(controlLedgerPhaseNames) - 3 + controlCommitCPU = len(controlLedgerPhaseNames) - 2 + controlCommitSync = len(controlLedgerPhaseNames) - 1 + controlBeginPolls = len(controlLedgerPhaseNames) + controlBeginPending = controlBeginPolls + 1 + controlBeginCPUPolls = controlBeginPending + 1 + controlPrepareCalls = controlBeginCPUPolls + 1 + controlPrepareCPUs = controlPrepareCalls + 1 + controlCommitPolls = controlPrepareCPUs + 1 + controlCommitPending = controlCommitPolls + 1 + controlCommitCPUs = controlCommitPending + 1 + controlCommitSyncs = controlCommitCPUs + 1 + controlLedgerFields = controlCommitSyncs + 1 +) + +type controlFirstFrameRow struct { + total int64 + open time.Duration + reused bool + phases [len(controlFirstFramePhaseNames)]int64 + transport [len(controlTransportPhaseNames)]int64 + ledger [2][controlLedgerFields]int64 +} + +func reportDriverBegin(b *testing.B, rows []controlFirstFrameRow, stage int, label string) { + b.Helper() + var longest, longestOutside, cpuAtLongest, pollAtLongest time.Duration + var polls, pending, slow, slowPending, slowCPUMajority int64 + begin := make([]time.Duration, 0, len(rows)) + cpu := make([]time.Duration, 0, len(rows)) + prepare, prepareCPU, restCPU := make([]time.Duration, 0, len(rows)), make([]time.Duration, 0, len(rows)), make([]time.Duration, 0, len(rows)) + for _, row := range rows { + sample := row.ledger[stage] + wall := time.Duration(sample[controlBeginWall]) + poll, active := time.Duration(sample[controlBeginPollWall]), time.Duration(sample[controlBeginCPUWall]) + if wall > longest { + longest, cpuAtLongest, pollAtLongest = wall, active, poll + } + longestOutside = max(longestOutside, wall-poll) + begin = append(begin, wall) + prepare = append(prepare, time.Duration(sample[controlPrepareWall])) + if sample[controlBeginCPUPolls] != 0 { + cpu = append(cpu, active) + prepareCPU = append(prepareCPU, time.Duration(sample[controlPrepareCPU])) + restCPU = append(restCPU, max(0, active-time.Duration(sample[controlPrepareCPU]))) + } + polls += sample[controlBeginPolls] + pending += sample[controlBeginPending] + if wall >= time.Millisecond { + slow++ + if sample[controlBeginPending] != 0 { + slowPending++ + } + if active >= poll/2 { + slowCPUMajority++ + } + } + } + b.ReportMetric(tailMillis(begin, 99), label+"-begin-p99-ms") + b.ReportMetric(millis(longest), label+"-begin-max-ms") + b.ReportMetric(millis(longestOutside), label+"-begin-outside-poll-max-ms") + b.ReportMetric(float64(polls), label+"-begin-polls") + b.ReportMetric(float64(pending), label+"-begin-pending") + b.ReportMetric(float64(slow), label+"-begin-ge1ms") + b.ReportMetric(float64(slowPending), label+"-begin-ge1ms-with-pending") + b.ReportMetric(tailMillis(prepare, 50), label+"-begin-sql-prepare-p50-ms") + if len(cpu) != 0 { + b.ReportMetric(float64(len(cpu)), label+"-begin-cpu-samples") + b.ReportMetric(tailMillis(cpu, 50), label+"-begin-cpu-p50-ms") + b.ReportMetric(millis(cpuAtLongest), label+"-begin-cpu-at-max-wall-ms") + b.ReportMetric(millis(pollAtLongest), label+"-begin-poll-at-max-wall-ms") + b.ReportMetric(float64(slowCPUMajority), label+"-begin-ge1ms-cpu-majority") + b.ReportMetric(tailMillis(prepareCPU, 50), label+"-begin-sql-prepare-cpu-p50-ms") + b.ReportMetric(tailMillis(restCPU, 50), label+"-begin-rest-poll-cpu-p50-ms") + } +} + +func reportDriverCommit(b *testing.B, rows []controlFirstFrameRow, stage int, label string) { + b.Helper() + commits := make([]time.Duration, 0, len(rows)) + var longest [controlLedgerFields]int64 + var pending, syncs int64 + for _, row := range rows { + sample := row.ledger[stage] + commits = append(commits, time.Duration(sample[controlCommitWall])) + pending += sample[controlCommitPending] + syncs += sample[controlCommitSyncs] + if sample[controlCommitWall] > longest[controlCommitWall] { + longest = sample + } + } + b.ReportMetric(tailMillis(commits, 99), label+"-commit-p99-ms") + b.ReportMetric(millis(time.Duration(longest[controlCommitWall])), label+"-commit-max-ms") + b.ReportMetric(millis(time.Duration(longest[controlCommitPoll])), label+"-commit-max-poll-ms") + b.ReportMetric(millis(time.Duration(longest[controlCommitCPU])), label+"-commit-max-thread-cpu-ms") + b.ReportMetric(millis(time.Duration(longest[controlCommitSync])), label+"-commit-max-sync-ms") + b.ReportMetric(float64(longest[controlCommitPending]), label+"-commit-max-pending") + b.ReportMetric(float64(pending), label+"-commit-pending") + b.ReportMetric(float64(syncs), label+"-commit-sync-count") +} + +func reportControlFirstFrame(b *testing.B, arm *controlBenchArm, label string) { + b.Helper() + rows := controlFirstFramePhases(b, arm) + enqueue := make([]time.Duration, 0, len(rows)) + open := make([]time.Duration, 0, len(rows)) + domainWait := make([]time.Duration, 0, len(rows)) + domainHold := make([]time.Duration, 0, len(rows)) + domainPrepare := make([]time.Duration, 0, len(rows)) + var reused int + for _, row := range rows { + enqueue = append(enqueue, time.Duration(row.phases[3])) + open = append(open, row.open) + if row.reused { + reused++ + } + domainWait = append(domainWait, time.Duration(row.ledger[0][1])) + domainHold = append(domainHold, time.Duration(row.ledger[0][3])) + domainPrepare = append(domainPrepare, time.Duration(row.ledger[0][controlDomainPrepare])) + } + if label != "reuse" && reused != 0 { + b.Fatal("unexpected connection reuse in the reference arm") + } + b.ReportMetric(float64(reused)/float64(len(rows)), label+"-reused-fraction") + b.ReportMetric(tailMillis(domainWait, 95), label+"-enqueue-domain-wait-p95-ms") + b.ReportMetric(tailMillis(domainHold, 50), label+"-enqueue-domain-hold-p50-ms") + b.ReportMetric(tailMillis(domainHold, 99), label+"-enqueue-domain-hold-p99-ms") + b.ReportMetric(tailMillis(domainPrepare, 50), label+"-enqueue-domain-prepare-p50-ms") + b.ReportMetric(tailMillis(open, 50), label+"-ledger-open-p50-ms") + b.ReportMetric(tailMillis(open, 99), label+"-ledger-open-p99-ms") + b.ReportMetric(tailMillis(enqueue, 50), label+"-enqueue-p50-ms/stream") + b.ReportMetric(tailMillis(enqueue, 99), label+"-enqueue-p99-ms/stream") + // Attribute the observed P99 stream as a whole. Independently ranked phase + // percentiles cannot be added or subtracted to explain this stream. + slices.SortFunc(rows, func(a, b controlFirstFrameRow) int { + return cmp.Compare(a.total, b.total) + }) + tail := rows[tailRank(len(rows), 99)] + for i, name := range controlFirstFramePhaseNames { + b.ReportMetric(millis(time.Duration(tail.phases[i])), label+"-first-frame-p99-"+name+"-ms") + } + for i, name := range controlTransportPhaseNames { + b.ReportMetric(millis(time.Duration(tail.transport[i])), label+"-first-frame-p99-upstream-"+name+"-ms") + } + // Ledger counters overlap inside each outer stage. + for stage, name := range []string{"enqueue", "consume"} { + reportDriverBegin(b, rows, stage, label+"-"+name) + reportDriverCommit(b, rows, stage, label+"-"+name) + for i, phase := range controlLedgerPhaseNames { + b.ReportMetric(millis(time.Duration(tail.ledger[stage][i])), label+"-first-frame-p99-"+name+"-"+phase+"-ms") + } + } + if os.Getenv("WEAVER_TEST_PROVIDER_SCOPE_TIMELINE") != "" { + log, err := os.ReadFile(filepath.Join(arm.f.directory, "server.log")) + if err != nil { + b.Fatal(err) + } + for _, line := range strings.Split(string(log), "\n") { + if strings.HasPrefix(line, "weaver-provider-scope ") || + strings.HasPrefix(line, "weaver-provider-scope-timeline ") { + b.Log(label, line) + } + } + } +} + +func controlFirstFramePhases(t testing.TB, arm *controlBenchArm) []controlFirstFrameRow { + t.Helper() + log, err := os.ReadFile(filepath.Join(arm.f.directory, "server.log")) + if err != nil { + t.Fatal(err) + } + const transportOffset = 13 + const timingFields = transportOffset + len(controlTransportPhaseNames) + brokerTimes := make(map[[2]string][timingFields + 2*controlLedgerFields]int64) + for _, line := range strings.Split(string(log), "\n") { + raw, ok := strings.CutPrefix(line, "weaver-provider-first-frame ") + if !ok { + continue + } + fields := strings.Fields(raw) + if len(fields) != 2+timingFields+2*controlLedgerFields { + t.Fatalf("invalid first-frame observation: %q", raw) + } + key := [2]string{fields[0], fields[1]} + if _, exists := brokerTimes[key]; exists { + t.Fatalf("duplicate first-frame observation: %v", key) + } + var values [timingFields + 2*controlLedgerFields]int64 + for i, value := range fields[2:] { + nanos, err := strconv.ParseInt(value, 10, 64) + if err != nil || nanos < 0 { + t.Fatalf("invalid first-frame timing: %q", value) + } + values[i] = nanos + } + brokerTimes[key] = values + } + rows := make([]controlFirstFrameRow, 0, len(arm.frames)) + for _, stream := range arm.frames { + key := [2]string{stream.family, stream.node} + times, ok := brokerTimes[key] + first, received := stream.first, stream.first != 0 + submitted, workerWait, workerSetup, headers, queued, transport := times[0], times[1], times[2], times[3], times[4], times[5] + enqueue, consume, prepare, dispatch, writeTransport := times[6], times[7], times[8], times[9], times[10] + if !ok || !received { + t.Fatalf("missing first-frame observation for %v: server=%t client=%t", key, ok, received) + } + if submitted < stream.started || headers < submitted || + headers-submitted < workerWait || headers-submitted-workerWait < workerSetup || + headers-submitted-workerWait-workerSetup < transport || queued < headers || first < queued || + dispatch < writeTransport || transport < writeTransport { + t.Fatalf("unjoinable first-frame observation for %v: started=%d received=%d trace=%v", + key, stream.started, first, times) + } + outsideTransport := headers - submitted - workerWait - workerSetup - transport + dispatchOutsideTransport := dispatch - writeTransport + for _, phase := range [...]int64{enqueue, consume, prepare, dispatchOutsideTransport} { + if phase > outsideTransport { + t.Fatalf("overlapping broker phase observation for %v: phase %d exceeds remaining %d ns (broker timings %v)", key, phase, outsideTransport, times) + } + outsideTransport -= phase + } + if times[12] > 1 { + t.Fatalf("invalid connection reuse observation for %v", key) + } + upstream := [len(controlTransportPhaseNames)]int64(times[transportOffset:timingFields]) + connect, tls, write, head := upstream[0], upstream[1], upstream[2], upstream[3] + if connect > writeTransport || tls > writeTransport-connect || + write != writeTransport-connect-tls || head != transport-writeTransport { + t.Fatalf("unjoinable upstream transport stages for %v: %v", key, upstream) + } + row := controlFirstFrameRow{total: first - stream.started, open: time.Duration(times[11]), reused: times[12] == 1, phases: [...]int64{ + submitted - stream.started, workerWait, workerSetup, enqueue, consume, prepare, + dispatchOutsideTransport, outsideTransport, transport, queued - headers, first - queued, + }, transport: upstream} + for stage := range row.ledger { + start := timingFields + stage*controlLedgerFields + sample := &row.ledger[stage] + copy(sample[:], times[start:start+controlLedgerFields]) + if sample[controlBeginPolls] != sample[controlBeginPending]+1 || + sample[controlBeginPollWall] > sample[controlBeginWall] || + sample[controlPrepareCalls] != 1 || sample[controlPrepareWall] > sample[controlBeginPollWall] { + t.Fatalf("unjoinable transaction begin for %v stage %d: %v", key, stage, *sample) + } + if sample[controlCommitPolls] != sample[controlCommitPending]+1 || + sample[controlCommitPoll] > sample[controlCommitWall] || sample[controlCommitSync] > sample[controlCommitPoll] { + t.Fatalf("unjoinable transaction commit for %v stage %d: %v", key, stage, *sample) + } + if (runtime.GOOS == "darwin" || runtime.GOOS == "linux") && + (sample[controlBeginCPUPolls] != sample[controlBeginPolls] || + sample[controlPrepareCPUs] != sample[controlPrepareCalls] || + sample[controlCommitCPUs] != sample[controlCommitPolls]) { + t.Fatalf("missing transaction thread CPU for %v stage %d: %v", key, stage, *sample) + } + } + rows = append(rows, row) + delete(brokerTimes, key) + } + if len(brokerTimes) != 0 { + t.Fatal("unexpected broker first-frame observations") + } + return rows +} + +func controlArrivalLatencies(t testing.TB, arm *controlBenchArm) (first, gaps []time.Duration) { + t.Helper() + for _, stream := range arm.frames { + firstAt := stream.first + if firstAt == 0 || firstAt < stream.started { + t.Fatal("invalid request to first-frame observation") + } + first = append(first, time.Duration(firstAt-stream.started)) + if len(stream.frameGaps) != len(stream.received)-1 { + t.Fatal("missing client inter-frame observation") + } + for _, gap := range stream.frameGaps { + if gap < 0 { + t.Fatal("client receive clock moved backward") + } + gaps = append(gaps, gap) + } + } + return first, gaps +} + func controlFrameLatencies(t testing.TB, arm *controlBenchArm) []time.Duration { t.Helper() groups := providerHandoffGroups(t, arm.f) if len(groups) != len(arm.plans) { - t.Fatal("missing native handoff family") + t.Fatal("missing broker handoff family") } total := 0 for _, plans := range arm.plans { if len(groups[plans[0].Family]) != len(plans) { - t.Fatal("missing or duplicate native handoff group") + t.Fatal("missing or duplicate broker handoff group") } total += len(plans) } @@ -272,12 +777,12 @@ func controlFrameLatencies(t testing.TB, arm *controlBenchArm) []time.Duration { seen[stream.family][stream.wave] = true stamps := rows[stream.wave] if len(stamps) != len(stream.received) { - t.Fatal("missing native or client frame") + t.Fatal("missing broker or client frame") } for sequence, received := range stream.received { staged, ok := stamps[sequence] if !ok || received < staged { - t.Fatal("unjoinable native queue to client observation") + t.Fatal("unjoinable broker queue to client observation") } latencies = append(latencies, time.Duration(received-staged)) } diff --git a/go/dev/provider_control_test.go b/go/dev/provider_control_test.go index a982a15b..24a5a09c 100644 --- a/go/dev/provider_control_test.go +++ b/go/dev/provider_control_test.go @@ -65,13 +65,15 @@ when { context.family == "control" && ["infer", "next"].contains(context.node) & } type controlProcess struct { - fixture *fixture - ingress *testPKI - env []string - address, directory string - child *exec.Cmd - exited chan error - client *gatewayclient.Client + fixture *fixture + ingress *testPKI + env []string + address, directory string + child *exec.Cmd + exited chan error + client *gatewayclient.Client + heapInput, heapOutput *os.File + image string } func newControlProcess(t testing.TB, f *fixture, path string) *controlProcess { @@ -96,7 +98,7 @@ func newControlProcess(t testing.TB, f *fixture, path string) *controlProcess { leaf, token := sha256.Sum256(f.pki.client.Certificate[0]), sha256.Sum256([]byte(ownerToken)) settings := map[string]string{"CONFIG": path, "SERVER_CERT": filepath.Join(d, "server"), "SERVER_KEY": filepath.Join(d, "server-key"), "CLIENT_CA": filepath.Join(d, "ca"), "PEER_SHA256": hex.EncodeToString(leaf[:]), "TOKEN_SHA256": hex.EncodeToString(token[:]), "LISTEN": address, "AUTHORITY_CA": filepath.Join(d, "ca"), "AUTHORITY_OPERATION_CERT": filepath.Join(d, "operation"), "AUTHORITY_OPERATION_KEY": filepath.Join(d, "operation-key"), "AUTHORITY_SOURCE_CERT": filepath.Join(d, "source"), "AUTHORITY_SOURCE_KEY": filepath.Join(d, "source-key"), "AUTHORITY_OPERATION_TOKEN": ownerToken, "AUTHORITY_SOURCE_TOKEN": adminToken, "AUTHORITY_OPERATION_ADDRESS": f.address, "AUTHORITY_SOURCE_ADDRESS": f.sourceAddress, "AUTHORITY_SERVER_NAME": "localhost"} - c := &controlProcess{fixture: f, address: address, directory: d} + c := &controlProcess{fixture: f, address: address, directory: d, image: controlBinary} for name, value := range settings { c.env = append(c.env, "WEAVER_CONTROL_"+name+"="+value) } @@ -117,9 +119,27 @@ func (c *controlProcess) start(t testing.TB) { log.Close() t.Fatal(err) } - child := exec.Command(controlBinary) + child := exec.Command(c.image) child.Env = append(os.Environ(), c.env...) child.Stdout, child.Stderr = log, log + if os.Getenv("WEAVER_TEST_CONTROL_HEAP") == "1" { + if os.Getenv("WEAVER_TEST_CONTROL_PROFILE_ROOT") != "" { + child.Env = append(child.Env, "WEAVER_TEST_CONTROL_PROFILE_DIR="+c.directory) + } + input, err := child.StdinPipe() + if err != nil { + log.Close() + t.Fatal(err) + } + child.Stdout = nil + output, err := child.StdoutPipe() + if err != nil { + input.Close() + log.Close() + t.Fatal(err) + } + c.heapInput, c.heapOutput = input.(*os.File), output.(*os.File) + } if err := child.Start(); err != nil { log.Close() t.Fatal(err) diff --git a/go/dev/provider_domain_program_test.go b/go/dev/provider_domain_program_test.go index ee4de8aa..164038ba 100644 --- a/go/dev/provider_domain_program_test.go +++ b/go/dev/provider_domain_program_test.go @@ -233,6 +233,8 @@ type domainStreamTransport struct { frames, messageBytes int recv, decode time.Duration received map[uint64]int64 + firstTick int64 + frameGaps []time.Duration } func readDomainProgramStream(ctx context.Context, f *fixture, plan v1.ProviderPlan, encoding pb.Encoding, rows uint32) (int, domainStreamTransport, error) { @@ -244,6 +246,10 @@ func readDomainProgramStreamWithClient(ctx context.Context, client *gatewayclien } func readDomainProgramStreamObserved(ctx context.Context, client *gatewayclient.Client, plan v1.ProviderPlan, encoding pb.Encoding, rows uint32, onFirst func()) (int, domainStreamTransport, error) { + return readDomainProgramStreamTimed(ctx, client, plan, encoding, rows, onFirst, nil) +} + +func readDomainProgramStreamTimed(ctx context.Context, client *gatewayclient.Client, plan v1.ProviderPlan, encoding pb.Encoding, rows uint32, onFirst func(), observeFirst func() int64) (int, domainStreamTransport, error) { timing := domainStreamTransport{received: make(map[uint64]int64)} stream, err := client.RPC.ExecuteProvider(client.Context(ctx), &pb.ProviderRequest{ Plan: gatewayclient.Plan(plan), Encoding: encoding, BatchRows: rows, @@ -252,10 +258,19 @@ func readDomainProgramStreamObserved(ctx context.Context, client *gatewayclient. return 0, timing, err } next, done := 0, false + var previous time.Time for { started := time.Now() frame, err := stream.Recv() received := time.Now() + if err == nil && observeFirst != nil { + if previous.IsZero() { + timing.firstTick = observeFirst() + } else { + timing.frameGaps = append(timing.frameGaps, received.Sub(previous)) + } + previous = received + } timing.recv += received.Sub(started) if err == io.EOF && done { return next, timing, nil diff --git a/go/dev/provider_fixture_test.go b/go/dev/provider_fixture_test.go index 6a257a50..2a4ccb88 100644 --- a/go/dev/provider_fixture_test.go +++ b/go/dev/provider_fixture_test.go @@ -58,6 +58,13 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) } benchmark := flag.Lookup("test.bench").Value.String() + // These experiments build and run their own Cargo benchmark executable. + if benchmark == "" { + switch flag.Lookup("test.run").Value.String() { + case "^TestContentionPairs$", "^TestHeaderSealPairs$": + os.Exit(m.Run()) + } + } args, optimized, err := providerCargoBuildArgs(providerRuntimeFeatures, benchmark, os.LookupEnv) if err != nil { fmt.Fprintln(os.Stderr, err) @@ -109,6 +116,9 @@ func TestMain(m *testing.M) { } controlBinary = filepath.Join(directory, "weaver-control") controlArgs := []string{"-C", "go", "build", "-mod=readonly"} + if os.Getenv("WEAVER_TEST_CONTROL_HEAP") == "1" { + controlArgs = []string{"-C", "go", "test", "-c", "-mod=readonly", "-tags=integration"} + } if benchmark == "" { controlArgs = append(controlArgs, "-race") } @@ -120,6 +130,16 @@ func TestMain(m *testing.M) { fmt.Fprintln(os.Stderr, err) os.Exit(1) } + image, err := os.ReadFile(controlBinary) + if err != nil { + os.RemoveAll(directory) + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + fmt.Fprintf(os.Stderr, "test-owned Go control image sha256=%x\n", sha256.Sum256(image)) + if os.Getenv("WEAVER_TEST_CONTROL_HEAP") == "1" { + fmt.Fprintf(os.Stderr, "Go control heap observation image sha256=%x\n", sha256.Sum256(image)) + } result := m.Run() os.RemoveAll(directory) os.Exit(result) @@ -402,6 +422,37 @@ func (f *fixture) start(t testing.TB) { } f.child = exec.Command(f.binary, f.arguments...) f.child.Env = append(os.Environ(), f.env...) + if slices.Contains(f.env, "WEAVER_TEST_RUST_HEAP_ARM=1") { + library := os.Getenv("WEAVER_TEST_RUST_HEAP_LIBRARY") + if runtime.GOOS != "darwin" || !filepath.IsAbs(library) || os.Getenv("DYLD_INSERT_LIBRARIES") != "" { + log.Close() + t.Fatal("native heap counter requires Darwin and exclusive ownership of an absolute interposer path") + } + path := filepath.Join(f.directory, "rust-heap.counter") + if err := os.WriteFile(path, make([]byte, 72), 0600); err != nil { + log.Close() + t.Fatal(err) + } + f.child.Env = append(f.child.Env, "DYLD_INSERT_LIBRARIES="+library, "WEAVER_TEST_RUST_HEAP_COUNTER="+path) + if root := os.Getenv("WEAVER_TEST_RUST_HEAP_STACK_ROOT"); root != "" { + if !filepath.IsAbs(root) { + log.Close() + t.Fatal("native allocation stacks require an absolute evidence directory") + } + path := filepath.Join(f.directory, "rust-heap.stacks") + file, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0600) + if err != nil { + log.Close() + t.Fatal(err) + } + sizeErr := file.Truncate(24 + 65536*208) + if closeErr := file.Close(); sizeErr != nil || closeErr != nil { + log.Close() + t.Fatalf("native stack profile file: %v, %v", sizeErr, closeErr) + } + f.child.Env = append(f.child.Env, "WEAVER_TEST_RUST_HEAP_STACKS="+path) + } + } if !slices.Contains(f.env, "WEAVER_TEST_PROVIDER_SCOPE_TRACE=1") { f.child.Stdout = log } @@ -410,6 +461,7 @@ func (f *fixture) start(t testing.TB) { log.Close() t.Fatal(err) } + t.Logf("Rust owner startup process-spawn elapsed=%s", time.Since(started)) f.exited = make(chan error, 1) child, exited := f.child, f.exited go func() { err := child.Wait(); log.Close(); exited <- err }() diff --git a/go/dev/provider_governor_performance_test.go b/go/dev/provider_governor_performance_test.go index 2ed8a160..e9b2eeca 100644 --- a/go/dev/provider_governor_performance_test.go +++ b/go/dev/provider_governor_performance_test.go @@ -19,11 +19,16 @@ import ( ) type governorTrial struct { - arm string - replay bool - retained bool - innerJoinCut string - outerJoinCut string + arm string + replay bool + retained bool + fullCut bool + namedResult bool + preopen bool + changedSources bool + packedFacts bool + innerJoinCut string + outerJoinCut string } func (trial governorTrial) offerReplay(ctx context.Context, f *fixture, producer string) <-chan error { @@ -76,6 +81,11 @@ func (trial *governorTrial) finish(t *testing.T, f *fixture, c *controlProcess) var modeObserved bool var derivations int var ownerDecisions int + var transports, resultModes, factModes, relationModes, roundtrips, resolutions int + var lastRoundtrip uint64 + var reducedSources bool + var ascentMode string + var hasGovernorFFI bool var innerJoinCut, outerJoinCut string readyDigest := func(result string) string { digest := sha256.Sum256([]byte(result)) @@ -119,11 +129,32 @@ func (trial *governorTrial) finish(t *testing.T, f *fixture, c *controlProcess) t.Logf("governor trial arm=%s replay=%t status=failed drain_ns=%d", trial.arm, trial.replay, drain.Nanoseconds()) return } + preparing, prepared, preparedRules := false, false, false for _, line := range lines { if !strings.HasPrefix(line, "weaver-governor-") { continue } fields := strings.Fields(line) + if fields[0] == "weaver-governor-preopen" { + switch { + case len(fields) == 2 && fields[1] == "begin" && trial.preopen && !preparing && !prepared && derivations == 0: + preparing = true + case len(fields) == 4 && fields[1] == "end" && fields[2] == "ok=true" && preparing && preparedRules: + preparing, prepared = false, true + default: + t.Fatal("invalid Governor preparation trace", line) + } + continue + } + if preparing { + if fields[0] == "weaver-governor-ascent" { + if preparedRules || len(fields) != 4 || fields[3] != "mode=open" { + t.Fatal("preparation did not open exactly one ASCENT session", line) + } + preparedRules = true + } + continue + } switch fields[0] { case "weaver-governor-mode": if len(fields) != 2 || fields[1] != mode { @@ -135,18 +166,103 @@ func (trial *governorTrial) finish(t *testing.T, f *fixture, c *controlProcess) if trial.retained { // The scenario keeps its topology fixed while release facts change. expected = "open" - if derivations > 0 { + if derivations > 0 || prepared { expected = "replace" } } + if trial.changedSources && expected == "replace" && len(fields) == 4 && fields[3] == "mode=reuse" { + expected = "reuse" + } if len(fields) != 4 || fields[3] != "mode="+expected { t.Fatalf("Governor decision %d expected %s: %s", derivations+1, expected, line) } + ascentMode = expected derivations++ + case "weaver-governor-relations": + if len(fields) != 2 || !strings.HasPrefix(fields[1], "count=") { + t.Fatal("invalid Governor source count", line) + } + count := parse(strings.TrimPrefix(fields[1], "count=")) + if relationModes >= derivations || count > 7 || + (!trial.changedSources && count != 7) || + (ascentMode == "reuse" && count != 0) || + (ascentMode != "reuse" && count == 0) { + t.Fatal("unexpected Governor source replacement", line) + } + reducedSources = reducedSources || count < 7 + relationModes++ + case "weaver-governor-roundtrip": + if len(fields) != 8 || roundtrips >= derivations { + t.Fatal("unmatched Governor roundtrip", line) + } + var sum uint64 + for i, key := range []string{"capacity_ns=", "submit_ns=", "wait_ns=", "derive_ns=", "trace_ns=", "response_ns="} { + if !strings.HasPrefix(fields[i+1], key) { + t.Fatal("invalid Governor roundtrip phase", line) + } + sum += parse(strings.TrimPrefix(fields[i+1], key)) + } + lastRoundtrip = parse(strings.TrimPrefix(fields[7], "total_ns=")) + if sum != lastRoundtrip || lastRoundtrip == 0 { + t.Fatal("Governor roundtrip phases do not cover the call", line) + } + roundtrips++ + case "weaver-governor-resolve": + if len(fields) != 5 || resolutions >= roundtrips { + t.Fatal("unmatched Governor resolution", line) + } + elapsed := parse(strings.TrimPrefix(fields[1], "elapsed_ns=")) + prepare := parse(strings.TrimPrefix(fields[2], "prepare_ns=")) + roundtrip := parse(strings.TrimPrefix(fields[3], "roundtrip_ns=")) + validate := parse(strings.TrimPrefix(fields[4], "validate_ns=")) + if elapsed != prepare+roundtrip+validate || roundtrip < lastRoundtrip { + t.Fatal("Governor resolution phases do not cover the call", line) + } + resolutions++ + case "weaver-governor-transport": + expected := "full" + if trial.retained && !trial.fullCut { + expected = "compact" + if transports == 0 && !prepared { + expected = "bind" + } + } + if len(fields) != 2 || fields[1] != "mode="+expected { + t.Fatalf("Governor transport %d expected %s: %s", transports+1, expected, line) + } + transports++ + case "weaver-governor-result": + expected := "named" + if trial.retained && !trial.fullCut && !trial.namedResult { + expected = "indexed" + } + if len(fields) != 2 || fields[1] != "mode="+expected { + t.Fatalf("Governor result %d expected %s: %s", resultModes+1, expected, line) + } + resultModes++ + case "weaver-governor-facts": + expected := "named" + if trial.packedFacts && (prepared || factModes > 0) { + expected = "packed" + } + if len(fields) != 2 || fields[1] != "mode="+expected { + t.Fatalf("Governor facts %d expected %s: %s", factModes+1, expected, line) + } + factModes++ + case "weaver-governor-ffi": + if hasGovernorFFI || len(fields) != 4 { + t.Fatal("unmatched Governor FFI observation", line) + } + hasGovernorFFI = true case "weaver-governor-owner": if len(fields) != 6 || fields[3] != "ok=true" { t.Fatal("invalid or failed Governor owner decision", line) } + // Fact impact uses the same owner but does not enter Governor FFI. + if !hasGovernorFFI { + continue + } + hasGovernorFFI = false ownerDecisions++ cut := readDigest(fields[4], "cut_sha256=") ready := readDigest(fields[5], "ready_sha256=") @@ -171,30 +287,31 @@ func (trial *governorTrial) finish(t *testing.T, f *fixture, c *controlProcess) } at := parse(fields[2]) if at == 0 { - t.Fatal("zero native compile timestamp", line) + t.Fatal("zero Scheme compile timestamp", line) } switch fields[1] { case "begin": if begin != 0 { - t.Fatal("duplicate native compile entry", line) + t.Fatal("duplicate Scheme compile entry", line) } begin = at case "end": if end != 0 { - t.Fatal("duplicate native compile exit", line) + t.Fatal("duplicate Scheme compile exit", line) } end = at default: - t.Fatal("unknown native compile boundary", line) + t.Fatal("unknown Scheme compile boundary", line) } } } if !modeObserved { t.Fatal("missing Scheme Governor mode observation") } - if derivations < 2 || ownerDecisions != derivations || innerJoinCut == "" || outerJoinCut == "" { + if preparing || prepared != trial.preopen || hasGovernorFFI || derivations < 2 || ownerDecisions != derivations || transports != derivations || resultModes != derivations || factModes != derivations || relationModes != derivations || roundtrips < 2 || resolutions < 2 || resolutions > roundtrips || roundtrips > derivations || (trial.changedSources && !reducedSources) || innerJoinCut == "" || outerJoinCut == "" { t.Fatalf("incomplete Governor decision trace: ASCENT=%d owner=%d inner cut=%q outer cut=%q", derivations, ownerDecisions, innerJoinCut, outerJoinCut) } + t.Logf("governor observations derived=%d replied=%d resolved=%d", derivations, roundtrips, resolutions) a, b := commits["release/fork-a"], commits["release/fork-b"] innerRelease, innerReserve := commits["release/inner-finish"], commits["reserve/inner-finish"] outer := commits["reserve/finish"] @@ -204,7 +321,7 @@ func (trial *governorTrial) finish(t *testing.T, f *fixture, c *controlProcess) } overlap := a.wall < begin && begin < b.wall && b.wall < end if begin == 0 || end <= begin || end >= a.wall { - t.Fatalf("unexpected native compile entry: replay=%t fork-a=%d begin=%d fork-b=%d end=%d", trial.replay, a.wall, begin, b.wall, end) + t.Fatalf("unexpected Scheme compile entry: replay=%t fork-a=%d begin=%d fork-b=%d end=%d", trial.replay, a.wall, begin, b.wall, end) } trial.innerJoinCut = innerJoinCut trial.outerJoinCut = outerJoinCut diff --git a/go/dev/provider_module_routing_test.go b/go/dev/provider_module_routing_test.go index ec38e522..82d179d4 100644 --- a/go/dev/provider_module_routing_test.go +++ b/go/dev/provider_module_routing_test.go @@ -214,22 +214,27 @@ forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { c seen = true } } - done := make(chan error, 2) - for range 2 { + const contenders = 4 + done := make(chan error, contenders) + for range contenders { go func() { done <- execute(ctx, true) }() } - first, other := <-done, <-done + var successes int + for range contenders { + if <-done == nil { + successes++ + } + } if mode == "deny" { - if first == nil || other == nil || f.primary.Load() != 0 { - t.Fatalf("import bypassed Cedar invocation: %v %v", first, other) + if successes != 0 || f.primary.Load() != 0 { + t.Fatalf("import bypassed Cedar invocation: successes=%d calls=%d", successes, f.primary.Load()) } return } - if (mode == "complete" && first != nil && other != nil) || - (mode == "partial" && (first == nil || other == nil)) || f.primary.Load() != 1 { - t.Fatalf("expected a single provider dispatch: %v %v, calls=%d", first, other, f.primary.Load()) + if (mode == "complete" && successes != 1) || (mode == "partial" && successes != 0) || f.primary.Load() != 1 { + t.Fatalf("expected a single provider dispatch: successes=%d calls=%d", successes, f.primary.Load()) } withdrawal, err := json.Marshal(map[string]any{"parent": current.Version, "entries": map[string]any{}}) if err != nil { diff --git a/go/dev/provider_process_accounting_test.go b/go/dev/provider_process_accounting_test.go new file mode 100644 index 00000000..be377f12 --- /dev/null +++ b/go/dev/provider_process_accounting_test.go @@ -0,0 +1,302 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build integration && !windows + +package dev + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "os" + "os/exec" + "path/filepath" + "runtime" + "slices" + "strconv" + "strings" + "testing" + "time" +) + +type controlAccounting struct { + before map[int]time.Duration + driver runtime.MemStats + pids [2][5]int + heapBefore [2][4][2]uint64 + heapIdle [2][2]uint64 + heapEnabled bool + profileRoot string + rustHeapBefore [2][8]uint64 + rustHeapIdle [2][8]uint64 + rustStackStart [2]uint64 +} + +func startControlAccounting(b *testing.B, arms [2]*controlBenchArm) controlAccounting { + b.Helper() + var measurement controlAccounting + for i, arm := range arms { + measurement.pids[i][0] = arm.f.child.Process.Pid + for j, owner := range arm.control { + measurement.pids[i][j+1] = owner.child.Process.Pid + } + if slices.Contains(arm.f.env, "WEAVER_TEST_RUST_HEAP_ARM=1") { + idle := readRustHeapCounters(b, arm.f) + measurement.rustHeapBefore[i] = readRustHeapCounters(b, arm.f) + if os.Getenv("WEAVER_TEST_RUST_HEAP_STACK_ROOT") != "" { + measurement.rustStackStart[i] = rustAllocationStackCursor(b, arm.f) + } + for metric, current := range measurement.rustHeapBefore[i] { + if current < idle[metric] { + b.Fatal("Rust heap counter moved backwards") + } + measurement.rustHeapIdle[i][metric] = current - idle[metric] + } + } + } + measurement.before = measurement.cpuTimes(b) + runtime.ReadMemStats(&measurement.driver) + measurement.heapEnabled = os.Getenv("WEAVER_TEST_CONTROL_HEAP") == "1" + measurement.profileRoot = os.Getenv("WEAVER_TEST_CONTROL_PROFILE_ROOT") + if measurement.profileRoot != "" && (!measurement.heapEnabled || !filepath.IsAbs(measurement.profileRoot)) { + b.Fatal("control heap profiles require the heap observer and an absolute evidence directory") + } + if measurement.heapEnabled { + for i, arm := range arms { + for j, owner := range arm.control { + if measurement.profileRoot != "" { + controlHeapCommand(b, owner, 2, 10*time.Second) + } + idle := readControlHeap(b, owner) + measurement.heapBefore[i][j] = readControlHeap(b, owner) + for metric, after := range measurement.heapBefore[i][j] { + if after < idle[metric] { + b.Fatal("control heap counter moved backwards during idle control") + } + measurement.heapIdle[i][metric] += after - idle[metric] + } + } + } + } + return measurement +} + +func (m *controlAccounting) finish(b *testing.B, arms [2]*controlBenchArm, labels [2]string, streams int) { + b.Helper() + var driver runtime.MemStats + runtime.ReadMemStats(&driver) + after := m.cpuTimes(b) + cpu := func(pid int) time.Duration { + before, end := m.before[pid], after[pid] + if end < before { + b.Fatalf("process CPU moved backwards for %d", pid) + } + return end - before + } + if driver.TotalAlloc < m.driver.TotalAlloc || driver.Mallocs < m.driver.Mallocs { + b.Fatal("benchmark driver allocation counters moved backwards") + } + for arm, label := range labels { + pids := m.pids[arm] + var goCPU time.Duration + for _, pid := range pids[1:] { + goCPU += cpu(pid) + } + b.ReportMetric(millis(cpu(pids[0]))/float64(streams), label+"-rust-cpu-ms/stream") + b.ReportMetric(millis(goCPU)/float64(streams), label+"-go-control-cpu-ms/stream") + if slices.Contains(arms[arm].f.env, "WEAVER_TEST_RUST_HEAP_ARM=1") { + after := readRustHeapCounters(b, arms[arm].f) + if root := os.Getenv("WEAVER_TEST_RUST_HEAP_STACK_ROOT"); root != "" { + end := rustAllocationStackCursor(b, arms[arm].f) + start := m.rustStackStart[arm] + if end <= start || end > 65536 { + b.Fatalf("invalid Rust allocation stack window %d..%d", start, end) + } + data, err := os.ReadFile(filepath.Join(arms[arm].f.directory, "rust-heap.stacks")) + if err != nil { + b.Fatal(err) + } + dir := filepath.Join(root, b.Name()) + if err := os.MkdirAll(dir, 0700); err != nil { + b.Fatal(err) + } + if err := os.WriteFile(filepath.Join(dir, label+".bin"), data[:24+208*end], 0600); err != nil { + b.Fatal(err) + } + b.ReportMetric(float64(start), label+"-stack-window-start") + b.ReportMetric(float64(end), label+"-stack-window-end") + } + for i, name := range []string{"malloc", "calloc", "realloc", "memalign"} { + for j, unit := range []string{"calls", "bytes"} { + index := 2*i + j + before := m.rustHeapBefore[arm][index] + if after[index] < before { + b.Fatal("Rust heap counter moved backwards") + } + b.ReportMetric(float64(after[index]-before)/float64(streams), label+"-"+name+"-"+unit+"/stream") + b.ReportMetric(float64(m.rustHeapIdle[arm][index]), label+"-"+name+"-idle-"+unit) + } + } + } + if m.heapEnabled { + var delta [2]uint64 + for j, owner := range arms[arm].control { + for metric, after := range readControlHeap(b, owner) { + before := m.heapBefore[arm][j][metric] + if after < before { + b.Fatal("control heap counter moved backwards") + } + delta[metric] += after - before + } + if m.profileRoot != "" { + controlHeapCommand(b, owner, 3, 10*time.Second) + dir := filepath.Join(m.profileRoot, b.Name(), label, strconv.Itoa(j)) + if err := os.MkdirAll(dir, 0700); err != nil { + b.Fatal(err) + } + for _, name := range []string{"before.pprof", "after.pprof"} { + profile, err := os.ReadFile(filepath.Join(owner.directory, name)) + if err != nil { + b.Fatal(err) + } + if err := os.WriteFile(filepath.Join(dir, name), profile, 0600); err != nil { + b.Fatal(err) + } + } + } + } + b.ReportMetric(float64(delta[0])/float64(streams), label+"-go-control-heap-bytes/stream") + b.ReportMetric(float64(delta[1])/float64(streams), label+"-go-control-heap-allocs/stream") + b.ReportMetric(float64(m.heapIdle[arm][0]), label+"-go-control-idle-snapshot-bytes") + b.ReportMetric(float64(m.heapIdle[arm][1]), label+"-go-control-idle-snapshot-allocs") + } + } + total := float64(streams * len(labels)) + b.ReportMetric(millis(cpu(os.Getpid()))/total, "combined-driver-cpu-ms/stream") + b.ReportMetric(float64(driver.TotalAlloc-m.driver.TotalAlloc)/total, "combined-driver-heap-bytes/stream") + b.ReportMetric(float64(driver.Mallocs-m.driver.Mallocs)/total, "combined-driver-heap-allocs/stream") +} + +func rustAllocationStackCursor(b *testing.B, f *fixture) uint64 { + b.Helper() + file, err := os.Open(filepath.Join(f.directory, "rust-heap.stacks")) + if err != nil { + b.Fatal(err) + } + defer file.Close() + var header [24]byte + if _, err := io.ReadFull(file, header[:]); err != nil || binary.LittleEndian.Uint64(header[:]) != 1 { + b.Fatalf("Rust allocation stack observer did not initialize: %v", err) + } + return binary.LittleEndian.Uint64(header[8:]) +} + +func readRustHeapCounters(b *testing.B, f *fixture) [8]uint64 { + b.Helper() + path := filepath.Join(f.directory, "rust-heap.counter") + var previous []byte + for range 16 { + data, err := os.ReadFile(path) + if err != nil || len(data) != 72 || binary.LittleEndian.Uint64(data) != 1 { + b.Fatalf("Rust allocator counter did not initialize: %v", err) + } + if bytes.Equal(data, previous) { + var result [8]uint64 + for i := range result { + result[i] = binary.LittleEndian.Uint64(data[8+8*i:]) + } + return result + } + previous = data + } + b.Fatal("Rust allocator counter did not stabilize at the workload boundary") + return [8]uint64{} +} + +func readControlHeap(b *testing.B, owner *controlProcess) [2]uint64 { + return controlHeapCommand(b, owner, 1, time.Second) +} + +func controlHeapCommand(b *testing.B, owner *controlProcess, command byte, timeout time.Duration) [2]uint64 { + b.Helper() + if owner.heapInput == nil || owner.heapOutput == nil { + b.Fatal("Go control heap observer is missing") + } + deadline := time.Now().Add(timeout) + if err := owner.heapInput.SetWriteDeadline(deadline); err != nil { + b.Fatal(err) + } + if err := owner.heapOutput.SetReadDeadline(deadline); err != nil { + b.Fatal(err) + } + if _, err := owner.heapInput.Write([]byte{command}); err != nil { + b.Fatal(err) + } + var response [16]byte + if _, err := io.ReadFull(owner.heapOutput, response[:]); err != nil { + b.Fatal(err) + } + return [2]uint64{binary.LittleEndian.Uint64(response[:8]), binary.LittleEndian.Uint64(response[8:])} +} + +func (m *controlAccounting) cpuTimes(b *testing.B) map[int]time.Duration { + b.Helper() + pids := []string{strconv.Itoa(os.Getpid())} + for _, arm := range m.pids { + for _, pid := range arm { + pids = append(pids, strconv.Itoa(pid)) + } + } + output, err := exec.Command("ps", "-o", "pid=", "-o", "time=", "-p", strings.Join(pids, ",")).Output() + if err != nil { + b.Fatalf("steady process CPU snapshot: %v", err) + } + rows := make(map[int]time.Duration) + for _, line := range strings.Split(strings.TrimSpace(string(output)), "\n") { + fields := strings.Fields(line) + if len(fields) != 2 { + b.Fatalf("unexpected process CPU row %q", line) + } + pid, err := strconv.Atoi(fields[0]) + elapsed, clockErr := processCPUClock(fields[1]) + if err != nil || clockErr != nil { + b.Fatalf("invalid process CPU row %q", line) + } + rows[pid] = elapsed + } + for _, text := range pids { + pid, _ := strconv.Atoi(text) + if _, ok := rows[pid]; !ok { + b.Fatalf("process CPU snapshot omitted PID %d", pid) + } + } + return rows +} + +// ps emits [[days-]hours:]minutes:seconds, with fractions where supported. +func processCPUClock(clock string) (time.Duration, error) { + var elapsed time.Duration + if days, rest, ok := strings.Cut(clock, "-"); ok { + count, err := strconv.Atoi(days) + if err != nil || count < 0 { + return 0, fmt.Errorf("invalid process CPU day %q", days) + } + elapsed, clock = time.Duration(count)*24*time.Hour, rest + } + parts := strings.Split(clock, ":") + if len(parts) != 2 && len(parts) != 3 { + return 0, fmt.Errorf("invalid process CPU clock %q", clock) + } + for i, part := range parts { + unit := [...]string{"h", "m", "s"}[3-len(parts)+i] + duration, err := time.ParseDuration(part + unit) + if err != nil || duration < 0 { + return 0, fmt.Errorf("invalid process CPU clock %q", clock) + } + elapsed += duration + } + return elapsed, nil +} diff --git a/go/dev/provider_range_group_test.go b/go/dev/provider_range_group_test.go index 6e708992..bb0c0dc8 100644 --- a/go/dev/provider_range_group_test.go +++ b/go/dev/provider_range_group_test.go @@ -18,6 +18,8 @@ import ( pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" ) +const providerUsageAndDone = "data: {\"id\":\"stream-1\",\"object\":\"chat.completion.chunk\",\"model\":\"model-a\",\"choices\":[],\"usage\":{\"total_tokens\":7}}\n\ndata: [DONE]\n\n" + func burstProviderSSE(events int) http.HandlerFunc { return func(w http.ResponseWriter, _ *http.Request) { var burst strings.Builder @@ -25,7 +27,7 @@ func burstProviderSSE(events int) http.HandlerFunc { writeProviderChunk(&burst, "delta", false) } writeProviderChunk(&burst, "", true) - fmt.Fprint(&burst, "data: {\"id\":\"stream-1\",\"object\":\"chat.completion.chunk\",\"model\":\"model-a\",\"choices\":[],\"usage\":{\"total_tokens\":7}}\n\ndata: [DONE]\n\n") + burst.WriteString(providerUsageAndDone) w.Header().Set("Content-Type", "text/event-stream") fmt.Fprint(w, burst.String()) } diff --git a/go/dev/provider_range_scopes_test.go b/go/dev/provider_range_scopes_test.go index d3b2a608..4f4ff3ba 100644 --- a/go/dev/provider_range_scopes_test.go +++ b/go/dev/provider_range_scopes_test.go @@ -261,6 +261,12 @@ func reportProviderRangeScopes(b *testing.B, arm *providerTailArm, name string, } } label := name + "-" + phase + b.ReportMetric(float64(len(waits))/float64(len(arm.streams)), label+"-scopes/stream") + // Delivery revalidation is conditional on the current receipt and + // capacity. With no such scopes there is no latency sample. + if len(waits) == 0 { + continue + } b.ReportMetric(tailMillis(waits, 99), label+"-wait-p99-ms") b.ReportMetric(tailMillis(holds, 99), label+"-hold-p99-ms") b.ReportMetric(millis(atP99Wait), label+"-wait-at-stream-p99-ms") diff --git a/go/dev/provider_workflow_nested_test.go b/go/dev/provider_workflow_nested_test.go index 7e710c09..182ff584 100644 --- a/go/dev/provider_workflow_nested_test.go +++ b/go/dev/provider_workflow_nested_test.go @@ -36,8 +36,8 @@ func TestProviderControlGovernorPerformance(t *testing.T) { cohort := os.Getenv("WEAVER_TEST_GOVERNOR_COHORT") switch cohort { case "": - t.Skip("select the preregistered aa, replay, or retained cohort") - case "aa", "replay", "retained": + t.Skip("select the preregistered aa, replay, retained, transport, indices, preopen, packed, or changed cohort") + case "aa", "replay", "retained", "transport", "indices", "preopen", "packed", "changed": default: t.Fatal("unknown Governor performance cohort", cohort) } @@ -53,7 +53,12 @@ func TestProviderControlGovernorPerformance(t *testing.T) { t.Parallel() trials[i] = governorTrial{ arm: arm, replay: cohort == "replay" && arm == "B", - retained: cohort == "retained" && arm == "B", + retained: cohort == "changed" || cohort == "packed" || cohort == "preopen" || cohort == "indices" || cohort == "transport" || (cohort == "retained" && arm == "B"), + fullCut: cohort == "transport" && arm == "A", + namedResult: cohort == "indices" && arm == "A", + preopen: cohort == "changed" || cohort == "packed" || (cohort == "preopen" && arm == "B"), + packedFacts: cohort == "changed" || (cohort == "packed" && arm == "B"), + changedSources: cohort == "changed" && arm == "B", } runNestedSession(t, false, &trials[i]) }) @@ -209,6 +214,31 @@ func runNestedSession(t *testing.T, outerRight bool, trial *governorTrial) { } else { f.env = append(f.env, "WEAVER_TEST_GOVERNOR_RETAINED=0") } + if trial.fullCut { + f.env = append(f.env, "WEAVER_TEST_GOVERNOR_FULL_CUT=1") + } else { + f.env = append(f.env, "WEAVER_TEST_GOVERNOR_FULL_CUT=0") + } + if trial.namedResult { + f.env = append(f.env, "WEAVER_TEST_GOVERNOR_NAMED_RESULT=1") + } else { + f.env = append(f.env, "WEAVER_TEST_GOVERNOR_NAMED_RESULT=0") + } + if trial.preopen { + f.env = append(f.env, "WEAVER_TEST_GOVERNOR_PREOPEN=1") + } else { + f.env = append(f.env, "WEAVER_TEST_GOVERNOR_PREOPEN=0") + } + if trial.changedSources { + f.env = append(f.env, "WEAVER_TEST_GOVERNOR_CHANGED_SOURCES=1") + } else { + f.env = append(f.env, "WEAVER_TEST_GOVERNOR_CHANGED_SOURCES=0") + } + if trial.packedFacts { + f.env = append(f.env, "WEAVER_TEST_GOVERNOR_PACKED_FACTS=1") + } else { + f.env = append(f.env, "WEAVER_TEST_GOVERNOR_PACKED_FACTS=0") + } } f.env = append(f.env, credentials, hardFactFeedSetting(t, f, root.Family, root.Node, graph.WorkflowEdges, nil, graph.Schema, graph.WorkflowSelectors, graph.OpenNodes...)) diff --git a/go/go.mod b/go/go.mod index 28c3fd0f..6e67b824 100644 --- a/go/go.mod +++ b/go/go.mod @@ -9,6 +9,7 @@ go 1.25.0 require ( github.com/Open-MBEE/OpenSysML v0.10.1 github.com/apache/arrow-go/v18 v18.4.1 + golang.org/x/sys v0.45.0 google.golang.org/grpc v1.75.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 @@ -26,7 +27,6 @@ require ( golang.org/x/mod v0.35.0 // indirect golang.org/x/net v0.53.0 // indirect golang.org/x/sync v0.20.0 // indirect - golang.org/x/sys v0.45.0 // indirect golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa // indirect golang.org/x/text v0.37.0 // indirect golang.org/x/tools v0.44.0 // indirect diff --git a/go/internal/controlplane/deployment.go b/go/internal/controlplane/deployment.go index 8ec1cd06..b30ddda9 100644 --- a/go/internal/controlplane/deployment.go +++ b/go/internal/controlplane/deployment.go @@ -191,7 +191,7 @@ func RunFromEnv(ctx context.Context) error { } defer source.Connection.Close() trace("source-channel-connected") - gateway, err := input.bootstrap(startup, source, operation) + gateway, err := input.bootstrap(startup, source, operation, trace) if err != nil { return err } diff --git a/go/internal/controlplane/deployment_source.go b/go/internal/controlplane/deployment_source.go index eb13d3cb..7d408b36 100644 --- a/go/internal/controlplane/deployment_source.go +++ b/go/internal/controlplane/deployment_source.go @@ -43,9 +43,9 @@ func selectDeploymentSource(lookup func(string) (string, bool)) (deploymentSourc return deploymentSource{path: path}, nil } -func (input deploymentSource) bootstrap(ctx context.Context, source, operation *gatewayclient.Client) (*Gateway, error) { +func (input deploymentSource) bootstrap(ctx context.Context, source, operation *gatewayclient.Client, trace bootstrapTrace) (*Gateway, error) { if input.producer != "" { - return BootstrapProducer(ctx, source, operation, input.producer) + return bootstrapProducer(ctx, source, operation, input.producer, trace) } - return Bootstrap(ctx, source, operation, input.bundle) + return bootstrap(ctx, source, operation, input.bundle, trace) } diff --git a/go/internal/controlplane/deployment_source_test.go b/go/internal/controlplane/deployment_source_test.go index b539694b..69f820c1 100644 --- a/go/internal/controlplane/deployment_source_test.go +++ b/go/internal/controlplane/deployment_source_test.go @@ -17,7 +17,7 @@ func TestUnavailableDeploymentProducerCannotUseDataFallback(t *testing.T) { client := &gatewayclient.Client{RPC: rpc, Token: "source-token"} // Even accidental internal coexistence cannot turn failure into fallback. input := deploymentSource{producer: "approved", bundle: bundle} - _, err := input.bootstrap(context.Background(), client, client) + _, err := input.bootstrap(context.Background(), client, client, nil) if err == nil || !reflect.DeepEqual(rpc.calls, []string{"compile"}) { t.Fatal("producer failure fell back or published", rpc.calls, err) } diff --git a/go/internal/controlplane/gateway.go b/go/internal/controlplane/gateway.go index 66d8b93c..9bd5abaf 100644 --- a/go/internal/controlplane/gateway.go +++ b/go/internal/controlplane/gateway.go @@ -8,34 +8,49 @@ package controlplane import ( "context" "errors" + "io" + "slices" + "sync" + "sync/atomic" + "unicode/utf8" + pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" v1 "github.com/HardenedLinux/weaver/go/api/v1" "github.com/HardenedLinux/weaver/go/internal/config" "github.com/HardenedLinux/weaver/go/internal/gatewayclient" - "github.com/HardenedLinux/weaver/go/internal/routing" "github.com/HardenedLinux/weaver/go/internal/telemetry" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "io" - "unicode/utf8" ) type Gateway struct { pb.UnimplementedGatewayServer - metrics telemetry.Metrics - owner *gatewayclient.Client - tasks map[string]v1.Task - operations map[[2]string]bool - view v1.View - source *gatewayclient.Client - deferred *config.Bundle - publication *pb.PublicationKey - oauthRelay bool + metrics telemetry.Metrics + owner *gatewayclient.Client + operations map[[2]string]v1.ProviderPlan + source *gatewayclient.Client + deferred *config.Bundle + catalog atomic.Pointer[catalogProjection] + catalogBuildMu sync.Mutex + publication *pb.PublicationKey + oauthRelay bool } // Bootstrap has no execution API calls. Unknown publication outcomes never activate ingress. // Task registration is persistent and idempotent, not an atomic multi-task transaction. func Bootstrap(ctx context.Context, source, owner *gatewayclient.Client, bundle config.Bundle) (*Gateway, error) { + return bootstrap(ctx, source, owner, bundle, nil) +} + +type bootstrapTrace func(string) + +func (trace bootstrapTrace) phase(name string) { + if trace != nil { + trace(name) + } +} + +func bootstrap(ctx context.Context, source, owner *gatewayclient.Client, bundle config.Bundle, trace bootstrapTrace) (*Gateway, error) { if source == nil || owner == nil { return nil, errors.New("source and operation authority roles required") } @@ -43,12 +58,13 @@ func Bootstrap(ctx context.Context, source, owner *gatewayclient.Client, bundle if err != nil { return nil, err } - return bootstrapFrozen(ctx, source, owner, frozen) + return bootstrapFrozen(ctx, source, owner, frozen, trace) } // Both callers own a fully validated independent image. Keep this private: // it removes repeated local projection, never a source or final-use CAS. -func bootstrapFrozen(ctx context.Context, source, owner *gatewayclient.Client, frozen config.Bundle) (*Gateway, error) { +func bootstrapFrozen(ctx context.Context, source, owner *gatewayclient.Client, frozen config.Bundle, trace bootstrapTrace) (*Gateway, error) { + trace.phase("publication-inspect-start") receipt, err := source.InspectPublication(ctx, frozen.Publication) if err == nil && receipt.GetOutcome() == pb.PublicationOutcome_REJECTED { return nil, gatewayclient.ErrPublicationRejected @@ -57,6 +73,7 @@ func bootstrapFrozen(ctx context.Context, source, owner *gatewayclient.Client, f if status.Code(err) != codes.NotFound { return nil, err } + trace.phase("publication-stage-start") if err = source.StagePublication(ctx, frozen.Publication); err != nil { return nil, err } @@ -66,15 +83,16 @@ func bootstrapFrozen(ctx context.Context, source, owner *gatewayclient.Client, f if err != nil { return nil, err } - for _, task := range frozen.Tasks { - if frozen.SelectOnRequest { - break - } - if _, err = source.RPC.RegisterPublishedTask(source.Context(ctx), &pb.RegisterPublishedTaskRequest{Task: gatewayclient.Task(task), Publication: &pb.PublicationKey{OperationId: frozen.Publication.OperationID, Digest: digest}}); err != nil { - return nil, err + if !frozen.SelectOnRequest { + trace.phase("task-registration-start") + for _, task := range frozen.Tasks { + if _, err = source.RPC.RegisterPublishedTask(source.Context(ctx), &pb.RegisterPublishedTaskRequest{Task: gatewayclient.Task(task), Publication: &pb.PublicationKey{OperationId: frozen.Publication.OperationID, Digest: digest}}); err != nil { + return nil, err + } } } if receipt == nil { + trace.phase("publication-finalize-start") receipt, err = source.FinalizePublication(ctx, frozen.Publication) if err != nil { return nil, err @@ -83,18 +101,18 @@ func bootstrapFrozen(ctx context.Context, source, owner *gatewayclient.Client, f if receipt.GetRevision() != frozen.View().Revision || receipt.GetFence() != frozen.View().Fence { return nil, errors.New("source activation observation") } - g := &Gateway{owner: owner, tasks: map[string]v1.Task{}, operations: map[[2]string]bool{}, view: frozen.View()} - for _, task := range frozen.Tasks { - g.tasks[task.Family] = task - } + trace.phase("publication-confirmed") + g := &Gateway{owner: owner, operations: make(map[[2]string]v1.ProviderPlan, len(frozen.Plans))} + view := frozen.View() for _, plan := range frozen.Plans { - g.operations[[2]string{plan.Family, plan.Node}] = true + plan.Revision, plan.Fence = view.Revision, view.Fence + g.operations[[2]string{plan.Family, plan.Node}] = plan } if frozen.SelectOnRequest { g.source = source g.deferred = &frozen g.publication = &pb.PublicationKey{OperationId: frozen.Publication.OperationID, Digest: digest} - g.operations[[2]string{frozen.Tasks[0].Family, frozen.Routing[0].Node}] = true + g.operations[[2]string{frozen.Tasks[0].Family, frozen.Routing[0].Node}] = v1.ProviderPlan{} } return g, nil } @@ -112,7 +130,7 @@ func (g *Gateway) ExecuteProvider(in *pb.ProviderRequest, out pb.Gateway_Execute return status.Error(codes.InvalidArgument, "provider proposal required") } p := in.Plan - if !g.operations[[2]string{p.Family, p.Node}] { + if _, registered := g.operations[[2]string{p.Family, p.Node}]; !registered { return status.Error(codes.PermissionDenied, "unregistered operation") } routes := make([]v1.ProviderRoute, 0, len(p.Routes)) @@ -162,7 +180,7 @@ func (g *Gateway) InspectTelemetry(context.Context, *pb.Empty) (*pb.TelemetrySna } func (g *Gateway) Inspect(ctx context.Context, key *pb.OperationKey) (*pb.ProviderReceipt, error) { - if key == nil || !g.operations[[2]string{key.Family, key.Node}] { + if _, registered := g.operations[[2]string{key.GetFamily(), key.GetNode()}]; !registered { return nil, status.Error(codes.PermissionDenied, "unregistered operation") } forward, err := g.providerContext(ctx) @@ -174,11 +192,15 @@ func (g *Gateway) Inspect(ctx context.Context, key *pb.OperationKey) (*pb.Provid func (g *Gateway) compileProvider(ctx context.Context, proposal v1.ProviderPlan) (v1.ProviderPlan, string, error) { if g.deferred == nil { - plan, err := routing.CompileProvider(g.tasks[proposal.Family], proposal, g.view) - if err != nil { - return plan, "", status.Error(codes.PermissionDenied, "source contract rejected") + original, registered := g.operations[[2]string{proposal.Family, proposal.Node}] + // Bootstrap validated and took ownership of the exact original. The + // Rust owner still checks current authority on the submitted plan. + if !registered || proposal.Profile != original.Profile || proposal.ProfileCommitment != original.ProfileCommitment || + proposal.Model != original.Model || proposal.Ceiling != original.Ceiling || + !slices.Equal(proposal.Routes, original.Routes) || proposal.Body != original.Body { + return v1.ProviderPlan{}, "", status.Error(codes.PermissionDenied, "source contract rejected") } - return plan, "", nil + return original, "", nil } if proposal.Body != "" || proposal.Model != "" || proposal.Profile != "" || proposal.ProfileCommitment != "" || len(proposal.Routes) != 0 || proposal.Ceiling != 0 { @@ -188,11 +210,9 @@ func (g *Gateway) compileProvider(ctx context.Context, proposal v1.ProviderPlan) if err != nil { return v1.ProviderPlan{}, "", status.Error(codes.FailedPrecondition, "source routing rejected") } - _, err = g.source.RPC.RegisterPublishedTask(g.source.Context(ctx), &pb.RegisterPublishedTaskRequest{ - Task: gatewayclient.Task(selected.Tasks[0]), Publication: g.publication, - }) + _, err = g.source.RPC.RegisterPublishedTask(g.source.Context(ctx), selected.registration) if err != nil { return v1.ProviderPlan{}, "", err } - return selected.Plans[0], catalog, nil + return selected.bundle.Plans[0], catalog, nil } diff --git a/go/internal/controlplane/provider_binding_test.go b/go/internal/controlplane/provider_binding_test.go new file mode 100644 index 00000000..2bc085b9 --- /dev/null +++ b/go/internal/controlplane/provider_binding_test.go @@ -0,0 +1,103 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +package controlplane + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "fmt" + "reflect" + "slices" + "strings" + "testing" + + v1 "github.com/HardenedLinux/weaver/go/api/v1" + "github.com/HardenedLinux/weaver/go/internal/gatewayclient" + "github.com/HardenedLinux/weaver/go/internal/routing" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func TestPublishedProviderBindingOwnsExactOriginal(t *testing.T) { + _, bundle := artifactFixture(t) + client := &gatewayclient.Client{RPC: &sourceRPC{publication: bundle.Publication}, Token: "source-token"} + gateway, err := Bootstrap(t.Context(), client, client, bundle) + if err != nil { + t.Fatal(err) + } + proposal := bundle.Plans[0] + proposal.Routes = slices.Clone(proposal.Routes) + expected, err := routing.CompileProvider(bundle.Tasks[0], proposal, bundle.View()) + if err != nil { + t.Fatal(err) + } + bundle.Plans[0].Body = "replaced" + bundle.Plans[0].Routes[0].Endpoint = "https://replacement.invalid" + proposal.Revision, proposal.Fence = 999, 999 + got, _, err := gateway.compileProvider(t.Context(), proposal) + if err != nil || !reflect.DeepEqual(got, expected) { + t.Fatalf("published binding diverged from the admitted original: %v", err) + } + for _, change := range []func(*v1.ProviderPlan){ + func(p *v1.ProviderPlan) { p.Family += "-changed" }, + func(p *v1.ProviderPlan) { p.Node += "-changed" }, + func(p *v1.ProviderPlan) { p.Profile += "-changed" }, + func(p *v1.ProviderPlan) { p.ProfileCommitment += "-changed" }, + func(p *v1.ProviderPlan) { p.Model += "-changed" }, + func(p *v1.ProviderPlan) { p.Ceiling++ }, + func(p *v1.ProviderPlan) { p.Body += " " }, + func(p *v1.ProviderPlan) { p.Routes[0].Endpoint += "/changed" }, + } { + changed := proposal + changed.Routes = slices.Clone(proposal.Routes) + change(&changed) + if _, _, err := gateway.compileProvider(t.Context(), changed); status.Code(err) != codes.PermissionDenied { + t.Fatalf("changed original was not rejected: %v", err) + } + } +} + +func BenchmarkPublishedProviderBinding(b *testing.B) { + for _, size := range []int{128, 65536} { + _, bundle := artifactFixture(b) + task, proposal := bundle.Tasks[0], bundle.Plans[0] + task.ProviderProfile.MaxBodyBytes = 1 << 20 + proposal.Body = strings.Replace(proposal.Body, "hello", strings.Repeat("x", size), 1) + var err error + proposal.ProfileCommitment, err = task.ProviderProfile.Digest() + if err != nil { + b.Fatal(err) + } + task.StreamContracts[proposal.Node], err = proposal.Digest() + if err != nil { + b.Fatal(err) + } + body := sha256.Sum256([]byte(proposal.Body)) + task.BodyDigests[proposal.Node] = hex.EncodeToString(body[:]) + view := bundle.View() + original, err := routing.CompileProvider(task, proposal, view) + if err != nil { + b.Fatal(err) + } + gateway := &Gateway{operations: map[[2]string]v1.ProviderPlan{{proposal.Family, proposal.Node}: original}} + proposal.Body = strings.Clone(proposal.Body) + for _, name := range []string{"repeat-projection", "published-binding"} { + b.Run(fmt.Sprintf("%d/%s", size, name), func(b *testing.B) { + b.ReportAllocs() + for b.Loop() { + if name == "repeat-projection" { + _, err = routing.CompileProvider(task, proposal, view) + } else { + _, _, err = gateway.compileProvider(context.Background(), proposal) + } + if err != nil { + b.Fatal(err) + } + } + }) + } + } +} diff --git a/go/internal/controlplane/provider_catalog.go b/go/internal/controlplane/provider_catalog.go index a843e5c1..67c92160 100644 --- a/go/internal/controlplane/provider_catalog.go +++ b/go/internal/controlplane/provider_catalog.go @@ -5,12 +5,14 @@ package controlplane import ( + "bytes" "context" "encoding/json" "errors" pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" "github.com/HardenedLinux/weaver/go/internal/config" + "github.com/HardenedLinux/weaver/go/internal/gatewayclient" "github.com/HardenedLinux/weaver/go/internal/routing" ) @@ -26,27 +28,81 @@ type catalogEntry struct { } `json:"quote"` } -func (g *Gateway) materializeProvider(ctx context.Context) (config.Bundle, string, error) { +// A projection owns its input and selected bundle. It carries no authority. +type catalogProjection struct { + version string + record []byte + bundle config.Bundle + registration *pb.RegisterPublishedTaskRequest +} + +func (g *Gateway) materializeProvider(ctx context.Context) (*catalogProjection, string, error) { snapshot, err := g.source.RPC.InspectProviderCatalog(g.source.Context(ctx), &pb.Empty{}) if err != nil { - return config.Bundle{}, "", err + return nil, "", err } - bundle := *g.deferred - if snapshot.Version != "" { - var catalog struct { - Entries map[string]catalogEntry `json:"entries"` - } - if len(snapshot.Record) > 262144 || json.Unmarshal(snapshot.Record, &catalog) != nil { - return config.Bundle{}, "", errors.New("invalid provider catalog") - } - selection, err := catalogSelection(bundle.Routing[0], catalog.Entries) + selected, err := g.projectCatalog(snapshot) + return selected, snapshot.Version, err +} + +func (g *Gateway) projectCatalog(snapshot *pb.ProviderCatalogSnapshot) (*catalogProjection, error) { + if snapshot.Version == "" { + selected, err := g.deferred.MaterializeRequest() if err != nil { - return config.Bundle{}, "", err + return nil, err } - bundle.Routing = []routing.Selection{selection} + return &catalogProjection{bundle: selected, registration: g.catalogRegistration(selected)}, nil } - selected, err := bundle.MaterializeRequest() - return selected, snapshot.Version, err + if current := g.cachedCatalog(snapshot); current != nil { + return current, nil + } + // Requests still read the catalog independently. Share the projection + // work when they arrive together with the same new snapshot. + g.catalogBuildMu.Lock() + defer g.catalogBuildMu.Unlock() + if current := g.cachedCatalog(snapshot); current != nil { + return current, nil + } + selected, err := projectCatalog(*g.deferred, snapshot.Record) + if err != nil { + return nil, err + } + projection := &catalogProjection{ + version: snapshot.Version, record: bytes.Clone(snapshot.Record), bundle: selected, + registration: g.catalogRegistration(selected), + } + g.catalog.Store(projection) + return projection, nil +} + +func (g *Gateway) catalogRegistration(selected config.Bundle) *pb.RegisterPublishedTaskRequest { + // This request owns the wire projection. Concurrent RPCs marshal it read-only. + return &pb.RegisterPublishedTaskRequest{ + Task: gatewayclient.Task(selected.Tasks[0]), Publication: g.publication, + } +} + +func (g *Gateway) cachedCatalog(snapshot *pb.ProviderCatalogSnapshot) *catalogProjection { + current := g.catalog.Load() + if current != nil && current.version == snapshot.Version && bytes.Equal(current.record, snapshot.Record) { + return current + } + return nil +} + +func projectCatalog(bundle config.Bundle, record []byte) (config.Bundle, error) { + var catalog struct { + Entries map[string]catalogEntry `json:"entries"` + } + if len(record) > 262144 || json.Unmarshal(record, &catalog) != nil { + return config.Bundle{}, errors.New("invalid provider catalog") + } + selection, err := catalogSelection(bundle.Routing[0], catalog.Entries) + if err != nil { + return config.Bundle{}, err + } + bundle.Routing = []routing.Selection{selection} + return bundle.MaterializeRequest() } func catalogSelection(source routing.Selection, entries map[string]catalogEntry) (routing.Selection, error) { diff --git a/go/internal/controlplane/provider_catalog_test.go b/go/internal/controlplane/provider_catalog_test.go index 74acb4da..9440d26a 100644 --- a/go/internal/controlplane/provider_catalog_test.go +++ b/go/internal/controlplane/provider_catalog_test.go @@ -5,11 +5,22 @@ package controlplane import ( + "bytes" + "context" + "encoding/json" + "strings" + "sync" "testing" "testing/quick" + pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" v1 "github.com/HardenedLinux/weaver/go/api/v1" + "github.com/HardenedLinux/weaver/go/internal/config" + "github.com/HardenedLinux/weaver/go/internal/gatewayclient" "github.com/HardenedLinux/weaver/go/internal/routing" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) func TestCatalogSelectionUsesOnlyCurrentEntries(t *testing.T) { @@ -50,3 +61,166 @@ func TestCatalogSelectionUsesOnlyCurrentEntries(t *testing.T) { t.Fatal(err) } } + +func catalogProjectionFixture(t testing.TB) (config.Bundle, []byte, v1.ProviderPlan) { + t.Helper() + _, bundle := artifactFixture(t) + plan := bundle.Plans[0] + entry := catalogEntry{Module: "catalog", Latency: 1} + entry.Quote.TokenBounds[3] = 8 + digest, err := plan.Digest() + if err != nil { + t.Fatal(err) + } + record, err := json.Marshal(map[string]any{"entries": map[string]catalogEntry{digest: entry}}) + if err != nil { + t.Fatal(err) + } + bundle.Plans = nil + bundle.SelectOnRequest = true + bundle.Tasks[0].BodyDigests, bundle.Tasks[0].StreamContracts = nil, nil + bundle.Routing = []routing.Selection{{ + Node: plan.Node, AllowedModules: []string{entry.Module}, MaxLatencyMillis: 100, + Candidates: []routing.Candidate{{Module: entry.Module, LatencyMillis: entry.Latency, TokenBounds: entry.Quote.TokenBounds, Plan: plan}}, + }} + frozen, err := config.FreezeBundle(bundle) + if err != nil { + t.Fatal(err) + } + return frozen, record, v1.ProviderPlan{Family: plan.Family, Node: plan.Node} +} + +type catalogRPC struct { + sourceRPC + snapshot *pb.ProviderCatalogSnapshot + readErr error +} + +func (r *catalogRPC) InspectProviderCatalog(context.Context, *pb.Empty, ...grpc.CallOption) (*pb.ProviderCatalogSnapshot, error) { + r.calls = append(r.calls, "catalog") + return r.snapshot, r.readErr +} + +func TestCatalogProjectionRequiresExactSnapshotAndLiveAuthority(t *testing.T) { + bundle, record, key := catalogProjectionFixture(t) + rpc := &catalogRPC{snapshot: &pb.ProviderCatalogSnapshot{Version: "a", Record: bytes.Clone(record)}} + gateway := &Gateway{deferred: &bundle, source: &gatewayclient.Client{RPC: rpc}} + check := func(version string, code codes.Code, wantCalls string) { + t.Helper() + rpc.calls = nil + _, got, err := gateway.compileProvider(t.Context(), key) + if got != version || status.Code(err) != code || strings.Join(rpc.calls, ",") != wantCalls { + t.Fatalf("catalog version=%q status=%v calls=%v", got, err, rpc.calls) + } + } + check("a", codes.OK, "catalog,register") + a := gateway.catalog.Load() + check("a", codes.OK, "catalog,register") + if gateway.catalog.Load() != a { + t.Fatal("identical catalog was projected again") + } + rpc.failRegister = true + check("", codes.Unknown, "catalog,register") + rpc.failRegister = false + rpc.readErr = status.Error(codes.PermissionDenied, "catalog authority denied") + check("", codes.FailedPrecondition, "catalog") + rpc.readErr = nil + // The snapshot buffer can be reused by its caller. An invalid replacement + // with the same version must miss the cache and fail closed. + rpc.snapshot.Record[0] = '[' + check("", codes.FailedPrecondition, "catalog") + rpc.snapshot = &pb.ProviderCatalogSnapshot{Version: "b", Record: record} + check("b", codes.OK, "catalog,register") + if gateway.catalog.Load() == a || gateway.catalog.Load().version != "b" { + t.Fatal("a different version reused the original projection") + } + rpc.snapshot = &pb.ProviderCatalogSnapshot{Version: "withdrawn", Record: []byte(`{"entries":{}}`)} + check("", codes.FailedPrecondition, "catalog") +} + +func projectCatalogWave(t testing.TB, gateway *Gateway, snapshots [4]*pb.ProviderCatalogSnapshot) [4]config.Bundle { + t.Helper() + var bundles [4]config.Bundle + var errs [4]error + var workers sync.WaitGroup + start := make(chan struct{}) + for i, snapshot := range snapshots { + workers.Go(func() { + <-start + projection, err := gateway.projectCatalog(snapshot) + errs[i] = err + if err == nil { + bundles[i] = projection.bundle + } + }) + } + close(start) + workers.Wait() + for _, err := range errs { + if err != nil { + t.Fatal(err) + } + } + return bundles +} + +func TestConcurrentCatalogProjectionSharesExactSnapshot(t *testing.T) { + bundle, record, _ := catalogProjectionFixture(t) + gateway := &Gateway{deferred: &bundle} + for _, version := range []string{"a", "b"} { + var snapshots [4]*pb.ProviderCatalogSnapshot + for i := range snapshots { + snapshots[i] = &pb.ProviderCatalogSnapshot{Version: version, Record: bytes.Clone(record)} + } + bundles := projectCatalogWave(t, gateway, snapshots) + current := gateway.catalog.Load() + if current.version != version { + t.Fatal("catalog version was not replaced") + } + for _, projected := range bundles { + if &projected.Plans[0] != ¤t.bundle.Plans[0] { + t.Fatal("concurrent request did not reuse the retained projection") + } + } + } +} + +func BenchmarkProviderCatalogProjection(b *testing.B) { + bundle, record, _ := catalogProjectionFixture(b) + for _, size := range []struct { + name string + padding int + }{{"one-entry", 0}, {"padded-64KiB", 65536}} { + snapshot := &pb.ProviderCatalogSnapshot{Version: "a", Record: append(bytes.Clone(record), bytes.Repeat([]byte(" "), size.padding)...)} + gateway := &Gateway{deferred: &bundle} + if _, err := gateway.projectCatalog(snapshot); err != nil { + b.Fatal(err) + } + b.Run(size.name+"/repeat-projection", func(b *testing.B) { + b.ReportAllocs() + for b.Loop() { + if _, err := projectCatalog(bundle, snapshot.Record); err != nil { + b.Fatal(err) + } + } + }) + b.Run(size.name+"/exact-snapshot", func(b *testing.B) { + b.ReportAllocs() + for b.Loop() { + if _, err := gateway.projectCatalog(snapshot); err != nil { + b.Fatal(err) + } + } + }) + b.Run(size.name+"/four-misses", func(b *testing.B) { + var snapshots [4]*pb.ProviderCatalogSnapshot + for i := range snapshots { + snapshots[i] = &pb.ProviderCatalogSnapshot{Version: snapshot.Version, Record: bytes.Clone(snapshot.Record)} + } + b.ReportAllocs() + for b.Loop() { + projectCatalogWave(b, &Gateway{deferred: &bundle}, snapshots) + } + }) + } +} diff --git a/go/internal/controlplane/source_compile.go b/go/internal/controlplane/source_compile.go index 126df314..f0c99ddc 100644 --- a/go/internal/controlplane/source_compile.go +++ b/go/internal/controlplane/source_compile.go @@ -18,18 +18,25 @@ import ( // BootstrapProducer joins native registered compilation to the existing exact // source reconciliation/publication and routing path. Compilation never sends. func BootstrapProducer(ctx context.Context, source, owner *gatewayclient.Client, producer string) (*Gateway, error) { + return bootstrapProducer(ctx, source, owner, producer, nil) +} + +func bootstrapProducer(ctx context.Context, source, owner *gatewayclient.Client, producer string, trace bootstrapTrace) (*Gateway, error) { if source == nil || owner == nil { return nil, errors.New("source and operation authority roles required") } + trace.phase("source-compile-start") reply, err := source.CompileSource(ctx, producer) if err != nil { return nil, err } + trace.phase("source-compile-complete") bundle, err := compiledBundle(reply.Artifact) if err != nil { return nil, err } - return bootstrapFrozen(ctx, source, owner, bundle) + trace.phase("source-bundle-decoded") + return bootstrapFrozen(ctx, source, owner, bundle, trace) } // Decode concrete protobuf fields directly. No interop JSON/YAML roundtrip and diff --git a/go/internal/controlplane/source_compile_bench_test.go b/go/internal/controlplane/source_compile_bench_test.go index fbec11f1..1a9bbaf1 100644 --- a/go/internal/controlplane/source_compile_bench_test.go +++ b/go/internal/controlplane/source_compile_bench_test.go @@ -53,7 +53,7 @@ func BenchmarkCompiledSourceAdmission(b *testing.B) { if bootstrap { rpc.calls = rpc.calls[:0] result, err := BootstrapProducer(context.Background(), client, client, "approved") - if err != nil || result.tasks[task.Family].BodyDigests[plan.Node] != task.BodyDigests[plan.Node] || len(rpc.calls) != 6 { + if err != nil || result.operations[[2]string{task.Family, plan.Node}].Body != plan.Body || len(rpc.calls) != 6 { b.Fatal("local source bootstrap", err) } } else { diff --git a/go/internal/devrunner/contention.go b/go/internal/devrunner/contention.go index 9bceb4ca..6030ce5b 100644 --- a/go/internal/devrunner/contention.go +++ b/go/internal/devrunner/contention.go @@ -40,17 +40,42 @@ func (sample *TimingSample) UnmarshalJSON(data []byte) error { } type TransactionTimings struct { - OwnerGateWait TimingSample `json:"owner_gate_wait"` - DomainKeys TimingSample `json:"domain_keys"` - DomainWait TimingSample `json:"domain_wait"` - TransactionBegin TimingSample `json:"transaction_begin"` - OwnerGateHold TimingSample `json:"owner_gate_hold"` - DomainHold TimingSample `json:"domain_hold"` - TransactionHold TimingSample `json:"transaction_hold"` - Commit TimingSample `json:"commit"` - Rollback TimingSample `json:"rollback"` - ProviderRequest TimingSample `json:"provider_request"` - ProviderQueue TimingSample `json:"provider_queue"` + OwnerGateWait TimingSample `json:"owner_gate_wait"` + DomainKeys TimingSample `json:"domain_keys"` + DomainWait TimingSample `json:"domain_wait"` + AuthoritySpan TimingSample `json:"authority_span"` + TransactionBegin TimingSample `json:"transaction_begin"` + TransactionBeginPoll *TimingSample `json:"transaction_begin_poll,omitempty"` + TransactionBeginCPU *TimingSample `json:"transaction_begin_cpu,omitempty"` + TransactionBeginPrepare *TimingSample `json:"transaction_begin_prepare,omitempty"` + TransactionBeginPrepareCPU *TimingSample `json:"transaction_begin_prepare_cpu,omitempty"` + TransactionBeginPending *uint64 `json:"transaction_begin_pending,omitempty"` + OwnerGateHold TimingSample `json:"owner_gate_hold"` + DomainHold TimingSample `json:"domain_hold"` + TransactionHold TimingSample `json:"transaction_hold"` + Commit TimingSample `json:"commit"` + CommitPoll *TimingSample `json:"commit_poll,omitempty"` + CommitCPU *TimingSample `json:"commit_cpu,omitempty"` + CommitSync *TimingSample `json:"commit_sync,omitempty"` + CommitPending *uint64 `json:"commit_pending,omitempty"` + Rollback TimingSample `json:"rollback"` + ProviderOAuthPrepare TimingSample `json:"provider_oauth_prepare"` + ProviderOAuthCheck TimingSample `json:"provider_oauth_check"` + ProviderDomain TimingSample `json:"provider_domain"` + ProviderDomainPrepare TimingSample `json:"provider_domain_prepare"` + ProviderPending TimingSample `json:"provider_pending"` + ProviderReview TimingSample `json:"provider_review"` + ProviderBirth TimingSample `json:"provider_birth"` + ProviderPublicationPrepare TimingSample `json:"provider_publication_prepare"` + ProviderProfile TimingSample `json:"provider_profile"` + ProviderClaim TimingSample `json:"provider_claim"` + ProviderHistory TimingSample `json:"provider_history"` + ProviderManifest TimingSample `json:"provider_manifest"` + ProviderOriginal TimingSample `json:"provider_original"` + ProviderOriginalPrepare TimingSample `json:"provider_original_prepare"` + ProviderCedar TimingSample `json:"provider_cedar"` + ProviderRequest TimingSample `json:"provider_request"` + ProviderQueue TimingSample `json:"provider_queue"` } type ContentionObservation struct { First TransactionTimings `json:"first"` @@ -109,28 +134,28 @@ func ReadContentionEvidence(input io.Reader) (*ContentionEvidence, error) { for i, timing := range []TransactionTimings{row.Observation.First, row.Observation.Second} { attempts := uint64(2) requests := uint64(1) - if publication && i == 1 { + global := publication && i == 1 + if global { attempts = 1 requests = 0 } - if timing.TransactionBegin.Attempts != attempts || timing.Commit.Attempts != attempts || timing.TransactionHold.Attempts != attempts || timing.ProviderRequest.Attempts != requests || timing.ProviderQueue.Attempts != 0 || timing.Rollback.Attempts != 0 || timing.TransactionHold.Nanos < timing.ProviderRequest.Nanos { + if timing.TransactionBegin.Attempts != attempts || timing.Commit.Attempts != attempts || timing.TransactionHold.Attempts != attempts || timing.AuthoritySpan.Attempts != attempts || timing.ProviderRequest.Attempts != requests || timing.ProviderQueue.Attempts != 0 || timing.Rollback.Attempts != 0 || timing.TransactionHold.Nanos < timing.ProviderRequest.Nanos || timing.AuthoritySpan.Nanos < timing.TransactionHold.Nanos { return nil, fmt.Errorf("invalid deciding-scope observation") } - if row.Profile == "wal-writer" { - if timing.DomainWait.Attempts != 0 || timing.OwnerGateWait.Attempts != 0 { - return nil, fmt.Errorf("WAL observations claim MVCC locks") - } - } else { - if timing.OwnerGateWait.Attempts != attempts || timing.OwnerGateHold.Attempts != attempts { - return nil, fmt.Errorf("missing publication gate observation") - } - domains := attempts - if publication && i == 1 { - domains = 0 - } - if timing.DomainWait.Attempts != domains || timing.DomainHold.Attempts != domains || timing.DomainKeys.Attempts != domains { - return nil, fmt.Errorf("missing shared-domain observation") - } + // The MVCC scheduler grants one scope per transaction. + // Publication takes the global scope, provider sends take + // domain scopes, and WAL takes neither. + var owners, domains uint64 + if global { + owners = attempts + } else if row.Profile != "wal-writer" { + domains = attempts + } + if timing.OwnerGateWait.Attempts != owners || timing.OwnerGateHold.Attempts != owners { + return nil, fmt.Errorf("invalid publication gate observation") + } + if timing.DomainWait.Attempts != domains || timing.DomainHold.Attempts != domains || timing.DomainKeys.Attempts != domains { + return nil, fmt.Errorf("invalid shared-domain observation") } } result.Samples = append(result.Samples, row) diff --git a/go/internal/devrunner/contention_test.go b/go/internal/devrunner/contention_test.go index a06b6f22..676d2e48 100644 --- a/go/internal/devrunner/contention_test.go +++ b/go/internal/devrunner/contention_test.go @@ -20,17 +20,15 @@ func contentionFixture(t *testing.T) []ContentionSample { for _, profile := range contentionProfiles { for block := 0; block < 6; block++ { for slot := 0; slot < 4; slot++ { - timing := TransactionTimings{TransactionBegin: TimingSample{Attempts: 2, Nanos: 1}, TransactionHold: TimingSample{Attempts: 2, Nanos: 2}, Commit: TimingSample{Attempts: 2, Nanos: 1}, ProviderRequest: TimingSample{Attempts: 1, Nanos: 1}} + timing := TransactionTimings{TransactionBegin: TimingSample{Attempts: 2, Nanos: 1}, TransactionHold: TimingSample{Attempts: 2, Nanos: 2}, AuthoritySpan: TimingSample{Attempts: 2, Nanos: 2}, Commit: TimingSample{Attempts: 2, Nanos: 1}, ProviderRequest: TimingSample{Attempts: 1, Nanos: 1}} if profile != "wal-writer" { - timing.OwnerGateWait.Attempts = 2 - timing.OwnerGateHold.Attempts = 2 timing.DomainWait.Attempts = 2 timing.DomainKeys.Attempts = 2 timing.DomainHold.Attempts = 2 } second := timing if profile == "mvcc-publication" { - second = TransactionTimings{OwnerGateWait: TimingSample{Attempts: 1}, OwnerGateHold: TimingSample{Attempts: 1}, TransactionBegin: TimingSample{Attempts: 1}, TransactionHold: TimingSample{Attempts: 1}, Commit: TimingSample{Attempts: 1}} + second = TransactionTimings{OwnerGateWait: TimingSample{Attempts: 1}, OwnerGateHold: TimingSample{Attempts: 1}, TransactionBegin: TimingSample{Attempts: 1}, TransactionHold: TimingSample{Attempts: 1}, AuthoritySpan: TimingSample{Attempts: 1}, Commit: TimingSample{Attempts: 1}} } rows = append(rows, ContentionSample{Profile: profile, Optimized: true, Block: block, Slot: slot, Contended: slot == 1 || slot == 2, Observation: ContentionObservation{First: timing, Second: second}}) } @@ -59,7 +57,7 @@ func TestContentionEvidenceRejectsPartialReorderedOrDebugObservations(t *testing property := func(raw uint8, fault uint8) bool { rows := append([]ContentionSample(nil), original...) index := int(raw) % len(rows) - switch fault % 5 { + switch fault % 7 { case 0: rows = append(rows[:index], rows[index+1:]...) case 1: @@ -70,6 +68,10 @@ func TestContentionEvidenceRejectsPartialReorderedOrDebugObservations(t *testing rows[index].Slot = 99 case 4: rows = append(rows, rows[index]) + case 5: + rows[index].Observation.First.OwnerGateHold.Attempts = 2 + case 6: + rows[index].Observation.First.AuthoritySpan.Attempts = 0 } _, err := ReadContentionEvidence(strings.NewReader(contentionLog(t, rows))) return err != nil diff --git a/go/internal/devrunner/header_seal.go b/go/internal/devrunner/header_seal.go index 56d4a00b..7df37b71 100644 --- a/go/internal/devrunner/header_seal.go +++ b/go/internal/devrunner/header_seal.go @@ -63,7 +63,9 @@ func ReadHeaderSealEvidence(input io.Reader, cpus int) (*HeaderSealEvidence, err return nil, fmt.Errorf("invalid header-seal coordinates/exposure at %d", n) } timing := row.Timings - if timing.ProviderRequest.Attempts != 1 || timing.ProviderQueue.Attempts != 3 || timing.Commit.Attempts == 0 || timing.Rollback.Attempts != 0 || timing.ProviderRequest.Nanos == 0 || timing.TransactionHold.Nanos < timing.ProviderRequest.Nanos || row.Wall < timing.TransactionHold.Nanos { + // One snapshot stages the first frame under the writer. The + // remaining frames use their committed delivery receipts. + if timing.ProviderRequest.Attempts != 1 || timing.ProviderQueue.Attempts != 1 || timing.Commit.Attempts == 0 || timing.Rollback.Attempts != 0 || timing.ProviderRequest.Nanos == 0 || timing.TransactionHold.Nanos < timing.ProviderRequest.Nanos || row.Wall < timing.TransactionHold.Nanos { return nil, fmt.Errorf("invalid header-seal timing scope") } result.Samples = append(result.Samples, row) diff --git a/go/internal/devrunner/header_seal_test.go b/go/internal/devrunner/header_seal_test.go index 1b14b557..85245017 100644 --- a/go/internal/devrunner/header_seal_test.go +++ b/go/internal/devrunner/header_seal_test.go @@ -18,7 +18,7 @@ func headerEvidence(t *testing.T) string { var out strings.Builder fmt.Fprintf(&out, "weaver-header-seal-image sha256=%s profile=release\n", strings.Repeat("a", 64)) for i := 0; i < 24; i++ { - timing := &TransactionTimings{ProviderRequest: TimingSample{1, 10}, ProviderQueue: TimingSample{3, 5}, Commit: TimingSample{1, 5}, TransactionHold: TimingSample{1, 20}} + timing := &TransactionTimings{ProviderRequest: TimingSample{1, 10}, ProviderQueue: TimingSample{1, 5}, Commit: TimingSample{1, 5}, TransactionHold: TimingSample{1, 20}} row := HeaderSealSample{Block: i / 4, Slot: i % 4, Delayed: i%4 == 1 || i%4 == 2, Optimized: true, CPUs: 12, Wall: 100, Held: 4, Events: 3, Calls: i + 1, Timings: timing} data, err := json.Marshal(row) if err != nil { @@ -41,7 +41,7 @@ func TestHeaderSealEvidenceRejectsIncompleteAndCorruptPairs(t *testing.T) { check := func(selector uint8) bool { lines := strings.Split(strings.TrimSpace(valid), "\n") index := 1 + int(selector)%24 - switch selector % 7 { + switch selector % 8 { case 0: lines = append(lines[:index], lines[index+1:]...) case 1: @@ -56,6 +56,8 @@ func TestHeaderSealEvidenceRejectsIncompleteAndCorruptPairs(t *testing.T) { lines[0] = strings.Replace(lines[0], "release", "dev", 1) case 6: lines[0] = "" + case 7: + lines[index] = strings.Replace(lines[index], `"provider_queue":{"attempts":1`, `"provider_queue":{"attempts":3`, 1) } _, err := ReadHeaderSealEvidence(strings.NewReader(strings.Join(lines, "\n")), 12) return err != nil diff --git a/go/internal/devrunner/runner.go b/go/internal/devrunner/runner.go index 6fd0527f..a61957eb 100644 --- a/go/internal/devrunner/runner.go +++ b/go/internal/devrunner/runner.go @@ -361,11 +361,14 @@ func runStageObserved(ctx context.Context, root, directory string, environment [ result.Lean, proofErr = readLeanEvidence(root, source, filepath.Join(directory, result.Log)) err = errors.Join(err, proofErr) } + // Go benchmarks label rows with the effective GOMAXPROCS inherited + // by the child. The separate Rust header-seal report uses host CPUs. + goCPUs := runtime.GOMAXPROCS(0) if stage.Name == "runtime-projection-benchmark" && err == nil && closeErr == nil { - result.GoBenchmarks, err = readGoBenchmarks(filepath.Join(directory, result.Log), runtime.NumCPU(), sourceAdmissionBenchmarks...) + result.GoBenchmarks, err = readGoBenchmarks(filepath.Join(directory, result.Log), goCPUs, sourceAdmissionBenchmarks...) } if stage.Name == "published-pipeline-benchmark" && err == nil && closeErr == nil { - result.PipelineBenchmarks, err = readPipelineBenchmarks(filepath.Join(directory, result.Log), runtime.NumCPU(), "BenchmarkGatewayPublishedPipeline/registered") + result.PipelineBenchmarks, err = readPipelineBenchmarks(filepath.Join(directory, result.Log), goCPUs, "BenchmarkGatewayPublishedPipeline/registered") result.Details = "Real Go/Cedar/Rust path; Scheme preparation excluded, not a latency qualification." } if stage.Name == "execution-contention-pair" && err == nil && closeErr == nil { @@ -383,20 +386,20 @@ func runStageObserved(ctx context.Context, root, directory string, environment [ } if stage.Name == "execution-header-wait-pair" && err == nil && closeErr == nil { - result.PipelineBenchmarks, err = readProviderPairBenchmarks(filepath.Join(directory, result.Log), runtime.NumCPU(), "BenchmarkGatewayHeaderWaitPair", "immediate", "delayed") + result.PipelineBenchmarks, err = readProviderPairBenchmarks(filepath.Join(directory, result.Log), goCPUs, "BenchmarkGatewayHeaderWaitPair", "immediate", "delayed") result.Details = "Six complete same-image ABBA blocks; fully consumed HTTPS request, immediate versus 30ms delayed headers. Sensitivity control, not an early-unlock speedup." } if stage.Name == "execution-streaming-pair" && err == nil && closeErr == nil { - result.PipelineBenchmarks, err = readStreamingPairBenchmarks(filepath.Join(directory, result.Log), runtime.NumCPU()) + result.PipelineBenchmarks, err = readStreamingPairBenchmarks(filepath.Join(directory, result.Log), goCPUs) result.Details = "Six complete same-image ABBA blocks, Arrow rows=1 versus rows=32; not a before/after implementation speedup." } if stage.Name == "runtime-pipeline-benchmark" && err == nil && closeErr == nil { - result.PipelineBenchmarks, err = readPipelineBenchmarks(filepath.Join(directory, result.Log), runtime.NumCPU()) + result.PipelineBenchmarks, err = readPipelineBenchmarks(filepath.Join(directory, result.Log), goCPUs) result.Details = "Complete functional pipeline samples; no end-to-end speedup or non-regression qualification." } if stage.Name == "grpc-benchmark" && err == nil && closeErr == nil { - result.GoBenchmarks, err = readGoBenchmarks(filepath.Join(directory, result.Log), runtime.NumCPU()) + result.GoBenchmarks, err = readGoBenchmarks(filepath.Join(directory, result.Log), goCPUs) } if (stage.Name == "storage-final-benchmark" || stage.Name == "telemetry-benchmark" || stage.Name == "execution-policy-benchmark" || stage.Name == "execution-ledger-benchmark" || stage.Name == "execution-provider-benchmark" || stage.Name == "execution-encoding-benchmark") && err == nil && closeErr == nil { cases := storageBenchmarkCases diff --git a/scheme/gateway/compiled.ss b/scheme/gateway/compiled.ss index bf172694..2419fa11 100644 --- a/scheme/gateway/compiled.ss +++ b/scheme/gateway/compiled.ss @@ -5,7 +5,7 @@ ;;; Fixed linked ABI. The approved application is an explicit build graph root. ;;; No application, Governor, Profile, module path or Policy is selected by RPC. (import :std/ffi - (only-in :clan/poo/object .get) + (only-in :clan/poo/object .get .o) :gerbil-scheme-rust/scheme/runtime (only-in "./func.ss" governor-ready-steps make-retained-governor gateway-source-cancelled?) (only-in "./program.ss" make-gateway-program hard-fact-affected) @@ -38,7 +38,16 @@ (def (derive-request value) (with-catch (lambda (_) #f) (lambda () - (source-data->scheme-value (derive-governor (scheme-value->source-data value)))))) + (let (packed (table-ref value 'packed_facts #f)) + (source-data->scheme-value + (if packed + (begin + (unless (and retained-governor? (= (table-length value) 3)) + (error "Packed Governor cut requires a retained binding")) + (derive-governor (.o topology_binding: (table-ref value 'topology_binding) + indexed_result: (table-ref value 'indexed_result)) + packed)) + (derive-governor (scheme-value->source-data value)))))))) (def (fact-impact-request value) (with-catch (lambda (_) #f) (lambda () diff --git a/scheme/gateway/func.ss b/scheme/gateway/func.ss index e4e6b5dc..5758e4d9 100644 --- a/scheme/gateway/func.ss +++ b/scheme/gateway/func.ss @@ -3,7 +3,7 @@ ;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 ;;; Compose admitted module capabilities into the existing typed wire artifact. -(import (only-in :clan/poo/object .get .o .slot?) +(import (only-in :clan/poo/object .get .ref .o .slot?) (only-in :clan/poo/mop validate json<-) (only-in :std/encoding/json json->string JSONWriteOptions) (only-in :yuanxu/module-system/interface yuanxu-load-modules) @@ -17,6 +17,7 @@ (only-in :hardenedlinux/weaver/scheme/policy/types PolicyProjection) (only-in :hardenedlinux/weaver/scheme/policy/func validate-policy-projection!) (only-in :gerbil-ascent/program/scheme-language relational-program) + (only-in :gerbil-ascent/program/func gerbil-ascent-program) (only-in :gerbil-ascent/program/session gerbil-ascent-open-session gerbil-ascent-session-run gerbil-ascent-session-replace-sources!) (only-in "./capture.ss" deliver-gateway-source) @@ -129,95 +130,202 @@ ;;; All values are detached observations from the Rust ledger. Derived nodes ;;; carry no authority across the subsequent ledger admission transaction. (def (governor-ready-steps cut) - (derive-governor-steps cut #f)) + (derive-governor-steps cut (apply project-governor-topology (governor-topology-key cut)) #f)) -;;; The linked owner retains at most one graph and one completed ASCENT session. -;;; The linked image fixes the rules. Each new cut replaces every dynamic input. -(def (make-retained-governor) +(defstruct governor-topology (nodes ids edges arm join nested-nodes nested-root gate)) + +(def (governor-topology-key cut) + (def (optional slot) (if (.slot? cut slot) (.ref cut slot) '())) + (list (.get cut nodes) (.get cut edges) (optional 'choice_arms) + (optional 'choice_join) (optional 'nested_selectors))) + +(def (project-governor-topology nodes links arms joins selectors) + (def ids (make-hash-table)) + (for-each (lambda (node index) (hash-put! ids node index)) nodes (iota (length nodes))) + (def edges + (map (lambda (edge) (map (lambda (node) (hash-ref ids node)) edge)) links)) + (def arm + (map (lambda (node tag) (list (hash-ref ids node) tag)) arms (iota (length arms)))) + (def join (map (lambda (node) (list (hash-ref ids node))) joins)) + (def nested-nodes (if (null? selectors) '() (map list (iota (length nodes))))) + (def nested-root (if (null? selectors) '() '((0)))) + (def gate + (apply append (map (lambda (row) + (let ((selector (hash-ref ids (car row)))) + (list (list (hash-ref ids (cadr row)) selector 0) + (list (hash-ref ids (caddr row)) selector 1)))) selectors))) + (make-governor-topology nodes ids edges arm join nested-nodes nested-root gate)) + +;;; The linked owner retains one static projection and one ASCENT session. +;;; The linked image fixes the rules. Each cut supplies all dynamic inputs. +(def (make-retained-governor + (changed-only? (equal? (getenv "WEAVER_TEST_GOVERNOR_CHANGED_SOURCES" #f) "1"))) + (def binding #f) + (def key #f) (def topology #f) (def session #f) + (def previous #f) (def (forget!) + (set! binding #f) + (set! key #f) (set! topology #f) - (set! session #f)) - (def (derive graph sources build-program) - (if (and session (equal? topology graph)) - (values (gerbil-ascent-session-replace-sources! session sources) 'replace) - (begin - (forget!) - (let* ((candidate (gerbil-ascent-open-session (build-program))) - (result (gerbil-ascent-session-run candidate))) - (when (.ref result 'finished) - (set! topology (copy-source-data graph)) - (set! session candidate)) - (values result 'open))))) - (lambda (cut) + (set! session #f) + (set! previous #f)) + (def (derive sources build-program) + (if session + (let* ((replacements + (if changed-only? + (filter (lambda (relation) (not (equal? relation (assq (car relation) previous)))) + sources) + sources)) + (result (if (null? replacements) + (gerbil-ascent-session-run session) + (gerbil-ascent-session-replace-sources! session replacements)))) + (when (and changed-only? (.ref result 'finished)) + (set! previous sources)) + (values result (if (null? replacements) 'reuse 'replace) (length replacements))) + (let* ((candidate (gerbil-ascent-open-session (build-program))) + (result (gerbil-ascent-session-run candidate))) + (when (.ref result 'finished) + (set! session candidate) + (when changed-only? (set! previous sources))) + (values result 'open (length sources))))) + (lambda (cut (packed #f)) (with-catch (lambda (failure) (forget!) (raise failure)) - (lambda () (derive-governor-steps cut derive))))) + (lambda () + (let (requested (and (.slot? cut 'topology_binding) (.get cut topology_binding))) + (if (.slot? cut 'nodes) + (let (incoming (governor-topology-key cut)) + (unless (and topology (equal? requested binding) (equal? incoming key)) + (forget!) + (set! key (copy-source-data incoming)) + (set! topology (apply project-governor-topology key)) + (set! binding requested))) + (unless (and topology binding (equal? requested binding)) + (error "Governor topology binding unavailable"))) + (when (and packed (or (.slot? cut 'nodes) (not binding) (not (.slot? cut 'indexed_result)))) + (error "Packed Governor cut requires a retained binding")) + (derive-governor-steps cut topology derive packed)))))) -(def (derive-governor-steps cut retained) +;;; Decode one complete mutable relation set in its bound node namespace. +(def (unpack-governor-facts packed node-count) + (unless (u8vector? packed) (error "Invalid packed Governor cut")) + (def length (u8vector-length packed)) + (def offset 0) + (def (byte) + (when (>= offset length) (error "Truncated packed Governor cut")) + (begin0 (u8vector-ref packed offset) (set! offset (1+ offset)))) + (def (node) + (let (index (byte)) + (unless (< index node-count) (error "Foreign packed Governor node")) + index)) + (def (route) + (let (tag (byte)) + (unless (< tag 2) (error "Invalid packed Governor route")) + tag)) + (def (group name row) + (let (count (byte)) + (when (> count 64) (error "Packed Governor relation exceeds bound")) + (cons name (map (lambda (_) (row)) (iota count))))) + (def (node-row) (list (node))) + (def (route-row) + (let (index (node)) (list index (route)))) + (let* ((complete (group 'complete node-row)) + (available (group 'available node-row)) + (pending (group 'pending node-row)) + (route (group 'route (lambda () (list (route))))) + (decided (group 'decided node-row)) + (results (group 'selector-result route-row)) + (decisions (group 'selector-decision route-row))) + (unless (= offset length) (error "Extra bytes in packed Governor cut")) + (list complete available pending route decided results decisions))) + +;;; Partially apply the fixed rule family to an already admitted topology. +;;; The full fresh program remains the oracle. Never remove source-bearing +;;; declarations or alter its budgets; ASCENT still owns admission/replacement. +(def (prepare-retained-governor-program program topology retained) + (if (and retained + (pair? (governor-topology-nested-nodes topology)) + (= (length (governor-topology-nested-nodes topology)) + (length (governor-topology-nodes topology))) + (null? (governor-topology-arm topology)) + (null? (governor-topology-join topology))) + (let () + (def (flat-private? name) (memq name '(choice-made skip missing))) + (def (flat-rule? rule) + (or (ormap (lambda (head) (flat-private? (.ref head 'relation))) (.ref rule 'heads)) + (ormap (lambda (clause) + (and (.slot? clause 'ascent-clause-kind) + (eq? (.ref clause 'ascent-clause-kind) 'negation) + (eq? (.ref clause 'relation) 'nested-node))) + (.ref rule 'body)))) + (def prepared + (gerbil-ascent-program + (filter (lambda (relation) (not (flat-private? (.ref relation 'name)))) + (.ref program 'relations)) + (filter (lambda (rule) (not (flat-rule? rule))) (.ref program 'rules)) + (.ref program 'max-input-facts) (.ref program 'max-derived-facts) + (.ref program 'max-output-facts) + (filter (lambda (name) (not (flat-private? name))) (.ref program 'source-handles)))) + (when (getenv "WEAVER_TEST_GOVERNOR_TIMING" #f) + (let (port (current-error-port)) + (display "weaver-governor-program mode=nested relations=" port) + (display (length (.ref prepared 'relations)) port) + (display " rules=" port) (display (length (.ref prepared 'rules)) port) + (newline port) (force-output port))) + prepared) + program)) + +(def (derive-governor-steps cut topology retained (packed #f)) (def timing? (getenv "WEAVER_TEST_GOVERNOR_TIMING" #f)) - (def nodes (.get cut nodes)) - (def ids (make-hash-table)) - (for-each (lambda (node index) (hash-put! ids node index)) nodes (iota (length nodes))) + (def ids (governor-topology-ids topology)) (def (rows slot) (map (lambda (node) (list (hash-ref ids node))) (.ref cut slot))) - (def edges - (map (lambda (edge) (map (lambda (node) (hash-ref ids node)) edge)) - (.get cut edges))) - (def arms (if (.slot? cut 'choice_arms) (.get cut choice_arms) '())) (def (choice-rows slot) (if (.slot? cut slot) (rows slot) '())) (def route (if (.slot? cut 'choice_result) (map (lambda (value) (list (if (equal? value "left") 0 1))) (.get cut choice_result)) '())) - (def selectors (if (.slot? cut 'nested_selectors) (.get cut nested_selectors) '())) (def (routes slot) (if (.slot? cut slot) (map (lambda (row) (list (hash-ref ids (car row)) (if (equal? (cadr row) "left") 0 1))) (.ref cut slot)) '())) - (def arm - (map (lambda (node tag) (list (hash-ref ids node) tag)) arms (iota (length arms)))) - (def join (choice-rows 'choice_join)) - (def nested-nodes (if (null? selectors) '() (map list (iota (length nodes))))) - (def nested-root (if (null? selectors) '() '((0)))) - (def gate - (apply append (map (lambda (row) - (let ((selector (hash-ref ids (car row)))) - (list (list (hash-ref ids (cadr row)) selector 0) - (list (hash-ref ids (caddr row)) selector 1)))) selectors))) (def sources - (list (cons 'complete (rows 'complete)) - (cons 'available (rows 'available)) - (cons 'pending (rows 'pending)) - (cons 'route route) - (cons 'decided (choice-rows 'choice_decided)) - (cons 'selector-result (routes 'nested_results)) - (cons 'selector-decision (routes 'nested_decisions)))) + (if packed + (unpack-governor-facts packed (length (governor-topology-nodes topology))) + (list (cons 'complete (rows 'complete)) + (cons 'available (rows 'available)) + (cons 'pending (rows 'pending)) + (cons 'route route) + (cons 'decided (choice-rows 'choice_decided)) + (cons 'selector-result (routes 'nested_results)) + (cons 'selector-decision (routes 'nested_decisions))))) (def (source name) (cdr (assq name sources))) (def setup 0) (def (build-program) (def started (and timing? (real-time))) (begin0 - (relational-program - (relation edge (child parent) edges) + (prepare-retained-governor-program + (relational-program + (relation edge (child parent) (governor-topology-edges topology)) (relation complete (node) (source 'complete)) (relation available (node) (source 'available)) (relation pending (node) (source 'pending)) - (relation arm (node tag) arm) + (relation arm (node tag) (governor-topology-arm topology)) (relation route (tag) (source 'route)) - (relation join (node) join) + (relation join (node) (governor-topology-join topology)) (relation decided (node) (source 'decided)) (relation choice-made (node) '()) (relation skip (child parent) '()) (relation missing (node) '()) (relation successor (node) '()) (relation ready (node) '()) - (relation nested-node (node) nested-nodes) - (relation nested-root (node) nested-root) - (relation gate (child selector tag) gate) + (relation nested-node (node) (governor-topology-nested-nodes topology)) + (relation nested-root (node) (governor-topology-nested-root topology)) + (relation gate (child selector tag) (governor-topology-gate topology)) (relation selector-result (selector tag) (source 'selector-result)) (relation selector-decision (selector tag) (source 'selector-decision)) (relation gated (child parent) '()) @@ -248,13 +356,14 @@ (rule (ready ?n) (nested-node ?n) (active ?n) (successor ?n) (pending ?n) (available ?n) (not (blocked ?n))) (rule (ready ?n) (gate ?n ?p ?tag) (selector-result ?p ?tag) (active ?p) (complete ?p) (available ?p) (available ?n) (pending ?n) (not (decided-selector ?p))) - (limits 640 768 1408)) + (limits 640 768 1408)) topology retained) (when started (set! setup (- (real-time) started))))) (def run-start (and timing? (real-time))) - (defvalues (result mode) + (defvalues (result mode source-count) (if retained - (retained (list nodes edges arm join nested-nodes nested-root gate) sources build-program) - (values (gerbil-ascent-session-run (gerbil-ascent-open-session (build-program))) 'fresh))) + (retained sources build-program) + (values (gerbil-ascent-session-run (gerbil-ascent-open-session (build-program))) + 'fresh (length sources)))) (when timing? (let ((end (real-time)) (port (current-error-port))) (display "weaver-governor-ascent setup_s=" port) @@ -264,9 +373,17 @@ (display " mode=" port) (display mode port) (newline port) + (display "weaver-governor-relations count=" port) + (display source-count port) + (newline port) (force-output port))) (unless (eq? (.ref result 'finished) #t) (error "Session derivation incomplete")) - (map (lambda (row) (list-ref nodes (car row))) ((.ref result 'rows-of) 'ready))) + (let (ready ((.ref result 'rows-of) 'ready)) + (if (.slot? cut 'indexed_result) + (let (binding (and retained (.slot? cut 'topology_binding) (.get cut topology_binding))) + (unless binding (error "Indexed Governor result requires a binding")) + (cons binding (map car ready))) + (map (lambda (row) (list-ref (governor-topology-nodes topology) (car row))) ready)))) (def (compile-gateway-source governance policy governor profile context states task-values plan-values publication-value) (unless (= (length task-values) 1) diff --git a/t/gateway-governor-retained-test.ss b/t/gateway-governor-retained-test.ss index 35525070..fd6d2d52 100644 --- a/t/gateway-governor-retained-test.ss +++ b/t/gateway-governor-retained-test.ss @@ -3,7 +3,11 @@ ;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 (import :std/test + (only-in :std/error Error? Error-message) (only-in :clan/poo/object .o) + (prefix-in :clan/poo/testing/property/generator generator.) + (prefix-in :clan/poo/testing/property property.) + (only-in :clan/poo/testing/property/test check-property) (only-in "../scheme/gateway/func.ss" governor-ready-steps make-retained-governor)) (export gateway-governor-retained-test) @@ -22,8 +26,54 @@ (def gateway-governor-retained-test (test-suite "Retained Governor cut equivalence" + (test-case "prepared nested rules agree with full fresh snapshots under replacement" + (def snapshots + (list + (cut '("infer") '("gate" "outer-skip") '(("infer" "left")) '()) + (cut '("infer") '("gate" "outer-skip") '(("infer" "right")) '()) + (cut '("infer" "gate") '("side" "next") left-right '(("infer" "left"))) + (cut '("infer" "gate" "side") '("fork-a" "fork-b" "inner-finish") left-right left-right) + (cut '("infer" "gate" "side" "fork-a") '("fork-b" "inner-finish") left-right left-right) + (cut '("infer" "gate" "side" "fork-a" "fork-b") '("inner-finish" "finish") left-right left-right) + (cut '("infer" "gate" "side" "fork-a" "fork-b" "inner-finish") '("finish") left-right left-right) + (cut '("infer" "gate" "side" "fork-a" "fork-b") '("inner-finish" "finish") left-right left-right + (filter (lambda (node) (not (equal? node "fork-b"))) graph-nodes)))) + ;; Open the unchanged full fresh program once per snapshot. Generated + ;; sequences exercise deletion, restoration and replacement in one owner. + (def expected (map (lambda (value) (list-sort string Date: Tue, 10 Nov 2026 16:47:07 +0800 Subject: [PATCH 101/105] Establish Scheme source composition and direct Rust ingress --- crates/broker/src/provider/runtime.rs | 2 +- crates/broker/src/transport/https.rs | 15 + crates/broker/tests/unit/https_transport.rs | 30 + crates/contracts/src/lib.rs | 5 + crates/contracts/src/provider_routing.rs | 172 ++++ .../benches/support/governor_owner.rs | 1 + .../governance/src/catalog/configuration.rs | 29 +- crates/governance/src/composition.rs | 114 +++ crates/governance/src/host/client.rs | 18 +- crates/governance/src/host/owner.rs | 8 +- crates/governance/src/host/state.rs | 2 + crates/governance/src/lib.rs | 2 + crates/governance/src/program/compiler.rs | 65 +- crates/governance/src/program/linked.rs | 10 + crates/governance/src/scheme_input/mod.rs | 2 +- crates/governance/src/scheme_input/records.rs | 109 +- crates/governance/src/source.rs | 6 +- crates/governance/tests/unit/configuration.rs | 95 ++ crates/governance/tests/unit/source.rs | 30 + crates/ledger/src/lib.rs | 2 + crates/ledger/src/provider_routing.rs | 226 +++++ crates/ledger/src/schema.rs | 2 + crates/ledger/tests/unit/provider_routing.rs | 234 +++++ crates/server/src/governance_deployment.rs | 95 +- crates/server/src/grpc.rs | 140 ++- crates/server/src/grpc_contracts.rs | 7 +- crates/server/src/grpc_provider.rs | 71 +- crates/server/src/lib.rs | 1 + crates/server/src/provider_oauth.rs | 35 + crates/server/src/session_workflow.rs | 3 + crates/server/src/single_provider.rs | 28 + crates/server/src/source_artifact.rs | 6 +- crates/server/src/source_composition.rs | 223 +++++ crates/server/src/source_owner.rs | 244 ++++- crates/server/tests/unit/source_owner.rs | 2 + dev/sysml/ArchitectureEvolution.sysml | 153 +++ dev/sysml/ProviderRpc.sysml | 127 ++- dev/sysml/WeaverExecution.sysml | 58 +- dev/sysml/runtime-trace.json | 2 +- .../59.87-spec-upgrade-and-delivery-plan.org | 365 +++++++ docs/architecture/00-system-design.org | 172 ++-- .../architecture/06-go-control-plane-role.org | 369 +++---- go/api/gateway/v1/gateway.pb.go | 937 ++++++++++++------ go/api/gateway/v1/gateway_grpc.pb.go | 40 + go/cmd/weaver-control/main.go | 12 +- go/dev/provider_control_test.go | 26 +- go/dev/provider_grpc_test.go | 8 +- go/dev/provider_module_routing_test.go | 93 +- go/dev/provider_program_deployment_test.go | 189 ++++ go/internal/config/bundle.go | 16 + go/internal/config/freeze.go | 84 +- go/internal/controlplane/deployment.go | 57 +- go/internal/controlplane/deployment_source.go | 18 + go/internal/controlplane/gateway.go | 27 +- go/internal/controlplane/provider_catalog.go | 79 +- .../controlplane/provider_catalog_test.go | 134 ++- go/internal/controlplane/source_compile.go | 7 +- .../controlplane/source_compile_test.go | 19 +- .../controlplane/source_composition.go | 60 ++ go/internal/devrunner/plan.go | 2 +- proto/gateway/v1/gateway.proto | 21 +- scheme/gateway/compiled.ss | 8 + scheme/gateway/contracts.ss | 19 +- scheme/gateway/func.ss | 34 +- scheme/gateway/provider-program.ss | 15 +- scheme/gateway/provider-source.ss | 112 ++- scheme/gateway/types.ss | 2 +- t/gateway-source-test.ss | 26 +- 68 files changed, 4376 insertions(+), 949 deletions(-) create mode 100644 crates/contracts/src/provider_routing.rs create mode 100644 crates/governance/src/composition.rs create mode 100644 crates/ledger/src/provider_routing.rs create mode 100644 crates/ledger/tests/unit/provider_routing.rs create mode 100644 crates/server/src/source_composition.rs create mode 100644 go/internal/controlplane/source_composition.go diff --git a/crates/broker/src/provider/runtime.rs b/crates/broker/src/provider/runtime.rs index c44f162e..ddcaa421 100644 --- a/crates/broker/src/provider/runtime.rs +++ b/crates/broker/src/provider/runtime.rs @@ -177,7 +177,7 @@ impl ProviderTransport { route: &ProviderRoute, protocol: ProviderProtocol, ) -> Result { - crate::HttpsTransport::validate_endpoint(&route.endpoint)?; + crate::HttpsTransport::validate_provider_endpoint(&route.endpoint, protocol)?; let runtime = self.inner.runtime.clone(); let token = if let Some(federation) = self.inner.federation.get(&route.target) { if !matches!(protocol, ProviderProtocol::Anthropic) || route.endpoint != wif::MESSAGES { diff --git a/crates/broker/src/transport/https.rs b/crates/broker/src/transport/https.rs index 30149495..39fe795f 100644 --- a/crates/broker/src/transport/https.rs +++ b/crates/broker/src/transport/https.rs @@ -53,6 +53,21 @@ impl HttpsTransport { } Ok(()) } + /// Validate the destination against the selected provider protocol before + /// preparation or effect consumption; source adapters reuse this same guard. + pub fn validate_provider_endpoint( + endpoint: &str, + protocol: weaver_contracts::ProviderProtocol, + ) -> Result<()> { + Self::validate_endpoint(endpoint)?; + if matches!(protocol, weaver_contracts::ProviderProtocol::Anthropic) { + let url = Url::parse(endpoint).map_err(|_| Error::Invalid("provider endpoint"))?; + if url.path() != "/v1/messages" || url.query().is_some() { + return Err(Error::Invalid("Anthropic Messages endpoint required")); + } + } + Ok(()) + } // Deliberately crate-private: callers must pass through durable consumption. pub(crate) fn send(&self, p: &Proposal) -> SendObservation { if Self::validate_endpoint(&p.endpoint).is_err() { diff --git a/crates/broker/tests/unit/https_transport.rs b/crates/broker/tests/unit/https_transport.rs index c74ce668..9fbc4471 100644 --- a/crates/broker/tests/unit/https_transport.rs +++ b/crates/broker/tests/unit/https_transport.rs @@ -153,3 +153,33 @@ fn destination_aliases_credentials_and_http_are_rejected() { assert!(HttpsTransport::validate_endpoint(endpoint).is_err()); } } + +#[test] +fn provider_endpoint_guard_preserves_anthropic_source_path_constraints() { + use weaver_contracts::ProviderProtocol; + assert!( + HttpsTransport::validate_provider_endpoint( + "https://provider.invalid/v1/messages", + ProviderProtocol::Anthropic + ) + .is_ok() + ); + for endpoint in [ + "http://provider.invalid/v1/messages", + "https://provider.invalid/other", + "https://provider.invalid/v1/messages?", + "https://provider.invalid/v1/messages#fragment", + ] { + assert!( + HttpsTransport::validate_provider_endpoint(endpoint, ProviderProtocol::Anthropic) + .is_err() + ); + } + assert!( + HttpsTransport::validate_provider_endpoint( + "https://provider.invalid/v1/chat/completions", + ProviderProtocol::OpenAi + ) + .is_ok() + ); +} diff --git a/crates/contracts/src/lib.rs b/crates/contracts/src/lib.rs index cc1ae8b5..2cdab829 100644 --- a/crates/contracts/src/lib.rs +++ b/crates/contracts/src/lib.rs @@ -25,6 +25,11 @@ pub use metering::{ }; mod provider; mod provider_catalog; +mod provider_routing; +pub use provider_routing::{ + ProviderOperationBinding, ProviderOperationScope, ProviderRoutingScope, RoutingCandidate, + RoutingSelection, +}; mod provider_oauth; pub use provider_catalog::{CatalogEntry, ProviderCatalog}; pub use provider_oauth::{ diff --git a/crates/contracts/src/provider_routing.rs b/crates/contracts/src/provider_routing.rs new file mode 100644 index 00000000..0030072f --- /dev/null +++ b/crates/contracts/src/provider_routing.rs @@ -0,0 +1,172 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Bounded declarative provider selection; no rule evaluator or execution permit. +use crate::{Error, ProviderPlan, Publication, Result, Task, identifier}; +use serde::Deserialize; + +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +/// Source selection policy for one original operation; conveys no send authority. +pub struct RoutingSelection { + /// Original operation node to select. + pub node: String, + /// Tenant-admitted module identifiers. + pub allowed_modules: Vec, + /// Capabilities required by this source profile. + pub required: Vec, + /// Maximum admitted latency observation in milliseconds. + pub max_latency_ms: u64, + /// Maximum rounded procurement charge. + pub max_procurement_cost: u64, + /// Four integer token prices per million tokens. + pub user_token_rates: [u64; 4], + /// Bounded source offers; invalid request bindings are ineligible. + pub candidates: Vec, +} +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +/// Concrete offer and conservative token facts; Rust validates its plan binding. +pub struct RoutingCandidate { + /// Module identity supplied by the trusted source. + pub module: String, + /// Capabilities advertised by this admitted module. + pub capabilities: Vec, + /// Positive observed latency in milliseconds. + pub latency_ms: u64, + /// Four integer procurement prices per million tokens. + pub procurement_rates: [u64; 4], + /// Conservative token bounds in the existing four metering categories. + pub token_bounds: [u64; 4], + /// Concrete immutable plan, independently checked by Rust. + pub plan: ProviderPlan, +} + +/// A source-owned one-operation selection declared before its first use. +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct ProviderRoutingScope { + pub task: Task, + pub selection_schema: String, + pub selection: RoutingSelection, + pub publication: Publication, +} +impl ProviderRoutingScope { + pub fn validate(&self) -> Result<()> { + self.publication.validate()?; + identifier(&self.selection_schema)?; + identifier(&self.task.family)?; + identifier(&self.selection.node)?; + if self.task.nodes != [self.selection.node.clone()] + || !self.task.body_digests.is_empty() + || !self.task.stream_contracts.is_empty() + || self.selection.candidates.is_empty() + || self.selection.candidates.len() > 8 + || self.selection.allowed_modules.len() > 64 + || self.selection.required.len() > 64 + || serde_json::to_vec(self)?.len() > 8 * 1024 * 1024 + { + return Err(Error::Invalid("provider routing scope bounds")); + } + Ok(()) + } + /// Registration may fill only the selected original's commitment maps. + pub fn admits(&self, task: &Task, plan: &ProviderPlan) -> Result<()> { + self.validate()?; + task.validate()?; + plan.validate()?; + let mut expected = self.task.clone(); + expected.body_digests.clone_from(&task.body_digests); + expected.stream_contracts.clone_from(&task.stream_contracts); + if *task != expected + || plan.node != self.selection.node + || !plan.matches(task)? + || !self + .selection + .candidates + .iter() + .any(|candidate| candidate.plan == *plan) + { + return Err(Error::Denied); + } + Ok(()) + } +} + +/// Published immutable original data or a source-declared deferred selection. +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, Deserialize)] +#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)] +pub enum ProviderOperationScope { + Fixed { + task: Task, + plan: ProviderPlan, + publication: Publication, + }, + Catalog { + routing: ProviderRoutingScope, + }, +} +impl ProviderOperationScope { + pub fn task(&self) -> &Task { + match self { + Self::Fixed { task, .. } => task, + Self::Catalog { routing } => &routing.task, + } + } + pub fn node(&self) -> &str { + match self { + Self::Fixed { plan, .. } => &plan.node, + Self::Catalog { routing } => &routing.selection.node, + } + } + pub fn publication(&self) -> &Publication { + match self { + Self::Fixed { publication, .. } => publication, + Self::Catalog { routing } => &routing.publication, + } + } + pub fn validate(&self) -> Result<()> { + match self { + Self::Catalog { routing } => routing.validate(), + Self::Fixed { + task, + plan, + publication, + } => { + publication.validate()?; + task.validate()?; + plan.validate()?; + if !plan.matches(task)? { + return Err(Error::Denied); + } + Ok(()) + } + } + } + pub fn admits(&self, task: &Task, plan: &ProviderPlan) -> Result<()> { + self.validate()?; + match self { + Self::Catalog { routing } => routing.admits(task, plan), + Self::Fixed { + task: original, + plan: chosen, + .. + } => { + if task == original && plan == chosen { + Ok(()) + } else { + Err(Error::Denied) + } + } + } + } +} + +/// Durable source provenance, not an operation caller's delegated source credential. +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct ProviderOperationBinding { + pub authority: crate::SourceAuthority, + pub scope: ProviderOperationScope, +} diff --git a/crates/governance/benches/support/governor_owner.rs b/crates/governance/benches/support/governor_owner.rs index 776f4581..b611707d 100644 --- a/crates/governance/benches/support/governor_owner.rs +++ b/crates/governance/benches/support/governor_owner.rs @@ -117,6 +117,7 @@ fn phase(input: &Derivation) -> usize { fn verify(output: DerivationOutput, topology: &GovernorTopology, phase: usize) { let mut nodes = match output { DerivationOutput::Nodes(nodes) => nodes, + DerivationOutput::Source(_) => panic!("source reply cannot advance a Governor"), DerivationOutput::Indices(indices) => indices .into_iter() .map(|i| topology.nodes.get(i).expect("bound index").clone()) diff --git a/crates/governance/src/catalog/configuration.rs b/crates/governance/src/catalog/configuration.rs index 06d12a9a..d8f975ed 100644 --- a/crates/governance/src/catalog/configuration.rs +++ b/crates/governance/src/catalog/configuration.rs @@ -4,7 +4,7 @@ //! External data configuration, not the Scheme/Rust interop representation. use super::{ApprovedProducer, CatalogError, ProducerCatalog}; -use crate::{OwnedSource, SourceData}; +use crate::{MAX_SOURCE_BYTES, OwnedSource, SourceComposition, SourceData, SourceError}; use serde::Deserialize; use weaver_contracts::SourceAuthority; #[derive(Deserialize)] @@ -17,13 +17,27 @@ struct Configuration { struct Binding { name: String, authority: SourceAuthority, - original: SourceData, + #[serde(default)] + original: Option, + #[serde(default)] + composition: Option, } impl ProducerCatalog { /// Decode duplicate-free bounded startup data and reuse sealed catalog /// admission. Authority values are eligibility bindings, not authenticated /// observations, enrollment commands or permission to publish/send. pub fn from_configuration(bytes: &[u8]) -> Result { + Self::from_configuration_with(bytes, |_| Err(SourceError::Contract)) + } + /// Compose trusted startup configuration on the already tracked Scheme owner, + /// then reuse the unchanged exact-original catalog and source lane. + pub fn from_configuration_with( + bytes: &[u8], + mut compose: impl FnMut(&SourceComposition) -> Result, + ) -> Result { + if bytes.len() > MAX_SOURCE_BYTES { + return Err(CatalogError::Invalid); + } let input: Configuration = weaver_contracts::decode(bytes).map_err(|_| CatalogError::Invalid)?; if input.producers.is_empty() || input.producers.len() > 64 { @@ -33,8 +47,15 @@ impl ProducerCatalog { .producers .into_iter() .map(|entry| { - let original = - OwnedSource::from_source(entry.original).map_err(|_| CatalogError::Invalid)?; + let original = match (entry.original, entry.composition) { + (Some(data), None) => OwnedSource::from_source(data), + (None, Some(configuration)) => compose(&configuration).and_then(|selected| { + configuration.validate_selected(&selected)?; + Ok(selected) + }), + _ => return Err(CatalogError::Invalid), + } + .map_err(|_| CatalogError::Invalid)?; ApprovedProducer::new(entry.name, entry.authority, original) }) .collect::, CatalogError>>()?; diff --git a/crates/governance/src/composition.rs b/crates/governance/src/composition.rs new file mode 100644 index 00000000..16e8c36e --- /dev/null +++ b/crates/governance/src/composition.rs @@ -0,0 +1,114 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Trusted startup configuration; Scheme selects, Rust seals the resulting original. +use crate::SourceData; +use serde::Deserialize; + +#[derive(Clone, serde::Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +/// Deployment-owned source and bounded selections, composed before original sealing. +pub struct SourceComposition { + /// Unmaterialized source with no preexisting body or stream commitments. + pub source: SourceData, + /// At most 64 selections, each with at most eight candidates. + pub routing: Vec, +} +pub use weaver_contracts::{RoutingCandidate, RoutingSelection}; + +impl SourceComposition { + /// Independently preserve the supplied original scope before sealing a result. + /// Scheme chooses listed plans and fills commitments; it cannot rewrite the + /// principal, profile, budget, endpoints, publication or declared topology. + /// This checks scope preservation, not a second ranking implementation. + pub fn validate_selected( + &self, + selected: &crate::OwnedSource, + ) -> Result<(), crate::SourceError> { + self.validate_inventory(selected)?; + self.validate_scope(selected)?; + self.validate_plan_membership(selected) + } + fn validate_inventory(&self, selected: &crate::OwnedSource) -> Result<(), crate::SourceError> { + use crate::SourceError; + if self.source.tasks.len() != 1 + || !self.source.plans.is_empty() + || !self.source.tasks[0].body_digests.is_empty() + || !self.source.tasks[0].stream_contracts.is_empty() + || self.routing.len() != selected.plans().len() + { + return Err(SourceError::Binding); + } + Ok(()) + } + fn validate_scope(&self, selected: &crate::OwnedSource) -> Result<(), crate::SourceError> { + use crate::SourceError; + let actual = selected.data(); + let original = &self.source; + let mut expected_task = original.tasks[0].clone(); + expected_task + .body_digests + .clone_from(&selected.task().body_digests); + expected_task + .stream_contracts + .clone_from(&selected.task().stream_contracts); + if selected.task() != &expected_task + || actual.publication != original.publication + || actual.governance.schema != original.governance.schema + || actual.governance.family != original.governance.family + || actual.governance.open_nodes != original.governance.open_nodes + || (!original.governance.workflow_edges.is_empty() + && actual.governance.workflow_edges != original.governance.workflow_edges) + || (!original.governance.workflow_selectors.is_empty() + && actual.governance.workflow_selectors != original.governance.workflow_selectors) + { + return Err(SourceError::Binding); + } + Ok(()) + } + fn validate_plan_membership( + &self, + selected: &crate::OwnedSource, + ) -> Result<(), crate::SourceError> { + use crate::SourceError; + let mut nodes = std::collections::BTreeSet::new(); + let mut admitted = std::collections::BTreeMap::new(); + for row in &self.routing { + if !nodes.insert(&row.node) || row.candidates.is_empty() || row.candidates.len() > 8 { + return Err(SourceError::Binding); + } + for candidate in &row.candidates { + if let Ok(digest) = candidate.plan.digest() { + admitted.insert( + ( + row.node.as_str(), + digest, + candidate.plan.revision, + candidate.plan.fence, + ), + &candidate.plan, + ); + } + } + } + for plan in selected.plans() { + let digest = selected + .task() + .stream_contracts + .get(&plan.node) + .ok_or(SourceError::Binding)?; + if admitted + .get(&( + plan.node.as_str(), + digest.clone(), + plan.revision, + plan.fence, + )) + .is_none_or(|original| *original != plan) + { + return Err(SourceError::Binding); + } + } + Ok(()) + } +} diff --git a/crates/governance/src/host/client.rs b/crates/governance/src/host/client.rs index 7f6e5d5a..e628b738 100644 --- a/crates/governance/src/host/client.rs +++ b/crates/governance/src/host/client.rs @@ -95,7 +95,21 @@ impl SourceClient { .await? { crate::DerivationOutput::Nodes(nodes) => Ok(nodes), - crate::DerivationOutput::Indices(_) => Err(crate::SourceError::Contract.into()), + _ => Err(crate::SourceError::Contract.into()), + } + } + /// Compose detached source data on the existing bounded owner. No publication, + /// catalog installation or permission is obtained from this advisory result. + pub async fn compose( + &self, + input: crate::SourceComposition, + ) -> Result { + match self + .evaluate(crate::Derivation::Composition(Box::new(input))) + .await? + { + crate::DerivationOutput::Source(source) => Ok(source), + _ => Err(crate::SourceError::Contract.into()), } } async fn evaluate( @@ -111,7 +125,7 @@ impl SourceClient { _ = self.shared.shutdown.cancelled() => return Err(SourceJobError::Closed), slot = capacity.acquire_owned() => slot.map_err(|_| SourceJobError::Closed)?, }, - crate::Derivation::FactImpact { .. } => capacity + crate::Derivation::FactImpact { .. } | crate::Derivation::Composition(_) => capacity .try_acquire_owned() .map_err(|_| SourceJobError::Busy)?, }; diff --git a/crates/governance/src/host/owner.rs b/crates/governance/src/host/owner.rs index 9e48831a..fbb46000 100644 --- a/crates/governance/src/host/owner.rs +++ b/crates/governance/src/host/owner.rs @@ -39,7 +39,9 @@ impl SourceInbox { crate::Derivation::Governor(cut) => { derive(owner, cut).map(crate::DerivationOutput::Nodes) } - crate::Derivation::FactImpact { .. } => Err(SourceError::Contract), + crate::Derivation::FactImpact { .. } | crate::Derivation::Composition(_) => { + Err(SourceError::Contract) + } }, ); } @@ -115,7 +117,9 @@ impl SourceInbox { let derive_ns = finished.duration_since(started).as_nanos(); let cut_sha256 = match input { crate::Derivation::Governor(cut) => trace_digest(cut), - crate::Derivation::FactImpact { .. } => trace_digest(input), + crate::Derivation::FactImpact { .. } | crate::Derivation::Composition(_) => { + trace_digest(input) + } }; let ready_sha256 = match (input, result.as_ref().ok()) { (_, Some(crate::DerivationOutput::Nodes(nodes))) => Some(trace_digest(nodes)), diff --git a/crates/governance/src/host/state.rs b/crates/governance/src/host/state.rs index 72def5e6..54821ce5 100644 --- a/crates/governance/src/host/state.rs +++ b/crates/governance/src/host/state.rs @@ -107,6 +107,7 @@ impl serde::Serialize for GovernorCut { /// Inert observations evaluated by the existing linked Scheme owner. #[derive(serde::Serialize)] pub enum Derivation { + Composition(Box), Governor(Box), FactImpact { root: String, @@ -116,6 +117,7 @@ pub enum Derivation { /// Detached node identities. Indices belong to the topology of this Governor request. #[derive(Debug, PartialEq, Eq)] pub enum DerivationOutput { + Source(crate::OwnedSource), Nodes(Vec), Indices(Vec), } diff --git a/crates/governance/src/lib.rs b/crates/governance/src/lib.rs index 41e9619d..9f4390aa 100644 --- a/crates/governance/src/lib.rs +++ b/crates/governance/src/lib.rs @@ -6,6 +6,8 @@ #![deny(unsafe_code)] extern crate self as weaver_governance; mod binding; +mod composition; +pub use composition::{RoutingCandidate, RoutingSelection, SourceComposition}; mod catalog; mod host; mod source; diff --git a/crates/governance/src/program/compiler.rs b/crates/governance/src/program/compiler.rs index 6ea7d22f..57d9b085 100644 --- a/crates/governance/src/program/compiler.rs +++ b/crates/governance/src/program/compiler.rs @@ -48,8 +48,23 @@ impl SchemeCompiler { governor_topology: Weak::new(), }) } + /// Compose trusted startup data before sealing its exact original binding. + /// This does not authenticate source authority or publish any object. + pub fn compose( + &mut self, + configuration: &crate::SourceComposition, + ) -> Result { + let input = crate::scheme_input::records::root_composition(&self.runtime, configuration)?; + let output = linked::compose(&self.runtime, &input).map_err(|_| SourceError::Scheme)?; + let selected = materialize_source(output)?; + configuration.validate_selected(&selected)?; + Ok(selected) + } pub fn evaluate(&mut self, input: &crate::Derivation) -> Result { match input { + crate::Derivation::Composition(configuration) => { + self.compose(configuration).map(DerivationOutput::Source) + } crate::Derivation::Governor(cut) => self.derive(cut), crate::Derivation::FactImpact { root, dependencies } => { let input = crate::scheme_input::values::Input::new(&self.runtime); @@ -440,7 +455,8 @@ fn governor_indices_reject_stale_binding_and_foreign_node() { #[cfg(test)] #[test] fn rooted_governor_indices_preserve_full_width_binding_and_all_64_candidates() { - let compiler = SchemeCompiler::initialize().expect("approved linked application"); + let mut compiler = SchemeCompiler::initialize().expect("approved linked application"); + composition_uses_scheme_then_rust_seals_the_exact_original(&mut compiler); let vm = &compiler.runtime; let input = crate::scheme_input::values::Input::new(vm); let vector = |values: Vec>| { @@ -521,3 +537,50 @@ fn rooted_governor_indices_preserve_full_width_binding_and_all_64_candidates() { [0] ); } + +#[cfg(test)] +fn composition_uses_scheme_then_rust_seals_the_exact_original(compiler: &mut SchemeCompiler) { + use crate::{RoutingCandidate, RoutingSelection, SourceComposition}; + let original = crate::source_fixture::source(); + let mut raw = original.clone(); + raw.tasks[0].body_digests.clear(); + raw.tasks[0].stream_contracts.clear(); + raw.plans.clear(); + let routing = original + .plans + .iter() + .map(|plan| RoutingSelection { + node: plan.node.clone(), + allowed_modules: vec!["approved".into()], + required: vec!["text".into()], + max_latency_ms: 100, + max_procurement_cost: 4, + user_token_rates: [0; 4], + candidates: vec![RoutingCandidate { + module: "approved".into(), + capabilities: vec!["text".into()], + latency_ms: 10, + procurement_rates: [0; 4], + token_bounds: [0, 0, 0, 32], + plan: plan.clone(), + }], + }) + .collect(); + let mut configuration = SourceComposition { + source: raw, + routing, + }; + let selected = compiler + .compose(&configuration) + .expect("Scheme composition"); + assert!(selected.data() == &original); + let expected = crate::SourceExpectation::capture(&selected); + assert!(expected.bind(selected.clone()).is_ok()); + configuration.routing[0].allowed_modules.clear(); + assert!(compiler.compose(&configuration).is_err()); + configuration.routing[0] + .allowed_modules + .push("approved".into()); + configuration.routing[0].candidates[0].plan.body = "{}".into(); + assert!(compiler.compose(&configuration).is_err()); +} diff --git a/crates/governance/src/program/linked.rs b/crates/governance/src/program/linked.rs index a81bc150..c3e45e1f 100644 --- a/crates/governance/src/program/linked.rs +++ b/crates/governance/src/program/linked.rs @@ -37,6 +37,7 @@ unsafe extern "C" { fn weaver_governor_ready_steps_v1(root: i64) -> i64; fn weaver_hard_fact_impact_v1(root: i64) -> i64; fn weaver_capture_source_v1(root: i64) -> i64; + fn weaver_compose_source_v1(root: i64) -> i64; fn weaver_governance_ready_v1(root: i64) -> i64; fn weaver_install_source_cancel_v1(callback: *const std::ffi::c_void); } @@ -93,3 +94,12 @@ pub(super) fn fact_impact<'r>( let export = unsafe { runtime.bind_object_export(weaver_hard_fact_impact_v1) }?; export.call(input).into_result() } + +pub(super) fn compose<'r>( + runtime: &'r GerbilRuntime, + input: &RootedSchemeObject<'_>, +) -> Result, GerbilError> { + // SAFETY: fixed same-graph rooted export; input and result stay on this owner. + let export = unsafe { runtime.bind_object_export(weaver_compose_source_v1) }?; + export.call(input).into_result() +} diff --git a/crates/governance/src/scheme_input/mod.rs b/crates/governance/src/scheme_input/mod.rs index 3a7f9c58..06a215a5 100644 --- a/crates/governance/src/scheme_input/mod.rs +++ b/crates/governance/src/scheme_input/mod.rs @@ -3,6 +3,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 //! Typed, fallible Rust-to-Scheme construction on the VM owner thread. -mod records; +pub(crate) mod records; pub(crate) mod values; pub use records::root_source; diff --git a/crates/governance/src/scheme_input/records.rs b/crates/governance/src/scheme_input/records.rs index 89d678a9..e6d73c77 100644 --- a/crates/governance/src/scheme_input/records.rs +++ b/crates/governance/src/scheme_input/records.rs @@ -12,27 +12,30 @@ use weaver_contracts::{ProviderPlan, ProviderProfile, ProviderRoute, Publication /// raw object word, retained callback or authority is created. Partial construction /// failure drops owned roots naturally; bounds cover traversal, not hostile VM code. pub fn root_source<'r>(vm: &'r GerbilRuntime, source: &OwnedSource) -> Result> { - let input = Input::new(vm); + root_source_data(&Input::new(vm), source.data()) +} + +fn root_source_data<'r>(input: &Input<'r>, source: &SourceData) -> Result> { let SourceData { governance, tasks, plans, publication, - } = source.data(); - let selection = root_selection(&input, governance)?; + } = source; + let selection = root_selection(input, governance)?; let tasks = input.vector( tasks .iter() - .map(|task| root_task(&input, task)) + .map(|task| root_task(input, task)) .collect::>>()?, )?; let plans = input.vector( plans .iter() - .map(|plan| root_plan(&input, plan)) + .map(|plan| root_plan(input, plan)) .collect::>>()?, )?; - let publication = root_publication(&input, publication)?; + let publication = root_publication(input, publication)?; input.record(vec![ ("governance", selection), ("tasks", tasks), @@ -175,3 +178,97 @@ fn root_plan<'r>(input: &Input<'r>, plan: &ProviderPlan) -> Result> { ("routes", input.vector(routes)?), ]) } + +/// Prepare bounded facts and canonical commitments without choosing a candidate. +pub(crate) fn root_composition<'r>( + vm: &'r GerbilRuntime, + value: &crate::SourceComposition, +) -> Result> { + use crate::SourceError; + let source = &value.source; + if source.tasks.len() != 1 + || !source.plans.is_empty() + || value.routing.is_empty() + || value.routing.len() > 64 + || !source.tasks[0].body_digests.is_empty() + || !source.tasks[0].stream_contracts.is_empty() + { + return Err(SourceError::Binding); + } + let input = Input::new(vm); + let task = &source.tasks[0]; + let mut selections = Vec::new(); + for selection in &value.routing { + if selection.candidates.is_empty() || selection.candidates.len() > 8 { + return Err(SourceError::Bound); + } + let mut candidates = Vec::new(); + for candidate in &selection.candidates { + let plan = &candidate.plan; + if candidate + .procurement_rates + .iter() + .chain(&candidate.token_bounds) + .any(|value| *value > weaver_contracts::MAX_CREDITS) + { + continue; + } + let Ok(digest) = plan.digest() else { continue }; + let body = weaver_contracts::body_digest(&plan.body); + let mut bound = task.clone(); + bound.body_digests.insert(plan.node.clone(), body.clone()); + bound + .stream_contracts + .insert(plan.node.clone(), digest.clone()); + let Ok(Some(facts)) = plan.binding(&bound) else { + continue; + }; + if facts.model != plan.model || candidate.token_bounds[3] < facts.output_token_limit { + continue; + } + candidates.push(input.record(vec![ + ("module", input.text(&candidate.module)?), + ("capabilities", input.strings(&candidate.capabilities)?), + ("latency_ms", input.number(candidate.latency_ms)?), + ( + "procurement_rates", + numbers(&input, &candidate.procurement_rates)?, + ), + ("token_bounds", numbers(&input, &candidate.token_bounds)?), + ("plan", root_plan(&input, plan)?), + ("digest", input.text(&digest)?), + ("body_digest", input.text(&body)?), + ])?); + } + selections.push(input.record(vec![ + ("node", input.text(&selection.node)?), + ( + "allowed_modules", + input.strings(&selection.allowed_modules)?, + ), + ("required", input.strings(&selection.required)?), + ("max_latency_ms", input.number(selection.max_latency_ms)?), + ( + "max_procurement_cost", + input.number(selection.max_procurement_cost)?, + ), + ( + "user_token_rates", + numbers(&input, &selection.user_token_rates)?, + ), + ("candidates", input.vector(candidates)?), + ])?); + } + input.record(vec![ + ("source", root_source_data(&input, source)?), + ("routing", input.vector(selections)?), + ]) +} +fn numbers<'r>(input: &Input<'r>, values: &[u64]) -> Result> { + input.vector( + values + .iter() + .map(|value| input.number(*value)) + .collect::>>()?, + ) +} diff --git a/crates/governance/src/source.rs b/crates/governance/src/source.rs index 75d459dd..433632c0 100644 --- a/crates/governance/src/source.rs +++ b/crates/governance/src/source.rs @@ -23,7 +23,7 @@ pub enum SourceError { Scheme, } -#[derive(Clone, PartialEq, Eq, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, Deserialize)] #[serde(deny_unknown_fields)] /// Original governor family and selected node identities. pub struct SourceSelection { @@ -35,7 +35,7 @@ pub struct SourceSelection { #[serde(default)] pub workflow_selectors: Vec<[String; 3]>, } -#[derive(Clone, PartialEq, Eq, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, Deserialize)] #[serde(deny_unknown_fields)] /// Concrete source records; data ownership grants no execution authority. pub struct SourceData { @@ -47,7 +47,7 @@ pub struct SourceData { /// Rust-owned typed source data, not an encoded transport blob or publisher permit. /// No VM, callback, raw pointer or borrowed source survives in this type. -#[derive(Clone)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct OwnedSource { data: Arc, } diff --git a/crates/governance/tests/unit/configuration.rs b/crates/governance/tests/unit/configuration.rs index 440d5c42..a2091c82 100644 --- a/crates/governance/tests/unit/configuration.rs +++ b/crates/governance/tests/unit/configuration.rs @@ -39,3 +39,98 @@ fn configuration_rejects_duplicate_keys_code_and_source_substitution_fields() { } assert!(ProducerCatalog::from_configuration(br#"{"producers":[]}"#).is_err()); } + +#[test] +fn composition_requires_one_source_form_and_the_trusted_startup_owner() { + let mut data = configuration("approved", 0); + let original = data["producers"][0] + .as_object_mut() + .expect("binding") + .remove("original") + .expect("original"); + let mut raw = original.clone(); + raw["tasks"][0]["body_digests"] = json!({}); + raw["tasks"][0]["stream_contracts"] = json!({}); + raw["plans"] = json!([]); + let routing: Vec<_> = original["plans"].as_array().expect("plans").iter().map(|plan| + json!({"node":plan["node"],"allowed_modules":["approved"],"required":[],"max_latency_ms":100,"max_procurement_cost":4,"user_token_rates":[0,0,0,0], + "candidates":[{"module":"approved","capabilities":[],"latency_ms":10,"procurement_rates":[0,0,0,0],"token_bounds":[0,0,0,32],"plan":plan}]})).collect(); + data["producers"][0]["composition"] = json!({"source": raw, "routing": routing}); + let bytes = serde_json::to_vec(&data).expect("configuration"); + assert!(ProducerCatalog::from_configuration(&bytes).is_err()); + let mut calls = 0; + assert!( + ProducerCatalog::from_configuration_with(&bytes, |_| { + calls += 1; + crate::OwnedSource::from_source(source_fixture::source()) + }) + .is_ok() + ); + assert_eq!(calls, 1); + data["producers"][0]["original"] = data["producers"][0]["composition"]["source"].clone(); + assert!( + ProducerCatalog::from_configuration_with( + &serde_json::to_vec(&data).expect("configuration"), + |_| { panic!("ambiguous source entered composition") } + ) + .is_err() + ); +} + +#[test] +fn source_composition_cannot_seal_a_self_consistent_scope_substitution() { + let original = source_fixture::source(); + let mut raw = original.clone(); + raw.plans.clear(); + raw.tasks[0].body_digests.clear(); + raw.tasks[0].stream_contracts.clear(); + let composition = crate::SourceComposition { + source: raw, + routing: original + .plans + .iter() + .map(|plan| crate::RoutingSelection { + node: plan.node.clone(), + allowed_modules: vec!["approved".into()], + required: vec![], + max_latency_ms: 100, + max_procurement_cost: 4, + user_token_rates: [0; 4], + candidates: vec![crate::RoutingCandidate { + module: "approved".into(), + capabilities: vec![], + latency_ms: 10, + procurement_rates: [0; 4], + token_bounds: [0, 0, 0, 32], + plan: plan.clone(), + }], + }) + .collect(), + }; + for field in 0..5 { + let mut candidate = original.clone(); + match field { + 0 => candidate.tasks[0].principal = "other".into(), + 1 => candidate.tasks[0].budget += 1, + 2 => candidate.publication.policy = "permit(principal,action,resource);".into(), + 3 => { + candidate.plans[0].body = candidate.plans[0].body.replace("xxxxxxxx", "zzzzzzzz"); + candidate.tasks[0].body_digests.insert( + candidate.plans[0].node.clone(), + weaver_contracts::body_digest(&candidate.plans[0].body), + ); + candidate.tasks[0].stream_contracts.insert( + candidate.plans[0].node.clone(), + candidate.plans[0].digest().expect("self consistent plan"), + ); + } + _ => candidate.governance.open_nodes.reverse(), + } + let candidate = + crate::OwnedSource::from_source(candidate).expect("self consistent candidate"); + assert!( + composition.validate_selected(&candidate).is_err(), + "field {field}" + ); + } +} diff --git a/crates/governance/tests/unit/source.rs b/crates/governance/tests/unit/source.rs index 5797fe3b..bbe0ff12 100644 --- a/crates/governance/tests/unit/source.rs +++ b/crates/governance/tests/unit/source.rs @@ -33,3 +33,33 @@ proptest! { prop_assert!(OwnedSource::from_source(fixture::source()).is_ok()); } } + +#[test] +fn composed_original_rejects_mutated_wire_semantics_in_rust() { + for field in 0..6 { + let mut source = crate::source_fixture::source(); + match field { + 0 => source.governance.open_nodes[0] = "replacement".into(), + 1 => source.tasks[0].nodes[0] = "replacement".into(), + 2 => { + source.tasks[0].endpoints.insert( + source.plans[0].routes[0].target.clone(), + "https://replacement.invalid".into(), + ); + } + 3 => { + source.tasks[0] + .provider_profile + .as_mut() + .expect("fixture profile") + .max_output_tokens = 1 + } + 4 => source.plans[0].routes[0].endpoint = "https://replacement.invalid".into(), + _ => source.plans[0].body = "{}".into(), + } + assert!( + crate::OwnedSource::from_source(source).is_err(), + "field {field}" + ); + } +} diff --git a/crates/ledger/src/lib.rs b/crates/ledger/src/lib.rs index b328663f..6caa8ae3 100644 --- a/crates/ledger/src/lib.rs +++ b/crates/ledger/src/lib.rs @@ -32,7 +32,9 @@ pub use provider_delivery::{ ProviderDelivery, }; mod provider_catalog; +mod provider_routing; pub use provider_catalog::ProviderCatalogProjection; +pub use provider_routing::ProviderOperationCut; mod provider_oauth; mod provider_oauth_witness; mod provider_profiles; diff --git a/crates/ledger/src/provider_routing.rs b/crates/ledger/src/provider_routing.rs new file mode 100644 index 00000000..a7228e20 --- /dev/null +++ b/crates/ledger/src/provider_routing.rs @@ -0,0 +1,226 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Source-declared candidate custody; registration rejoins the exact deciding cut. +use crate::{ + Ledger, + persistence::{self, driver::Connection}, + store::{db, integer}, +}; +use weaver_contracts::{ + Error, ProviderCatalog, ProviderOperationBinding, ProviderOperationScope, ProviderPlan, + ProviderRoutingScope, PublicationOutcome, Result, Task, +}; + +/// A coherent read for bounded Scheme work, never a later registration permit. +#[derive(Clone)] +pub struct ProviderOperationCut { + pub binding: ProviderOperationBinding, + pub catalog_version: String, + pub catalog: Option, + pub revision: u64, + pub fence: u64, +} + +fn binding( + connection: &Connection, + family: &str, + node: &str, +) -> Result> { + let row: Option<(String, String)> = persistence::maybe( + connection, + "SELECT digest,record FROM provider_operation_scopes WHERE family=?1 AND node=?2", + [family, node], + |r| Ok((r.get(0)?, r.get(1)?)), + ) + .map_err(db)?; + row.map(|(digest, record)| { + if weaver_contracts::body_digest(&record) != digest { + return Err(Error::Conflict("provider routing record mismatch")); + } + let bound: ProviderOperationBinding = weaver_contracts::decode(record.as_bytes())?; + bound.scope.validate()?; + if bound.scope.task().family != family || bound.scope.node() != node { + return Err(Error::Conflict("provider routing identity mismatch")); + } + Ok(bound) + }) + .transpose() +} + +fn cut(connection: &Connection, bound: ProviderOperationBinding) -> Result { + if crate::source_authority::current(connection)?.as_ref() != Some(&bound.authority) { + return Err(Error::Denied); + } + let publication = bound.scope.publication(); + let receipt = crate::publication::lookup( + connection, + &publication.operation_id, + &publication.digest()?, + )? + .filter(|receipt| receipt.outcome == PublicationOutcome::Committed) + .ok_or(Error::Conflict("routing publication not committed"))?; + let (revision, fence): (u64, u64) = persistence::one( + connection, + "SELECT revision,fence FROM authority WHERE singleton=1", + (), + |r| Ok((integer(r, 0)?, integer(r, 1)?)), + ) + .map_err(db)?; + if receipt.revision != Some(revision) || receipt.fence != Some(fence) { + return Err(Error::Conflict("routing publication no longer current")); + } + let (catalog_version, catalog) = + if matches!(&bound.scope, ProviderOperationScope::Catalog { .. }) { + let (version, catalog) = crate::provider_catalog::current(connection)? + .ok_or(Error::Conflict("provider catalog unavailable"))?; + (version, Some(catalog)) + } else { + (String::new(), None) + }; + Ok(ProviderOperationCut { + binding: bound, + catalog_version, + catalog, + revision, + fence, + }) +} + +impl Ledger { + /// Explicit authenticated-source declaration. An operation credential cannot + /// create or replace this scope. Replays preserve its exact source epoch. + pub fn register_provider_routing(&mut self, scope: &ProviderRoutingScope) -> Result<()> { + self.register_provider_source(&ProviderOperationScope::Catalog { + routing: scope.clone(), + }) + } + pub fn register_provider_source(&mut self, scope: &ProviderOperationScope) -> Result<()> { + scope.validate()?; + let publication = scope.publication(); + let digest = publication.digest()?; + let tx = persistence::begin(&mut self.connection).map_err(db)?; + crate::source_authority::require(&tx, self.source.as_ref())?; + // Unlike trusted-host task registration, this durable delegation always + // requires an authenticated source identity, including its exact epoch. + let authority = crate::source_authority::current(&tx)?.ok_or(Error::Denied)?; + if self.source.as_ref() != Some(&authority.identity) { + return Err(Error::Denied); + } + let committed = crate::publication::lookup(&tx, &publication.operation_id, &digest)?; + if committed + .as_ref() + .is_some_and(|r| r.outcome == PublicationOutcome::Rejected) + { + return Err(Error::Denied); + } + if committed.is_none() { + let pending: Option<(String, String)> = persistence::maybe( + &tx, + "SELECT digest,proposal FROM authority_pending WHERE operation_id=?1", + [publication.operation_id.as_str()], + |r| Ok((r.get(0)?, r.get(1)?)), + ) + .map_err(db)?; + let (staged, record) = + pending.ok_or(Error::Conflict("routing publication not staged"))?; + let original: weaver_contracts::Publication = + weaver_contracts::decode(record.as_bytes())?; + if staged != digest || original != *publication { + return Err(Error::Denied); + } + } + let declared = ProviderOperationBinding { + authority, + scope: scope.clone(), + }; + if let Some(previous) = binding(&tx, &scope.task().family, scope.node())? { + if previous != declared { + return Err(Error::Conflict("provider routing scope is immutable")); + } + } else { + persistence::exec( + &tx, + "INSERT INTO provider_operation_scopes VALUES(?1,?2,?3,?4)", + persistence::params![ + scope.task().family.clone(), + scope.node().to_owned(), + weaver_contracts::body_digest(&serde_json::to_string(&declared)?), + serde_json::to_string(&declared)? + ], + ) + .map_err(db)?; + } + if let ProviderOperationScope::Fixed { task, .. } = scope { + let key = weaver_contracts::PublicationKey { + operation_id: publication.operation_id.clone(), + digest, + }; + crate::task_origins::default_binding(&tx, task, None, Some(&key))?; + crate::store::register_task_in(&tx, task, Some(&key), None)?; + } + tx.commit().map_err(db)?; + Ok(()) + } + + /// Trusted operation-owner read of a previously declared scope. It does not + /// enroll a source or derive source privileges from the operation caller. + pub fn provider_operation_cut( + &mut self, + family: &str, + node: &str, + ) -> Result> { + let tx = persistence::begin(&mut self.connection).map_err(db)?; + let observed = binding(&tx, family, node)? + .map(|bound| cut(&tx, bound)) + .transpose()?; + tx.commit().map_err(db)?; + Ok(observed) + } + + /// Finish Scheme derivation only against the same source, publication and + /// catalog. Registration and these checks share the existing write scope. + pub fn register_routed_task( + &mut self, + observed: &ProviderOperationCut, + task: &Task, + plan: &ProviderPlan, + ) -> Result<()> { + observed.binding.scope.admits(task, plan)?; + let digest = plan.digest()?; + let tx = persistence::begin(&mut self.connection).map_err(db)?; + let original = binding(&tx, &task.family, &plan.node)?.ok_or(Error::Denied)?; + if original != observed.binding { + return Err(Error::Denied); + } + let current = cut(&tx, original)?; + if current.catalog != observed.catalog + || current + .catalog + .as_ref() + .is_none_or(|catalog| !catalog.entries.contains_key(&digest)) + { + return Err(Error::Denied); + } + if current.catalog_version != observed.catalog_version + || current.revision != observed.revision + || current.fence != observed.fence + { + return Err(Error::Conflict("provider routing cut changed")); + } + let publication = observed.binding.scope.publication(); + let key = weaver_contracts::PublicationKey { + operation_id: publication.operation_id.clone(), + digest: publication.digest()?, + }; + crate::task_origins::default_binding(&tx, task, None, Some(&key))?; + crate::store::register_task_in(&tx, task, Some(&key), None)?; + tx.commit().map_err(db)?; + Ok(()) + } +} + +#[cfg(test)] +#[path = "../tests/unit/provider_routing.rs"] +mod tests; diff --git a/crates/ledger/src/schema.rs b/crates/ledger/src/schema.rs index a1ab2249..5a745bcb 100644 --- a/crates/ledger/src/schema.rs +++ b/crates/ledger/src/schema.rs @@ -25,6 +25,8 @@ CREATE TABLE IF NOT EXISTS domain_history ( origin TEXT NOT NULL, node TEXT NOT NULL, member TEXT NOT NULL, event TEXT NOT NULL, digest TEXT NOT NULL, PRIMARY KEY(origin,node,member,event)); CREATE TABLE IF NOT EXISTS domain_migrations (operation_id TEXT PRIMARY KEY, digest TEXT NOT NULL, receipt TEXT NOT NULL); +CREATE TABLE IF NOT EXISTS provider_operation_scopes ( + family TEXT NOT NULL, node TEXT NOT NULL, digest TEXT NOT NULL, record TEXT NOT NULL, PRIMARY KEY(family,node)); CREATE TABLE IF NOT EXISTS source_authority ( singleton INTEGER PRIMARY KEY CHECK(singleton=1), epoch INTEGER NOT NULL CHECK(epoch>=0), record TEXT NOT NULL); CREATE TABLE IF NOT EXISTS source_keys ( diff --git a/crates/ledger/tests/unit/provider_routing.rs b/crates/ledger/tests/unit/provider_routing.rs new file mode 100644 index 00000000..e17850f3 --- /dev/null +++ b/crates/ledger/tests/unit/provider_routing.rs @@ -0,0 +1,234 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +use crate::persistence::{Session, exec, one}; +use weaver_contracts::*; +use weaver_ledger::Ledger; + +fn identity(id: u8) -> SourceIdentity { + SourceIdentity { + certificate_sha256: body_digest(&format!("cert-{id}")), + public_key_sha256: body_digest(&format!("key-{id}")), + credential_sha256: body_digest("source"), + } +} +fn fixture( + path: &std::path::Path, +) -> ( + Ledger, + ProviderRoutingScope, + Task, + ProviderPlan, + ProviderCatalog, +) { + let mut ledger = Ledger::open(path).expect("ledger"); + let profile: ProviderProfile = decode(include_bytes!( + "../../../../prod/policies/provider/profile.json" + )) + .expect("profile"); + let plan=ProviderPlan { family:"f".into(),node:"infer".into(),profile:"p".into(),profile_commitment:profile.digest().expect("profile digest"),model:"model-a".into(),body:r#"{"model":"model-a","stream":true,"messages":[{"role":"user","content":"hello"}],"max_completion_tokens":32}"#.into(),routes:vec![ProviderRoute { target:"primary".into(),endpoint:"https://provider.invalid/v1/chat/completions".into() }],ceiling:4,revision:0,fence:1 }; + let task = Task { + family: "f".into(), + principal: "alice".into(), + profile: "p".into(), + provider_profile: Some(profile), + nodes: vec!["infer".into()], + targets: vec!["primary".into()], + endpoints: [("primary".into(), plan.routes[0].endpoint.clone())].into(), + body_digests: [("infer".into(), body_digest(&plan.body))].into(), + stream_contracts: [("infer".into(), plan.digest().expect("plan digest"))].into(), + node_cost_bounds: [("infer".into(), 4)].into(), + models: vec!["model-a".into()], + budget: 8, + }; + let mut raw = task.clone(); + raw.body_digests.clear(); + raw.stream_contracts.clear(); + let scope = ProviderRoutingScope { + task: raw, + selection_schema: "provider-v1".into(), + selection: RoutingSelection { + node: "infer".into(), + allowed_modules: vec!["premium".into()], + required: vec!["quality".into()], + max_latency_ms: 100, + max_procurement_cost: 100, + user_token_rates: [1, 0, 0, 0], + candidates: vec![RoutingCandidate { + module: "premium".into(), + capabilities: vec!["quality".into()], + latency_ms: 1, + procurement_rates: [1, 0, 0, 0], + token_bounds: [64, 0, 0, 32], + plan: plan.clone(), + }], + }, + publication: Publication { + operation_id: "routing-pub".into(), + expected_revision: None, + fence: 1, + policy: include_str!("../../../../prod/policies/provider/provider.cedar").into(), + schema: include_str!("../../../../prod/policies/provider/schema.json").into(), + }, + }; + assert!( + ledger.register_provider_routing(&scope).is_err(), + "no implicit trusted-host delegation" + ); + ledger + .with_authenticated_source(&identity(0), |ledger| { + ledger.stage_authority(&scope.publication) + }) + .expect("stage"); + ledger + .with_authenticated_source(&identity(0), |ledger| { + ledger.register_provider_routing(&scope) + }) + .expect("declare"); + assert!( + ledger.provider_operation_cut("f", "infer").is_err(), + "staged is not active" + ); + ledger + .with_authenticated_source(&identity(0), |ledger| { + ledger.publish_authority(&scope.publication) + }) + .expect("activate"); + let catalog = ProviderCatalog { + parent: String::new(), + entries: [( + plan.digest().expect("digest"), + CatalogEntry { + module: "premium".into(), + capabilities: vec!["quality".into()], + latency_millis: 1, + user_rates: [1, 0, 0, 0], + quote: ProviderQuote { + version: "v1".into(), + tenant: "tenant".into(), + formula_digest: body_digest("test formula"), + procurement_rates: [1, 0, 0, 0], + token_bounds: [64, 0, 0, 32], + }, + }, + )] + .into(), + }; + insert_catalog(path, 1, &catalog); + (ledger, scope, task, plan, catalog) +} +fn insert_catalog(path: &std::path::Path, revision: i64, catalog: &ProviderCatalog) { + let session = Session::open(path).expect("catalog fixture"); + exec( + &session, + "INSERT INTO provider_catalog_publications VALUES(?1,?2,?3)", + crate::persistence::params![ + revision, + catalog.digest().expect("digest"), + String::from_utf8(catalog.record().expect("record")).expect("UTF-8") + ], + ) + .expect("catalog"); +} +#[test] +fn routed_registration_rechecks_catalog_and_preserves_restart_scope() { + let directory = tempfile::tempdir().expect("directory"); + let path = directory.path().join("routing.db"); + let (mut ledger, scope, task, plan, mut catalog) = fixture(&path); + let stale = ledger + .provider_operation_cut("f", "infer") + .expect("cut") + .expect("scope"); + catalog.parent = catalog.digest().expect("parent"); + catalog + .entries + .values_mut() + .next() + .expect("entry") + .latency_millis = 2; + insert_catalog(&path, 2, &catalog); + assert!( + ledger.register_routed_task(&stale, &task, &plan).is_err(), + "old catalog cannot register" + ); + let session = Session::open(&path).expect("inspect"); + let count: i64 = + one(&session, "SELECT COUNT(*) FROM tasks", (), |row| row.get(0)).expect("count"); + assert_eq!(count, 0); + let current = ledger + .provider_operation_cut("f", "infer") + .expect("cut") + .expect("scope"); + let mut modified = plan.clone(); + modified.body.push(' '); + assert!( + ledger + .register_routed_task(¤t, &task, &modified) + .is_err(), + "candidate mutation" + ); + ledger + .register_routed_task(¤t, &task, &plan) + .expect("current exact registration"); + ledger.close().expect("close"); + let mut ledger = Ledger::open(&path).expect("restart"); + assert_eq!( + ledger + .provider_operation_cut("f", "infer") + .expect("cut") + .expect("scope") + .binding + .scope, + ProviderOperationScope::Catalog { routing: scope } + ); + ledger + .register_routed_task(¤t, &task, &plan) + .expect("idempotent restart registration"); +} +#[test] +fn source_rotation_and_record_corruption_cannot_reuse_routing_cut() { + let directory = tempfile::tempdir().expect("directory"); + let path = directory.path().join("routing.db"); + let (mut ledger, scope, task, plan, _) = fixture(&path); + let observed = ledger + .provider_operation_cut("f", "infer") + .expect("cut") + .expect("scope"); + let mut other = Ledger::open(&path).expect("other"); + other + .rotate_source_authority( + &identity(0), + &SourceRotation { + operation_id: "rotate".into(), + expected_epoch: 0, + next: identity(1), + }, + ) + .expect("rotate"); + assert!( + ledger + .register_routed_task(&observed, &task, &plan) + .is_err(), + "old source cannot register" + ); + assert!( + ledger.provider_operation_cut("f", "infer").is_err(), + "old declaration cannot survive source retirement" + ); + assert!( + ledger + .with_authenticated_source(&identity(1), |ledger| ledger + .register_provider_routing(&scope)) + .is_err(), + "new source cannot silently replace original scope" + ); + let session = Session::open(&path).expect("corrupt"); + exec( + &session, + "UPDATE provider_operation_scopes SET record='{}'", + (), + ) + .expect("inject corruption"); + assert!(ledger.provider_operation_cut("f", "infer").is_err()); +} diff --git a/crates/server/src/governance_deployment.rs b/crates/server/src/governance_deployment.rs index ca50b29b..78d5532f 100644 --- a/crates/server/src/governance_deployment.rs +++ b/crates/server/src/governance_deployment.rs @@ -10,7 +10,7 @@ use std::{num::NonZeroUsize, sync::Arc}; use weaver_contracts::{Error, Result}; use weaver_governance::ProducerCatalog; -pub(crate) fn load_catalog() -> Result> { +pub(crate) fn load_catalog() -> Result>> { let Some(path) = std::env::var_os("WEAVER_GOVERNANCE_CATALOG") else { return Ok(None); }; @@ -20,26 +20,52 @@ pub(crate) fn load_catalog() -> Result> { .take((weaver_contracts::MAX_BODY_BYTES * 2 + 1) as u64) .read_to_end(&mut bytes) .map_err(|_| Error::Invalid("governance catalog read"))?; - ProducerCatalog::from_configuration(&bytes) - .map(Some) - .map_err(|_| Error::Invalid("governance catalog configuration")) + Ok(Some(bytes)) } pub(crate) async fn start( runtime: &ServiceRuntime, - catalog: Option, + configuration: Option>, ) -> Result> { let retire = match std::env::var("WEAVER_GOVERNANCE_RETIRE_ON_ACTIVATION") { Ok(value) if value == "1" => true, Err(std::env::VarError::NotPresent) => false, _ => return Err(Error::Invalid("single-provider lifecycle setting")), }; + let Some(configuration) = configuration else { + if retire || runtime.fact_feed().is_some() { + return Err(Error::Invalid("linked Scheme owner requires a catalog")); + } + #[cfg(feature = "scheme-program")] + { + let capacity = std::thread::available_parallelism() + .map_err(|_| Error::Invalid("host compiler budget"))?; + return start_compiler(runtime, None, capacity) + .await + .map(|(worker, _)| Some(worker)); + } + #[cfg(not(feature = "scheme-program"))] + return Ok(None); + }; + #[cfg(not(feature = "scheme-program"))] + let catalog: ProducerCatalog = ProducerCatalog::from_configuration(&configuration) + .map_err(|_| Error::Invalid("compiled Scheme program feature required"))?; + #[cfg(feature = "scheme-program")] + let (worker, catalog) = { + let capacity = std::thread::available_parallelism() + .map_err(|_| Error::Invalid("host compiler budget"))?; + { + let (worker, catalog) = start_compiler(runtime, Some(configuration), capacity).await?; + ( + worker, + catalog.ok_or(Error::Invalid("prepared catalog missing"))?, + ) + } + }; let session_workflow = runtime .fact_feed() .filter(|feed| !feed.workflow_path.is_empty()); - let session_original = catalog - .as_ref() - .filter(|catalog| catalog.has_session_workflow()); + let session_original = catalog.has_session_workflow().then_some(&catalog); if !match (session_workflow, session_original) { (None, None) => true, (Some(feed), Some(catalog)) => { @@ -63,28 +89,12 @@ pub(crate) async fn start( } if let Some(feed) = runtime.fact_feed() && let Some(edge) = &feed.workflow - && (!retire - || !catalog - .as_ref() - .is_some_and(|catalog| catalog.admits_workflow(&feed.family, edge))) + && (!retire || !catalog.admits_workflow(&feed.family, edge)) { return Err(Error::Invalid( "workflow requires the single compiled provider original", )); } - let Some(catalog) = catalog else { - if runtime.fact_feed().is_some() { - return Err(Error::Invalid( - "hard fact feed requires the linked Scheme owner", - )); - } - if retire { - return Err(Error::Invalid( - "single-provider lifecycle requires a catalog", - )); - } - return Ok(None); - }; #[cfg(not(feature = "scheme-program"))] { let _ = (runtime, catalog); @@ -100,35 +110,50 @@ pub(crate) async fn start( } runtime.enable_single_provider()?; } - let capacity = std::thread::available_parallelism() - .map_err(|_| Error::Invalid("host compiler budget"))?; - start_compiler(runtime, catalog, capacity).await.map(Some) + worker.publish_producers(catalog)?; + Ok(Some(worker)) } } #[cfg(feature = "scheme-program")] async fn start_compiler( runtime: &ServiceRuntime, - catalog: ProducerCatalog, + configuration: Option>, capacity: NonZeroUsize, -) -> Result { +) -> Result<(crate::GovernanceWorker, Option)> { let slots = Arc::new(tokio::sync::Semaphore::new(capacity.get())); let slot = Arc::new( slots .try_acquire_owned() .map_err(|_| Error::Conflict("compiler owner budget"))?, ); + let (prepared, receive) = tokio::sync::oneshot::channel(); let worker = runtime .start_governance_with_governor( slot, capacity, - || { - weaver_governance::SchemeCompiler::initialize() - .map_err(|_| Error::Conflict("approved Scheme program unavailable")) + move || { + let mut compiler = weaver_governance::SchemeCompiler::initialize() + .map_err(|_| Error::Conflict("approved Scheme program unavailable"))?; + let catalog = configuration + .as_ref() + .map(|configuration| { + ProducerCatalog::from_configuration_with(configuration, |input| { + crate::source_composition::compose_catalog(&mut compiler, input) + }) + .map_err(|_| Error::Invalid("governance catalog configuration")) + }) + .transpose()?; + prepared + .send(catalog) + .map_err(|_| Error::Conflict("catalog preparation cancelled"))?; + Ok(compiler) }, weaver_governance::SchemeCompiler::compile_cancellable, weaver_governance::SchemeCompiler::evaluate, ) .await?; - worker.publish_producers(catalog)?; - Ok(worker) + let catalog = receive + .await + .map_err(|_| Error::Conflict("catalog preparation unavailable"))?; + Ok((worker, catalog)) } diff --git a/crates/server/src/grpc.rs b/crates/server/src/grpc.rs index a9324e48..1aee4812 100644 --- a/crates/server/src/grpc.rs +++ b/crates/server/src/grpc.rs @@ -31,11 +31,13 @@ pub(crate) struct Gateway { ingress: Ingress, peer: [u8; 32], operation_peer: [u8; 32], + pub(crate) routing: crate::source_owner::OperationResolver, pub(crate) transport: ProviderTransport, pub(crate) admission: Admission, pub(crate) runtime: RuntimeOwner, pub(crate) metering_enabled: bool, pub(crate) provider_oauth_enabled: bool, + pub(crate) provider_oauth_relay: bool, } #[derive(Clone)] enum Ingress { @@ -121,12 +123,14 @@ async fn serve_owned( Ingress::Operation, admission.clone(), runtime.clone(), + source_worker.client.operation_resolver(), ); let source = Gateway::new( &settings, Ingress::Source(source_worker.client.clone()), admission, runtime.clone(), + source_worker.client.operation_resolver(), ); let session = operation.clone(); let operation = serve_listener( @@ -250,6 +254,7 @@ impl Gateway { ingress: Ingress, admission: Admission, runtime: RuntimeOwner, + routing: crate::source_owner::OperationResolver, ) -> Self { let (peer, credential) = match ingress.role() { RpcRole::Operation => (settings.security.peer_sha256, settings.owner.token_sha256), @@ -259,6 +264,7 @@ impl Gateway { ), }; Self { + routing, config: settings.owner.clone(), credential, ingress, @@ -269,6 +275,10 @@ impl Gateway { runtime, metering_enabled: settings.metering.is_some(), provider_oauth_enabled: settings.provider_oauth.is_some(), + provider_oauth_relay: settings + .provider_oauth + .as_ref() + .is_some_and(|config| config.relay_certificate_sha256.is_some()), } } pub(crate) fn authenticate( @@ -572,6 +582,59 @@ impl pb::gateway_server::Gateway for Gateway { })) } type ExecuteProviderStream = ResponseStream; + async fn compose_source( + &self, + request: Request, + ) -> std::result::Result, Status> { + let caller = self.source_identity(&request)?; + let input = request.into_inner(); + let source = self.ingress.source()?; + let before = source.authority(caller.clone()).await?; + let use_catalog = input.use_catalog; + let snapshot = if use_catalog { + source.provider_catalog(caller.clone()).await? + } else { + None + }; + let version = snapshot + .as_ref() + .map(|(version, _)| version.as_str()) + .unwrap_or("") + .to_owned(); + if input.expected_catalog_version != version { + return Err(Status::failed_precondition( + "composition catalog version changed", + )); + } + let output = crate::source_composition::compose( + &self.runtime, + input, + snapshot.as_ref().map(|(_, bytes)| bytes.as_slice()), + ) + .await?; + if source.authority(caller.clone()).await? != before || self.runtime.closing() { + return Err(Status::permission_denied( + "source authority changed during composition", + )); + } + if use_catalog + && source + .provider_catalog(caller) + .await? + .as_ref() + .map(|(version, _)| version.as_str()) + .unwrap_or("") + != version + { + return Err(Status::failed_precondition( + "composition catalog version changed", + )); + } + Ok(Response::new(pb::SourceCompositionReply { + artifact: Some(crate::source_artifact::artifact_data(output.data())), + catalog_version: version, + })) + } async fn compile_source( &self, request: Request, @@ -617,6 +680,7 @@ impl pb::gateway_server::Gateway for Gateway { })?, _=self.runtime.cancellation()=>return Err(Status::unavailable("source compilation closed")), }; + crate::source_composition::validate_transport(bound.source())?; // No source SQL lane is retained while foreign code runs. Re-observe the // actual caller after completion; a captured old observation is not use. let after = source.authority(caller).await?; @@ -667,7 +731,11 @@ impl pb::gateway_server::Gateway for Gateway { request: Request, ) -> std::result::Result, Status> { self.authenticate(&request, RpcRole::Operation)?; - let oauth = crate::provider_oauth::observe(self.provider_oauth_enabled, &request)?; + let oauth = crate::provider_oauth::observe( + self.provider_oauth_enabled, + self.provider_oauth_relay, + &request, + )?; let slot = self.admission.observation()?; let key = request.into_inner(); let config = self.config.clone(); @@ -736,6 +804,76 @@ impl pb::gateway_server::Gateway for Gateway { ) -> std::result::Result, Status> { let caller = self.source_identity(&request)?; let registration = request.into_inner(); + if let Some(wire) = registration.source_scope { + if registration.task.is_some() + || wire.use_catalog + || !wire.expected_catalog_version.is_empty() + { + return Err(Status::invalid_argument("source registration shape")); + } + let key = registration + .publication + .ok_or(Status::invalid_argument("original publication missing"))?; + let input = crate::source_composition::decode(wire)?; + if input.source.publication.operation_id != key.operation_id + || input.source.publication.digest().map_err(status)? != key.digest + { + return Err(Status::invalid_argument("source publication mismatch")); + } + let selected = + crate::source_composition::compose_typed(&self.runtime, input.clone(), None) + .await?; + if input.routing.is_empty() { + for plan in selected.plans() { + self.ingress + .source()? + .register_operation_source( + caller.clone(), + weaver_contracts::ProviderOperationScope::Fixed { + task: selected.task().clone(), + plan: plan.clone(), + publication: selected.publication().clone(), + }, + ) + .await?; + } + } else { + if input.source.tasks.len() != 1 + || !input.source.plans.is_empty() + || input.routing.len() != 1 + || input.source.governance.family != input.source.tasks[0].family + || input.source.governance.open_nodes != input.source.tasks[0].nodes + || !input.source.governance.workflow_edges.is_empty() + || !input.source.governance.workflow_selectors.is_empty() + || self.runtime.single_provider().is_some() + { + return Err(Status::invalid_argument("deferred source scope mismatch")); + } + let scope = weaver_contracts::ProviderRoutingScope { + task: input + .source + .tasks + .into_iter() + .next() + .ok_or(Status::invalid_argument("source task missing"))?, + selection_schema: input.source.governance.schema, + selection: input + .routing + .into_iter() + .next() + .ok_or(Status::invalid_argument("source selection missing"))?, + publication: input.source.publication, + }; + self.ingress + .source()? + .register_operation_source( + caller, + weaver_contracts::ProviderOperationScope::Catalog { routing: scope }, + ) + .await?; + } + return Ok(Response::new(pb::Empty {})); + } let task = registration .task .ok_or(Status::invalid_argument("task missing"))?; diff --git a/crates/server/src/grpc_contracts.rs b/crates/server/src/grpc_contracts.rs index 6c10aa64..2a773f5b 100644 --- a/crates/server/src/grpc_contracts.rs +++ b/crates/server/src/grpc_contracts.rs @@ -56,6 +56,12 @@ pub(crate) fn rejection_reason(error: &Error) -> &'static str { #[path = "../tests/unit/grpc_rejection.rs"] mod rejection_tests; pub(crate) fn plan(p: pb::ProviderPlan) -> std::result::Result { + let plan = plan_data(p)?; + plan.validate().map_err(status)?; + Ok(plan) +} +/// Decode inert candidate fields; eligibility and final request guards remain separate. +pub(crate) fn plan_data(p: pb::ProviderPlan) -> std::result::Result { let body = String::from_utf8(p.body) .map_err(|_| Status::invalid_argument("UTF-8 provider body required"))?; let plan = ProviderPlan { @@ -77,7 +83,6 @@ pub(crate) fn plan(p: pb::ProviderPlan) -> std::result::Result Task { diff --git a/crates/server/src/grpc_provider.rs b/crates/server/src/grpc_provider.rs index 0e0c561b..aa974d6e 100644 --- a/crates/server/src/grpc_provider.rs +++ b/crates/server/src/grpc_provider.rs @@ -44,16 +44,15 @@ impl Gateway { if predecessors.is_empty() && !session { return Ok(Vec::new()); } - let source = self + let prepared = self .runtime .single_provider() .filter(|lifecycle| lifecycle.activated()) .and_then(|lifecycle| lifecycle.ready.get()) - .map(crate::single_provider::Prepared::source) .ok_or(Status::failed_precondition( "compiled workflow has not activated", ))?; - let selection = &source.data().governance; + let selection = &prepared.source().data().governance; let matches_path = if session { selection.schema == feed.session_schema() && selection.open_nodes == feed.workflow_path } else { @@ -73,23 +72,18 @@ impl Gateway { )); } let admitted = |node: &str| { - source - .plans() - .iter() - .find(|p| p.family == selection.family && p.node == node) + prepared + .operation_plan(&selection.family, node) .ok_or(Status::failed_precondition( "compiled workflow plan missing", )) }; - if admitted(&successor.node)? != successor { + if admitted(&successor.node)? != *successor { return Err(Status::failed_precondition( "successor differs from compiled original", )); } - predecessors - .into_iter() - .map(|node| admitted(node).cloned()) - .collect() + predecessors.into_iter().map(admitted).collect() } pub(super) async fn execute_provider_stream( @@ -97,7 +91,11 @@ impl Gateway { request: Request, ) -> std::result::Result, Status> { self.authenticate(&request, RpcRole::Operation)?; - let oauth = crate::provider_oauth::observe(self.provider_oauth_enabled, &request)?; + let oauth = crate::provider_oauth::observe( + self.provider_oauth_enabled, + self.provider_oauth_relay, + &request, + )?; if !cfg!(feature = "llm-provider") { return Err(Status::unimplemented("LLM provider feature disabled")); } @@ -112,11 +110,35 @@ impl Gateway { { return Err(Status::invalid_argument("response batch bound")); } - let plan = plan( - request - .plan - .ok_or(Status::invalid_argument("plan missing"))?, - )?; + let proposed = request + .plan + .ok_or(Status::invalid_argument("plan missing"))?; + let mut catalog = request.catalog_version; + let plan = if operation_key_only(&proposed) { + if let Some(plan) = self + .runtime + .single_provider() + .filter(|provider| provider.activated()) + .and_then(|provider| provider.ready.get()) + .and_then(|prepared| prepared.operation_plan(&proposed.family, &proposed.node)) + { + plan + } else { + let (plan, observed) = self + .routing + .resolve(&self.runtime, proposed.family, proposed.node, &catalog) + .await?; + if !catalog.is_empty() && catalog != observed { + return Err(Status::failed_precondition( + "provider catalog coordinate changed", + )); + } + catalog = observed; + plan + } + } else { + plan(proposed)? + }; let predecessors = self.workflow_predecessors(&plan)?; if self .runtime @@ -139,7 +161,7 @@ impl Gateway { StreamSettings { arrow, batch_rows: request.batch_rows, - catalog: request.catalog_version, + catalog, }, ) .map(Response::new) @@ -457,3 +479,14 @@ impl Gateway { )) } } + +fn operation_key_only(plan: &pb::ProviderPlan) -> bool { + plan.profile.is_empty() + && plan.profile_commitment.is_empty() + && plan.model.is_empty() + && plan.body.is_empty() + && plan.routes.is_empty() + && plan.ceiling == 0 + && plan.revision == 0 + && plan.fence == 0 +} diff --git a/crates/server/src/lib.rs b/crates/server/src/lib.rs index 39163bfa..a7e7423b 100644 --- a/crates/server/src/lib.rs +++ b/crates/server/src/lib.rs @@ -32,6 +32,7 @@ mod session_workflow; mod shutdown; mod single_provider; mod source_artifact; +mod source_composition; mod source_identity; mod source_owner; mod telemetry; diff --git a/crates/server/src/provider_oauth.rs b/crates/server/src/provider_oauth.rs index db3465a6..bd3a97a7 100644 --- a/crates/server/src/provider_oauth.rs +++ b/crates/server/src/provider_oauth.rs @@ -47,6 +47,7 @@ pub(crate) fn change( pub(crate) fn observe( enabled: bool, + relay: bool, request: &Request, ) -> Result, Status> { let metadata = request.metadata(); @@ -60,6 +61,11 @@ pub(crate) fn observe( } return Ok(None); } + if !relay && metadata.contains_key("weaver-provider-oauth-ingress-cert") { + return Err(Status::unauthenticated( + "direct ingress cannot supply relay evidence", + )); + } if metadata.get_all("weaver-provider-oauth").iter().count() != 1 { return Err(Status::unauthenticated( "delegated provider credential required", @@ -119,3 +125,32 @@ pub(crate) fn observe( ingress_certificate_sha256, })) } + +#[cfg(test)] +mod direct_ingress_tests { + use super::*; + #[test] + fn direct_ingress_rejects_forged_relay_evidence_before_credential_use() { + let mut request = Request::new(()); + request.metadata_mut().insert( + "weaver-provider-oauth-ingress-cert", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + .parse() + .expect("metadata"), + ); + assert_eq!( + observe(true, false, &request) + .err() + .expect("relay evidence refused") + .code(), + tonic::Code::Unauthenticated + ); + assert_eq!( + observe(false, false, &request) + .err() + .expect("disabled profile refused") + .code(), + tonic::Code::FailedPrecondition + ); + } +} diff --git a/crates/server/src/session_workflow.rs b/crates/server/src/session_workflow.rs index c2137c8f..9bb5c025 100644 --- a/crates/server/src/session_workflow.rs +++ b/crates/server/src/session_workflow.rs @@ -277,6 +277,9 @@ impl Gateway { }) .collect::>>()?, weaver_governance::DerivationOutput::Indices(indices) => indices, + weaver_governance::DerivationOutput::Source(_) => { + return Err(Error::Conflict("Governor result kind")); + } }; ready.sort_unstable(); ready.dedup(); diff --git a/crates/server/src/single_provider.rs b/crates/server/src/single_provider.rs index 2b141203..ebb0548d 100644 --- a/crates/server/src/single_provider.rs +++ b/crates/server/src/single_provider.rs @@ -31,6 +31,7 @@ pub(crate) struct Prepared { pub(crate) authority: SourceAuthority, wire_authority: Option, bound: BoundSource, + operations: std::collections::BTreeMap, session: Option>, operation_id: String, digest: String, @@ -60,7 +61,15 @@ impl Prepared { .filter(|feed| !feed.workflow_path.is_empty()) .map(|feed| SessionTopology::prepare(feed, bound.source().plans()).map(Arc::new)) .transpose()?; + let operations = bound + .source() + .plans() + .iter() + .enumerate() + .map(|(index, plan)| (plan.node.clone(), index)) + .collect(); Ok(Self { + operations, producer: reply.producer.clone(), wire_authority: reply.authority.clone(), operation_id: publication.operation_id.clone(), @@ -77,6 +86,25 @@ impl Prepared { self.bound.source() } + /// Resolve inert original data only; final ledger/Cedar admission remains fresh. + pub(crate) fn operation_plan( + &self, + family: &str, + node: &str, + ) -> Option { + if family != self.source().task().family { + return None; + } + let mut plan = self + .source() + .plans() + .get(*self.operations.get(node)?)? + .clone(); + plan.revision = self.revision; + plan.fence = self.fence; + Some(plan) + } + pub(crate) fn session(&self) -> Option<&Arc> { self.session.as_ref() } diff --git a/crates/server/src/source_artifact.rs b/crates/server/src/source_artifact.rs index aa16831d..b7133efa 100644 --- a/crates/server/src/source_artifact.rs +++ b/crates/server/src/source_artifact.rs @@ -7,12 +7,16 @@ use crate::pb; use weaver_contracts::{ProviderPlan, ProviderProfile, ProviderRoute, Publication, Task}; use weaver_governance::{BoundSource, SourceData, SourceSelection}; pub(crate) fn artifact(bound: &BoundSource) -> pb::SourceArtifact { + artifact_data(bound.source().data()) +} +/// Typed projection only; the caller retains source provenance and authority checks. +pub(crate) fn artifact_data(data: &SourceData) -> pb::SourceArtifact { let SourceData { governance, tasks, plans, publication, - } = bound.source().data(); + } = data; let SourceSelection { schema, family, diff --git a/crates/server/src/source_composition.rs b/crates/server/src/source_composition.rs new file mode 100644 index 00000000..c73ce6c7 --- /dev/null +++ b/crates/server/src/source_composition.rs @@ -0,0 +1,223 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Inert authenticated-source projection; no catalog installation or effect authority. +use crate::{ + grpc_contracts::{compilation_status, plan, plan_data, status, task_contract}, + pb, + runtime::RuntimeOwner, +}; +use tonic::Status; +use weaver_governance::{ + OwnedSource, RoutingCandidate, RoutingSelection, SourceComposition, SourceData, SourceSelection, +}; + +pub(crate) async fn compose( + runtime: &RuntimeOwner, + request: pb::SourceCompositionRequest, + catalog: Option<&[u8]>, +) -> Result { + let input = decode(request)?; + let catalog = catalog + .map(weaver_contracts::decode::) + .transpose() + .map_err(status)?; + compose_typed(runtime, input, catalog.as_ref()).await +} + +pub(crate) fn decode(request: pb::SourceCompositionRequest) -> Result { + let wire = request + .source + .ok_or_else(|| Status::invalid_argument("source required"))?; + let governance = wire + .governance + .ok_or_else(|| Status::invalid_argument("source selection required"))?; + let publication = wire + .publication + .ok_or_else(|| Status::invalid_argument("source publication required"))?; + let source = SourceData { + governance: SourceSelection { + schema: governance.schema, + family: governance.family, + open_nodes: governance.open_nodes, + workflow_edges: governance + .workflow_edges + .into_iter() + .map(|edge| (edge.dependent, edge.dependency)) + .collect(), + workflow_selectors: governance + .workflow_selectors + .into_iter() + .map(|choice| [choice.selector, choice.left, choice.right]) + .collect(), + }, + tasks: wire.tasks.into_iter().map(task_contract).collect(), + plans: wire.plans.into_iter().map(plan).collect::>()?, + publication: weaver_contracts::Publication { + operation_id: publication.operation_id, + expected_revision: publication.expected_revision, + fence: publication.fence, + policy: publication.policy, + schema: publication.schema, + }, + }; + if request.routing.len() > 64 { + return Err(Status::resource_exhausted("routing selection bound")); + } + let mut routing = Vec::with_capacity(request.routing.len()); + for row in request.routing { + if row.candidates.is_empty() || row.candidates.len() > 8 { + return Err(Status::invalid_argument("routing candidate bound")); + } + routing.push(RoutingSelection { + node: row.node, + allowed_modules: row.allowed_modules, + required: row.required, + max_latency_ms: row.max_latency_ms, + max_procurement_cost: row.max_procurement_cost, + user_token_rates: rates(row.user_token_rates)?, + candidates: row + .candidates + .into_iter() + .map(|candidate| { + Ok(RoutingCandidate { + module: candidate.module, + capabilities: candidate.capabilities, + latency_ms: candidate.latency_ms, + procurement_rates: rates(candidate.procurement_rates)?, + token_bounds: rates(candidate.token_bounds)?, + plan: plan_data( + candidate.plan.ok_or_else(|| { + Status::invalid_argument("candidate plan required") + })?, + )?, + }) + }) + .collect::>()?, + }); + } + Ok(SourceComposition { source, routing }) +} + +pub(crate) async fn compose_typed( + runtime: &RuntimeOwner, + input: SourceComposition, + catalog: Option<&weaver_contracts::ProviderCatalog>, +) -> Result { + let SourceComposition { + source, + mut routing, + } = input; + if routing.is_empty() { + let source = OwnedSource::from_source(source) + .map_err(|_| Status::failed_precondition("source projection rejected"))?; + validate_transport(&source)?; + return Ok(source); + } + if let Some(profile) = source + .tasks + .first() + .and_then(|task| task.provider_profile.as_ref()) + { + let protocol = profile.adapter().map_err(status)?; + for row in &mut routing { + row.candidates.retain(|candidate| { + candidate.plan.routes.iter().all(|route| { + weaver_broker::HttpsTransport::validate_provider_endpoint( + &route.endpoint, + protocol, + ) + .is_ok() + }) + }); + } + } + if let Some(catalog) = catalog { + for row in &mut routing { + let mut tariff = None; + let mut candidates = Vec::new(); + for mut candidate in row.candidates.drain(..) { + let Ok(digest) = candidate.plan.digest() else { + continue; + }; + let Some(entry) = catalog.entries.get(&digest) else { + continue; + }; + let current = (entry.user_rates, entry.quote.tenant.clone()); + if tariff.as_ref().is_some_and(|prior| prior != ¤t) { + return Err(Status::failed_precondition( + "mixed catalog tariffs for original operation", + )); + } + tariff = Some(current); + row.user_token_rates = entry.user_rates; + candidate.module.clone_from(&entry.module); + candidate.capabilities.clone_from(&entry.capabilities); + candidate.latency_ms = entry.latency_millis; + candidate.procurement_rates = entry.quote.procurement_rates; + candidate.token_bounds = entry.quote.token_bounds; + candidates.push(candidate); + } + row.candidates = candidates; + } + } + let source = runtime + .governor() + .map_err(status)? + .compose(SourceComposition { source, routing }) + .await + .map_err(|error| compilation_status(weaver_governance::CatalogError::Schedule(error)))?; + validate_transport(&source)?; + Ok(source) +} +fn rates(values: Vec) -> Result<[u64; 4], Status> { + values + .try_into() + .map_err(|_| Status::invalid_argument("four metering categories required")) +} + +pub(crate) fn validate_transport(source: &OwnedSource) -> Result<(), Status> { + let protocol = source + .task() + .provider_profile + .as_ref() + .ok_or_else(|| Status::failed_precondition("provider profile required"))? + .adapter() + .map_err(status)?; + for plan in source.plans() { + for route in &plan.routes { + weaver_broker::HttpsTransport::validate_provider_endpoint(&route.endpoint, protocol) + .map_err(status)?; + } + } + Ok(()) +} + +/// Startup uses the same transport eligibility guard as source RPC composition. +#[cfg(feature = "scheme-program")] +pub(crate) fn compose_catalog( + compiler: &mut weaver_governance::SchemeCompiler, + configuration: &SourceComposition, +) -> Result { + let mut configuration = configuration.clone(); + let profile = configuration + .source + .tasks + .first() + .and_then(|task| task.provider_profile.as_ref()) + .ok_or(weaver_governance::SourceError::Contract)?; + let protocol = profile + .adapter() + .map_err(|_| weaver_governance::SourceError::Contract)?; + for row in &mut configuration.routing { + row.candidates.retain(|candidate| { + candidate.plan.routes.iter().all(|route| { + weaver_broker::HttpsTransport::validate_provider_endpoint(&route.endpoint, protocol) + .is_ok() + }) + }); + } + let source = compiler.compose(&configuration)?; + validate_transport(&source).map_err(|_| weaver_governance::SourceError::Contract)?; + Ok(source) +} diff --git a/crates/server/src/source_owner.rs b/crates/server/src/source_owner.rs index 7987d7ef..9af64fce 100644 --- a/crates/server/src/source_owner.rs +++ b/crates/server/src/source_owner.rs @@ -26,6 +26,33 @@ pub(crate) struct SourceOwner { capacity: Arc, waiting: Arc, next_mutation: Arc, + routing: Arc>>, +} +#[derive(Clone)] +pub(crate) struct OperationResolver(SourceOwner); +enum OperationProjection { + Fixed(Arc), + Catalog(Box), +} +struct RoutingProjection { + binding: weaver_contracts::ProviderOperationBinding, + version: String, + revision: u64, + fence: u64, + selected: weaver_governance::OwnedSource, +} +impl OperationResolver { + pub(crate) async fn resolve( + &self, + runtime: &RuntimeOwner, + family: String, + node: String, + expected: &str, + ) -> std::result::Result<(weaver_contracts::ProviderPlan, String), Status> { + self.0 + .resolve_operation(runtime, family, node, expected) + .await + } } #[derive(Default)] struct MutationHandoff { @@ -65,9 +92,24 @@ impl Drop for MutationReservation<'_> { } } -struct Envelope { - caller: SourceIdentity, - command: Command, +enum Envelope { + Source { + caller: SourceIdentity, + command: Box, + }, + RoutingCut { + family: String, + node: String, + reply: oneshot::Sender>>, + slot: OwnedSemaphorePermit, + }, + RoutedTask { + observed: Box, + task: Box, + plan: Box, + reply: oneshot::Sender>, + slot: OwnedSemaphorePermit, + }, } struct SourceDeployment { review: Option, @@ -78,6 +120,12 @@ struct SourceDeployment { } enum Command { + RegisterOperationSource { + scope: Box, + reply: oneshot::Sender>, + slot: OwnedSemaphorePermit, + }, + StageFact { intent: FactIntent, reply: oneshot::Sender>, @@ -458,6 +506,7 @@ impl SourceOwner { capacity: Arc::new(Semaphore::new(1)), waiting: Arc::new(Semaphore::new(3)), next_mutation: Arc::new(MutationHandoff::default()), + routing: Arc::new(tokio::sync::Mutex::new(None)), }, job, }) @@ -552,9 +601,9 @@ impl SourceOwner { ) -> std::result::Result { let (reply, receiver) = oneshot::channel(); self.sender - .try_send(Envelope { + .try_send(Envelope::Source { caller, - command: make(reply, slot), + command: Box::new(make(reply, slot)), }) .map_err(|_| Status::unavailable("source owner stopped"))?; receiver @@ -567,6 +616,160 @@ impl SourceOwner { _ => Status::failed_precondition("source authority or state rejected"), }) } + pub(crate) async fn register_operation_source( + &self, + caller: SourceIdentity, + scope: weaver_contracts::ProviderOperationScope, + ) -> std::result::Result<(), Status> { + self.submit_with_wait(caller, true, |reply, slot| { + Command::RegisterOperationSource { + scope: Box::new(scope), + reply, + slot, + } + }) + .await + } + async fn internal( + &self, + make: impl FnOnce(oneshot::Sender>, OwnedSemaphorePermit) -> Envelope, + ) -> std::result::Result { + let slot = self.command_slot(true).await?; + let (reply, receive) = oneshot::channel(); + self.sender + .try_send(make(reply, slot)) + .map_err(|_| Status::unavailable("source owner stopped"))?; + receive + .await + .map_err(|_| Status::unavailable("source routing result unknown"))? + .map_err(crate::grpc_contracts::status) + } + pub(crate) fn operation_resolver(&self) -> OperationResolver { + OperationResolver(self.clone()) + } + async fn resolve_operation( + &self, + runtime: &RuntimeOwner, + family: String, + node: String, + expected: &str, + ) -> std::result::Result<(weaver_contracts::ProviderPlan, String), Status> { + // This hit returns inert immutable data only. The original activation + // coordinates remain sealed and the broker performs all fresh deciding + // checks. Catalog derivations always rejoin the source lane below. + let cached = { + let projection = self.routing.lock().await; + match projection.as_ref() { + Some(OperationProjection::Fixed(plan)) + if plan.family == family && plan.node == node => + { + Some(plan.clone()) + } + _ => None, + } + }; + if let Some(plan) = cached { + if !expected.is_empty() { + return Err(Status::failed_precondition( + "fixed original has no selected catalog coordinate", + )); + } + return Ok((plan.as_ref().clone(), String::new())); + } + let observed = self + .internal(|reply, slot| Envelope::RoutingCut { + family, + node, + reply, + slot, + }) + .await? + .ok_or(Status::failed_precondition( + "source routing scope unavailable", + ))?; + if !expected.is_empty() && expected != observed.catalog_version { + return Err(Status::failed_precondition( + "provider catalog coordinate changed", + )); + } + if let weaver_contracts::ProviderOperationScope::Fixed { plan, .. } = + &observed.binding.scope + { + let mut plan = plan.clone(); + plan.revision = observed.revision; + plan.fence = observed.fence; + *self.routing.lock().await = Some(OperationProjection::Fixed(Arc::new(plan.clone()))); + return Ok((plan, String::new())); + } + let mut projection = self.routing.lock().await; + let reusable = match projection.as_ref() { + Some(OperationProjection::Catalog(p)) + if p.binding == observed.binding + && p.version == observed.catalog_version + && p.revision == observed.revision + && p.fence == observed.fence => + { + Some(p) + } + _ => None, + }; + let selected = if let Some(prior) = reusable { + prior.selected.clone() + } else { + let weaver_contracts::ProviderOperationScope::Catalog { routing: scope } = + &observed.binding.scope + else { + unreachable!() + }; + let input = weaver_governance::SourceComposition { + source: weaver_governance::SourceData { + governance: weaver_governance::SourceSelection { + schema: scope.selection_schema.clone(), + family: scope.task.family.clone(), + open_nodes: scope.task.nodes.clone(), + workflow_edges: Vec::new(), + workflow_selectors: Vec::new(), + }, + tasks: vec![scope.task.clone()], + plans: Vec::new(), + publication: scope.publication.clone(), + }, + routing: vec![scope.selection.clone()], + }; + let selected = + crate::source_composition::compose_typed(runtime, input, observed.catalog.as_ref()) + .await?; + *projection = Some(OperationProjection::Catalog(Box::new(RoutingProjection { + binding: observed.binding.clone(), + version: observed.catalog_version.clone(), + revision: observed.revision, + fence: observed.fence, + selected: selected.clone(), + }))); + selected + }; + drop(projection); + let mut plan = selected + .plans() + .first() + .ok_or(Status::failed_precondition("source routing plan missing"))? + .clone(); + let task = selected.task().clone(); + let version = observed.catalog_version.clone(); + let revision = observed.revision; + let fence = observed.fence; + self.internal(|reply, slot| Envelope::RoutedTask { + observed: Box::new(observed), + task: Box::new(task), + plan: Box::new(plan.clone()), + reply, + slot, + }) + .await?; + plan.revision = revision; + plan.fence = fence; + Ok((plan, version)) + } pub(crate) async fn register( &self, caller: SourceIdentity, @@ -770,8 +973,37 @@ fn process( return Ok(()); }; ledger.require_quiescent()?; - let Envelope { caller, command } = command; + let (caller, command) = match command { + Envelope::Source { caller, command } => (caller, *command), + Envelope::RoutingCut { + family, + node, + reply, + slot, + } => { + let result = ledger.provider_operation_cut(&family, &node); + answer(ledger, reply, result, slot)?; + continue; + } + Envelope::RoutedTask { + observed, + task, + plan, + reply, + slot, + } => { + let result = ledger.register_routed_task(&observed, &task, &plan); + answer(ledger, reply, result, slot)?; + continue; + } + }; match command { + Command::RegisterOperationSource { scope, reply, slot } => { + let result = ledger.with_authenticated_source(&caller, |ledger| { + ledger.register_provider_source(&scope) + }); + answer(ledger, reply, result, slot)?; + } Command::StageFact { intent, reply, diff --git a/crates/server/tests/unit/source_owner.rs b/crates/server/tests/unit/source_owner.rs index 9e755f83..d44a90de 100644 --- a/crates/server/tests/unit/source_owner.rs +++ b/crates/server/tests/unit/source_owner.rs @@ -277,6 +277,7 @@ async fn bounded_catalog_wait_releases_cancelled_waiter_and_preserves_active_slo capacity: Arc::new(Semaphore::new(1)), waiting: Arc::new(Semaphore::new(3)), next_mutation: Arc::new(super::MutationHandoff::default()), + routing: Arc::new(tokio::sync::Mutex::new(None)), }; let held = source.command_slot(false).await.expect("active slot"); let mut first = Box::pin(source.command_slot(true)); @@ -320,6 +321,7 @@ async fn cancelled_priority_wait_does_not_send_a_source_command() { capacity: Arc::new(Semaphore::new(1)), waiting: Arc::new(Semaphore::new(3)), next_mutation: Arc::new(super::MutationHandoff::default()), + routing: Arc::new(tokio::sync::Mutex::new(None)), }; let held = source.command_slot(false).await.expect("active slot"); let mut command = Box::pin(source.publish(caller(), change("cancel", None))); diff --git a/dev/sysml/ArchitectureEvolution.sysml b/dev/sysml/ArchitectureEvolution.sysml index 539e6bcd..0103fd06 100644 --- a/dev/sysml/ArchitectureEvolution.sysml +++ b/dev/sysml/ArchitectureEvolution.sysml @@ -456,4 +456,157 @@ package ArchitectureEvolution { expose reinforcement::reconcile; render asInterconnectionDiagram; } + + requirement def SchemeSourceComposition { + doc /* Trusted startup routing is evaluated by the installed Scheme/POO + application with bounded gerbil-ascent eligibility and deterministic + cost/latency/canonical-digest ordering. Rust computes canonical facts, + validates the detached output against the independently retained task, + publication, declared topology and concrete candidate membership, and + only then seals its exact original. No second ranking engine is added. + Workflow topology comes from the existing Session/Funflow/Governor + producer. Later source captures retain unchanged SourceExpectation + equality; composition does not authenticate or publish a source. + The Go catalog adapter consumes the composed typed projection. + File syntax decoding and dynamic catalog reads use the same advisory + RPC; Go no longer selects candidates or interprets Workflow there. + Reference algorithms retain development consumers only. OpenSysML + tools remain Go. */ + } + requirement def AdvisorySourceComposition { + doc /* ComposeSource is restricted to authenticated source ingress. + Recheck source authority before and after the bounded existing owner + call. When catalog facts are requested, require the expected exact + catalog version and recheck it after derivation. The response contains + inert typed source data, never a publication receipt, catalog install, + source enrollment, consumed permit or barrier resolution. Complete + static projections reuse Rust validation; undecided offers use the + same affine Scheme owner. Preserve independent SPEC review custody. + Existing immutable projection caching may coalesce one new version; + each request still observes live source/catalog authority and final + Rust admission independently decides registration, reservation and use. */ + } + item def UnsealedSourceComposition { + item original : PolicyEvidenceDesign::SemanticCommitment; + attribute configurationIdentity : String; + doc /* Deployment-owned configuration and candidate facts, not a permit. + Exact byte/traversal and candidate limits bound application input. */ + } + action def ComposeSourceBeforeSeal { + in item configuration : UnsealedSourceComposition; + out item proposal : PolicyEvidenceDesign::SourceCommand; + doc /* Existing tracked Rust owner invokes the fixed rooted Scheme ABI; + reuse POO source contracts, gerbil-ascent and installed producer. + No additional VM, loader, runner, semantic cache or durable store. */ + } + requirement def SourceBoundOperationPreparation { + doc /* An authenticated source declares either exact fixed plans or one + bounded catalog selector before operations. Persist the tagged scope, + exact source authority epoch, publication and content digest in the + existing ledger. Only source ingress can declare it; the operation + listener receives a narrow resolver, never a source credential. + Fixed plans are inert original data; reuse their sealed projection + without a source-lane transaction on each hit. All fresh execution + guards remain broker/ledger decisions. Catalog derivation uses the + existing affine Scheme/POO/gerbil-ascent owner. Coalesce identical + immutable projections; never cache permission. Before registering a + selected task, one existing ledger transaction rejoins the exact + declared scope, current source epoch, committed original publication, + authority revision/fence and current catalog version/content. + Candidate/body mutation, stale cuts, withdrawal and source retirement + cannot register a new task. Restart reads the retained declaration, + not a Go service cache. Immutable task and spent claim rules remain. */ + } + requirement def DirectRustOperationIngress { + doc /* Rust's existing operation listener directly authenticates callers, + admits bounded streams and invokes the existing ledger/broker/output + path. Go preparation is a source-only command and exits before the + request; it needs neither operation credentials nor an ingress socket. + Default prepare enables direct fixed and catalog-selected operations; + explicit serve retains reference relay controls until R5. + A complete typed plan retains the existing direct protocol. An exact + family/node key resolves activated Prepared or declared ledger data; + partial overrides are not keys, and no lookup grants authority. + Resolve using the sealed activation revision/fence, never current-head + rebasing. All final guards, encoding, order, cancellation, backpressure, + terminal status and unknown holds remain in the existing Rust owners. + Direct OAuth observes the actual TLS sender and rejects caller-supplied + relay evidence before execution admission. Signed relay delegation is + a separate explicit deployment mode, not a direct-mode fallback. */ + } + requirement def RustSchemeRuntimeBoundary { + doc /* The target operation path terminates at the existing Rust server, + broker and ledger. Reuse the affine Scheme owner for necessary bounded + semantic derivation; publication preparation is not a per-frame task. + No Go relay, Kubernetes API call or controller reconciliation is required + for each request/frame. Rust preserves fresh source/version checks, + Cedar permission, reservation, frontier/claim, complete response release, + cancellation and unknown holds. This design is not a latency result. */ + } + requirement def CloudAdapterAuthorityBoundary { + doc /* A cloud adapter carries authenticated observations and proposals, + not business selection or effect authority. Kubernetes UID, resource + version and generation are observation coordinates, not ledger source + revisions. Persist hard-fact intent in the existing source lane/ledger + before ASCENT derives impact; release barriers only after transactional + exact-source and intent-prefix checks. Duplicate/reordered watches, + relist, deletion, restart and A-to-B-to-A cannot restore stale authority. + Separate bounded adapter work from operation admission and owner work. + A disconnected adapter cannot authorize new use of revoked facts. */ + } + requirement def GoIntegrationLeverage { + doc /* Go is optional in the target production graph. Retain an owned Go + adapter only for a named required integration whose maintained Go API + avoids substantial implementation and conformance work. Record SDK + coverage, protocol alternatives, trust custody, version/support cost, + failure isolation and retirement criteria. Go implementation of an + external cloud service does not require Weaver to embed a Go runtime. + Development OpenSysML tooling and independent signing services have + separate retirement decisions; migration cannot merge issuer custody. */ + } + item def CloudResourceObservation { + attribute resourceIdentity : String; + attribute resourceVersion : String; + attribute generation : String; + attribute authenticatedSource : String; + item cut : ReconciliationCut; + doc /* Target envelope over existing typed source/fact contracts, not a + second durable store. A partial watch image is not a coherent ledger + cut. Secret bytes stay with their existing credential owner. */ + } + item def CloudIntegrationAssessment { + attribute integration : String; + attribute requiredCapability : String; + attribute supportedInterface : String; + attribute maintainedSDKBenefit : String; + attribute operationalCost : String; + attribute retirementCondition : String; + item evidence : EvidenceAxis[0..*]; + } + action def IngestCloudObservation { + in item observation : CloudResourceObservation; + out item cut : ReconciliationCut; + doc /* Target Rust kube-rs or protocol adapter feeds existing source lane. + Observation admission precedes Scheme ReconcileObjectSet. No watch + callback directly publishes or executes an effect. */ + } + part def RustSchemeAllocation { + requirement composition : SchemeSourceComposition; + requirement advisory : AdvisorySourceComposition; + action compose : ComposeSourceBeforeSeal; + requirement operation : RustSchemeRuntimeBoundary; + requirement directIngress : DirectRustOperationIngress; + requirement sourcePreparation : SourceBoundOperationPreparation; + requirement cloud : CloudAdapterAuthorityBoundary; + requirement leverage : GoIntegrationLeverage; + action ingest : IngestCloudObservation; + action reconcile : ReconcileObjectSet; + action prepare : ControllerObjectLifecycle::PrepareObject; + action advance : AdvanceGovernedRoutine; + doc /* Target semantic owner is Scheme/POO/gerbil-ascent, effect owner is + existing Rust admission/broker/ledger, and cloud observation owner is + a bounded Rust adapter by default. Go development tooling is retained + while its existing OpenSysML SDK provides concrete leverage. */ + } + part rustSchemeTarget : RustSchemeAllocation; } diff --git a/dev/sysml/ProviderRpc.sysml b/dev/sysml/ProviderRpc.sysml index 5575b278..c2074ba9 100644 --- a/dev/sysml/ProviderRpc.sysml +++ b/dev/sysml/ProviderRpc.sysml @@ -14,7 +14,9 @@ package ProviderRpc { The deciding Turso scope joins active grant status with Cedar and the original claim before dispatch or response release. Revocation retains unknown holds, and credential renewal cannot reopen consumption. - Go projects its actual verified ingress certificate. Rust authenticates + Direct Rust ingress observes the actual TLS sender and rejects supplied + relay evidence. In explicit relay mode Go projects its verified ingress + certificate. Rust authenticates the relay TLS sender and prepares the signed grant lineage before the shared-domain lock. Each deciding scope matches the exact deployment, root and leaf records, reads both tombstones, checks current time and @@ -33,7 +35,7 @@ package ProviderRpc { doc /* Go proposes an exact original task, body and ordered route commitment. Rust selects one permitted configured route before durable consumption. */ } requirement def UnambiguousProviderRequestBounds { - doc /* Go rejects unsupported request shapes; Rust independently admits exactly one original token cap in the range 1 through 4096 before reservation or dispatch. Source commitments cannot qualify competing caps. Neither cap nor usage observations authorize monetary settlement. */ + doc /* Rust admits supported request shapes and independently admits exactly one original token cap in the range 1 through 4096 before reservation or dispatch. Source commitments cannot qualify competing caps. Neither cap nor usage observations authorize monetary settlement. */ } requirement def SourceProviderProfileBinding { doc /* Rust retains only immutable Cedar literals and parsed subject/ @@ -50,9 +52,9 @@ package ProviderRpc { evaluation before any queue callback. No read image crosses a write, capacity wait, transaction boundary, publication cut or owner restart. The prepare burn and final release remain distinct durable scopes. - Go config/publication/Routing and Rust final sends can be qualified - without Scheme preparation; this does not qualify a new Scheme - dependency or alter its source-currentness contract. */ + Static source publication and final Rust sends can be qualified without + Scheme inference. Undecided routing uses the installed Scheme owner; + neither path changes source-currentness or final-use contracts. */ doc /* Authenticated source registration atomically binds an immutable profile artifact and original task. Plans commit the exact profile digest. Fresh Cedar evaluates protocol, profile digest and validated request facts before final sends. */ } requirement def ClosedProviderRequestSchema { @@ -68,7 +70,8 @@ package ProviderRpc { doc /* Durable consume and dispatch burn precede the only possible provider request. RPC retry, redirect, fallback, restart and cancellation never reopen a consumed root. */ } requirement def TransportAndExecutionLatencySeparation { - doc /* Go forwards authenticated Protobuf request envelopes over + doc /* The direct client sends authenticated Protobuf requests to Rust. + The retained Go relay forwards authenticated Protobuf envelopes over gRPC. The streaming response carries either a Protobuf event or an Arrow IPC batch inside each Protobuf frame. The Go relay forwards frames unchanged. The Go client decodes Arrow only @@ -81,7 +84,9 @@ package ProviderRpc { upstream wait and terminal wall time as execution intervals. */ } requirement def ProviderSchedulerOwnership { - doc /* Go owns verified ingress, local admission limits, relay + doc /* Direct Rust ingress owns TLS identity, bounded worker admission, + backpressure and cancellation without a Go response hop. + For retained relay sessions Go owns verified ingress, local admission limits, relay backpressure and cancellation propagation. Rust owns provider worker admission, authoritative domain contention, resource lifetime and every deciding scope. Go has no authority to @@ -202,13 +207,56 @@ package ProviderRpc { port def EventPort { out item delta : StreamEvent; } port def FramePort { out item encoded : EncodedFrame; } port def PublicationPort { out item authority : AuthorityPublication; } - part def SourcePublisher { port authority : PublicationPort; } - part def RustSourceIngress { port authority : ~PublicationPort; port published : PublicationPort; } - part def RustSourceWorker { port command : ~PublicationPort; port decided : PublicationPort; } - part def GoRoutingControl { - doc /* RPC view of the existing Go cloud/protocol integration owner. - Kubernetes watches, SDK health and discovered routes are typed source - candidates. Go validates/consumes response data under the original + item def SourceCompositionInput { + item configuration : ArchitectureEvolution::UnsealedSourceComposition; + } + item def SourceCompositionObservation { + doc /* Inert source projection, not a publication or consumed permit. */ + } + port def CompositionPort { + out item input : SourceCompositionInput; + in item result : SourceCompositionObservation; + } + item def OperationSourceDeclaration { + item publication : AuthorityPublication; + item fixedOriginal : OriginalPlan[0..*]; + item candidateScope : SourceCompositionInput[0..1]; + doc /* Exactly one fixed original set or bounded catalog candidate scope; + Rust's tagged ProviderOperationScope enforces this representation. + The declaration is source-owned data, not an operation capability. */ + } + port def OperationSourcePort { out item declaration : OperationSourceDeclaration; } + port def OperationResolutionPort { + in item key : OriginalPlan; + out item selected : OriginalPlan; + } + part def SourcePublisher { + port authority : PublicationPort; + port composition : CompositionPort; + port declaration : OperationSourcePort; + } + part def RustSourceIngress { + port authority : ~PublicationPort; + port published : PublicationPort; + port composition : ~CompositionPort; + port declaration : ~OperationSourcePort; + port retained : OperationSourcePort; + requirement advisory : ArchitectureEvolution::AdvisorySourceComposition; + doc /* ComposeSource authenticates this source ingress, rechecks source + authority/catalog version around bounded Scheme work, and returns + inert data. It neither stages publication nor installs a producer. */ + } + part def RustSourceWorker { + port command : ~PublicationPort; + port decided : PublicationPort; + port declaration : ~OperationSourcePort; + port resolution : OperationResolutionPort; + requirement custody : ArchitectureEvolution::SourceBoundOperationPreparation; + } + part def GoSourceTransport { + doc /* RPC view of the current Go syntax/projection and transport owner. + Configuration and catalog candidates are composed by Rust/Scheme; + cloud discovery is a later adapter integration. Go validates/consumes response data under the original stream context, applies bounded backpressure and propagates cancellation. Compiled route slices, outbound Task maps/slices and the stream observer's plan are private typed copies. Copy before invoking RPC or @@ -220,7 +268,19 @@ package ProviderRpc { port proposal : PlanPort; port received : ~FramePort; } - part def RustGrpcOwner { port proposal : ~PlanPort; port forwarded : PlanPort; } + part def RustGrpcOwner { + port proposal : ~PlanPort; + port forwarded : PlanPort; + port resolution : ~OperationResolutionPort; + } + part def DirectOperationClient { + doc /* An external operation caller, with no source/publication rights. + A complete plan or declared family/node key is an inert proposal; + the Rust owner resolves only activated original data and all existing + deciding guards still apply. No Go process receives the response. */ + port proposal : PlanPort; + port received : ~FramePort; + } /* Request construction is inert. The fresh deciding scope owns connect, TLS and exactly one fixed-length HTTP request. WriteSeal observes accepted plaintext plus successful TLS flush, then permanently rejects every new @@ -261,8 +321,39 @@ package ProviderRpc { port frames : ~FramePort; port stream : FramePort; } + part directProviderPath { + doc /* R2 direct deployment alternative over the same owner types, + not another runtime, listener or ledger. Source preparation is a prior + phase and may exit; each operation has its own authenticated stream. + Deferred selection rejoins source/catalog state in the source lane. */ + requirement direct : ArchitectureEvolution::DirectRustOperationIngress; + part client : DirectOperationClient; + part source : SourcePublisher; + part publication : RustSourceIngress; + part sourceStore : RustSourceWorker; + part rpc : RustGrpcOwner; + part broker : RustProviderBroker; + part guard : RustCedarRelease; + part encoding : ProtobufOrArrowEncoder; + part output : RustBoundedOutput; + connect source.composition to publication.composition; + connect source.declaration to publication.declaration; + connect publication.retained to sourceStore.declaration; + connect sourceStore.resolution to rpc.resolution; + connect source.authority to publication.authority; + connect publication.published to sourceStore.command; + connect sourceStore.decided to broker.authority; + connect client.proposal to rpc.proposal; + connect rpc.forwarded to broker.proposal; + connect broker.response to encoding.response; + connect encoding.frames to guard.prepared; + connect guard.authorized to output.frames; + connect output.stream to client.received; + } part providerPath { - part control : GoRoutingControl; + doc /* Explicit serve reference deployment, retained for relay controls; + directProviderPath is the default R2 operation deployment. */ + part control : GoSourceTransport; part source : SourcePublisher; part publication : RustSourceIngress; part sourceStore : RustSourceWorker; @@ -271,6 +362,10 @@ package ProviderRpc { part guard : RustCedarRelease; part encoding : ProtobufOrArrowEncoder; part output : RustBoundedOutput; + connect source.composition to publication.composition; + connect source.declaration to publication.declaration; + connect publication.retained to sourceStore.declaration; + connect sourceStore.resolution to rpc.resolution; connect control.proposal to rpc.proposal; connect source.authority to publication.authority; connect publication.published to sourceStore.command; diff --git a/dev/sysml/WeaverExecution.sysml b/dev/sysml/WeaverExecution.sysml index bc56f24a..28957157 100644 --- a/dev/sysml/WeaverExecution.sysml +++ b/dev/sysml/WeaverExecution.sysml @@ -810,6 +810,7 @@ package WeaverExecution { This action grants no publication, consumption or transport right. */ } action deriveCandidate : DeriveSemanticCandidate; + action composeSource : ArchitectureEvolution::ComposeSourceBeforeSeal; action prepareObject : ControllerObjectLifecycle::PrepareObject; action replaceObject : ControllerObjectLifecycle::PrepareObjectReplacement; action reuseObject : ControllerObjectLifecycle::ReuseObjectProjection; @@ -871,8 +872,8 @@ package WeaverExecution { port effectObservations : ~PolicyEvidenceDesign::EffectObservationPort; } part def GoControlAdapter { - attribute overviewName : String = "Route proposal"; - attribute overviewSummary : String = "Suggest a provider"; + attribute overviewName : String = "Source transport"; + attribute overviewSummary : String = "Carry prepared source data"; attribute overviewGlyph : String = "route-choice"; private action def OrchestrateSourcePublication { in item candidate : PolicyEvidenceDesign::SourceCommand; @@ -881,24 +882,28 @@ package WeaverExecution { current-source commands; reconcile uncertain outcomes by identity. */ } action publishCandidate : OrchestrateSourcePublication; - doc /* Preserve the semantic original through configuration normalization, + doc /* The Scheme catalog path copies an already composed projection; + it does not run Go routing or interpret Workflow. File-source and dynamic + catalog requests now delegate composition through the same source-only + RPC. Remaining Go Bundle algorithms serve development/reference callers. + Preserve the semantic original through configuration normalization, protocol aliasing and authenticated publication. JSON/YAML populates the same admitted contracts; it cannot define another authorization language. Routing, retries and fallback select candidates within that original. Go neither invents original task keys from session labels nor treats compile/publication acknowledgments as final-use permits. */ - attribute displayName : String = "Go / Control + routing"; + attribute displayName : String = "Go / Configuration transport"; attribute leanDeclaration : String = "CedarPooSpec.Gateway.Context"; attribute leanFields : String = "scope,policyRevision,ownerEpoch,historyRevision,factFloor"; attribute securityName : String = "Go / Source publication"; attribute securityGlyph : String = "publication"; attribute securityResponsibility : String = "Carry the original context\nPublish over authenticated gRPC\nUnknown replies stay unresolved"; - attribute responsibility : String = "Cloud + protocol integration\nOne owned source image\nAuthenticated publication + routing"; + attribute responsibility : String = "Source preparation + optional adapters\nOne owned source image\nNo default response forwarding"; attribute glyph : String = "routing"; attribute visualRole : String = "selection"; doc /* BootstrapProducer receives the server's typed CompileSource artifact over authenticated gRPC and reobserves source authority. - Its bounded typed projection freezes and validates one owned image, then + Its bounded typed projection copies one already composed owned image, then shares the private publication implementation with file configuration. It neither JSON-roundtrips nor repeats normalization across these internal functions. No borrowed protobuf container escapes. Source @@ -907,27 +912,36 @@ package WeaverExecution { selects exactly one approved producer or JSON/YAML data file; Scheme files cannot launch a compiler, and producer failure cannot fall back to a file. The Rust deployment still must install its approved graph. */ - doc /* Refine routine node and routing preferences; emit typed data with - no send capability. Carry configuration/capture commitments and + doc /* R2 default/explicit prepare reuses source bootstrap without an + operation credential, frontend listener or response forwarding, then + exits. Fixed and catalog-selected clients use the existing Rust + operation listener. Source-owned typed declarations persist in the + existing ledger; the narrow operation resolver cannot publish source + authority. Catalog derivation rejoins current source, publication and + catalog in the registration transaction. Fixed plans and selected + originals retain their exact activation coordinates. Explicit serve + remains for reference controls until R5. */ + doc /* Carry routine node and routing preference data without selecting + candidates or interpreting Workflow; emit typed data with no send capability. Carry configuration/capture commitments and authenticated original source identity over gRPC. Reconcile ambiguity; never evaluate Scheme, manage GC roots or forward foreign pointers. */ - doc /* Go's target value is cloud/protocol integration, not a language - monopoly on Kubernetes or networking. Own discovery/watch/reconcile, - bounded ingress connections and protocol adapters, routing candidates, - source-outcome recovery and cloud lifecycle integration. Reuse the Go - ecosystem instead of implementing a duplicate Rust control adapter. - Ingress TLS/cloud-management credentials are distinct from provider - execution secrets. A provider SDK that performs its own final request - cannot bypass Rust; only inert encoding/metadata facilities may be - reused here without another governed transport refinement. */ + doc /* Rust/Scheme is the target production core. Kubernetes observation + and protocol adapters default to Rust; Scheme/POO/gerbil-ascent owns + composition and inference. Retain an optional Go adapter only when + a required maintained Go SDK contributes concrete lifecycle behavior. + Choose this from upstream interfaces and implementation evidence, + not a mandatory local ecosystem comparison experiment. Go-native + external services can be reused through supported protocols. Do not + implement duplicate Rust/Go adapters for the same integration. + Ingress/cloud credentials remain separate from execution secrets. */ doc /* Informer caches, health probes and SDK observations are candidates, not authoritative Policy/history facts. Re-list/reconnect preserves original identities and unresolved intent; all final deciding joins - remain Rust-owned. Current Go code implements config/routing/RPC - recovery, not Kubernetes controllers or complete protocol discovery. - Target ecosystem integrations must earn their cost through measurable - adapter reuse and operator behavior; a pure forwarding layer provides - insufficient justification. No Go-versus-Rust speed claim follows. */ + remain Rust-owned. Current Go handles file syntax, typed transport, + immutable projection caching and RPC recovery, not Kubernetes + controllers or semantic routing. Development/reference functions + remain outside the deployed planning call path. This allocation + does not claim a Go-versus-Rust speedup or submillisecond acceptance. */ doc /* Existing provider responses support default Protobuf events and optional Arrow IPC batches over the same gRPC stream. This is not a Flight service or end-to-end zero-copy path. Schema, row/range binding, diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index f5dc9448..8a64dbdb 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -1 +1 @@ -[{"id":"ProviderAdmissionTurn","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let selected_admission"},{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn begin_driver_counters_follow_their_admission_grant"},{"file":"crates/ledger/src/persistence/driver_observer.rs","pattern":"fn observe_read"},{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct AdmissionRequest"},{"file":"crates/ledger/tests/unit/provider_admission_turn.rs","pattern":"fn queued_unaccepted_admission_preserves_old_frame_and_original_hold"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionTurnProperty"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionCommitRecovery"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderAdmissionTurn"},{"file":"crates/broker/src/provider/request.rs","pattern":"Stage::Tls"},{"file":"go/dev/provider_transport_phases_test.go","pattern":"func reportProviderTransport"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run eagerQueueBlocksOldFrameCounterexampleTest"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem queue_preserves_arbitrary_requirement","declaration":"Weaver.ProviderAdmissionTurn.queue_preserves_arbitrary_requirement"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem finite_queue_preserves_final_offer","declaration":"Weaver.ProviderAdmissionTurn.finite_queue_preserves_final_offer"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem open_writer_cannot_mutate","declaration":"Weaver.ProviderAdmissionTurn.open_writer_cannot_mutate"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem accepted_hard_intent_blocks","declaration":"Weaver.ProviderAdmissionTurn.accepted_hard_intent_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_outcome_blocks","declaration":"Weaver.ProviderAdmissionTurn.unknown_outcome_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem changed_image_blocks","declaration":"Weaver.ProviderAdmissionTurn.changed_image_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem queued_admission_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.queued_admission_preserves_spec_final_use"},{"file":"go/internal/controlplane/deployment.go","pattern":"if gateway.source == nil"},{"file":"go/dev/provider_control_bench_test.go","pattern":"func TestProviderGoControlMeasuredChain"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem runtime_catalog_requires_source","declaration":"Weaver.ProviderAdmissionTurn.runtime_catalog_requires_source"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_activation_blocks_source_handoff","declaration":"Weaver.ProviderAdmissionTurn.unknown_activation_blocks_source_handoff"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem bootstrap_source_close_preserves_actual","declaration":"Weaver.ProviderAdmissionTurn.bootstrap_source_close_preserves_actual"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run failedBootstrapCleanupDoesNotActivateIngressTest"},{"file":"go/dev/provider_admission_overlap_bench_test.go","pattern":"func BenchmarkProviderAdmissionOverlap"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn collect_buffered"},{"file":"go/dev/provider_control_bench_test.go","pattern":"image := serverBinary"},{"file":"go/dev/provider_fixture_test.go","pattern":"test-owned Go control image sha256"},{"file":"crates/ledger/src/persistence/scope_trace.rs","pattern":"pub\\(super\\) fn observe_release"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"observed_release_covers_lease_removal_without_retaining_a_grant"},{"file":"crates/ledger/src/persistence/driver_observer.rs","pattern":"pub\\(super\\) fn observe_commit"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"commit_io_observes_native_spans_after_unobserved_setup"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"maybe_prepared\\(c, PREPARE"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn review_program_reuse_reads_replacement_and_rejects_projection_loss"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn review_program_reuse_preserves_native_receipts_and_currentness"},{"file":"go/dev/provider_control_bench_test.go","pattern":"both arms use Go forwarding"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"valid_review!\\(\"CROSS JOIN\"\\)"},{"file":"crates/ledger/src/domains/view.rs","pattern":"require_view\\(persistence::maybe_prepared"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn manifest_programs_rebind_current_members_and_reject_divergence"}]},{"id":"ProviderReadCustody","witnesses":[{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn conflicts"},{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn acquire_origin"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let shared_reads"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn compatible_origins_share_reads_but_an_older_writer_blocks_younger_readers"},{"file":"crates/ledger/tests/unit/provider_read_custody.rs","pattern":"fn shared_reads_keep_distinct_origin_native_writes_concurrent"},{"file":"go/dev/provider_read_custody_test.go","pattern":"func TestProviderReadCustodyProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderReadCustody"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem arbitrary_policy_preserved","declaration":"Weaver.ProviderReadCustody.arbitrary_policy_preserved"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem finite_interleaving_preserves_policy","declaration":"Weaver.ProviderReadCustody.finite_interleaving_preserves_policy"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem overlapping_writes_conflict","declaration":"Weaver.ProviderReadCustody.overlapping_writes_conflict"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessRetainsWriterAndSameOriginBarriers"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_binding_blocks","declaration":"Weaver.ProviderReadCustody.changed_binding_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_shared_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_shared_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_origin_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_origin_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_owner_blocks","declaration":"Weaver.ProviderReadCustody.changed_owner_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem shared_writer_conflicts","declaration":"Weaver.ProviderReadCustody.shared_writer_conflicts"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem older_conflicting_writer_blocks","declaration":"Weaver.ProviderReadCustody.older_conflicting_writer_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem read_custody_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.read_custody_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderReadCustody.qnt","pattern":"run unsafeSharedMutationCounterexampleTest"}]},{"id":"ProviderLifecycleFootprint","witnesses":[{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct OriginLifecycle"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"enum Impact"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_lifecycle"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_provider_lifecycle"},{"file":"crates/ledger/tests/unit/provider_lifecycle.rs","pattern":"fn peer_lifecycle_preserves_complete_view_but_shared_admission_does_not"},{"file":"go/dev/provider_lifecycle_test.go","pattern":"func TestProviderLifecycleCommitRecovery"},{"file":"crates/ledger/tests/unit/authority_footprint.rs","pattern":"fn local_commit_retires_whole_and_own_but_preserves_peer"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem origin_commit_retires_whole_reader","declaration":"Weaver.ProviderLifecycleFootprint.origin_commit_retires_whole_reader"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem arbitrary_cedar_predicate_preserved","declaration":"Weaver.ProviderLifecycleFootprint.arbitrary_cedar_predicate_preserved"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem shared_admission_requires_shared_invalidation","declaration":"Weaver.ProviderLifecycleFootprint.shared_admission_requires_shared_invalidation"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem peer_lifecycle_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.peer_lifecycle_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderLifecycleFootprint.qnt","pattern":"run unsafeNarrowAdmissionCounterexampleTest"}]},{"id":"ProviderSnapshotPublication","witnesses":[{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn release_provider_group_for_delivery"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"struct Snapshot"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn share_qualification"},{"file":"crates/ledger/src/provider.rs","pattern":"fn begin_snapshot_validation"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn take_refresh"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem pending_close_defers_renewal","declaration":"Weaver.ProviderSnapshotPublication.pending_close_defers_renewal"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn a_request_arriving_during_qualification_cannot_trigger_a_second_native_read"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn one_snapshot_requalification_covers_every_exact_frame"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn post_staging_native_failure_cannot_publish_a_partial_snapshot"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn queue_snapshot"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func awaitDeliveryCuts"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem final_use_joins_snapshot","declaration":"Weaver.ProviderSnapshotPublication.final_use_joins_snapshot"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem published_snapshot_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.published_snapshot_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSnapshotPublication.qnt","pattern":"run ungatedArcLoadIsCounterexampleTest"}]},{"id":"ProviderSemanticProgress","witnesses":[{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct RangeProgress"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_progress"},{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn stage_group"},{"file":"crates/ledger/tests/unit/provider_delivery.rs","pattern":"fn exact_range_progress_preserves_queued_authorization"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderSemanticProgressProperty"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_released_binding","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_released_binding"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_image","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_image"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem range_progress_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.range_progress_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSemanticProgress.qnt","pattern":"run hiddenSemanticEditIsCounterexampleTest"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"}]},{"id":"ProviderDeliveryJoin","witnesses":[{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn bounded_trace_retains_every_requalification"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeTraceChunksPreserveAllRecords"},{"file":"crates/ledger/tests/unit/persistence_owner.rs","pattern":"fn descriptor_copy_is_not_a_retained_execution_owner"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem retained_role_blocks_custody_retirement","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.retained_role_blocks_custody_retirement"},{"file":"dev/proofs/quint/ProviderDeliveryPipeline.qnt","pattern":"run threeInertFramesNeedNoStopAndWaitTest"},{"file":"crates/server/src/grpc_delivery_producer.rs","pattern":"fn reserve_guarded"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"pub fn poll"},{"file":"crates/server/src/grpc_delivery.rs","pattern":"impl Stream for ResponseStream"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryCommitAndReceiverRecovery"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryReceiverProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem orphaned_witness_cannot_activate","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.orphaned_witness_cannot_activate"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem acknowledged_delivery_preserves_same_actual_view","declaration":"Weaver.DomainMigrationComposition.acknowledged_delivery_preserves_same_actual_view"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run committedWithoutAcknowledgmentCannotAcceptTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run rollbackCannotEraseIndependentWitnessTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run oldOwnerCannotRequalifyAfterRestartTest"}]},{"id":"ProviderEgressPromotion","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_close_receipt_cannot_resolve_new_intent","declaration":"Weaver.ProviderEgressWindow.Promotion.old_close_receipt_cannot_resolve_new_intent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem expired_clock_blocks_receiver","declaration":"Weaver.ProviderEgressWindow.Promotion.expired_clock_blocks_receiver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem every_effect_writer_needs_mediation","declaration":"Weaver.ProviderEgressWindow.Promotion.every_effect_writer_needs_mediation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem other_writer_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.other_writer_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem uncertain_effect_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.uncertain_effect_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem unchanged_database_does_not_revalidate_old_read","declaration":"Weaver.ProviderEgressWindow.Promotion.unchanged_database_does_not_revalidate_old_read"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem witness_ahead_blocks_old_image","declaration":"Weaver.ProviderEgressWindow.Promotion.witness_ahead_blocks_old_image"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem only_current_owner_can_deliver","declaration":"Weaver.ProviderEgressWindow.Promotion.only_current_owner_can_deliver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_queued_frame_cannot_follow_replacement","declaration":"Weaver.ProviderEgressWindow.Promotion.old_queued_frame_cannot_follow_replacement"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem delivered_frame_cannot_be_delivered_twice","declaration":"Weaver.ProviderEgressWindow.Promotion.delivered_frame_cannot_be_delivered_twice"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem receiver_promotion_refines_interval_admission","declaration":"Weaver.ProviderEgressWindow.Promotion.receiver_promotion_refines_interval_admission"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run firstCommitCannotDeliverAnotherPendingWriterTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run independentWitnessBeforeDatabaseBlocksDeliveryTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run oldWorkerDeliveryCounterexampleTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run allWriterClassesUseTheSameCutTest"}]},{"id":"BoundedProviderEgressWindow","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem any_accepted_trace_keeps_disjoint_prefix","declaration":"Weaver.ProviderEgressWindow.any_accepted_trace_keeps_disjoint_prefix"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem loss_and_restart_close_old_window","declaration":"Weaver.ProviderEgressWindow.loss_and_restart_close_old_window"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem matching_image_does_not_reopen_old_cut","declaration":"Weaver.ProviderEgressWindow.matching_image_does_not_reopen_old_cut"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem connected_roots_cannot_use_distinct_lanes","declaration":"Weaver.ProviderEgressWindow.connected_roots_cannot_use_distinct_lanes"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem admitted_four_turn_envelope","declaration":"Weaver.ProviderEgressWindow.admitted_four_turn_envelope"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem settlement_is_idempotent","declaration":"Weaver.ProviderEgressWindow.settlement_is_idempotent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem holder_stage_overlap_cannot_exceed_ticket_wait","declaration":"Weaver.ProviderEgressWindow.holder_stage_overlap_cannot_exceed_ticket_wait"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run coherentStoreRollbackActuallyDuplicatesOfferTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run pendingRevocationStopsActualOfferTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run lostBurnAckSealsOriginalTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run rehydratingOldWindowActuallyDuplicatesOfferTest"}]},{"id":"OriginalFloorDecision","witnesses":[{"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run lostCommitResponseResolvesSameOperationTest"},{"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run unknownCommitCannotActivateTest"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"}]},{"id":"ProviderCurrentnessPerformance","witnesses":[{"file":"go/dev/provider_domain_program_test.go","pattern":"func BenchmarkProviderDomainProgram"},{"file":"go/dev/provider_domain_tail_test.go","pattern":"func BenchmarkProviderSharedLongTail"},{"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem prepared_domain_program_preserves_live_decision"}]},{"id":"ProviderSchedulerOwnership","witnesses":[{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn waiting_multi_root_range_precedes_younger_conflicts"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessCountsArrivalGrantInversions"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"}]},{"id":"SenderBoundProviderOAuth","witnesses":[{"file":"go/dev/provider_oauth_relay_test.go","pattern":"func TestProviderOAuthTwoHopRevocationAndRecovery"},{"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem retained_root_revocation_blocks_child"}]},{"id":"TransportAndExecutionLatencySeparation","witnesses":[{"file":"go/dev/provider_scheduler_bench_test.go","pattern":"func BenchmarkProviderScheduledEncoding"},{"file":"go/dev/provider_range_group_test.go","pattern":"func BenchmarkProviderRangePreparationGroup"}]},{"id":"TelemetryNoninterference","witnesses":[{"file":"crates/telemetry/tests/unit/metrics.rs","pattern":"fn observations_are_monotone_and_restart_local"},{"file":"go/internal/telemetry/metrics_test.go","pattern":"func TestPropertyCountersAreBoundedMonotoneAndRestartLocal"},{"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderTelemetryCannotRefundOrRedispatchUnknownSend"},{"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderControlTelemetryObservesBothServices"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryReadsAndRestartCannotRefundTest"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryAsRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem arbitrary_observations_keep_execution","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.arbitrary_observations_keep_execution"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem telemetry_reset_keeps_unknown_hold","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.telemetry_reset_keeps_unknown_hold"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem observations_preserve_effect_safety","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.observations_preserve_effect_safety"}]},{"id":"SharedDomainAuthority","witnesses":[{"file":"crates/ledger/src/domains/binding.rs","pattern":"fn bind"},{"file":"crates/ledger/src/domains/migration.rs","pattern":"fn migrate_execution_domains"},{"file":"crates/ledger/src/domains/view.rs","pattern":"fn require_stamp"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_cross_family_shared_history_serializes_final_use"},{"file":"crates/ledger/tests/unit/shared_domains.rs","pattern":"fn finite_families_never_split_a_shared_cap"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsProperty"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsCedarReadsCurrentAuthority"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run overCapacityUnionKeepsOriginalDecisionTest"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run domainSplitCounterexampleTest"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_cannot_split_any_shared_pair","declaration":"Weaver.SharedDomains.union_cannot_split_any_shared_pair"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem admitted_union_conserves_capacity","declaration":"Weaver.SharedDomains.admitted_union_conserves_capacity"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_retains_history","declaration":"Weaver.SharedDomains.union_retains_history"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_fences_both_old_permits","declaration":"Weaver.SharedDomains.union_fences_both_old_permits"}]},{"id":"TursoMvccCustody","witnesses":[{"file":"crates/ledger/src/persistence/owner.rs","pattern":"fn open"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_family"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_final_domains_overlap_including_new_executor_connection"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_same_budget_and_history_family_keeps_final_order"},{"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn mvcc_effect_before_failed_observation_never_releases_or_replays"},{"file":"go/dev/provider_final_domains_test.go","pattern":"func TestProviderMVCCIndependentFinalSendsAndRevocation"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run postSendCommitConflictKeepsPhysicalEffectTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem shared_final_readers_keep_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.shared_final_readers_keep_current_fence"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem failed_observation_after_send_keeps_spent_hold","declaration":"Weaver.RuntimeAdmission.MVCC.failed_observation_after_send_keeps_spent_hold"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_disjoint_admissions_have_overlapping_turso_writes"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_process_custody_refuses_a_second_process"},{"file":"crates/ledger/tests/unit/mvcc.rs","pattern":"fn mvcc_concurrent_family_budget_has_one_original_reservation"},{"file":"go/dev/provider_mvcc_test.go","pattern":"func TestProviderMVCCExecutionBoundary"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run snapshotWriteSkewCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem disjoint_domain_commits_commute","declaration":"Weaver.RuntimeAdmission.MVCC.disjoint_domain_commits_commute"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem family_step_preserves_all_budgets","declaration":"Weaver.RuntimeAdmission.MVCC.family_step_preserves_all_budgets"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exclusive_final_use_keeps_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.exclusive_final_use_keeps_current_fence"}]},{"id":"ArchitectureViewGrammar","witnesses":[{"file":"dev/sysml/ArchitectureViews.sysml","pattern":"view zeroTrust"},{"file":"go/internal/devrunner/model_views.go","pattern":"func CaptureModelViews"},{"file":"go/internal/devrunner/model_views_test.go","pattern":"func TestModelViewsUseActualSDK"},{"file":"go/internal/devrunner/model_views_test.go","pattern":"func FuzzModelViewCaptureTracksSource"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestArchitectureDiagramsUseDifferentViewProfiles"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramProfilesAreExplicitAndLocal"},{"file":"go/internal/devrunner/diagrams.go","pattern":"func RenderDiagrams"},{"file":"dev/d2/src/render.ts","pattern":"composeFigure[(]input,composer[)]"},{"file":"dev/d2/test/model-view.test.ts","pattern":"public Library binds SDK SysML identity"},{"file":"dev/d2/src/objects.ts","pattern":"export const composeObjects"},{"file":"dev/d2/test/model-view.test.ts","pattern":"missing captured views and unsupported source ports refuse"},{"file":"dev/d2/test/vector-readability.test.ts","pattern":"Preserve the original ordered-sequence line-overlap check"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramEvidenceRejectsLostNodesAndRelationships"}]},{"id":"ProductionAssetBoundary","witnesses":[{"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRuntimeAssetBoundary"},{"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRejectsRuntimeDevReferences"}]},{"id":"OriginalTaskBinding","witnesses":[{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem first_birth_seal_cannot_broaden","declaration":"Weaver.TaskOrigin.first_birth_seal_cannot_broaden"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem sealed_birth_cannot_be_replaced","declaration":"Weaver.TaskOrigin.sealed_birth_cannot_be_replaced"},{"file":"crates/ledger/tests/unit/task_publication.rs","pattern":"fn lost_birth_projection_cannot_authorize_or_be_silently_repaired"},{"file":"crates/ledger/src/task_origins.rs","pattern":"fn register_original_task"},{"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn source_rotation_cannot_reallocate_task_and_lost_reply_recovers_original_commit"},{"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn trusted_issuer_relabeling_every_identity_is_outside_local_deduplication"},{"file":"go/dev/provider_task_origin_test.go","pattern":"func TestProviderOriginalTaskOriginLostReplySourceSwitchAndRestart"},{"file":"dev/proofs/quint/TaskOrigin.qnt","pattern":"run issuerTrustCounterexampleTest"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem assigned_task_cannot_rebind","declaration":"Weaver.TaskOrigin.assigned_task_cannot_rebind"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem source_epoch_does_not_change_task_scope","declaration":"Weaver.TaskOrigin.source_epoch_does_not_change_task_scope"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem stale_source_command_cannot_commit","declaration":"Weaver.TaskOrigin.stale_source_command_cannot_commit"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn original_task_body_and_profile_cannot_be_replaced"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalBindingTest"}]},{"id":"SharedBudget","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn finite_manifest_siblings_cannot_mask_a_missing_original_member"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn maximum_manifest_cannot_replace_a_lost_sibling_after_restart"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityRecoveryGuardTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityFinalUseGuardTest"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn selected_message_binding_must_match_its_committed_digest_at_final_write"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn concurrent_message_admission_preserves_both_manifest_members"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exhausted_budget_cannot_publish_a_manifest_member_without_its_row"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem manifest_bound_runtime_step"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn surviving_stream_message_cannot_hide_a_lost_unknown_reservation"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exact_message_manifest_guards_recovery_and_existing_write_handles"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialMessageLossCounterexampleTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run digestSubstitutionFinalUseGuardTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exact_manifest_admission_covers_original_exposure"},{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn balanced_provider_projection_never_funds_a_different_original_plan"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_stream_projection_never_funds_the_next_logical_message"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem admission_covers_original_exposure"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run balancedProjectionCounterexampleTest"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_shrink_never_admits_a_different_node"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn require_family"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn mixed_request_and_stream_exposure_cannot_be_checked_in_separate_domains"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem orphaned_hold_blocks_new_admission"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run separateEffectDomainsCounterexampleTest"},{"file":"crates/ledger/tests/unit/properties.rs","pattern":"fn arbitrary_replays_restarts_and_consumption_preserve_claims"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run sharedBudgetTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalCostBoundTest"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn authored_ceiling_cannot_underreserve_the_original_wire_cost"}]},{"id":"ZeroTrustContractRefinement","witnesses":[{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem final_use_on_committed_union","declaration":"Weaver.DomainMigrationComposition.final_use_on_committed_union"},{"file":"crates/ledger/src/provider.rs","pattern":"actual.stamp != p.domains"},{"file":"crates/ledger/tests/unit/provider_domains.rs","pattern":"fn same_actual_domains_fence_original_provider_capability"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"actual migration committed; response discarded"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run committedUnionLostReplyKeepsBothOriginalsTest"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem gateway_final_use_preserves_domain_contract","declaration":"Weaver.DomainMigrationComposition.gateway_final_use_preserves_domain_contract"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem head_cas_preserves_original_obligations","declaration":"Weaver.DomainMigrationComposition.head_cas_preserves_original_obligations"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem overbooked_actual_view_cannot_supply_final_run","declaration":"Weaver.DomainMigrationComposition.overbooked_actual_view_cannot_supply_final_run"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureResearchModels"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainCommitRestartPositiveTest"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainRevocationKeepsOriginalExposureTest"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run detachedLogicalLedgerCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget","declaration":"Weaver.ProviderRpc.shared_exposure_keeps_original_budget"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework","declaration":"Weaver.ZeroTrustEnrichment.gateway_specialization_retains_generic_framework"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway","declaration":"Weaver.ZeroTrustEnrichment.retained_parent_and_selected_object_reach_gateway"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption","declaration":"Weaver.ZeroTrustEnrichment.usage_control_keeps_current_consumption"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use","declaration":"Weaver.ZeroTrustEnrichment.pending_policy_blocks_ongoing_use"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"}]},{"id":"ConsumeBeforeSend","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn final_write_requires_exact_durable_range"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run stateOnlyRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem inexact_cannot_refine_execution","declaration":"Weaver.StreamingExecution.RangeReceipt.inexact_cannot_refine_execution"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn crash_after_consumption_never_reopens_or_refunds"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run consumeBeforeSendTest"}]},{"id":"CurrentFinalGuard","witnesses":[{"file":"crates/ledger/tests/unit/serialization.rs","pattern":"fn effective_publication_cannot_overtake_the_locked_send_boundary"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run stalePermitTest"}]},{"id":"UnknownRetainsHold","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restart_never_backfills_request_claims_from_operations"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn orphaned_request_claim_cannot_admit_a_replacement_operation"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn next_stream_message_cannot_recreate_a_lost_node_claim"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn lost_message_projection_cannot_recycle_original_unknown_hold"},{"file":"crates/broker/tests/unit/https_transport.rs","pattern":"fn partial_transport_failure_is_unknown_and_never_retried"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run unknownRefundCounterexampleTest"}]},{"id":"NoImplicitRetry","witnesses":[{"file":"crates/ledger/tests/unit/concurrency.rs","pattern":"fn concurrent_consumers_invoke_once"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run duplicateRetryCounterexampleTest"}]},{"id":"DevelopmentPolicy","witnesses":[{"file":"crates/contracts/src/lib.rs","pattern":"mode = deny"}]},{"id":"MessageScopedAuthority","witnesses":[{"file":"crates/ledger/tests/unit/stream_properties.rs","pattern":"fn unknown_range_after_restart_blocks_new_nonce_and_authority"},{"file":"crates/policy/tests/unit/stream_policy.rs","pattern":"fn specification_derived_policy_is_typed_and_constrains_actual_range_facts"}]},{"id":"RangeFinalGuard","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn effective_revocation_stops_actual_next_range_and_prefix_reconnect"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run revokedBetweenBurnAndWriteTest"}]},{"id":"UnknownPrefixRecovery","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn rust_partial_write_freezes_tail_and_never_refunds"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unknown_cannot_resume"}]},{"id":"PrivateBufferCustody","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn tls_flush_cannot_release_a_tail_after_effective_revocation"},{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn recovered_old_worker_socket_cannot_use_new_custody"}]},{"id":"BoundedPerformanceWork","witnesses":[{"file":"crates/policy/tests/unit/cache_storage.rs","pattern":"fn compiled_storage_caps_slots_and_exact_hits_do_not_allocate_new_entries"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem bounded_range_copy_work"}]},{"id":"TrackedWriterDrain","witnesses":[{"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"async fn detached_executor_writer_keeps_slot_until_drain_acknowledges_completion"},{"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"fn arbitrary_disconnect_shutdown_and_drain_schedules_keep_executor_custody"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"},{"file":"dev/proofs/quint/RuntimeLifecycle.qnt","pattern":"run prematureAckCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem execution_and_drain_composition"}]},{"id":"GrpcCallerBinding","witnesses":[{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderRPCIdentityAndCancellation"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_name_is_not_key_authority"}]},{"id":"TransportSetupIsolation","witnesses":[{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run reconnectCannotUncancelOriginalStreamTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem crash_cannot_recreate_unknown_release"},{"file":"go/internal/gatewayclient/connection_test.go","pattern":"func TestConnectionSetupRetainsCallerDeadlineAndCancellation"},{"file":"go/dev/provider_startup_test.go","pattern":"func TestProviderFreshImageAndRestartStartup"},{"file":"dev/proofs/quint/GatewayComposition.qnt","pattern":"run reconnectRetainsSpentRootTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem gateway_run_preserves_original_execution_and_custody"}]},{"id":"CommittedProviderRouting","witnesses":[{"file":"go/internal/routing/provider_test.go","pattern":"func TestProviderRoutingCannotRewriteOriginalContract"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderGRPCStreamingAndArrowOption"}]},{"id":"UnambiguousProviderRequestBounds","witnesses":[{"file":"crates/contracts/tests/unit/provider_bounds.rs","pattern":"fn exactly_one_provider_cap_is_bounded"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn rejected_competing_caps_leave_no_claim_or_hold_after_restart"},{"file":"go/internal/routing/provider_test.go","pattern":"func FuzzProviderRequestBounds"},{"file":"go/dev/provider_bounds_test.go","pattern":"func TestProviderCompetingCapsCannotReachDispatch"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preferredCapPrecedenceCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem request_bounds_and_affine_execution_composition"}]},{"id":"SourceProviderProfileBinding","witnesses":[{"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceProfileAndCedarBindFinalSendAcrossRestart"},{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn concurrent_profile_registrations_cannot_fork_one_identity"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_task_registration_cannot_rebind"}]},{"id":"ClosedProviderRequestSchema","witnesses":[{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn provider_profile_cannot_fall_back_to_untyped_request_or_raw_stream"},{"file":"crates/contracts/tests/unit/provider_profiles.rs","pattern":"fn shared_closed_request_corpus_has_the_declared_semantics"},{"file":"go/api/v1/provider_profile_test.go","pattern":"func TestProviderProfileSharedClosedRequestCorpus"},{"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceCommittedExtensionsCannotBypassProfile"},{"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingSchemaGuardCounterexampleTest"}]},{"id":"RecoverableProfileFloor","witnesses":[{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn original_task_floor_prevents_missing_registry_from_rebinding_identity"},{"file":"crates/ledger/tests/unit/profile_floor_plan.rs","pattern":"fn semantic_floor_uses_two_composite_range_seeks"},{"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingFloorCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem missing_registry_cannot_erase_original_floor"}]},{"id":"CanonicalProfileConfiguration","witnesses":[{"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileJSONAndYAMLHaveOneCanonicalCommitment"},{"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileRejectsAmbiguousConfiguration"},{"file":"go/internal/config/provider_profile_test.go","pattern":"func FuzzProviderProfileConfiguration"}]},{"id":"AffineProviderAttempt","witnesses":[{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn arbitrary_provider_replays_restarts_and_release_batches_keep_original_claim"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run sdkRetryCannotConsumeAgainTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem consumed_unknown_retains_original_hold"}]},{"id":"EncodingAuthorityEquivalence","witnesses":[{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPolicyChangeDuringCapacityWait"},{"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowWireBoundDoesNotBoundDecodedText"},{"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowInvalidLaterRowReturnsNoPartialBatch"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preparedEncodingCannotSwitchTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem final_guard_checks_actual_owner_rows"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderArrowChecksEveryRow"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem arrow_cannot_weaken_row_authority"}]},{"id":"ProviderUnknownRetention","witnesses":[{"file":"crates/broker/src/provider/runtime.rs","pattern":"fn open_guarded"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn commit_provider"},{"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn failed_callback_never_enters_final_commit_and_retains_original_exposure"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn turso_applied_commit_without_ack_poison_is_not_reusable"},{"file":"go/dev/provider_commit_fault_test.go","pattern":"func TestProviderSealedTursoCommitRecovery"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run appliedLostAckPoisonsOldWorkerTest"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run durableCommitThenFenceThenLateAckTest"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run committingFailedCallbackCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem failed_callback_cannot_enter_commit","declaration":"Weaver.ProviderRpc.RequestWriteFence.failed_callback_cannot_enter_commit"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem applied_commit_without_ack_does_not_activate","declaration":"Weaver.ProviderRpc.RequestWriteFence.applied_commit_without_ack_does_not_activate"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem late_commit_ack_cannot_bypass_new_fence","declaration":"Weaver.ProviderRpc.RequestWriteFence.late_commit_ack_cannot_bypass_new_fence"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider[(]"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run individualHoldOnlyCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_provider_exposure_cannot_be_released"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem provider_exposure_strengthens_continuing_zero_trust"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerEnqueueBeforeCommitCrashCannotReplayPendingRange"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerCancellationAndReconnectRetainHistory"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run enqueueThenLostCommitRetainsUnknownTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem transport_history_preserves_original_hold"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderPartialRequestAndRestartRetainUnknownClaim"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run unknownRefundCounterexampleTest"}]},{"id":"ReservedAuthorityAdmission","witnesses":[{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run recoveryDoesNotRefreshUsageEvidenceTest"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn final_release_keeps_current_guard_and_unknown_commit_in_one_transaction"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run childOnlyPredicateDropsParentCounterexampleTest"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem continuing_uses_current_state_and_original_consumption"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem capacity_cannot_rebase_changed_floor"},{"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn waiting_capacity_does_not_hold_sql_or_authorize_after_publication"},{"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn pending_range_history_created_during_capacity_wait_cannot_be_replayed"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPositiveControlCompletesAfterCapacityReturns"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run returnedCapacityDoesNotAuthorizeStaleReleaseTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_backpressure_composition"},{"file":"crates/server/tests/unit/admission.rs","pattern":"async fn saturated_detached_execution_preserves_publication_and_observation_custody"},{"file":"go/dev/provider_capacity_test.go","pattern":"func TestProviderSaturatedExecutionPreservesRevocationAndObservation"},{"file":"dev/proofs/quint/AuthorityAdmission.qnt","pattern":"run sharedLaneStarvationCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_admission_composition"}]},{"id":"ConnectionCustodyBound","witnesses":[{"file":"crates/server/tests/unit/connections.rs","pattern":"async fn tcp_socket_owns_capacity_until_destruction_and_preserves_io_and_peer_identity"},{"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderPreTLSConnectionsAreBoundedAndExpire"},{"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderShutdownDestroysStalledTLSBeforeAcknowledgingExit"},{"file":"dev/proofs/quint/ConnectionAdmission.qnt","pattern":"run earlyReturnCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem provider_and_connection_composition"}]},{"id":"SourceIngressBinding","witnesses":[{"file":"go/dev/provider_source_test.go","pattern":"func TestProviderSourceIngressBindsCertificateCredentialAndMethod"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledCatalogRequiresExactSourceEpoch"},{"file":"go/dev/provider_capacity_test.go","pattern":"full operation ingress blocked new source session"},{"file":"crates/server/tests/unit/grpc_ingress.rs","pattern":"async fn aliased_or_empty_source_identity_is_rejected_before_serving"},{"file":"dev/proofs/quint/SourceIngress.qnt","pattern":"run forwardedCredentialCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem ingress_step_preserves_independent_custody"}]},{"id":"DurablePublicationDecision","witnesses":[{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn outcome_insert_failure_rolls_back_policy_schema_and_result_together"},{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn concurrent_same_identity_commits_only_one_revision"},{"file":"go/dev/publication_recovery_test.go","pattern":"func TestProviderPublicationLostReplyRestartAndHistoricalDecision"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run deletedOutcomeCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_and_provider_accounting_composition"}]},{"id":"OwnedSourceConnection","witnesses":[{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn cancelled_priority_wait_does_not_send_a_source_command"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn source_rotation_commits_before_queued_catalog_reads_recheck_identity"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run newCommandCanPrecedeOldReplyTest"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn completed_source_acknowledgment_returns_command_capacity"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run replyBeforeCapacityCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem command_ack_requires_returned_capacity"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn reused_source_connection_observes_other_writer_and_preserves_historical_result"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn disconnected_source_caller_keeps_capacity_until_original_sql_work_finishes"},{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn connection_reuse_rejects_an_unresolved_explicit_transaction"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run swallowedCloseErrorCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem owned_worker_and_publication_composition"}]},{"id":"FinalInvocationCancellation","witnesses":[{"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn cancellation_during_sql_wait_blocks_transport_and_keeps_spent_claim"},{"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn uncancelled_control_reaches_real_https_transport_once"},{"file":"dev/proofs/quint/DispatchCancellation.qnt","pattern":"run skippedRecheckCounterexampleTest"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run missingFinalCancellationCheckCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem cancellation_and_original_hold_composition"}]},{"id":"OriginalReleaseCapability","witnesses":[{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityBudgetHistoryChangeInvalidatesReleaseReadTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_plan_survives_batching"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn equal_batch_digests_cannot_transfer_release_between_original_nodes"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn release_encoding_cannot_change_after_preparation"},{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn release_capabilities_bind_plan_encoding_and_restart_session"},{"file":"dev/proofs/quint/ReleaseBinding.qnt","pattern":"run crossPlanCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem release_binding_and_execution_composition"}]},{"id":"SpecificSourceContracts","witnesses":[{"file":"crates/server/src/single_provider.rs","pattern":"bound: BoundSource"},{"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run governanceCannotReplaceGovernorTest"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run missingGovernorCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_cannot_replace_governor","declaration":"Weaver.PolicyBridge.governance_cannot_replace_governor"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governor_cannot_replace_governance","declaration":"Weaver.PolicyBridge.governor_cannot_replace_governance"},{"file":"scheme/governance/types.ss","pattern":"def GovernanceScopeContract\\s+\\(\\.cc \\(Record"},{"file":"scheme/gateway/contracts.ss","pattern":"def GatewayArtifact"},{"file":"t/gateway-contracts-test.ss","pattern":"def gateway-contracts-test"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityUncompiledSourceCannotRegisterTest"},{"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"},{"file":"t/gateway-contracts-test.ss","pattern":"module scopes use native POO Types and refuse evidence protocol hooks"}]},{"id":"GovernancePolicyProjection","witnesses":[{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrApprovalCannotOutliveExposureProjectionRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrCommitReplyLossAndReplayCannotMintAnotherTicketTest"},{"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn candidate_only_replay_cannot_register_for_a_real_predecessor"},{"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn replay_cannot_substitute_the_captured_predecessor"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem matched_replay_preserves_both_images"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run exactReplayPairSurvivesLostReplyAndCommitsOriginalTest"},{"file":"crates/ledger/tests/unit/source_authority.rs","pattern":"fn source_handoffs_and_old_workers_preserve_original_unknown_budget"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn consistent_whole_store_rollback_remains_a_local_authority_counterexample"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn residual_policy_schema_cannot_be_treated_as_an_empty_store_after_restart"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn first_enrollment_uses_all_durable_tables_without_temporary_aliases"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn committed_writer_before_enrollment_cannot_be_hidden_by_an_old_empty_read"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn callback_failure_after_enrollment_does_not_allow_a_replacement_identity"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem complete_catalog_refusal_preserves_original_state"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem source_enrollment_refusal_preserves_unknown_accounting"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run omittedProjectionEnrollmentCounterexampleTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateCatalogCommitMustReachDecidingGuardTest"},{"file":"go/dev/provider_source_authority_test.go","pattern":"func TestProviderPersistentSourceRotationLostReplyFencesExistingWorkerAndReissuedKey"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem retired_source_key_cannot_become_fresh"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_preserves_source_key_uniqueness"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run burnWithoutRetainedConfirmationCannotAdmitTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run cachedQualificationCannotAdmitWithZeroHeldProjectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run repairedProjectionDoesNotRecreateLostSendHandleTest"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_prefix_failure_atomically_rolls_back_burn"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_prefix_without_burn_projection_cannot_repeat_admission"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_burn_fenced_before_callback_keeps_original_unknown_exposure"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run confirmedRevocationAndHandoffRejectConsistentSourceRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run retainedRegistrationCannotReplaceAfterSnapshotRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run sameLengthArtifactReplacementCannotConfirmRetainedPrefixTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run wholeRetainedRootRollbackCanReplayQualificationCounterexampleTest"},{"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn identical_prefix_after_whole_store_restore_can_replay_dispatch_counterexample"},{"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn prefix_qualification_does_not_reconstruct_rolled_back_budget_counterexample"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run copiedRowsWithoutRecoveryQualificationCannotPublishTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateQualificationAfterRegistryAppendIsRefusedTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run recoveredNewOwnerRequalifiesOriginalArtifactTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run consistentAuthorityRollbackCanReplaySavedQualificationCounterexampleTest"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn stale_registry_read_and_reopened_worker_preserve_unknown_provider_exposure"},{"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn text_rendering_cannot_silently_replace_original_policy_ids"},{"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn actual_spec_replay_registration_persists_before_original_final_cas"},{"file":"go/dev/provider_policy_json_test.go","pattern":"func TestProviderControlNamedPolicyJSONRevocationAndRestart"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem finite_replay_does_not_certify_no_gain"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run observerRestartCannotRestoreReadCapabilityTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateRegistryReceiptAfterHandoffIsHistoricalTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run independentSnapshotRollbackResurrectsCredentialCounterexampleTest"},{"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn losing_verifier_metadata_cannot_downgrade_a_committed_served_profile"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem missing_verifier_cannot_downgrade"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run missingVerifierCannotDowngradeAfterRestartTest"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureComposition"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureRejectsFalseArithmetic"},{"file":"dev/proofs/cedar/SpecProofClosure.lean","pattern":"def proveClosedArithmetic"},{"file":"prod/policies/provider/ProviderReview.lean","pattern":"def entry"},{"file":"go/internal/specreview/producer.go","pattern":"Issue"},{"file":"crates/policy/src/qualified_delta.rs","pattern":"pub fn verify_qualified_delta"},{"file":"go/dev/provider_spec_review_test.go","pattern":"func TestProviderRealSPECReviewRevocationLostRepliesAndRestart"},{"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn historical_signature_only_nogain_is_not_semantic_qualification"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run signatureOnlyGainCounterexampleTest"},{"file":"dev/proofs/cedar/QualifiedReview.lean","pattern":"theorem qualified_execution_and_recovery_preserve_original","declaration":"Weaver.QualifiedReview.qualified_execution_and_recovery_preserve_original"},{"file":"crates/ledger/src/delta_registration.rs","pattern":"fn require_current"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"fn require"},{"file":"go/dev/provider_review_test.go","pattern":"func TestProviderReviewedPublicationLostRepliesAndRestart"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem reviewed_commit_composes_with_original_recovery"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run producerSignatureCannotReplaceQualificationTest"},{"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn consistent_snapshot_rollback_can_replace_local_registered_artifact_counterexample"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceLateCommitReplyAfterRotationRemainsHistorical"},{"file":"crates/ledger/tests/unit/publication_review.rs","pattern":"fn reviewed_prefixes_match_an_independent_model"},{"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn stage_review_requirement_and_legacy_final_cas_have_one_serial_order"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_registration_recovery_composes_without_releasing_unknown"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run latchedReviewCannotUseLegacyPublicationTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run configurationImageCannotErasePersistentRevocationTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registryAppendBetweenReadAndCASRequiresRejoinTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRollbackLostReplyRetainsUnknownConsumption"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem registrar_binding_reaches_final_cas"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run revocationBetweenValidationAndFinalCASTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run delayedIssuanceDecisionCannotReactivateOldEpochTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateRotationRecoversLostReplyAndPending"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateConfigRollbackReacceptsOldKeyCounterexample"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_recovery_keeps_original_constraints"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem durable_review_binding_survives_final_cas"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registrationLostReplyCannotPublishUnrecoveredProjectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run oldRegistrarCannotPublishAlreadyRegisteredArtifactTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderStagingLostReplyRetainsConcurrentPendingAcrossRestart"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRoleCredentialIsNotRegistrarIncarnationEvidence"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem reviewed_publication_keeps_recovery_contract"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run substitutedArtifactGetsOriginalRejectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run crossStoreReviewRollbackCounterexampleTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderPendingCommandSubstitutionAndHistoricalRecovery"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn typed_publication_does_not_yet_require_delta_evidence"},{"file":"scheme/policy/func.ss","pattern":"project-policy profile"},{"file":"scheme/policy/assets.ss","pattern":"read-policy-assets profile"},{"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"}]},{"id":"CompiledSourceStartup","witnesses":[{"file":"scheme/gateway/compiled.ss","pattern":"weaver_governance_ready_v1"},{"file":"crates/governance-build/src/application.rs","pattern":"pub fn approved"},{"file":"build.ss","pattern":"approved application root mismatch"},{"file":"crates/governance/src/program/compiler.rs","pattern":"pub fn initialize"},{"file":"crates/governance/src/catalog/configuration.rs","pattern":"pub fn from_configuration"},{"file":"crates/server/src/governance_deployment.rs","pattern":"async fn start_compiler"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRequiresRealInstallation"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"metadataAsInitializationCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem graph_membership_cannot_replace_initialization"}]},{"id":"GovernorSourceHandoff","witnesses":[{"file":"scheme/gateway/types.ss","pattern":"def GatewayProgram"},{"file":"scheme/gateway/program.ss","pattern":"def \\(make-gateway-program"},{"file":"t/gateway-source-test.ss","pattern":"program installation and close follow an irreversible lifecycle"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"caughtReentryPoisonsOuterDeliveryTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem program_result_composes_with_registered_original"},{"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"},{"file":"go/internal/controlplane/deployment_source_test.go","pattern":"func FuzzDeploymentSourceHasOneOwner"},{"file":"go/internal/controlplane/producer_deployment_test.go","pattern":"func exerciseProducerDeployment"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"deploymentCannotFallBackToFileTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem producer_deployment_keeps_registered_original"},{"file":"crates/server/src/grpc.rs","pattern":"async fn compile_source"},{"file":"go/internal/controlplane/source_compile.go","pattern":"func BootstrapProducer"},{"file":"go/internal/controlplane/approved_source_rpc_test.go","pattern":"func TestApprovedSourceMTLSBootstrap"},{"file":"go/internal/config/freeze_test.go","pattern":"func FuzzFrozenSourceDoesNotFollowCallerMutation"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem compilation_reply_keeps_registered_original"},{"file":"crates/governance/src/catalog/admission.rs","pattern":"pub struct ProducerCatalog"},{"file":"crates/governance/src/catalog/client.rs","pattern":"pub fn submit"},{"file":"crates/governance/tests/unit/catalog.rs","pattern":"changed_source_observations_and_fresh_names_cannot_select_original"},{"file":"crates/server/src/governance_owner.rs","pattern":"pub fn publish_producers"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"oldCatalogObservationStillCannotPublishThroughNewFenceTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"producer_selection_keeps_all_original_fields"},{"file":"crates/server/src/governance_owner.rs","pattern":"pub async fn start_governance"},{"file":"crates/server/src/grpc.rs","pattern":"pub async fn serve_grpc_with_runtime"},{"file":"crates/server/tests/unit/governance_owner.rs","pattern":"shared_owner_schedules_preserve_cleanup_and_terminal_admission"},{"file":"crates/server/tests/integration/governance_owner.rs","pattern":"actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"lateFactoryActivationCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_owner_join_preserves_cleanup"},{"file":"crates/governance/src/scheme_input/records.rs","pattern":"pub fn root_source"},{"file":"crates/governance/src/scheme_input/values.rs","pattern":"fn bytes"},{"file":"crates/governance/src/host/client.rs","pattern":"pub fn source_lane"},{"file":"crates/governance/src/host/owner.rs","pattern":"pub fn run"},{"file":"crates/governance/tests/unit/host.rs","pattern":"cancelled_running_work_keeps_its_slot_until_natural_return"},{"file":"crates/governance/tests/unit/host.rs","pattern":"active_compiler_observes_both_request_and_owner_cancellation"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSourceCancellationDrainsSchemeOwner"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"checkThenSendCloseRaceCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_host_delivery_requires_open_gate"},{"file":"crates/governance/src/binding.rs","pattern":"pub struct SourceExpectation"},{"file":"crates/governance/tests/unit/binding.rs","pattern":"coherent_replacements_cannot_change_original_content"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"unsafeSelfConsistentReplacementWitness"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"coherent_replacement_cannot_redefine_original"},{"file":"crates/governance/build.rs","pattern":"run_package_main"},{"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeQualificationStaysWithPreparedSchemeOwner"},{"file":"t/gateway-source-test.ss","pattern":"SDK field symbols and identifier strings cannot be interchanged"},{"file":"crates/governance/src/scheme.rs","pattern":"pub fn materialize_source"},{"file":"crates/governance/tests/integration/scheme_vm.rs","pattern":"actual_aa_capture_materializes_owned_data_before_vm_cleanup"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run unsafeEncodedBlobWitness"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem encoded_blob_cannot_claim_typed_capture"},{"file":"scheme/gateway/capture.ss","pattern":"Gateway capture requires one source emission"},{"file":"scheme/gateway/func.ss","pattern":"def \\(capture-governed-gateway"},{"file":"t/gateway-source-test.ss","pattern":"native PBT requires one completed emission"},{"file":"t/gateway-source-test.ss","pattern":"a late inherited sink cannot replace an active next capture"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run ignoredCaptureFuseCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem caught_duplicate_cannot_clear_capture_fuse"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"},{"file":"scheme/governance/capture.ss","pattern":"def \\(governance-profile-snapshot"},{"file":"t/governance-test.ss","pattern":"native PBT preserves every original assessment binding"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_assessment_snapshot_cannot_reuse_boundary"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run coordinatedLiveProfileLabelsCannotReplaceOriginalCaptureTest"},{"file":"scheme/gateway/func.ss","pattern":"assq 'open-patterns"},{"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"},{"file":"scheme/governance/types.ss","pattern":"def GovernanceAssessmentContext"},{"file":"scheme/gateway/func.ss","pattern":"same-node-set?"},{"file":"t/gateway-source-test.ss","pattern":"a false Governance assessment cannot emit a source handoff"},{"file":"t/governance-test.ss","pattern":"a typed ready assessment cannot omit an original blocking threat"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityChangedCompiledSourceCannotRecoverTest"},{"file":"scheme/policy/func.ss","pattern":"project-policy profile"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"},{"file":"t/integration/governed-control-test.ss","pattern":"def governed-control-test"},{"file":"go/internal/config/bundle_test.go","pattern":"func TestBundleRejectsSelectionAndCommitmentSubstitution"}]},{"id":"SourceStartupObservation","witnesses":[{"file":"scheme/gateway/provider-program.ss","pattern":"call-with-module-source-operation-measurement"},{"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeVerificationUsesOnlyPublicPackageEntries"},{"file":"crates/governance-build/src/program.rs","pattern":"build_program_archive_with_contract"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run releaseTagCannotRebaseCapturedSourceCounterexampleTest"},{"file":"go/internal/devrunner/retention_test.go","pattern":"func TestSchemePreparationFailureKeepsOriginalCutWithoutAmbientReceipt"},{"file":"go/internal/devrunner/retention_test.go","pattern":"func TestLateCleanupFailureCannotRetainPassingReceipt"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_preparation_cut_cannot_rebase_boundary","declaration":"Weaver.PolicyBridge.changed_preparation_cut_cannot_rebase_boundary"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run changedPackageMetadataCannotRebaseSnapshotTest"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run stalePreparationReceiptCounterexampleTest"},{"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"},{"file":"go/internal/controlplane/deployment.go","pattern":"trace\\(\"authority-reconciled\"\\)"},{"file":"scheme/gateway/func.ss","pattern":"source-selection-loaded"},{"file":"scheme/gateway/func.ss","pattern":"source-module-view-loaded"},{"file":"scheme/gateway/func.ss","pattern":"source-contracts-checked"},{"file":"scheme/gateway/func.ss","pattern":"source-advisory-derived"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"status=failed drain_ns"},{"file":"crates/governance/src/host/owner.rs","pattern":"scheme-owner-drop-begin"},{"file":"t/fixtures/governed-control.ss","pattern":"fixture-module-ready"},{"file":"go/dev/provider_control_test.go","pattern":"These unauthenticated diagnostics never replace readiness or exit checks"},{"file":"crates/governance-build/src/tooling.rs","pattern":"fn bind_package_sources"},{"file":"crates/governance-build/tests/unit/package_sources.rs","pattern":"fn native_package_inputs_follow_the_selected_store_without_overwriting_sources"}]},{"id":"PolicyCAbiIsInert","witnesses":[{"file":"scheme/policy/func.ss","pattern":"def \\(validate-policy-projection!"},{"file":"scheme/gateway/func.ss","pattern":"validate-policy-projection! projection"},{"file":"t/policy-test.ss","pattern":"real Rust preflight refuses cross-document syntax assembly"},{"file":"t/policy-projection-test.ss","pattern":"every named document precedes aggregate validation"},{"file":"crates/policy-ffi/tests/unit/validation.rs","pattern":"fn aggregate_validity_does_not_establish_complete_source_documents"},{"file":"crates/policy/tests/unit/decisions.rs","pattern":"fn default_deny_forbid_and_evaluation_error_are_fail_closed"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem incomplete_policy_document_cannot_admit"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run aggregateOnlyPolicyValidationCounterexampleTest"},{"file":"scheme/policy/source-bytes.ss","pattern":"def \\(cedar-source-utf8"},{"file":"t/policy-test.ss","pattern":"native PBT checks Unicode source bounds before the C ABI"},{"file":"crates/policy-ffi/tests/unit/abi.rs","pattern":"fn unicode_byte_limits_apply_to_each_actual_abi_region"},{"file":"crates/policy-ffi/src/abi.rs","pattern":"pub unsafe extern \"C\" fn weaver_policy_validate_v1"},{"file":"scheme/policy/cedar-ffi.ss","pattern":"def-C-lambda policy-validate/raw"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authoritySourceCommitNeverSendsTest"}]},{"id":"ControlActivationAcknowledgment","witnesses":[{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsStagingReplyLossAndRestart"},{"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlPublicationReplyLossCannotActivateOrRebase"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityLostReplyCannotActivateTest"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"}]},{"id":"ControlStreamRecoveryBinding","witnesses":[{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPartialRequestAndRestart"},{"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlCompleteStreamsShareBudgetAndRejectSDKRetry"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem profile_recovery_retains_original_hold"}]},{"id":"WorkspaceBenchmarkCoverage","witnesses":[{"file":"go/internal/devrunner/benchmark_test.go","pattern":"func TestBenchmarkEvidenceRequiresEveryCase"},{"file":"go/dev/workspace_test.go","pattern":"func TestCargoWorkspaceAndDevelopmentGates"},{"file":"crates/broker/benches/gateway.rs","pattern":"fn guarded_provider"},{"file":"go/dev/provider_bench_test.go","pattern":"func BenchmarkGatewayInspect"}]},{"id":"DurableRangeProgressJoin","witnesses":[{"file":"crates/ledger/src/stream_progress.rs","pattern":"fn message"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_message_cursor_cannot_hide_consumed_range"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_progress_cannot_release_old_writer_or_connection"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run restoredUnknownProjectionBlocksAdmissionTest"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run unknownResetDuplicatesRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unresolved_tail_blocks_admission","declaration":"Weaver.StreamingExecution.RangeProgress.unresolved_tail_blocks_admission"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem changed_progress_cannot_execute","declaration":"Weaver.StreamingExecution.RangeProgress.changed_progress_cannot_execute"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem joined_execution_preserves_safety","declaration":"Weaver.StreamingExecution.RangeProgress.joined_execution_preserves_safety"}]},{"id":"TursoAdmissionAtomicity","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"pub fn begin"},{"file":"crates/ledger/src/exposure_manifest.rs","pattern":"fn verified_members"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn failed_commit_releases_writer_and_poisoned_session_cannot_reenter"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn duplicate_claim_members_cannot_be_normalized_out_of_recovery"},{"file":"go/dev/workspace_test.go","pattern":"func TestProjectArchitectureStorageUsesMRRDataTursoOnly"},{"file":"dev/proofs/quint/TursoAdmission.qnt","pattern":"run tornCommitRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem storage_step_retains_admission_safety","declaration":"Weaver.RuntimeAdmission.Persistence.storage_step_retains_admission_safety"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem committed_consume_survives_reply_loss_and_restart","declaration":"Weaver.RuntimeAdmission.Persistence.committed_consume_survives_reply_loss_and_restart"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem commit_itself_does_not_send","declaration":"Weaver.RuntimeAdmission.Persistence.commit_itself_does_not_send"}]},{"id":"BoundedAdvisoryDerivation","witnesses":[{"file":"scheme/gateway/derivation.ss","pattern":"def \\(make-gateway-derivation"},{"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-gateway"},{"file":"t/gateway-derivation-test.ss","pattern":"generated source replacements agree with graph traversal and fresh results"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run derivedAdviceCannotChangeImageOrSpendTest"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run adviceAsOriginalCounterexampleTest"}]},{"id":"SessionWorkflowFrontier","witnesses":[{"file":"scheme/gateway/program.ss","pattern":"def \\(hard-fact-affected"},{"file":"go/dev/provider_hard_fact_test.go","pattern":"func TestProviderControlHardFactWithdrawalRestartAndABA"},{"file":"scheme/gateway/func.ss","pattern":"def \\(session-workflow-path"},{"file":"crates/server/src/governance_deployment.rs","pattern":"admits_session_workflow"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"fn bind_winner"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn provider_workflow_rechecks_prepared_floor_and_frontier_before_one_reservation"},{"file":"crates/server/src/session_workflow.rs","pattern":"async fn run_session_workflow"},{"file":"crates/server/src/single_provider.rs","pattern":"SessionTopology::prepare"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionWorkflowAutomaticallyResumes"},{"file":"scheme/gateway/func.ss","pattern":"def \\(governor-ready-steps"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"pub fn observe_workflow"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_workflow_observation"},{"file":"crates/governance/src/host/owner.rs","pattern":"cut_sha256=.*ready_sha256="},{"file":"crates/governance/src/program/compiler.rs","pattern":"topology_binding"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn governor_indices_reject_stale_binding_and_foreign_node"},{"file":"crates/server/src/session_workflow.rs","pattern":"DerivationOutput::Indices"},{"file":"crates/server/src/single_provider.rs","pattern":"topology.preopen"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn pack_governor_facts"},{"file":"t/gateway-governor-retained-test.ss","pattern":"packed facts are complete and bounded by the live binding"},{"file":"t/gateway-governor-retained-test.ss","pattern":"a compact cut must name the current binding"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"Governor transport %d expected"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched inner-join cut_sha256="},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched outer-join cut_sha256="},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionDAGConcurrentJoinAndRecovery"},{"file":"crates/ledger/src/provider_workflow_choice.rs","pattern":"fn record_result"},{"file":"go/dev/provider_workflow_choice_test.go","pattern":"func TestProviderControlSessionChoiceFromReleasedResult"},{"file":"crates/ledger/src/provider_workflow_nested.rs","pattern":"fn load"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn nested_workflow_rejects_stale_decision_and_keeps_winner_after_reopen"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSessionNestedChoiceAndParallelRecovery"},{"file":"scheme/gateway/func.ss","pattern":"WEAVER_TEST_GOVERNOR_CHANGED_SOURCES"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"unexpected Governor source replacement"},{"file":"crates/governance/src/host/client.rs","pattern":"weaver-governor-roundtrip"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"Governor roundtrip phases do not cover the call"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider_metering_with_deployment"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"a new frontier transaction must read the current deployment"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"prepare\\(tx, &proposal.predecessors, plan, current\\)"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn rooted_governor_indices_preserve_full_width_binding_and_all_64_candidates"},{"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-retained-governor-program"},{"file":"t/gateway-governor-retained-test.ss","pattern":"prepared nested rules agree with full fresh snapshots under replacement"},{"file":"t/gateway-governor-retained-test.ss","pattern":"prepared nested rules preserve source budget rejection and recovery"}]}] +[{"id":"ProviderAdmissionTurn","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let selected_admission"},{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn begin_driver_counters_follow_their_admission_grant"},{"file":"crates/ledger/src/persistence/driver_observer.rs","pattern":"fn observe_read"},{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct AdmissionRequest"},{"file":"crates/ledger/tests/unit/provider_admission_turn.rs","pattern":"fn queued_unaccepted_admission_preserves_old_frame_and_original_hold"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionTurnProperty"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionCommitRecovery"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderAdmissionTurn"},{"file":"crates/broker/src/provider/request.rs","pattern":"Stage::Tls"},{"file":"go/dev/provider_transport_phases_test.go","pattern":"func reportProviderTransport"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run eagerQueueBlocksOldFrameCounterexampleTest"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem queue_preserves_arbitrary_requirement","declaration":"Weaver.ProviderAdmissionTurn.queue_preserves_arbitrary_requirement"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem finite_queue_preserves_final_offer","declaration":"Weaver.ProviderAdmissionTurn.finite_queue_preserves_final_offer"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem open_writer_cannot_mutate","declaration":"Weaver.ProviderAdmissionTurn.open_writer_cannot_mutate"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem accepted_hard_intent_blocks","declaration":"Weaver.ProviderAdmissionTurn.accepted_hard_intent_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_outcome_blocks","declaration":"Weaver.ProviderAdmissionTurn.unknown_outcome_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem changed_image_blocks","declaration":"Weaver.ProviderAdmissionTurn.changed_image_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem queued_admission_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.queued_admission_preserves_spec_final_use"},{"file":"go/internal/controlplane/deployment.go","pattern":"if gateway.source == nil"},{"file":"go/dev/provider_control_bench_test.go","pattern":"func TestProviderGoControlMeasuredChain"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem runtime_catalog_requires_source","declaration":"Weaver.ProviderAdmissionTurn.runtime_catalog_requires_source"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_activation_blocks_source_handoff","declaration":"Weaver.ProviderAdmissionTurn.unknown_activation_blocks_source_handoff"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem bootstrap_source_close_preserves_actual","declaration":"Weaver.ProviderAdmissionTurn.bootstrap_source_close_preserves_actual"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run failedBootstrapCleanupDoesNotActivateIngressTest"},{"file":"go/dev/provider_admission_overlap_bench_test.go","pattern":"func BenchmarkProviderAdmissionOverlap"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn collect_buffered"},{"file":"go/dev/provider_control_bench_test.go","pattern":"image := serverBinary"},{"file":"go/dev/provider_fixture_test.go","pattern":"test-owned Go control image sha256"},{"file":"crates/ledger/src/persistence/scope_trace.rs","pattern":"pub\\(super\\) fn observe_release"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"observed_release_covers_lease_removal_without_retaining_a_grant"},{"file":"crates/ledger/src/persistence/driver_observer.rs","pattern":"pub\\(super\\) fn observe_commit"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"commit_io_observes_native_spans_after_unobserved_setup"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"maybe_prepared\\(c, PREPARE"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn review_program_reuse_reads_replacement_and_rejects_projection_loss"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn review_program_reuse_preserves_native_receipts_and_currentness"},{"file":"go/dev/provider_control_bench_test.go","pattern":"both arms use Go forwarding"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"valid_review!\\(\"CROSS JOIN\"\\)"},{"file":"crates/ledger/src/domains/view.rs","pattern":"require_view\\(persistence::maybe_prepared"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn manifest_programs_rebind_current_members_and_reject_divergence"}]},{"id":"ProviderReadCustody","witnesses":[{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn conflicts"},{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn acquire_origin"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let shared_reads"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn compatible_origins_share_reads_but_an_older_writer_blocks_younger_readers"},{"file":"crates/ledger/tests/unit/provider_read_custody.rs","pattern":"fn shared_reads_keep_distinct_origin_native_writes_concurrent"},{"file":"go/dev/provider_read_custody_test.go","pattern":"func TestProviderReadCustodyProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderReadCustody"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem arbitrary_policy_preserved","declaration":"Weaver.ProviderReadCustody.arbitrary_policy_preserved"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem finite_interleaving_preserves_policy","declaration":"Weaver.ProviderReadCustody.finite_interleaving_preserves_policy"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem overlapping_writes_conflict","declaration":"Weaver.ProviderReadCustody.overlapping_writes_conflict"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessRetainsWriterAndSameOriginBarriers"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_binding_blocks","declaration":"Weaver.ProviderReadCustody.changed_binding_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_shared_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_shared_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_origin_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_origin_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_owner_blocks","declaration":"Weaver.ProviderReadCustody.changed_owner_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem shared_writer_conflicts","declaration":"Weaver.ProviderReadCustody.shared_writer_conflicts"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem older_conflicting_writer_blocks","declaration":"Weaver.ProviderReadCustody.older_conflicting_writer_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem read_custody_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.read_custody_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderReadCustody.qnt","pattern":"run unsafeSharedMutationCounterexampleTest"}]},{"id":"ProviderLifecycleFootprint","witnesses":[{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct OriginLifecycle"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"enum Impact"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_lifecycle"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_provider_lifecycle"},{"file":"crates/ledger/tests/unit/provider_lifecycle.rs","pattern":"fn peer_lifecycle_preserves_complete_view_but_shared_admission_does_not"},{"file":"go/dev/provider_lifecycle_test.go","pattern":"func TestProviderLifecycleCommitRecovery"},{"file":"crates/ledger/tests/unit/authority_footprint.rs","pattern":"fn local_commit_retires_whole_and_own_but_preserves_peer"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem origin_commit_retires_whole_reader","declaration":"Weaver.ProviderLifecycleFootprint.origin_commit_retires_whole_reader"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem arbitrary_cedar_predicate_preserved","declaration":"Weaver.ProviderLifecycleFootprint.arbitrary_cedar_predicate_preserved"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem shared_admission_requires_shared_invalidation","declaration":"Weaver.ProviderLifecycleFootprint.shared_admission_requires_shared_invalidation"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem peer_lifecycle_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.peer_lifecycle_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderLifecycleFootprint.qnt","pattern":"run unsafeNarrowAdmissionCounterexampleTest"}]},{"id":"ProviderSnapshotPublication","witnesses":[{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn release_provider_group_for_delivery"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"struct Snapshot"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn share_qualification"},{"file":"crates/ledger/src/provider.rs","pattern":"fn begin_snapshot_validation"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn take_refresh"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem pending_close_defers_renewal","declaration":"Weaver.ProviderSnapshotPublication.pending_close_defers_renewal"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn a_request_arriving_during_qualification_cannot_trigger_a_second_native_read"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn one_snapshot_requalification_covers_every_exact_frame"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn post_staging_native_failure_cannot_publish_a_partial_snapshot"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn queue_snapshot"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func awaitDeliveryCuts"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem final_use_joins_snapshot","declaration":"Weaver.ProviderSnapshotPublication.final_use_joins_snapshot"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem published_snapshot_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.published_snapshot_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSnapshotPublication.qnt","pattern":"run ungatedArcLoadIsCounterexampleTest"}]},{"id":"ProviderSemanticProgress","witnesses":[{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct RangeProgress"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_progress"},{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn stage_group"},{"file":"crates/ledger/tests/unit/provider_delivery.rs","pattern":"fn exact_range_progress_preserves_queued_authorization"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderSemanticProgressProperty"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_released_binding","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_released_binding"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_image","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_image"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem range_progress_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.range_progress_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSemanticProgress.qnt","pattern":"run hiddenSemanticEditIsCounterexampleTest"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"}]},{"id":"ProviderDeliveryJoin","witnesses":[{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn bounded_trace_retains_every_requalification"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeTraceChunksPreserveAllRecords"},{"file":"crates/ledger/tests/unit/persistence_owner.rs","pattern":"fn descriptor_copy_is_not_a_retained_execution_owner"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem retained_role_blocks_custody_retirement","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.retained_role_blocks_custody_retirement"},{"file":"dev/proofs/quint/ProviderDeliveryPipeline.qnt","pattern":"run threeInertFramesNeedNoStopAndWaitTest"},{"file":"crates/server/src/grpc_delivery_producer.rs","pattern":"fn reserve_guarded"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"pub fn poll"},{"file":"crates/server/src/grpc_delivery.rs","pattern":"impl Stream for ResponseStream"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryCommitAndReceiverRecovery"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryReceiverProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem orphaned_witness_cannot_activate","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.orphaned_witness_cannot_activate"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem acknowledged_delivery_preserves_same_actual_view","declaration":"Weaver.DomainMigrationComposition.acknowledged_delivery_preserves_same_actual_view"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run committedWithoutAcknowledgmentCannotAcceptTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run rollbackCannotEraseIndependentWitnessTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run oldOwnerCannotRequalifyAfterRestartTest"}]},{"id":"ProviderEgressPromotion","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_close_receipt_cannot_resolve_new_intent","declaration":"Weaver.ProviderEgressWindow.Promotion.old_close_receipt_cannot_resolve_new_intent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem expired_clock_blocks_receiver","declaration":"Weaver.ProviderEgressWindow.Promotion.expired_clock_blocks_receiver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem every_effect_writer_needs_mediation","declaration":"Weaver.ProviderEgressWindow.Promotion.every_effect_writer_needs_mediation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem other_writer_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.other_writer_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem uncertain_effect_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.uncertain_effect_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem unchanged_database_does_not_revalidate_old_read","declaration":"Weaver.ProviderEgressWindow.Promotion.unchanged_database_does_not_revalidate_old_read"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem witness_ahead_blocks_old_image","declaration":"Weaver.ProviderEgressWindow.Promotion.witness_ahead_blocks_old_image"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem only_current_owner_can_deliver","declaration":"Weaver.ProviderEgressWindow.Promotion.only_current_owner_can_deliver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_queued_frame_cannot_follow_replacement","declaration":"Weaver.ProviderEgressWindow.Promotion.old_queued_frame_cannot_follow_replacement"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem delivered_frame_cannot_be_delivered_twice","declaration":"Weaver.ProviderEgressWindow.Promotion.delivered_frame_cannot_be_delivered_twice"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem receiver_promotion_refines_interval_admission","declaration":"Weaver.ProviderEgressWindow.Promotion.receiver_promotion_refines_interval_admission"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run firstCommitCannotDeliverAnotherPendingWriterTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run independentWitnessBeforeDatabaseBlocksDeliveryTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run oldWorkerDeliveryCounterexampleTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run allWriterClassesUseTheSameCutTest"}]},{"id":"BoundedProviderEgressWindow","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem any_accepted_trace_keeps_disjoint_prefix","declaration":"Weaver.ProviderEgressWindow.any_accepted_trace_keeps_disjoint_prefix"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem loss_and_restart_close_old_window","declaration":"Weaver.ProviderEgressWindow.loss_and_restart_close_old_window"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem matching_image_does_not_reopen_old_cut","declaration":"Weaver.ProviderEgressWindow.matching_image_does_not_reopen_old_cut"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem connected_roots_cannot_use_distinct_lanes","declaration":"Weaver.ProviderEgressWindow.connected_roots_cannot_use_distinct_lanes"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem admitted_four_turn_envelope","declaration":"Weaver.ProviderEgressWindow.admitted_four_turn_envelope"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem settlement_is_idempotent","declaration":"Weaver.ProviderEgressWindow.settlement_is_idempotent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem holder_stage_overlap_cannot_exceed_ticket_wait","declaration":"Weaver.ProviderEgressWindow.holder_stage_overlap_cannot_exceed_ticket_wait"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run coherentStoreRollbackActuallyDuplicatesOfferTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run pendingRevocationStopsActualOfferTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run lostBurnAckSealsOriginalTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run rehydratingOldWindowActuallyDuplicatesOfferTest"}]},{"id":"OriginalFloorDecision","witnesses":[{"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run lostCommitResponseResolvesSameOperationTest"},{"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run unknownCommitCannotActivateTest"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"}]},{"id":"ProviderCurrentnessPerformance","witnesses":[{"file":"go/dev/provider_domain_program_test.go","pattern":"func BenchmarkProviderDomainProgram"},{"file":"go/dev/provider_domain_tail_test.go","pattern":"func BenchmarkProviderSharedLongTail"},{"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem prepared_domain_program_preserves_live_decision"}]},{"id":"ProviderSchedulerOwnership","witnesses":[{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn waiting_multi_root_range_precedes_younger_conflicts"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessCountsArrivalGrantInversions"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"}]},{"id":"SenderBoundProviderOAuth","witnesses":[{"file":"go/dev/provider_oauth_relay_test.go","pattern":"func TestProviderOAuthTwoHopRevocationAndRecovery"},{"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem retained_root_revocation_blocks_child"}]},{"id":"TransportAndExecutionLatencySeparation","witnesses":[{"file":"go/dev/provider_scheduler_bench_test.go","pattern":"func BenchmarkProviderScheduledEncoding"},{"file":"go/dev/provider_range_group_test.go","pattern":"func BenchmarkProviderRangePreparationGroup"}]},{"id":"TelemetryNoninterference","witnesses":[{"file":"crates/telemetry/tests/unit/metrics.rs","pattern":"fn observations_are_monotone_and_restart_local"},{"file":"go/internal/telemetry/metrics_test.go","pattern":"func TestPropertyCountersAreBoundedMonotoneAndRestartLocal"},{"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderTelemetryCannotRefundOrRedispatchUnknownSend"},{"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderControlTelemetryObservesBothServices"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryReadsAndRestartCannotRefundTest"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryAsRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem arbitrary_observations_keep_execution","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.arbitrary_observations_keep_execution"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem telemetry_reset_keeps_unknown_hold","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.telemetry_reset_keeps_unknown_hold"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem observations_preserve_effect_safety","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.observations_preserve_effect_safety"}]},{"id":"SharedDomainAuthority","witnesses":[{"file":"crates/ledger/src/domains/binding.rs","pattern":"fn bind"},{"file":"crates/ledger/src/domains/migration.rs","pattern":"fn migrate_execution_domains"},{"file":"crates/ledger/src/domains/view.rs","pattern":"fn require_stamp"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_cross_family_shared_history_serializes_final_use"},{"file":"crates/ledger/tests/unit/shared_domains.rs","pattern":"fn finite_families_never_split_a_shared_cap"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsProperty"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsCedarReadsCurrentAuthority"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run overCapacityUnionKeepsOriginalDecisionTest"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run domainSplitCounterexampleTest"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_cannot_split_any_shared_pair","declaration":"Weaver.SharedDomains.union_cannot_split_any_shared_pair"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem admitted_union_conserves_capacity","declaration":"Weaver.SharedDomains.admitted_union_conserves_capacity"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_retains_history","declaration":"Weaver.SharedDomains.union_retains_history"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_fences_both_old_permits","declaration":"Weaver.SharedDomains.union_fences_both_old_permits"}]},{"id":"TursoMvccCustody","witnesses":[{"file":"crates/ledger/src/persistence/owner.rs","pattern":"fn open"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_family"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_final_domains_overlap_including_new_executor_connection"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_same_budget_and_history_family_keeps_final_order"},{"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn mvcc_effect_before_failed_observation_never_releases_or_replays"},{"file":"go/dev/provider_final_domains_test.go","pattern":"func TestProviderMVCCIndependentFinalSendsAndRevocation"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run postSendCommitConflictKeepsPhysicalEffectTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem shared_final_readers_keep_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.shared_final_readers_keep_current_fence"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem failed_observation_after_send_keeps_spent_hold","declaration":"Weaver.RuntimeAdmission.MVCC.failed_observation_after_send_keeps_spent_hold"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_disjoint_admissions_have_overlapping_turso_writes"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_process_custody_refuses_a_second_process"},{"file":"crates/ledger/tests/unit/mvcc.rs","pattern":"fn mvcc_concurrent_family_budget_has_one_original_reservation"},{"file":"go/dev/provider_mvcc_test.go","pattern":"func TestProviderMVCCExecutionBoundary"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run snapshotWriteSkewCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem disjoint_domain_commits_commute","declaration":"Weaver.RuntimeAdmission.MVCC.disjoint_domain_commits_commute"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem family_step_preserves_all_budgets","declaration":"Weaver.RuntimeAdmission.MVCC.family_step_preserves_all_budgets"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exclusive_final_use_keeps_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.exclusive_final_use_keeps_current_fence"}]},{"id":"ArchitectureViewGrammar","witnesses":[{"file":"dev/sysml/ArchitectureViews.sysml","pattern":"view zeroTrust"},{"file":"go/internal/devrunner/model_views.go","pattern":"func CaptureModelViews"},{"file":"go/internal/devrunner/model_views_test.go","pattern":"func TestModelViewsUseActualSDK"},{"file":"go/internal/devrunner/model_views_test.go","pattern":"func FuzzModelViewCaptureTracksSource"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestArchitectureDiagramsUseDifferentViewProfiles"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramProfilesAreExplicitAndLocal"},{"file":"go/internal/devrunner/diagrams.go","pattern":"func RenderDiagrams"},{"file":"dev/d2/src/render.ts","pattern":"composeFigure[(]input,composer[)]"},{"file":"dev/d2/test/model-view.test.ts","pattern":"public Library binds SDK SysML identity"},{"file":"dev/d2/src/objects.ts","pattern":"export const composeObjects"},{"file":"dev/d2/test/model-view.test.ts","pattern":"missing captured views and unsupported source ports refuse"},{"file":"dev/d2/test/vector-readability.test.ts","pattern":"Preserve the original ordered-sequence line-overlap check"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramEvidenceRejectsLostNodesAndRelationships"}]},{"id":"ProductionAssetBoundary","witnesses":[{"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRuntimeAssetBoundary"},{"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRejectsRuntimeDevReferences"}]},{"id":"OriginalTaskBinding","witnesses":[{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem first_birth_seal_cannot_broaden","declaration":"Weaver.TaskOrigin.first_birth_seal_cannot_broaden"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem sealed_birth_cannot_be_replaced","declaration":"Weaver.TaskOrigin.sealed_birth_cannot_be_replaced"},{"file":"crates/ledger/tests/unit/task_publication.rs","pattern":"fn lost_birth_projection_cannot_authorize_or_be_silently_repaired"},{"file":"crates/ledger/src/task_origins.rs","pattern":"fn register_original_task"},{"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn source_rotation_cannot_reallocate_task_and_lost_reply_recovers_original_commit"},{"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn trusted_issuer_relabeling_every_identity_is_outside_local_deduplication"},{"file":"go/dev/provider_task_origin_test.go","pattern":"func TestProviderOriginalTaskOriginLostReplySourceSwitchAndRestart"},{"file":"dev/proofs/quint/TaskOrigin.qnt","pattern":"run issuerTrustCounterexampleTest"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem assigned_task_cannot_rebind","declaration":"Weaver.TaskOrigin.assigned_task_cannot_rebind"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem source_epoch_does_not_change_task_scope","declaration":"Weaver.TaskOrigin.source_epoch_does_not_change_task_scope"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem stale_source_command_cannot_commit","declaration":"Weaver.TaskOrigin.stale_source_command_cannot_commit"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn original_task_body_and_profile_cannot_be_replaced"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalBindingTest"}]},{"id":"SharedBudget","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn finite_manifest_siblings_cannot_mask_a_missing_original_member"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn maximum_manifest_cannot_replace_a_lost_sibling_after_restart"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityRecoveryGuardTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityFinalUseGuardTest"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn selected_message_binding_must_match_its_committed_digest_at_final_write"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn concurrent_message_admission_preserves_both_manifest_members"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exhausted_budget_cannot_publish_a_manifest_member_without_its_row"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem manifest_bound_runtime_step"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn surviving_stream_message_cannot_hide_a_lost_unknown_reservation"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exact_message_manifest_guards_recovery_and_existing_write_handles"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialMessageLossCounterexampleTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run digestSubstitutionFinalUseGuardTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exact_manifest_admission_covers_original_exposure"},{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn balanced_provider_projection_never_funds_a_different_original_plan"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_stream_projection_never_funds_the_next_logical_message"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem admission_covers_original_exposure"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run balancedProjectionCounterexampleTest"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_shrink_never_admits_a_different_node"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn require_family"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn mixed_request_and_stream_exposure_cannot_be_checked_in_separate_domains"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem orphaned_hold_blocks_new_admission"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run separateEffectDomainsCounterexampleTest"},{"file":"crates/ledger/tests/unit/properties.rs","pattern":"fn arbitrary_replays_restarts_and_consumption_preserve_claims"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run sharedBudgetTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalCostBoundTest"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn authored_ceiling_cannot_underreserve_the_original_wire_cost"}]},{"id":"ZeroTrustContractRefinement","witnesses":[{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem final_use_on_committed_union","declaration":"Weaver.DomainMigrationComposition.final_use_on_committed_union"},{"file":"crates/ledger/src/provider.rs","pattern":"actual.stamp != p.domains"},{"file":"crates/ledger/tests/unit/provider_domains.rs","pattern":"fn same_actual_domains_fence_original_provider_capability"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"actual migration committed; response discarded"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run committedUnionLostReplyKeepsBothOriginalsTest"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem gateway_final_use_preserves_domain_contract","declaration":"Weaver.DomainMigrationComposition.gateway_final_use_preserves_domain_contract"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem head_cas_preserves_original_obligations","declaration":"Weaver.DomainMigrationComposition.head_cas_preserves_original_obligations"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem overbooked_actual_view_cannot_supply_final_run","declaration":"Weaver.DomainMigrationComposition.overbooked_actual_view_cannot_supply_final_run"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureResearchModels"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainCommitRestartPositiveTest"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainRevocationKeepsOriginalExposureTest"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run detachedLogicalLedgerCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget","declaration":"Weaver.ProviderRpc.shared_exposure_keeps_original_budget"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework","declaration":"Weaver.ZeroTrustEnrichment.gateway_specialization_retains_generic_framework"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway","declaration":"Weaver.ZeroTrustEnrichment.retained_parent_and_selected_object_reach_gateway"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption","declaration":"Weaver.ZeroTrustEnrichment.usage_control_keeps_current_consumption"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use","declaration":"Weaver.ZeroTrustEnrichment.pending_policy_blocks_ongoing_use"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"}]},{"id":"ConsumeBeforeSend","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn final_write_requires_exact_durable_range"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run stateOnlyRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem inexact_cannot_refine_execution","declaration":"Weaver.StreamingExecution.RangeReceipt.inexact_cannot_refine_execution"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn crash_after_consumption_never_reopens_or_refunds"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run consumeBeforeSendTest"}]},{"id":"CurrentFinalGuard","witnesses":[{"file":"crates/ledger/tests/unit/serialization.rs","pattern":"fn effective_publication_cannot_overtake_the_locked_send_boundary"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run stalePermitTest"}]},{"id":"UnknownRetainsHold","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restart_never_backfills_request_claims_from_operations"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn orphaned_request_claim_cannot_admit_a_replacement_operation"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn next_stream_message_cannot_recreate_a_lost_node_claim"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn lost_message_projection_cannot_recycle_original_unknown_hold"},{"file":"crates/broker/tests/unit/https_transport.rs","pattern":"fn partial_transport_failure_is_unknown_and_never_retried"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run unknownRefundCounterexampleTest"}]},{"id":"NoImplicitRetry","witnesses":[{"file":"crates/ledger/tests/unit/concurrency.rs","pattern":"fn concurrent_consumers_invoke_once"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run duplicateRetryCounterexampleTest"}]},{"id":"DevelopmentPolicy","witnesses":[{"file":"crates/contracts/src/lib.rs","pattern":"mode = deny"}]},{"id":"MessageScopedAuthority","witnesses":[{"file":"crates/ledger/tests/unit/stream_properties.rs","pattern":"fn unknown_range_after_restart_blocks_new_nonce_and_authority"},{"file":"crates/policy/tests/unit/stream_policy.rs","pattern":"fn specification_derived_policy_is_typed_and_constrains_actual_range_facts"}]},{"id":"RangeFinalGuard","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn effective_revocation_stops_actual_next_range_and_prefix_reconnect"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run revokedBetweenBurnAndWriteTest"}]},{"id":"UnknownPrefixRecovery","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn rust_partial_write_freezes_tail_and_never_refunds"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unknown_cannot_resume"}]},{"id":"PrivateBufferCustody","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn tls_flush_cannot_release_a_tail_after_effective_revocation"},{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn recovered_old_worker_socket_cannot_use_new_custody"}]},{"id":"BoundedPerformanceWork","witnesses":[{"file":"crates/policy/tests/unit/cache_storage.rs","pattern":"fn compiled_storage_caps_slots_and_exact_hits_do_not_allocate_new_entries"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem bounded_range_copy_work"}]},{"id":"TrackedWriterDrain","witnesses":[{"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"async fn detached_executor_writer_keeps_slot_until_drain_acknowledges_completion"},{"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"fn arbitrary_disconnect_shutdown_and_drain_schedules_keep_executor_custody"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"},{"file":"dev/proofs/quint/RuntimeLifecycle.qnt","pattern":"run prematureAckCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem execution_and_drain_composition"}]},{"id":"GrpcCallerBinding","witnesses":[{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderRPCIdentityAndCancellation"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_name_is_not_key_authority"}]},{"id":"TransportSetupIsolation","witnesses":[{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run reconnectCannotUncancelOriginalStreamTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem crash_cannot_recreate_unknown_release"},{"file":"go/internal/gatewayclient/connection_test.go","pattern":"func TestConnectionSetupRetainsCallerDeadlineAndCancellation"},{"file":"go/dev/provider_startup_test.go","pattern":"func TestProviderFreshImageAndRestartStartup"},{"file":"dev/proofs/quint/GatewayComposition.qnt","pattern":"run reconnectRetainsSpentRootTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem gateway_run_preserves_original_execution_and_custody"}]},{"id":"CommittedProviderRouting","witnesses":[{"file":"go/internal/routing/provider_test.go","pattern":"func TestProviderRoutingCannotRewriteOriginalContract"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderGRPCStreamingAndArrowOption"}]},{"id":"UnambiguousProviderRequestBounds","witnesses":[{"file":"crates/contracts/tests/unit/provider_bounds.rs","pattern":"fn exactly_one_provider_cap_is_bounded"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn rejected_competing_caps_leave_no_claim_or_hold_after_restart"},{"file":"go/internal/routing/provider_test.go","pattern":"func FuzzProviderRequestBounds"},{"file":"go/dev/provider_bounds_test.go","pattern":"func TestProviderCompetingCapsCannotReachDispatch"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preferredCapPrecedenceCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem request_bounds_and_affine_execution_composition"}]},{"id":"SourceProviderProfileBinding","witnesses":[{"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceProfileAndCedarBindFinalSendAcrossRestart"},{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn concurrent_profile_registrations_cannot_fork_one_identity"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_task_registration_cannot_rebind"}]},{"id":"ClosedProviderRequestSchema","witnesses":[{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn provider_profile_cannot_fall_back_to_untyped_request_or_raw_stream"},{"file":"crates/contracts/tests/unit/provider_profiles.rs","pattern":"fn shared_closed_request_corpus_has_the_declared_semantics"},{"file":"go/api/v1/provider_profile_test.go","pattern":"func TestProviderProfileSharedClosedRequestCorpus"},{"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceCommittedExtensionsCannotBypassProfile"},{"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingSchemaGuardCounterexampleTest"}]},{"id":"RecoverableProfileFloor","witnesses":[{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn original_task_floor_prevents_missing_registry_from_rebinding_identity"},{"file":"crates/ledger/tests/unit/profile_floor_plan.rs","pattern":"fn semantic_floor_uses_two_composite_range_seeks"},{"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingFloorCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem missing_registry_cannot_erase_original_floor"}]},{"id":"CanonicalProfileConfiguration","witnesses":[{"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileJSONAndYAMLHaveOneCanonicalCommitment"},{"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileRejectsAmbiguousConfiguration"},{"file":"go/internal/config/provider_profile_test.go","pattern":"func FuzzProviderProfileConfiguration"}]},{"id":"AffineProviderAttempt","witnesses":[{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn arbitrary_provider_replays_restarts_and_release_batches_keep_original_claim"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run sdkRetryCannotConsumeAgainTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem consumed_unknown_retains_original_hold"}]},{"id":"EncodingAuthorityEquivalence","witnesses":[{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPolicyChangeDuringCapacityWait"},{"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowWireBoundDoesNotBoundDecodedText"},{"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowInvalidLaterRowReturnsNoPartialBatch"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preparedEncodingCannotSwitchTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem final_guard_checks_actual_owner_rows"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderArrowChecksEveryRow"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem arrow_cannot_weaken_row_authority"}]},{"id":"ProviderUnknownRetention","witnesses":[{"file":"crates/broker/src/provider/runtime.rs","pattern":"fn open_guarded"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn commit_provider"},{"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn failed_callback_never_enters_final_commit_and_retains_original_exposure"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn turso_applied_commit_without_ack_poison_is_not_reusable"},{"file":"go/dev/provider_commit_fault_test.go","pattern":"func TestProviderSealedTursoCommitRecovery"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run appliedLostAckPoisonsOldWorkerTest"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run durableCommitThenFenceThenLateAckTest"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run committingFailedCallbackCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem failed_callback_cannot_enter_commit","declaration":"Weaver.ProviderRpc.RequestWriteFence.failed_callback_cannot_enter_commit"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem applied_commit_without_ack_does_not_activate","declaration":"Weaver.ProviderRpc.RequestWriteFence.applied_commit_without_ack_does_not_activate"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem late_commit_ack_cannot_bypass_new_fence","declaration":"Weaver.ProviderRpc.RequestWriteFence.late_commit_ack_cannot_bypass_new_fence"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider[(]"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run individualHoldOnlyCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_provider_exposure_cannot_be_released"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem provider_exposure_strengthens_continuing_zero_trust"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerEnqueueBeforeCommitCrashCannotReplayPendingRange"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerCancellationAndReconnectRetainHistory"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run enqueueThenLostCommitRetainsUnknownTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem transport_history_preserves_original_hold"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderPartialRequestAndRestartRetainUnknownClaim"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run unknownRefundCounterexampleTest"}]},{"id":"ReservedAuthorityAdmission","witnesses":[{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run recoveryDoesNotRefreshUsageEvidenceTest"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn final_release_keeps_current_guard_and_unknown_commit_in_one_transaction"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run childOnlyPredicateDropsParentCounterexampleTest"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem continuing_uses_current_state_and_original_consumption"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem capacity_cannot_rebase_changed_floor"},{"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn waiting_capacity_does_not_hold_sql_or_authorize_after_publication"},{"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn pending_range_history_created_during_capacity_wait_cannot_be_replayed"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPositiveControlCompletesAfterCapacityReturns"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run returnedCapacityDoesNotAuthorizeStaleReleaseTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_backpressure_composition"},{"file":"crates/server/tests/unit/admission.rs","pattern":"async fn saturated_detached_execution_preserves_publication_and_observation_custody"},{"file":"go/dev/provider_capacity_test.go","pattern":"func TestProviderSaturatedExecutionPreservesRevocationAndObservation"},{"file":"dev/proofs/quint/AuthorityAdmission.qnt","pattern":"run sharedLaneStarvationCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_admission_composition"}]},{"id":"ConnectionCustodyBound","witnesses":[{"file":"crates/server/tests/unit/connections.rs","pattern":"async fn tcp_socket_owns_capacity_until_destruction_and_preserves_io_and_peer_identity"},{"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderPreTLSConnectionsAreBoundedAndExpire"},{"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderShutdownDestroysStalledTLSBeforeAcknowledgingExit"},{"file":"dev/proofs/quint/ConnectionAdmission.qnt","pattern":"run earlyReturnCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem provider_and_connection_composition"}]},{"id":"SourceIngressBinding","witnesses":[{"file":"go/dev/provider_source_test.go","pattern":"func TestProviderSourceIngressBindsCertificateCredentialAndMethod"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledCatalogRequiresExactSourceEpoch"},{"file":"go/dev/provider_capacity_test.go","pattern":"full operation ingress blocked new source session"},{"file":"crates/server/tests/unit/grpc_ingress.rs","pattern":"async fn aliased_or_empty_source_identity_is_rejected_before_serving"},{"file":"dev/proofs/quint/SourceIngress.qnt","pattern":"run forwardedCredentialCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem ingress_step_preserves_independent_custody"}]},{"id":"DurablePublicationDecision","witnesses":[{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn outcome_insert_failure_rolls_back_policy_schema_and_result_together"},{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn concurrent_same_identity_commits_only_one_revision"},{"file":"go/dev/publication_recovery_test.go","pattern":"func TestProviderPublicationLostReplyRestartAndHistoricalDecision"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run deletedOutcomeCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_and_provider_accounting_composition"}]},{"id":"OwnedSourceConnection","witnesses":[{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn cancelled_priority_wait_does_not_send_a_source_command"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn source_rotation_commits_before_queued_catalog_reads_recheck_identity"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run newCommandCanPrecedeOldReplyTest"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn completed_source_acknowledgment_returns_command_capacity"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run replyBeforeCapacityCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem command_ack_requires_returned_capacity"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn reused_source_connection_observes_other_writer_and_preserves_historical_result"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn disconnected_source_caller_keeps_capacity_until_original_sql_work_finishes"},{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn connection_reuse_rejects_an_unresolved_explicit_transaction"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run swallowedCloseErrorCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem owned_worker_and_publication_composition"}]},{"id":"FinalInvocationCancellation","witnesses":[{"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn cancellation_during_sql_wait_blocks_transport_and_keeps_spent_claim"},{"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn uncancelled_control_reaches_real_https_transport_once"},{"file":"dev/proofs/quint/DispatchCancellation.qnt","pattern":"run skippedRecheckCounterexampleTest"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run missingFinalCancellationCheckCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem cancellation_and_original_hold_composition"}]},{"id":"OriginalReleaseCapability","witnesses":[{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityBudgetHistoryChangeInvalidatesReleaseReadTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_plan_survives_batching"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn equal_batch_digests_cannot_transfer_release_between_original_nodes"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn release_encoding_cannot_change_after_preparation"},{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn release_capabilities_bind_plan_encoding_and_restart_session"},{"file":"dev/proofs/quint/ReleaseBinding.qnt","pattern":"run crossPlanCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem release_binding_and_execution_composition"}]},{"id":"SpecificSourceContracts","witnesses":[{"file":"crates/server/src/single_provider.rs","pattern":"bound: BoundSource"},{"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run governanceCannotReplaceGovernorTest"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run missingGovernorCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_cannot_replace_governor","declaration":"Weaver.PolicyBridge.governance_cannot_replace_governor"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governor_cannot_replace_governance","declaration":"Weaver.PolicyBridge.governor_cannot_replace_governance"},{"file":"scheme/governance/types.ss","pattern":"def GovernanceScopeContract\\s+\\(\\.cc \\(Record"},{"file":"scheme/gateway/contracts.ss","pattern":"def GatewayArtifact"},{"file":"t/gateway-contracts-test.ss","pattern":"def gateway-contracts-test"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityUncompiledSourceCannotRegisterTest"},{"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"},{"file":"t/gateway-contracts-test.ss","pattern":"module scopes use native POO Types and refuse evidence protocol hooks"}]},{"id":"GovernancePolicyProjection","witnesses":[{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrApprovalCannotOutliveExposureProjectionRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrCommitReplyLossAndReplayCannotMintAnotherTicketTest"},{"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn candidate_only_replay_cannot_register_for_a_real_predecessor"},{"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn replay_cannot_substitute_the_captured_predecessor"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem matched_replay_preserves_both_images"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run exactReplayPairSurvivesLostReplyAndCommitsOriginalTest"},{"file":"crates/ledger/tests/unit/source_authority.rs","pattern":"fn source_handoffs_and_old_workers_preserve_original_unknown_budget"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn consistent_whole_store_rollback_remains_a_local_authority_counterexample"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn residual_policy_schema_cannot_be_treated_as_an_empty_store_after_restart"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn first_enrollment_uses_all_durable_tables_without_temporary_aliases"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn committed_writer_before_enrollment_cannot_be_hidden_by_an_old_empty_read"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn callback_failure_after_enrollment_does_not_allow_a_replacement_identity"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem complete_catalog_refusal_preserves_original_state"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem source_enrollment_refusal_preserves_unknown_accounting"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run omittedProjectionEnrollmentCounterexampleTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateCatalogCommitMustReachDecidingGuardTest"},{"file":"go/dev/provider_source_authority_test.go","pattern":"func TestProviderPersistentSourceRotationLostReplyFencesExistingWorkerAndReissuedKey"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem retired_source_key_cannot_become_fresh"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_preserves_source_key_uniqueness"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run burnWithoutRetainedConfirmationCannotAdmitTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run cachedQualificationCannotAdmitWithZeroHeldProjectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run repairedProjectionDoesNotRecreateLostSendHandleTest"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_prefix_failure_atomically_rolls_back_burn"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_prefix_without_burn_projection_cannot_repeat_admission"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_burn_fenced_before_callback_keeps_original_unknown_exposure"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run confirmedRevocationAndHandoffRejectConsistentSourceRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run retainedRegistrationCannotReplaceAfterSnapshotRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run sameLengthArtifactReplacementCannotConfirmRetainedPrefixTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run wholeRetainedRootRollbackCanReplayQualificationCounterexampleTest"},{"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn identical_prefix_after_whole_store_restore_can_replay_dispatch_counterexample"},{"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn prefix_qualification_does_not_reconstruct_rolled_back_budget_counterexample"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run copiedRowsWithoutRecoveryQualificationCannotPublishTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateQualificationAfterRegistryAppendIsRefusedTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run recoveredNewOwnerRequalifiesOriginalArtifactTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run consistentAuthorityRollbackCanReplaySavedQualificationCounterexampleTest"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn stale_registry_read_and_reopened_worker_preserve_unknown_provider_exposure"},{"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn text_rendering_cannot_silently_replace_original_policy_ids"},{"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn actual_spec_replay_registration_persists_before_original_final_cas"},{"file":"go/dev/provider_policy_json_test.go","pattern":"func TestProviderControlNamedPolicyJSONRevocationAndRestart"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem finite_replay_does_not_certify_no_gain"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run observerRestartCannotRestoreReadCapabilityTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateRegistryReceiptAfterHandoffIsHistoricalTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run independentSnapshotRollbackResurrectsCredentialCounterexampleTest"},{"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn losing_verifier_metadata_cannot_downgrade_a_committed_served_profile"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem missing_verifier_cannot_downgrade"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run missingVerifierCannotDowngradeAfterRestartTest"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureComposition"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureRejectsFalseArithmetic"},{"file":"dev/proofs/cedar/SpecProofClosure.lean","pattern":"def proveClosedArithmetic"},{"file":"prod/policies/provider/ProviderReview.lean","pattern":"def entry"},{"file":"go/internal/specreview/producer.go","pattern":"Issue"},{"file":"crates/policy/src/qualified_delta.rs","pattern":"pub fn verify_qualified_delta"},{"file":"go/dev/provider_spec_review_test.go","pattern":"func TestProviderRealSPECReviewRevocationLostRepliesAndRestart"},{"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn historical_signature_only_nogain_is_not_semantic_qualification"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run signatureOnlyGainCounterexampleTest"},{"file":"dev/proofs/cedar/QualifiedReview.lean","pattern":"theorem qualified_execution_and_recovery_preserve_original","declaration":"Weaver.QualifiedReview.qualified_execution_and_recovery_preserve_original"},{"file":"crates/ledger/src/delta_registration.rs","pattern":"fn require_current"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"fn require"},{"file":"go/dev/provider_review_test.go","pattern":"func TestProviderReviewedPublicationLostRepliesAndRestart"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem reviewed_commit_composes_with_original_recovery"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run producerSignatureCannotReplaceQualificationTest"},{"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn consistent_snapshot_rollback_can_replace_local_registered_artifact_counterexample"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceLateCommitReplyAfterRotationRemainsHistorical"},{"file":"crates/ledger/tests/unit/publication_review.rs","pattern":"fn reviewed_prefixes_match_an_independent_model"},{"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn stage_review_requirement_and_legacy_final_cas_have_one_serial_order"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_registration_recovery_composes_without_releasing_unknown"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run latchedReviewCannotUseLegacyPublicationTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run configurationImageCannotErasePersistentRevocationTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registryAppendBetweenReadAndCASRequiresRejoinTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRollbackLostReplyRetainsUnknownConsumption"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem registrar_binding_reaches_final_cas"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run revocationBetweenValidationAndFinalCASTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run delayedIssuanceDecisionCannotReactivateOldEpochTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateRotationRecoversLostReplyAndPending"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateConfigRollbackReacceptsOldKeyCounterexample"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_recovery_keeps_original_constraints"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem durable_review_binding_survives_final_cas"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registrationLostReplyCannotPublishUnrecoveredProjectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run oldRegistrarCannotPublishAlreadyRegisteredArtifactTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderStagingLostReplyRetainsConcurrentPendingAcrossRestart"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRoleCredentialIsNotRegistrarIncarnationEvidence"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem reviewed_publication_keeps_recovery_contract"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run substitutedArtifactGetsOriginalRejectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run crossStoreReviewRollbackCounterexampleTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderPendingCommandSubstitutionAndHistoricalRecovery"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn typed_publication_does_not_yet_require_delta_evidence"},{"file":"scheme/policy/func.ss","pattern":"project-policy profile"},{"file":"scheme/policy/assets.ss","pattern":"read-policy-assets profile"},{"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"}]},{"id":"CompiledSourceStartup","witnesses":[{"file":"scheme/gateway/compiled.ss","pattern":"weaver_governance_ready_v1"},{"file":"crates/governance-build/src/application.rs","pattern":"pub fn approved"},{"file":"build.ss","pattern":"approved application root mismatch"},{"file":"crates/governance/src/program/compiler.rs","pattern":"pub fn initialize"},{"file":"crates/governance/src/catalog/configuration.rs","pattern":"pub fn from_configuration"},{"file":"crates/server/src/governance_deployment.rs","pattern":"async fn start_compiler"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRequiresRealInstallation"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"metadataAsInitializationCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem graph_membership_cannot_replace_initialization"}]},{"id":"GovernorSourceHandoff","witnesses":[{"file":"scheme/gateway/types.ss","pattern":"def GatewayProgram"},{"file":"scheme/gateway/program.ss","pattern":"def \\(make-gateway-program"},{"file":"t/gateway-source-test.ss","pattern":"program installation and close follow an irreversible lifecycle"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"caughtReentryPoisonsOuterDeliveryTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem program_result_composes_with_registered_original"},{"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"},{"file":"go/internal/controlplane/deployment_source_test.go","pattern":"func FuzzDeploymentSourceHasOneOwner"},{"file":"go/internal/controlplane/producer_deployment_test.go","pattern":"func exerciseProducerDeployment"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"deploymentCannotFallBackToFileTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem producer_deployment_keeps_registered_original"},{"file":"crates/server/src/grpc.rs","pattern":"async fn compile_source"},{"file":"go/internal/controlplane/source_compile.go","pattern":"func BootstrapProducer"},{"file":"go/internal/controlplane/approved_source_rpc_test.go","pattern":"func TestApprovedSourceMTLSBootstrap"},{"file":"go/internal/config/freeze_test.go","pattern":"func FuzzFrozenSourceDoesNotFollowCallerMutation"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem compilation_reply_keeps_registered_original"},{"file":"crates/governance/src/catalog/admission.rs","pattern":"pub struct ProducerCatalog"},{"file":"crates/governance/src/catalog/client.rs","pattern":"pub fn submit"},{"file":"crates/governance/tests/unit/catalog.rs","pattern":"changed_source_observations_and_fresh_names_cannot_select_original"},{"file":"crates/server/src/governance_owner.rs","pattern":"pub fn publish_producers"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"oldCatalogObservationStillCannotPublishThroughNewFenceTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"producer_selection_keeps_all_original_fields"},{"file":"crates/server/src/governance_owner.rs","pattern":"pub async fn start_governance"},{"file":"crates/server/src/grpc.rs","pattern":"pub async fn serve_grpc_with_runtime"},{"file":"crates/server/tests/unit/governance_owner.rs","pattern":"shared_owner_schedules_preserve_cleanup_and_terminal_admission"},{"file":"crates/server/tests/integration/governance_owner.rs","pattern":"actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"lateFactoryActivationCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_owner_join_preserves_cleanup"},{"file":"crates/governance/src/scheme_input/records.rs","pattern":"pub fn root_source"},{"file":"crates/governance/src/scheme_input/values.rs","pattern":"fn bytes"},{"file":"crates/governance/src/host/client.rs","pattern":"pub fn source_lane"},{"file":"crates/governance/src/host/owner.rs","pattern":"pub fn run"},{"file":"crates/governance/tests/unit/host.rs","pattern":"cancelled_running_work_keeps_its_slot_until_natural_return"},{"file":"crates/governance/tests/unit/host.rs","pattern":"active_compiler_observes_both_request_and_owner_cancellation"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSourceCancellationDrainsSchemeOwner"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"checkThenSendCloseRaceCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_host_delivery_requires_open_gate"},{"file":"crates/governance/src/binding.rs","pattern":"pub struct SourceExpectation"},{"file":"crates/governance/tests/unit/binding.rs","pattern":"coherent_replacements_cannot_change_original_content"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"unsafeSelfConsistentReplacementWitness"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"coherent_replacement_cannot_redefine_original"},{"file":"crates/governance/build.rs","pattern":"run_package_main"},{"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeQualificationStaysWithPreparedSchemeOwner"},{"file":"t/gateway-source-test.ss","pattern":"SDK field symbols and identifier strings cannot be interchanged"},{"file":"crates/governance/src/scheme.rs","pattern":"pub fn materialize_source"},{"file":"crates/governance/tests/integration/scheme_vm.rs","pattern":"actual_aa_capture_materializes_owned_data_before_vm_cleanup"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run unsafeEncodedBlobWitness"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem encoded_blob_cannot_claim_typed_capture"},{"file":"scheme/gateway/capture.ss","pattern":"Gateway capture requires one source emission"},{"file":"scheme/gateway/func.ss","pattern":"def \\(capture-governed-gateway"},{"file":"t/gateway-source-test.ss","pattern":"native PBT requires one completed emission"},{"file":"t/gateway-source-test.ss","pattern":"a late inherited sink cannot replace an active next capture"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run ignoredCaptureFuseCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem caught_duplicate_cannot_clear_capture_fuse"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"},{"file":"scheme/governance/capture.ss","pattern":"def \\(governance-profile-snapshot"},{"file":"t/governance-test.ss","pattern":"native PBT preserves every original assessment binding"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_assessment_snapshot_cannot_reuse_boundary"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run coordinatedLiveProfileLabelsCannotReplaceOriginalCaptureTest"},{"file":"scheme/gateway/func.ss","pattern":"assq 'open-patterns"},{"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"},{"file":"scheme/governance/types.ss","pattern":"def GovernanceAssessmentContext"},{"file":"scheme/gateway/func.ss","pattern":"same-node-set?"},{"file":"t/gateway-source-test.ss","pattern":"a false Governance assessment cannot emit a source handoff"},{"file":"t/governance-test.ss","pattern":"a typed ready assessment cannot omit an original blocking threat"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityChangedCompiledSourceCannotRecoverTest"},{"file":"scheme/policy/func.ss","pattern":"project-policy profile"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"},{"file":"t/integration/governed-control-test.ss","pattern":"def governed-control-test"},{"file":"go/internal/config/bundle_test.go","pattern":"func TestBundleRejectsSelectionAndCommitmentSubstitution"}]},{"id":"SourceStartupObservation","witnesses":[{"file":"scheme/gateway/provider-program.ss","pattern":"call-with-module-source-operation-measurement"},{"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeVerificationUsesOnlyPublicPackageEntries"},{"file":"crates/governance-build/src/program.rs","pattern":"build_program_archive_with_contract"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run releaseTagCannotRebaseCapturedSourceCounterexampleTest"},{"file":"go/internal/devrunner/retention_test.go","pattern":"func TestSchemePreparationFailureKeepsOriginalCutWithoutAmbientReceipt"},{"file":"go/internal/devrunner/retention_test.go","pattern":"func TestLateCleanupFailureCannotRetainPassingReceipt"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_preparation_cut_cannot_rebase_boundary","declaration":"Weaver.PolicyBridge.changed_preparation_cut_cannot_rebase_boundary"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run changedPackageMetadataCannotRebaseSnapshotTest"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run stalePreparationReceiptCounterexampleTest"},{"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"},{"file":"go/internal/controlplane/deployment.go","pattern":"trace\\(\"authority-reconciled\"\\)"},{"file":"scheme/gateway/func.ss","pattern":"source-selection-loaded"},{"file":"scheme/gateway/func.ss","pattern":"source-module-view-loaded"},{"file":"scheme/gateway/func.ss","pattern":"source-contracts-checked"},{"file":"scheme/gateway/func.ss","pattern":"source-advisory-derived"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"status=failed drain_ns"},{"file":"crates/governance/src/host/owner.rs","pattern":"scheme-owner-drop-begin"},{"file":"t/fixtures/governed-control.ss","pattern":"fixture-module-ready"},{"file":"go/dev/provider_control_test.go","pattern":"These unauthenticated diagnostics never replace readiness or exit checks"},{"file":"crates/governance-build/src/tooling.rs","pattern":"fn bind_package_sources"},{"file":"crates/governance-build/tests/unit/package_sources.rs","pattern":"fn native_package_inputs_follow_the_selected_store_without_overwriting_sources"}]},{"id":"PolicyCAbiIsInert","witnesses":[{"file":"scheme/policy/func.ss","pattern":"def \\(validate-policy-projection!"},{"file":"scheme/gateway/func.ss","pattern":"validate-policy-projection! projection"},{"file":"t/policy-test.ss","pattern":"real Rust preflight refuses cross-document syntax assembly"},{"file":"t/policy-projection-test.ss","pattern":"every named document precedes aggregate validation"},{"file":"crates/policy-ffi/tests/unit/validation.rs","pattern":"fn aggregate_validity_does_not_establish_complete_source_documents"},{"file":"crates/policy/tests/unit/decisions.rs","pattern":"fn default_deny_forbid_and_evaluation_error_are_fail_closed"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem incomplete_policy_document_cannot_admit"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run aggregateOnlyPolicyValidationCounterexampleTest"},{"file":"scheme/policy/source-bytes.ss","pattern":"def \\(cedar-source-utf8"},{"file":"t/policy-test.ss","pattern":"native PBT checks Unicode source bounds before the C ABI"},{"file":"crates/policy-ffi/tests/unit/abi.rs","pattern":"fn unicode_byte_limits_apply_to_each_actual_abi_region"},{"file":"crates/policy-ffi/src/abi.rs","pattern":"pub unsafe extern \"C\" fn weaver_policy_validate_v1"},{"file":"scheme/policy/cedar-ffi.ss","pattern":"def-C-lambda policy-validate/raw"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authoritySourceCommitNeverSendsTest"}]},{"id":"ControlActivationAcknowledgment","witnesses":[{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsStagingReplyLossAndRestart"},{"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlPublicationReplyLossCannotActivateOrRebase"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityLostReplyCannotActivateTest"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"}]},{"id":"ControlStreamRecoveryBinding","witnesses":[{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPartialRequestAndRestart"},{"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlCompleteStreamsShareBudgetAndRejectSDKRetry"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem profile_recovery_retains_original_hold"}]},{"id":"WorkspaceBenchmarkCoverage","witnesses":[{"file":"go/internal/devrunner/benchmark_test.go","pattern":"func TestBenchmarkEvidenceRequiresEveryCase"},{"file":"go/dev/workspace_test.go","pattern":"func TestCargoWorkspaceAndDevelopmentGates"},{"file":"crates/broker/benches/gateway.rs","pattern":"fn guarded_provider"},{"file":"go/dev/provider_bench_test.go","pattern":"func BenchmarkGatewayInspect"}]},{"id":"DurableRangeProgressJoin","witnesses":[{"file":"crates/ledger/src/stream_progress.rs","pattern":"fn message"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_message_cursor_cannot_hide_consumed_range"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_progress_cannot_release_old_writer_or_connection"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run restoredUnknownProjectionBlocksAdmissionTest"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run unknownResetDuplicatesRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unresolved_tail_blocks_admission","declaration":"Weaver.StreamingExecution.RangeProgress.unresolved_tail_blocks_admission"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem changed_progress_cannot_execute","declaration":"Weaver.StreamingExecution.RangeProgress.changed_progress_cannot_execute"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem joined_execution_preserves_safety","declaration":"Weaver.StreamingExecution.RangeProgress.joined_execution_preserves_safety"}]},{"id":"TursoAdmissionAtomicity","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"pub fn begin"},{"file":"crates/ledger/src/exposure_manifest.rs","pattern":"fn verified_members"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn failed_commit_releases_writer_and_poisoned_session_cannot_reenter"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn duplicate_claim_members_cannot_be_normalized_out_of_recovery"},{"file":"go/dev/workspace_test.go","pattern":"func TestProjectArchitectureStorageUsesMRRDataTursoOnly"},{"file":"dev/proofs/quint/TursoAdmission.qnt","pattern":"run tornCommitRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem storage_step_retains_admission_safety","declaration":"Weaver.RuntimeAdmission.Persistence.storage_step_retains_admission_safety"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem committed_consume_survives_reply_loss_and_restart","declaration":"Weaver.RuntimeAdmission.Persistence.committed_consume_survives_reply_loss_and_restart"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem commit_itself_does_not_send","declaration":"Weaver.RuntimeAdmission.Persistence.commit_itself_does_not_send"}]},{"id":"BoundedAdvisoryDerivation","witnesses":[{"file":"scheme/gateway/derivation.ss","pattern":"def \\(make-gateway-derivation"},{"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-gateway"},{"file":"t/gateway-derivation-test.ss","pattern":"generated source replacements agree with graph traversal and fresh results"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run derivedAdviceCannotChangeImageOrSpendTest"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run adviceAsOriginalCounterexampleTest"}]},{"id":"SessionWorkflowFrontier","witnesses":[{"file":"scheme/gateway/program.ss","pattern":"def \\(hard-fact-affected"},{"file":"go/dev/provider_hard_fact_test.go","pattern":"func TestProviderControlHardFactWithdrawalRestartAndABA"},{"file":"scheme/gateway/func.ss","pattern":"def \\(session-workflow-path"},{"file":"crates/server/src/governance_deployment.rs","pattern":"admits_session_workflow"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"fn bind_winner"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn provider_workflow_rechecks_prepared_floor_and_frontier_before_one_reservation"},{"file":"crates/server/src/session_workflow.rs","pattern":"async fn run_session_workflow"},{"file":"crates/server/src/single_provider.rs","pattern":"SessionTopology::prepare"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionWorkflowAutomaticallyResumes"},{"file":"scheme/gateway/func.ss","pattern":"def \\(governor-ready-steps"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"pub fn observe_workflow"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_workflow_observation"},{"file":"crates/governance/src/host/owner.rs","pattern":"cut_sha256=.*ready_sha256="},{"file":"crates/governance/src/program/compiler.rs","pattern":"topology_binding"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn governor_indices_reject_stale_binding_and_foreign_node"},{"file":"crates/server/src/session_workflow.rs","pattern":"DerivationOutput::Indices"},{"file":"crates/server/src/single_provider.rs","pattern":"topology.preopen"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn pack_governor_facts"},{"file":"t/gateway-governor-retained-test.ss","pattern":"packed facts are complete and bounded by the live binding"},{"file":"t/gateway-governor-retained-test.ss","pattern":"a compact cut must name the current binding"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"Governor transport %d expected"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched inner-join cut_sha256="},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched outer-join cut_sha256="},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionDAGConcurrentJoinAndRecovery"},{"file":"crates/ledger/src/provider_workflow_choice.rs","pattern":"fn record_result"},{"file":"go/dev/provider_workflow_choice_test.go","pattern":"func TestProviderControlSessionChoiceFromReleasedResult"},{"file":"crates/ledger/src/provider_workflow_nested.rs","pattern":"fn load"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn nested_workflow_rejects_stale_decision_and_keeps_winner_after_reopen"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSessionNestedChoiceAndParallelRecovery"},{"file":"scheme/gateway/func.ss","pattern":"WEAVER_TEST_GOVERNOR_CHANGED_SOURCES"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"unexpected Governor source replacement"},{"file":"crates/governance/src/host/client.rs","pattern":"weaver-governor-roundtrip"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"Governor roundtrip phases do not cover the call"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider_metering_with_deployment"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"a new frontier transaction must read the current deployment"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"prepare\\(tx, &proposal.predecessors, plan, current\\)"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn rooted_governor_indices_preserve_full_width_binding_and_all_64_candidates"},{"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-retained-governor-program"},{"file":"t/gateway-governor-retained-test.ss","pattern":"prepared nested rules agree with full fresh snapshots under replacement"},{"file":"t/gateway-governor-retained-test.ss","pattern":"prepared nested rules preserve source budget rejection and recovery"}]},{"id":"RustSchemeRuntimeBoundary","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"RustSchemeRuntimeBoundary"}]},{"id":"CloudAdapterAuthorityBoundary","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"CloudAdapterAuthorityBoundary"}]},{"id":"GoIntegrationLeverage","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"GoIntegrationLeverage"}]},{"id":"SchemeSourceComposition","witnesses":[{"file":"scheme/gateway/provider-source.ss","pattern":"def \\(compose-provider-configuration"},{"file":"scheme/gateway/compiled.ss","pattern":"weaver_compose_source_v1"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn composition_uses_scheme_then_rust_seals_the_exact_original"},{"file":"crates/server/src/governance_deployment.rs","pattern":"from_configuration_with"},{"file":"go/internal/controlplane/source_compile.go","pattern":"config.CloneArtifact"},{"file":"t/gateway-source-test.ss","pattern":"ASCENT routing filters modules"},{"file":"go/internal/controlplane/gateway.go","pattern":"composeSourceBundle"},{"file":"go/internal/controlplane/provider_catalog.go","pattern":"func \\(g \\*Gateway\\) composeCatalog"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSchemeCompositionRevocationAndRestart"},{"file":"crates/governance/src/composition.rs","pattern":"pub fn validate_selected"},{"file":"crates/governance/tests/unit/configuration.rs","pattern":"fn source_composition_cannot_seal_a_self_consistent_scope_substitution"}]},{"id":"AdvisorySourceComposition","witnesses":[{"file":"crates/server/src/grpc.rs","pattern":"async fn compose_source"},{"file":"crates/governance/src/host/client.rs","pattern":"pub async fn compose"},{"file":"go/dev/provider_module_routing_test.go","pattern":"operation caller entered semantic composition"},{"file":"go/internal/controlplane/provider_catalog_test.go","pattern":"func TestCatalogCompositionCoalescesFourRequests"},{"file":"crates/broker/tests/unit/https_transport.rs","pattern":"fn provider_endpoint_guard_preserves_anthropic_source_path_constraints"}]},{"id":"DirectRustOperationIngress","witnesses":[{"file":"go/internal/controlplane/deployment.go","pattern":"func PrepareFromEnv"},{"file":"go/cmd/weaver-control/main.go","pattern":"action := controlplane.PrepareFromEnv"},{"file":"crates/server/src/grpc_provider.rs","pattern":"operation_key_only"},{"file":"crates/server/src/single_provider.rs","pattern":"fn operation_plan"},{"file":"crates/server/src/provider_oauth.rs","pattern":"direct ingress cannot supply relay evidence"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderRustDirectPreparedOperationWithoutGoRelay"}]},{"id":"SourceBoundOperationPreparation","witnesses":[{"file":"crates/contracts/src/provider_routing.rs","pattern":"pub enum ProviderOperationScope"},{"file":"crates/ledger/src/provider_routing.rs","pattern":"pub fn register_provider_source"},{"file":"crates/ledger/src/provider_routing.rs","pattern":"pub fn register_routed_task"},{"file":"crates/server/src/source_owner.rs","pattern":"struct OperationResolver"},{"file":"go/dev/provider_module_routing_test.go","pattern":"func TestProviderRustDirectCatalogSelection"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderRustDirectFilePreparation"}]}] diff --git a/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org b/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org index 06e433df..3ef98c21 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org +++ b/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org @@ -32,6 +32,371 @@ focused devrunner evidence/source-integrity controls and the architecture/ requirement-trace checks. The complete devrunner race invocation exceeded its 90-second submission-check limit; it is not counted as a full-suite pass. +* Rust + Scheme responsibility audit and refactoring decision + +** Decision and evidence standard + +The production target is Rust + Scheme/POO/gerbil-ascent. Go is not a mandatory +operation hop. Keep the existing Go implementation until its owned behavior +has a qualified successor; this plan does not remove it. Retain Go development +tooling for its concrete OpenSysML SDK reuse. Do not implement hypothetical +cloud adapters solely to justify keeping a language. + +Architecture selection uses existing upstream implementation, public interface, +conformance coverage and maintenance evidence. It does not require implementing +two Weaver integrations or rebenchmarking established language ecosystems. +Local checks establish correct Weaver integration and preserved authority; +they do not prove the general value of Go, Rust or Kubernetes again. + +The target allocation is ArchitectureEvolution::RustSchemeAllocation with +requirements RustSchemeRuntimeBoundary, CloudAdapterAuthorityBoundary and +GoIntegrationLeverage. These are design requirements with documentary trace +witnesses, not claims of implemented migration or behavioral proof. Existing +WeaverExecution Go/Rust ports and measured cohorts describe today's path and +remain valid until each consumer and model is migrated together. + +** R1 implementation: compose before sealing + +SchemeSourceComposition allocates source planning to the existing Scheme/POO +application. The existing Rust startup catalog accepts exactly one of original +or composition per entry. A composition contains source (the unmaterialized +SourceData with empty plans/body/stream commitment maps) and routing (bounded +selections/candidates with existing Go field names). It is trusted deployment +data, not an RPC-selected module or policy. Rust prepares canonical plan/body +digests and checked profile/request facts. Scheme uses gerbil-ascent to join +allowed modules, capabilities and admissible offers, then ranks by exact rounded +procurement cost, latency and canonical digest. It fills commitments and reuses the Session/Funflow/Governor pure topology +projection for Workflow composition. Full source assessment stays at CompileSource, +not before listener readiness. +Rust validates the detached result as OwnedSource and independently checks that +it preserves the supplied task/principal/profile/budget/endpoints/publication, +explicit topology and concrete candidate membership before sealing. It does not +reimplement ranking. Self-consistent substitutions remain rejected, even if +all returned hashes agree. Catalog admission retains its existing authority bindings. Subsequent source captures retain exact +SourceExpectation equality. No arbitrary callback is accepted from a request. + +The same tracked owner performs startup composition and later source work; +there is no second VM or command transport. The catalog is installed only after +composition and existing Workflow/feed checks succeed. Failure closes/drains +through the existing runtime guard. This retains the existing source intent, +publication, activation and final-use transactions unchanged. + +The catalog, file-source and dynamic catalog paths now consume composed typed +projections. Go file handling decodes syntax and owns its data; bootstrap calls +source-only ComposeSource instead of FreezeBundle. Dynamic materialization +retains the existing immutable version/record cache and coalescing mutex, but +calls the same RPC for a new projection. Rust reads the existing catalog through +the source owner, projects its typed entries, and passes eligibility/ranking to +the same Scheme owner. It compares the expected catalog version and current +source authority both around derivation and before delivering the result. No +source SQL grant remains held during Scheme evaluation. Each final operation +still performs its original fresh Rust checks. + +AdvisorySourceComposition distinguishes this source-only RPC from CompileSource: +it returns inert OwnedSource data and cannot install an approved producer, +publish, enroll a source, resolve a barrier or mint a send permit. Complete +static projections reuse Rust validation without a redundant Scheme inference. +Undecided selections use the existing bounded source lane, fixed C ABI and +application. A Scheme-enabled standalone deployment starts one tracked owner +even without a producer catalog; no second VM or loader is introduced. Header +and route checks reuse Rust contracts and the transport's HTTPS validation; +the Anthropic Messages path guard is shared with final transport preparation. +Independent SPEC review is copied as separately issued transport data, never +recreated by Scheme. OpenSysML development tooling is retained. + +Existing Go Bundle/routing algorithms retain development/reference consumers; +they are no longer called by deployed bootstrap or request materialization. +The old local catalog model lives in its existing test file as an oracle rather +than in the deployed adapter. R5 may remove remaining reference algorithms once +their development consumers migrate. R2 direct ingress is recorded below; cloud adapters remain +later stages; the current Go relay is not claimed to have disappeared. + +Validation for this R1 slice uses existing native entrypoints and four workers: +- Native Scheme source suite, including exact cost/latency/digest ordering, + denied modules, latency bounds and integer overflow, passed. +- The final real linked Weaver Scheme owner passed all 29 governance library + tests, including native index width/bounds, source-form exclusivity, independent + scope preservation and five self-consistent substitution refusals. ASP Rust + passed. The shared Anthropic endpoint unit test passed with the existing + commit-observer test feature. Production-feature all-target Clippy passed. +- Go controlplane/config/routing race tests passed, including one semantic RPC + for four concurrent requests against the same new catalog projection. +- The same frozen release passed four integration selections in 39.016 seconds: + source composition with partial release/revocation/dual restart; dynamic module + selection (complete, partial and deny, stale version and operation-role refusal, + including an invalid offer that must not suppress a valid alternative); + shared budget with SDK retry rejection; nested choice/parallel recovery and + skipping an inactive nested arm. Original per-stage limits were retained. +- Failed attempts remain outside Git: an old frozen import path shadowed current + Scheme exports; initial POO fixture slots had cyclic names/string map keys; + startup improperly ran full source assessment before the 3-second listener + deadline; a sandbox refused loopback bind; a Go TestMain build exceeded its + runtime test alarm. Initial lint preparation also exceeded a 120-second tool + limit while filling Arrow compilation caches; isolated broker tests needed + their existing ledger commit-observer feature. ASP rejected the first nested + membership scan/control-flow shape; the final implementation uses an index and + named validation steps. These are not passes. Corrected wiring uses pure startup + topology projection and separate bounded release build followed by the existing + frozen-image test entry; no repeated cold dependency installation or widened + recovery deadline was used. + +The final strict linked-model/Project and named requirement-trace gates passed; +the existing RPC generation and focused Scheme qualification driver checks passed. +Compilation was measured separately under the existing 480-second build budget; +the final business regression used a frozen executable and a 90-second runtime +budget, with original per-stage limits unchanged. Native Scheme source tests use +./build.ss compile --debug followed by gerbil test -g -v 5 t/gateway-source-test.ss. +Native Rust owner tests use cargo test -p weaver-governance --features scheme-program +--lib with four test threads. Go consumers use the existing integration,schemeintegration +tag and frozen-image inputs, with parallel/cpu both four. No generated logs, +local image hashes or machine-specific preparation paths are versioned. + +This is correctness/integration evidence, not a new submillisecond benchmark or +exact-head CI result. The prior 1 ms and four-way readiness failures remain open. + +** R2 implementation: direct Rust operation ingress + +DirectRustOperationIngress and SourceBoundOperationPreparation refine the +existing RustSchemeRuntimeBoundary. The default =weaver-control= command is +source preparation; =prepare= names the same action. It opens no operation +listener, needs no operation certificate/token and exits after known source +activation. Operation clients connect directly to Rust's existing authenticated +gRPC listener. Explicit =serve= retains the old relay for reference controls; +its packaging retirement is R5. Go OpenSysML tooling and independently held +review/metering keys remain separate responsibilities. + +| Stage | Implemented owner/mechanism | Acceptance | +|-------+-----------------------------+------------| +| R2-A source preparation and direct fixed operations | Existing source bootstrap, RegisterPublishedTask and ledger; exact fixed plans retained as inert declared data | Ordinary JSON source and compiled Weaver Scheme producer; source-only command exits; no Go process in response path; exact complete output; mutation refusal and restart replay refusal | +| R2-B identity and delivery | Existing Rust TLS, provider_oauth, bounded output and broker; direct mode rejects supplied relay evidence before execution admission | Direct OAuth and explicit signed two-hop controls; cancellation, status, both encodings, every-row validation and complete/partial response controls | +| R2-C default/consumer migration | Default prepare, generated source-scope RPC field and existing Rust operation listener; explicit serve for reference tests | Same frozen release; direct fixed and catalog operations; old relay comparison; shared-budget contention and native Workflow regression | +| R2-D dynamic source custody | Existing source lane and ledger provider_operation_scopes; retained Scheme/POO/gerbil-ascent composition owner | Alternate candidate, four contenders, no duplicate effects, catalog replacement, cached-projection source retirement, restart and source/catalog cut negative controls | + +*** Declare, derive and register + +RegisterPublishedTask accepts exactly one existing Task or typed source_scope. +Source scopes use the existing SourceCompositionRequest and preserve its original +publication key. They are bounded authenticated-source declarations, never +operation-supplied templates or module paths. Rust's ProviderOperationScope is +an explicit tagged union: Fixed retains an exact task/plan/publication; Catalog +retains the unmaterialized one-node task and its bounded candidates. The routing +fact DTOs are shared Rust contracts and reexported by governance, rather than +copied into a second ledger representation or a second selector. + +The existing ledger retains scope identity, source authority epoch, publication, +content digest and exact declaration. Replays cannot replace scope bytes or +silently rebind them to a later source. Fixed declarations use the existing +original-task registration in the same deciding transaction. The publication +must still commit before direct resolution. An interrupted preparation cannot fabricate a successful activation or bypass +the ledger publication decision. Unknown replies remain subject to the existing +publication-receipt reconciliation; a process response is not execution permission. + +An operation-only OperationResolver handle provides no source mutator or source +credential to the operation listener. It reads one coherent source/publication +cut on the existing bounded source lane. Fixed plans resolve without Scheme +work. Catalog selection reads the current catalog, uses the existing affine +Scheme owner and ASCENT rules, then rejoins the exact retained scope, source +epoch, publication revision/fence and catalog version/content in the transaction +that registers the selected task. Rust reuses ProviderPlan.matches and existing +immutable task/origin registration; it does not duplicate eligibility/ranking. +The current catalog must contain the exact selected commitment. + +The existing bounded projection retains one fixed original or one coalesced +catalog result. A fixed hit returns immutable plan data with sealed activation +coordinates, avoiding a source-lane transaction on every request; it is never a +permission check. The broker still rejoins current authority on every effect. +Catalog projections reuse inert OwnedSource data only for identical scope, +catalog and revision/fence. Every catalog caller rereads source state and +completes the registration transaction checks; a warmed catalog projection +cannot survive source retirement. +Task immutability remains: a newly selected alternative cannot rewrite an +already registered original task or reopen a spent claim. After registration, +existing broker admission independently decides current Cedar, profile, +reservation, source/fact barriers, catalog binding and response release. + +An exact family/node key cannot contain plan overrides. Returned plans retain +the original activation revision/fence; they are never rebased to the current +head. Complete typed plans retain the prior direct protocol. No Go process, +additional VM, database or per-frame Scheme call is introduced. The existing +source owner, affine Scheme owner, ledger and broker retain their shutdown and +resource custody. + +*** Finite verification and limits + +The final frozen release passed sixteen named native tests in 53.065 seconds +within a 90-second test-process budget. These cover direct JSON and compiled +Scheme preparation, two different selected candidate commitments, four-way +request contention, complete/partial streams, Cedar denial, source retirement +with a warmed projection and restart, catalog replacement/recovery, both frame +encodings, malformed row rejection, cancellation, OAuth one/two-hop controls, +shared quota, indeterminate failures without retry/fallback, nested Workflow and +hard-fact withdrawal/restart/A-to-B-to-A. The ordinary JSON and catalog tests +invoke the default command with source credentials only; the compiled producer +also exercises explicit prepare. Old relay controls invoke serve explicitly. + +The direct file control warms a denied fixed original, then permits its node +under a new policy and restores the earlier policy. The cached old plan cannot +rebase to either new authority revision, send a request or reopen after restart. +Partial-SSE failure also asserts the actual terminal gRPC failure status, rather +than accepting a clean EOF or a local decoder error. + +Ledger unit controls reject stale catalog registration before task insertion, +modified selected plans, source rotation after observation, silent scope +rebinding and corrupted records; they verify exact current registration and +restart idempotence. Existing source-owner tests retain priority handoff, +cancelled waiters, ambiguous results, source rotation and natural cleanup. +The same Scheme integration stage includes RustDirect tests; ledger tests use +the existing Cargo test entry. No new runner or CI Bash orchestration is added. + +Compilation/preparation remains separate from runtime timing. Preserve existing +480-second build, 3-second readiness, 10-second source, 12-second recovery and +15-second drain budgets. Go test parallel/cpu and Rust test threads remain four. +No cold dependency installation or repeated startup sampling is part of R2. + +Retain unfavorable evidence. An initial alternative-model fixture was correctly +refused by its Cedar policy, which only allowed model-a. The corrected independent +alternative changes the admitted request body, retains that policy, and asserts +the different original commitment. Original controls were not relaxed. A prior +broad development-runner invocation hit its 75-second total watchdog; related +focused model/stage controls passed, not the whole package. A sandboxed client +check also failed loopback binding; the same relevant race packages were rerun +with local-network access. None of these is an exact-head CI-green claim. +The current observer-backed backpressure control passed in 11.115 seconds +under its separate 60-second process budget, after observer preparation was +measured separately. It uses a separate test executable and is not included in +the frozen-server identity or a pure-runtime latency claim. +The previous submillisecond performance gate remains open. + +R3 still owns further startup/configuration consolidation. R4 cloud adapters +and R5 reference/packaging removal are separate work; neither is required to +route a default R2 operation through Go. + +** Current implementation and destination matrix + +| Existing owner | Actual responsibility | Target owner and reuse | Migration obligation | +|----------------+-----------------------+------------------------+----------------------| +| go/internal/controlplane/gateway.go ExecuteProvider | Explicit serve reference only; the default operation stream bypasses this Go method | Existing crates/server grpc_provider, grpc_delivery and broker output | Direct authenticated Rust ingress; preserve cancellation, trailers, order, full-release and backpressure | +| controlplane/server.go, deployment.go | TLS peer/token checks, bounded listeners, environment loading, bootstrap custody | server rpc_security, grpc_listeners, runtime, shutdown and entrypoint | Equivalent principal identities, source/operation listener separation, bounded admission and natural drain; default prepare exits; direct fixed/catalog and explicit relay controls passed locally | +| controlplane/provider_oauth.go | Bind incoming verified TLS sender to forwarded delegated credential | Rust provider_oauth and direct-ingress security | Redesign trusted first-hop binding explicitly; never copy caller-supplied relay metadata or remove child-grant binding | +| controlplane/source_compile.go, deployment_source.go | Invoke existing source compilation, decode typed artifact, bootstrap | Rust governance_deployment, source_artifact, governance owner | One admitted artifact path; existing Build Packages ABI, exact source/version and failed/unknown activation custody retained | +| config/bundle.go, freeze.go, routing/selection.go | Workflow validation, freeze, materialize request, capability/cost/latency selection with digest tie-break | Scheme gateway objects/contracts/provider-program, POO and gerbil-ascent | Preserve deterministic tie-break, overflow-safe pricing, no-eligible rejection and original scope; ASCENT derives eligibility, existing Scheme functions order candidates; Rust independently validates authority and numeric bounds | +| routing/compile.go, provider.go, streaming/contract.go | Construct/refine proposals, digests and stream obligations | Scheme owns composition; Rust contracts owns canonical encoding, bounds and final checks | Golden wire/digest and rejection vectors; avoid a new semantic selector or third canonical representation | +| config/provider_import.go, provider_yaml.go, provider_profile.go | Decode external formats and reviewed catalog mappings | Rust decoding adapter feeding existing typed source input; Scheme owns profile interpretation | Reuse current source contract, limits and review binding; TOML/YAML/JSON are syntax, not new planning languages | +| controlplane/provider_catalog.go | Catalog currentness, projection cache and registration | Rust source_owner/ledger/catalog admission; Scheme object projection | Cache only exact version-bound immutable projections, never permission; no second cache or ledger | +| gatewayclient | RPC client, publication/source operations, Arrow observation decoding | Existing Rust RPC/contracts/encoding; generated client retained only for remaining Go consumers | Arrow limits and malformed-batch controls remain at actual consumer; do not convert columnar data to row objects just for forwarding | +| metering/issuer.go and cmd/weaver-meter | Independent terminal-usage signing and settlement | Separate issuer role, optionally implemented in Rust | Preserve independent key custody, deterministic application ID and restart idempotence; do not fold signer into gateway authority | +| specreview/producer.go | Deployment-qualified SPEC catalog binding and independent review signing | Separate review role using existing SPEC outputs and Rust contracts | Preserve pinned artifact, audience/epoch and independent keys; Scheme cannot self-approve a migration | +| telemetry/metrics.go | Admission/completion/frame counters | Rust telemetry plus bounded protocol export | Equivalent meanings; no synchronous collector dependency in frame loop | +| cmd/weaver-import-provider | Operator import utility | Rust adapter + existing Scheme profile entry | Preserve explicit review; no hot-path interpreter or second build entry | +| internal/devrunner, go/dev, cmd/weaver-dev | OpenSysML analysis/rendering, finite orchestration, Go reference/negative controls | Retain now; use existing SDK and runners | No rewrite merely for language uniformity; Go-less production can coexist with Go development tools | +| go/api | Generated RPC and Go-side contract/reference code | Keep generated bindings for live consumers; Rust contract is execution owner | Remove handwritten duplicates only after all callers and reference tests have a replacement | + +Current go/go.mod contains OpenSysML, Arrow, gRPC, Protobuf and format handling; +it does not contain Kubernetes client-go/controller-runtime, Helm or Istio. +Thus current production Go forwarding and semantic duplication have concrete +maintenance cost; present cloud-native SDK reuse is not their justification. +This is a source/dependency finding, not a claim that Go is generally slow. + +** Cloud-native integration beyond Kubernetes + +| Evidence already available | Architectural conclusion | Weaver boundary | +|----------------------------+--------------------------+-----------------| +| kube-rs supplies client, watcher/reflector, controller runtime and CRD derive; Praxis Grid declares kube client/derive/runtime and k8s-openapi | Rust supports the required controller building blocks without a Go process | Default Rust Kubernetes adapter; API bindings do not alone certify Gateway API conformance | +| Agentgateway Go dependency set includes client-go, controller-runtime, Gateway API, Istio, Helm and Go xDS | A Go controller can aggregate substantial existing Go integration code | Retain this option for a concrete required integration, without duplicating Scheme policy | +| Helm pkg/action exposes Go release lifecycle machinery | Embedded Helm release management can justify an isolated Go deployment adapter | Prefer externally managed chart deployment when embedding is unnecessary; do not port Helm release semantics to Rust | +| containerd supplies a high-level Go client and remote service APIs | Rich SDK behavior and protocol access are different reuse levels | Gateway does not become a container orchestrator by default; use external runtime boundary, or justify an owned Go adapter for required high-level behavior | +| OpenTelemetry Collector is a separately deployable component; Rust has an OTel SDK | Reuse the Collector regardless of its implementation language | Rust emits supported telemetry; do not embed/rewrite Collector processors merely to remove Go | +| Envoy external authorization uses a published service protocol | Go-based ecosystem participants can interoperate across language boundaries | Typed protocol adapter where needed; policy outage semantics explicit; final local authority remains in Rust | + +References (capability evidence, not Weaver qualification): +- https://github.com/kube-rs/kube +- https://github.com/praxis-proxy/grid/blob/main/Cargo.toml +- https://github.com/agentgateway/agentgateway/blob/main/go.mod +- https://github.com/helm/helm/blob/main/pkg/action/action.go +- https://github.com/containerd/containerd/blob/main/client/client.go +- https://opentelemetry.io/docs/collector/ +- https://opentelemetry.io/docs/languages/rust/ +- https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/security/ext_authz_filter + +A Go-native cloud project is not evidence that every client must be Go. First +choose supported protocol reuse or deployment of the existing component; choose +a Go SDK when its higher-level lifecycle behavior materially avoids implementing +that behavior ourselves. This decision is made from upstream evidence and the +required product surface, without a mandatory local comparative experiment. +An optional adapter owns only translation, SDK lifecycle and observations; +Scheme owns business semantics, Rust owns deciding effects. Do not add a generic +plugin host, sidecar fleet, xDS server or cloud abstraction in anticipation. + +** Operation and adaptation paths + +Target operation path: +client -> existing Rust authenticated ingress -> bounded admission -> existing +prepared projection / bounded Scheme owner derivation when needed -> current +ledger/Cedar/claim/reservation checks -> broker/provider -> Rust response release. +Reuse the current Session/frontier/claim/reservation transactions. Complete +released responses drive Scheme Governor progression; receipt notification is +not permission to send. Do not build a new Workflow runtime in the adapter. +The placement of checks remains governed by existing final-use contracts; this +sequence does not allow external I/O inside a deciding ledger transaction. + +Target configuration/fact path: +weaver.toml or authenticated cloud observation -> Rust syntax/source adapter -> +existing source lane and persisted ledger intent -> Scheme/POO composition and +ASCENT impact/readiness derivation -> existing preparation/publication/activation +transactions -> observed status. Rust verifies exact source revision and intent +prefix before unblocking use. Preparation uses native SDK Build Packages and +existing owner/C ABI; no module scan, per-request compile or alternate builder. + +Kubernetes resource identity is cluster + kind + namespace + name + UID. +Track opaque resourceVersion and generation as source observation coordinates; +never compare resourceVersion lexicographically as a ledger revision. A coherent +admitted snapshot maps to existing source identity. Duplicate/reordered events, +410/relist, deletion/recreation, reconnect and A-to-B-to-A require currentness +checks. Coalesce recomputation demand, never accepted hard-fact intent. Status +reports observed generation and admitted/prepared/active/refused state separately; +a Status write or observedGeneration is not an activation receipt. Scope RBAC +and secret access to the adapter's owned resources. + +Adapter queues, retries, shutdown and credentials have separate bounded owners. +No Kubernetes API call or reconciliation is required to forward a response frame. +On disconnection the existing configured fact validity/barrier policy decides +whether an admitted image remains usable; no new blanket offline allowance. +An in-process Rust adapter is not automatically isolated from Tokio or Scheme +owner contention: preserve separate queues/concurrency budgets and track tasks +through normal shutdown. No unlimited mailbox or retry storm. + +** Ordered migration and finite acceptance + +| Stage | Deliverable using existing owners | Acceptance before retirement | +|-------+-----------------------------------+------------------------------| +| R0 allocation (this change) | SysML target, source audit, upstream evidence and authority map | Existing strict linked-model and named trace gates; design-only status explicit | +| R1 semantic consolidation | Move Go selection/freeze composition to existing Scheme gateway contracts and gerbil-ascent; keep Rust canonical guards | Existing selection/rejection vectors, deterministic ties, overflow, missing facts, source-budget and replacement properties; do not shadow-execute effects | +| R2 direct Rust operation | Expose equivalent external operation on existing server; reuse broker streaming, TLS/authentication and ledger | Existing Snake Oil workloads: allowed/denied, malformed Arrow, cancellation, partial/complete SSE release, shared quota concurrency, fallback/retry binding; direct OAuth first-hop negative controls; same release and original benchmark thresholds | +| R3 source/bootstrap consolidation | Existing Rust source and governance owners prepare/publish/activate without Go relay | Existing unknown activation, restart, hard-fact withdrawal and A-to-B-to-A controls; exact source checks and 10/12/15 second limits retained | +| R4 first required cloud integration | Rust kube-rs adapter feeding source lane, Scheme reconcile and existing ledger | Finite event schedule for duplicate/reorder/relist/recreate/restart/revocation; no duplicate activation, correct Status and bounded shutdown; supported API versions and RBAC declared | +| R5 production Go retirement | Remove obsolete relay/config/routing runtime owners and packaging after consumers migrate | SysML Project runtime inventories, generated client consumers, trust keys, operational docs and deployment all agree; development tooling and independently justified adapters decided separately | + +Each stage is its own reviewable change. Reuse native module tests, Rust tests, +existing Go integration/reference controls and OpenSysML rather than inventing a +new acceptance harness. No hundreds of cold-start trials and no ecosystem +benchmark campaign. Select the smallest existing suite covering changed behavior, +use four workers for comparable existing runtime tests, stop at the first failed +stage and preserve its result. Separate compilation, owner startup, hot execution +and network delivery. Existing performance gates remain open until their exact +consumer paths pass; eliminating a Go relay does not by itself solve the measured +3.419--3.605 ms Scheme-owner tail. + +The existing TestProjectArchitecture and TestSysMLSDKAndRequirementTrace +gates passed for this linked-model change. This qualifies model structure and +named trace coverage only. R1 composition and R2 direct ingress have passed +local acceptance. Their behavioral evidence is recorded above. R3 startup +consolidation, R4 cloud integration and R5 retirement have separate gates. + +Production approval/site replay remain separate deployment gaps. No production +Go code is deleted by this architecture decision; no hypothetical Go adapter is +added. Final removal follows proven replacement of the existing behavior, not +new experiments to establish general ecosystem benefits. + * Runtime delivery plan ** Execution from a published plan diff --git a/docs/architecture/00-system-design.org b/docs/architecture/00-system-design.org index 3e7e5856..d00f38be 100644 --- a/docs/architecture/00-system-design.org +++ b/docs/architecture/00-system-design.org @@ -4,8 +4,8 @@ #+title: Weaver Unified Gateway: System Design #+language: en -#+date: 2026-10-18 -#+property: STATUS proposed +#+date: 2026-11-10 +#+property: STATUS R1-implemented-target-planned #+options: toc:3 * Decision summary @@ -21,46 +21,21 @@ each resource boundary. The normative security baseline and review findings are in [[file:04-zero-trust-and-review.org][Zero Trust baseline and architecture review]]. This requirement does not assert that the current proposal already implements those protections. -Scheme, Go, and Rust are selected for their respective ecosystem strengths. -The architecture does not infer a language assignment from agentgateway's -repository layout. Go is a serious candidate for network ingress, protocol -adapters, service integrations, and cloud-native coordination. Rust is a -strong candidate for bounded runtime kernels, native authorization integration, -and forwarding workloads sensitive to allocation and memory ownership. -Scheme retains the public POO-native governance and composition model. - -These are responsibility boundaries, not claims that a language is inherently -faster or that it makes an implementation secure. Go and Rust forwarding -placement remains subject to the matched experiment in -[[file:03-performance-and-validation.org][Performance and validation]]. - -Code as Policy is required for the Zero Trust baseline. Scheme owns POO -composition, Cedar remains the selected authorization Provider boundary, and -Go/Rust enforce the admitted artifact and operation contracts without defining -competing policy semantics. The concrete closure and known error-admission gap -are specified in [[file:09-code-as-policy.org][Code as Policy and Cedar integration]]. - -The [[file:10-zero-trust-assurance.org][mandatory Quint and Lean framework]] binds this contract to cedar-poo-spec, -existing POO proof owners, explicit transition/refinement obligations and -concrete Scheme/Go/Rust evidence. FM1-FM12 remain pending. A source digest, -certificate constructor, bounded model run or proof of pure guards alone -cannot qualify the complete authorization-to-execution path. - -Cedar is the authorization kernel because it gives governed operations one -explicit permission meaning and reuses the existing POO specification foundation. -Scheme owns Governance and composition; Cedar does not replace that domain. -The gateway must carry the decision through current source facts, history/budget -coordination and the final credentialed effect. Quint examines fault/concurrency -schedules, Lean states preservation obligations, and runtime controls establish -the physical premises. See [[file:09-code-as-policy.org][why Cedar and formal assurance belong in the gateway]] -and its core policy-to-execution diagram. - -Weaver is greenfield: existing Gateway APIs, old Policy encodings and native -objects need no compatibility layer. Reuse owner semantics and source contracts -against one deliberately selected baseline, then regenerate and qualify its -consumers. Research pins document evidence rather than mandate legacy support. -[[file:12-fm1-baseline-and-runtime-qualification.org][FM1 baseline selection]] distinguishes internal semantic/native consistency -from backward compatibility and defines the direct migration boundary. +The target production core is Rust + Scheme/POO/gerbil-ascent. Scheme owns +higher-order source composition, candidate inference and Workflow meaning; +Rust owns the network/runtime, durable coordination and final effect guards. +Go remains for its existing OpenSysML development SDK and concrete integration +reuse, and currently relays requests until the direct-Rust ingress stage. +It is not required for Kubernetes or for using Go-implemented cloud services. + +R1 routes deployed configuration and dynamic selection through the existing +Rust source lane and affine Scheme owner. Go decodes external syntax and copies +typed projections. The complete allocation, implemented boundaries and staged +retirement are in [[file:06-go-control-plane-role.org][language and cloud integration boundaries]] and the +[[file:../50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org][delivery plan]]. Upstream interfaces and implementation evidence determine +ecosystem reuse; local tests qualify integration behavior and runtime limits. +Existing failed performance cohorts remain failures; this allocation does not +establish submillisecond execution or remote CI qualification. * One architecture, three different kinds of responsibility @@ -73,7 +48,7 @@ owned parts of the system to which those contracts apply. | Element | Core architectural role | Relationship to the execution chain | |---------+-------------------------+-------------------------------------| | Scheme / POO | Governance authoring, composition, source and lifecycle ownership | Selects the admitted policy closure and supplies owner-bound operation/currentness contracts | -| Go | Cloud-native control services and selected network/protocol integrations | Reconciles infrastructure, integrates workload identity, distributes admitted publications and normalizes operations; cannot mint an execution right | +| Go | Current typed transport; OpenSysML development tooling; optional justified SDK integration | Carries source proposals and observations; no deployed semantic selector, Workflow interpreter or execution right | | Rust | Reference authority integration, durable coordinator and constrained broker | Enforces consumption, ledger transitions, unique claims and final transport guards | | Cedar | Shared authorization language and selected evaluation kernel | Evaluates the complete required permission questions on the bound operation; allow alone cannot send | | Quint | Concurrent/fault state model | Models consumption, commit, claim, send, recovery and cloud-update races across all implementation owners | @@ -86,13 +61,12 @@ and Lean proof checking are not per-packet RPCs. An admitted profile may still require a Lean-native evaluator at operation time: proof checking and policy evaluation are distinct activities, and optimization must preserve that profile. -The reference placement is deliberate: Go brings the Kubernetes/network/Gerbil toolchain -integration ecosystem; Rust reuses the native authority boundary and provides -explicit ownership for physical coordination; Scheme preserves POO-native -Governance. Neither cloud readiness nor the implementation language confers -trust. Moving a qualified adapter to Go does not move policy ownership or relax -the final-send contract. The overview below shows this relationship; the -[[file:09-code-as-policy.org][policy-to-wire contract]] specifies how it constrains actual egress. +The allocation is deliberate: Rust owns bounded execution and default cloud +adaptation; Scheme preserves POO-native Governance and gerbil-ascent inference. +Go retains concrete development/integration reuse. Cloud readiness and language +choice grant no authority. Supported protocols can connect external components +without importing their implementation language. The overview below shows the +owner relationships; [[file:09-code-as-policy.org][policy-to-wire contracts]] constrain actual egress. #+caption: Core ownership and assurance relationships; dashed links describe design contracts, not request traffic. [[file:diagrams/01-system-boundaries.svg]] @@ -189,59 +163,51 @@ state transition or a field named =signature= or =durability= cannot establish cryptographic verification, serialized consumption, or durable storage. Preserve these host obligations when reusing the existing semantic APIs. -** Go: networking, protocol integration, and cloud-native operation - -Go has a substantive network-runtime role available to Weaver. Its standard -HTTP transport and reverse-proxy APIs, cancellation conventions, gRPC -ecosystem, and cloud SDKs make it a candidate for network services and -integration-heavy adapters. Kubernetes client and controller libraries add -resource watching, reconciliation, leader election, and status publication. -The source basis is listed as E1 through E5 in the comparison document. - -Possible Go-owned components include: - -- A complete HTTP/gRPC ingress and forwarding service, if qualified. -- Protocol adapters or connectors whose mature SDKs reduce semantic risk. -- Identity-provider, cloud-service, and service-discovery integrations. -- Kubernetes resource ingestion and reconciliation. -- Publication transport and operational administration. - -The concrete initial Go role is cloud-native integration and operational network -services, including backend discovery and publication/status distribution. Go -ingress and selected connectors remain qualified candidates. The inspected -upstream responsibilities and their relevance to an AI-native gateway are in -[[file:06-go-control-plane-role.org][Go's cloud-native and Agent Gateway role]]. This establishes Go's value beyond -an arbitrary language split without granting its controller effect authority. - -Go-owned ingress is a trusted enforcement component. Rust authorization does -not compensate for a Go adapter mutating the authorized target or payload. -Measure GC work, allocation, goroutine retention, and cancellation under -slow clients; do not assume those costs disqualify Go in advance. - -** Rust: bounded kernels, native integration, and forwarding candidates - -Rust is the initial integration choice for the existing Cedar Rust authority -and native Host boundary, since those components already exist in Rust/C/Lean. -It is also a candidate for parsers, artifact checks, connection management, -stream forwarding, and workloads requiring explicit ownership control. - -This does not imply copying the authority code into Weaver. Prefer an -owner-maintained library or service contract with fixed artifact identities. -Rust async tasks, queues, locks, and allocations still require budgets. -An unsafe or FFI boundary requires its own ownership and lifecycle evidence. - -For the reference coordination topology, Rust owns the physical durable state -adapter and minimal credentialed broker. Scheme retains the existing source, -semantic transition, and local lifecycle ownership. This concrete reference -assignment is defined in [[file:05-authorization-execution-protocol.org][Authorization-to-execution coordination]], while the -Go/Rust forwarding comparison remains a separate decision. - -The exact owner contracts are refined in -[[file:07-source-admission-ledger-fencing.org][Source admission, durable ledger, and fencing contracts]]. The current Scheme -preflight is deliberately undecided; production source admission needs a -distinct issued-family extension, not a wrapper that renames preflight as allow. -The existing backend descriptor also needs a versioned coordination facet and -physical qualification before its capabilities can support this ledger. +** Go: typed transport, development tools and selected SDK reuse + +The default Go command performs source preparation and exits; operation clients +connect directly to the existing Rust listener. JSON/YAML and compiled Scheme +sources declare exact fixed plans or a bounded catalog selector through the +existing authenticated source RPC. The existing ledger retains those source +scopes. Rust resolves fixed plans directly; dynamic selection uses the existing +Scheme/POO/ASCENT owner and rejoins current source/publication/catalog state in +the task-registration transaction. Reused projections carry no permission. +Go's explicit =serve= path remains for reference controls and later R5 retirement. +R1's remaining Bundle/routing functions serve development/reference callers. + +OpenSysML development analysis/rendering remains Go because the project already +reuses its SDK. Future production Go adapters need a concrete required library +surface, such as embedded Helm release lifecycle behavior, whose upstream code +justifies keeping that adapter. Kubernetes is supported directly by Rust kube-rs; +OTel Collector and other external services can be reused over supported protocols. +Do not implement both ecosystems locally to prove established capabilities. + +R2 supplies direct Rust ingress for fixed and catalog-selected operations, preserving +first-hop OAuth identity, complete response release, trailers, cancellation and +backpressure. R5 removes obsolete packaging after all consumers migrate. +Independent review/metering issuer custody is a separate decision and cannot +be merged into the runtime during language consolidation. + +** Rust: bounded execution and cloud adaptation + +Rust owns the current ledger, admission, source lane, broker and native authority +integration. Reuse those owners and the upstream Cedar/SPEC contracts rather +than copying their policy semantics. Rust/Tokio is also the default placement +for Kubernetes and protocol adaptation, with explicit queue/concurrency and +shutdown isolation from request processing. + +The existing SDK Build Packages mechanism builds the fixed Scheme application; +the affine owner invokes it through rooted C ABI values. Configuration, source +assessment, hot inference, network delivery and drain have separate lifecycles +and budgets. A build is not a per-request operation. FFI and async ownership +still require concrete lifetime and cancellation checks. + +Scheme retains semantic composition and local object/Workflow behavior; Rust +performs current Cedar/ledger checks and owns physical effects. See +[[file:05-authorization-execution-protocol.org][authorization-to-execution coordination]] and +[[file:07-source-admission-ledger-fencing.org][source admission and ledger fencing]]. CompileSource's source assessment, +ComposeSource's inert advisory projection and actual publication/consumption +are distinct contracts. Neither source API response establishes permission. ** Cross-language boundary rules diff --git a/docs/architecture/06-go-control-plane-role.org b/docs/architecture/06-go-control-plane-role.org index 29fe169e..9acc8d1f 100644 --- a/docs/architecture/06-go-control-plane-role.org +++ b/docs/architecture/06-go-control-plane-role.org @@ -2,238 +2,139 @@ # # SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 -#+title: Go in Weaver and Agentgateway: Cloud-Native Role and Boundaries +#+title: Rust, Scheme and Go: Runtime and Cloud Integration Boundaries #+language: en -#+date: 2026-10-18 -#+property: STATUS source-reviewed-proposed-placement -#+options: toc:3 -#+link: ag https://github.com/agentgateway/agentgateway/blob/955d56fae09b45f3cb8e85e797dbb1eb06134f77/%s - -* Answer and evidence boundary - -Go's role is to make an AI-native gateway an operable network/cloud service: -infrastructure discovery, resource reconciliation, identity integration, -configuration distribution, deployment lifecycle, and potentially selected -network adapters. It need not run an AI agent, implement model reasoning, or -own the policy semantics to provide substantial value. - -The inspected agentgateway snapshot uses Go for its Kubernetes/controller and -control-plane integration and Rust for its proxy runtime. That observation is -not an argument that Weaver must use the same placement. The ecosystem rationale -below is an inference from the inspected integrations, not a statement of the -upstream authors' undocumented motives or a benchmark result. - -For reproducibility, a clone of the earlier fetched snapshot now exists at -=.data/agentgateway=, with origin set to the upstream URL and HEAD fixed at -=955d56fae09b45f3cb8e85e797dbb1eb06134f77=. It was cloned locally from the -already fetched upstream reference, not refreshed to a new remote head. -The research checkout is ignored and is not a Weaver runtime dependency. - -* Code as Policy responsibility - -Go makes the policy service operable through Kubernetes/network ecosystem -integration: bounded discovery, authenticated artifact delivery, workload -identity, generation-aware status, and requested drain/replacement. It cannot -turn controller acceptance, a callback acknowledgment, or a Pod deletion request -into policy approval, source admission, physical retirement evidence, or a new -emission handle. The admitted Code as Policy closure and its error behavior -remain the same for a Go connector and a Rust connector. See -[[file:09-code-as-policy.org][Code as Policy]] and the [[file:05-authorization-execution-protocol.org][callback and state contracts]]. - -* What the inspected Go code actually does - -| Source | Observed responsibility | Relevance to an AI-native gateway | -|--------+-------------------------+----------------------------------| -| [[ag:controller/cmd/agentgateway/main.go][Controller command]] | Starts setup and its managed services | Deployment and operational lifecycle entrypoint | -| [[ag:controller/pkg/setup/setup.go][Setup]] | Creates controller-runtime manager and leader election configuration | Coordinate Kubernetes controllers without inventing a second watch stack | -| [[ag:controller/pkg/syncer/syncer.go][Syncer]] | Watches/joins Kubernetes resource collections and produces gateway resources | Keep routing/backends aligned with dynamic cloud infrastructure | -| [[ag:controller/pkg/agentgateway/translator/agw.go][Gateway API translation]] | Translates route matches and reports unsupported values | Map Kubernetes-facing APIs into proxy configuration | -| [[ag:controller/pkg/syncer/backend/mcp.go][MCP selector targets]] | Selects Services/namespaces and translates MCP backend targets | Discover tool backends through the same service inventory | -| [[ag:controller/pkg/setup/controlplane.go][xDS server]] | Hosts gRPC discovery service, TLS/authentication hooks and shutdown | Distribute changing configuration to proxy instances | -| [[ag:controller/pkg/setup/authn.go][Kubernetes JWT authentication]] | TokenReview with an agentgateway audience and service-account/namespace identity | Authenticate a control-plane peer using cloud-native identity | -| [[ag:controller/pkg/syncer/krtxds/pushqueue.go][Push queue]] | Coalesces pending changes and tracks pushes in progress | Avoid redundant update fanout under churn | -| [[ag:controller/pkg/syncer/status_syncer.go][Status synchronization]] | Writes conditions for gateways, routes, backends, models and inference pools | Expose reconciliation feedback to operators | -| [[ag:crates/agentgateway/src/proxy/httpproxy.rs][Rust HTTP proxy]] | Processes protocol/backend request paths | Demonstrates that Go integration and proxy forwarding are distinct owners here | - -These files establish responsibilities, not their correctness under every -deployment. Dependency presence, controller readiness, and successful xDS delivery -do not establish exact application authorization or final effect admission. - -* Why Go is a useful fit - -Kubernetes resources change continuously: Pods move, Services select endpoints, -Secrets rotate, route references cross namespaces, and backends become ready or -unavailable. Go's controller-runtime/client-go ecosystem provides reusable -patterns for this reconciliation, cache/watch, identity, and status work. The -inspected syncer also uses Istio KRT collections; it is not simply a handwritten -HTTP server. Compatibility and dependency cost still need evaluation. - -For an AI-native gateway, the same lifecycle applies to tool servers, model -backends, inference pools, workload identities, and their discovery metadata. -This makes Go useful even when all payload forwarding remains in Rust. An -MCP target appearing in a Service selector is discovery evidence; it is not -permission to invoke that tool. - -Go also has a substantial networking/SDK ecosystem. Qualified Go ingress, -gRPC services, provider connectors, and identity adapters remain placement -candidates. Measure their actual streaming, cancellation, allocation, GC, and -integration behavior. Do not demote Go to a controller by language rule, or -assume that cloud-native friendliness proves it should own every hot path. - -* Concrete Weaver reference placement - -1. Go owns the cloud integration services: observe Kubernetes/infrastructure, - reconcile operational state, propose scoped endpoint/route updates, deliver - admitted publications, and report their observed activation/rejection. -2. Scheme owns POO semantic composition, domain Governance, capability selection, - source-bound assessment and lifecycle transitions. Go submits authenticated - observations and intent; it does not recreate these meanings in CRD handlers. -3. The reference Rust runtime owns physical durable coordination, strict Cedar - authority integration, credentialed final dispatch, and their failure handling, - following [[file:05-authorization-execution-protocol.org][Authorization-to-execution coordination]]. -4. A selected Go or Rust protocol adapter produces the frozen request. A Go - adapter that actually emits credentialed traffic becomes a qualified final - broker with the same obligations, not an exemption from the Rust reference path. - -This gives Go a concrete first responsibility while keeping network placement -evidence-driven. Standalone Weaver can omit Kubernetes reconciliation and use -the same publication/authority contracts. A Kubernetes installation does not -need to import a second agent orchestration framework merely to use Go. - -* Go interfaces: operational control without ambient send authority - -Go's initial placement is a first-class control and integration plane, not a -requirement to implement an agent reasoning loop. An AI gateway must keep tool -servers, model endpoints, identities and routes operable as cloud resources -change. Reusing Go's ecosystem for that work avoids rebuilding the surrounding -cloud platform inside the policy kernel. - -| Go boundary | Input and output | Consumer and authority limit | -|-------------+------------------+------------------------------| -| Infrastructure observer | Scoped watch events become endpoint/route proposals with tenant, provenance and freshness | Scheme/source owner assesses semantic eligibility; runtime activates only admitted scope | -| Identity integration | Authenticated workload/issuer/audience facts with their expiry and acquisition context | Authority binds the exact actor/delegation; authentication does not imply permission | -| Publication transport | Owner-admitted closure and dependency set delivered to named runtime instances | Runtime validates activation and rollback constraints; Go reports actual observed status | -| Protocol adapter | HTTP/gRPC/MCP/provider input becomes one immutable operation and bounded payload reference | Authority/coordinator receives the exact action, recipient, payload and obligations | -| Lifecycle operator | Scoped drain/replacement intent and observed health | Physical owner retires or fences capabilities; controller cannot declare an old emitter stopped | - -These are logical service contracts, not new RPC implementations or a selected -serialization library. Preserve the existing POO owner interfaces and extend -only their identified missing contracts. Endpoint proposals, identity facts, -policy publications and frozen operations must not share an untyped -configuration channel that lets a controller accidentally issue authority. -An operational constraint may narrow an admitted route; widening it requires -fresh owner admission. - -** An agent tool call through the reference placement - -Go discovers candidate tool backends and integrates the caller's workload -identity. Scheme selects the applicable Governance closure and supplies its -source/lifecycle contract. A Go or Rust adapter freezes the specific tool -operation. The Rust authority evaluates the required Cedar checks, and the -coordinator consumes the grant, commits history/budget obligations and claims -one attempt. Only the constrained broker can redeem that claim for the bound -credentialed upstream operation. Returning a tool result crosses a separate -response-release boundary. - -An SDK convenience call cannot occur between discovery and that broker as an -unrecorded shortcut. A Go connector either hands off the complete frozen -operation without unrestricted application credentials, or is explicitly -selected as the final broker and assumes the same isolation, claim and transport -contract. Its provider SDK must expose control over retries, redirects, token -scope, connection identity and streaming behavior. If those controls cannot -preserve the contract, that connector is unavailable for the protected profile. - -** Watch loss, update churn and control-plane outage - -Watches and reconciliation are asynchronous. Queue coalescing may reduce work, -but cannot erase an ordered revocation or label stale observations as current. -An endpoint replacement cannot mutate an already authorized operation. It must -satisfy that operation's admitted destination constraints or start a newly -admitted operation; frozen intent does not mean blindly using a stale endpoint. - -If Go's control services are unavailable, the data path may use only a still -valid admitted closure and source/identity leases whose contract explicitly -permits that independence. Required freshness that cannot be established blocks -admission or the applicable checkpoint. There is no unconditional cached-allow -or last-known-good permission mode. A restarted controller reobserves state; -it cannot restore a spent claim or turn an unknown send into an absent effect. - -Keep watches, joins and status fanout outside the per-operation serialization -section. Reuse bounded connection pools and immutable admitted artifacts where -their currentness contracts allow it. Request-time identity/source checks that -are mandatory remain explicit costs, even when their integration is Go-owned. - -* Deep adapter-to-broker contract - -The focused [[file:13-go-adapter-broker-boundary.org][Go adapter to Rust broker review]] defines exact SDK construction/handoff, -application-start multiplicity below client APIs, immutable message/range staging, -route/connection identity, credential release and conservative unknown outcomes. -Its [[file:diagrams/14-adapter-broker-boundary.svg][core boundary view]] makes the constrained submission path explicit. Go -control-plane integration does not grant the adapter an upstream network path; -SDK plugins and background work cannot inherit such authority. Retried internal -RPCs resolve the same bound command; they do not retry the external effect. - -* Streaming producer limits - -The selected [[file:14-stream-message-authorization.org][message-stream profile]] keeps Go's assembly/staging bounded and inert. -Rust verifies complete immutable messages, holds parent-backed credits before -queue eligibility and owns the stream writer. Multiple Go producers cannot -convert their local queue or a Session pending list into budget or dispatch -rights. The one authorized message slot per stream preserves P15's finite -synchronous lifecycle reuse; independent streams can still run concurrently. - -* Cloud-native state versus execution authority - -| Cloud observation or mechanism | Permitted conclusion | Forbidden conclusion | -|--------------------------------+----------------------+----------------------| -| TokenReview succeeds | Peer has the validated workload identity/audience | It may issue grants, change another tenant, or invoke arbitrary internal RPCs | -| Controller wins leader election | It may perform its delegated reconciliation role | Old dispatch workers are fenced or an effect may be replayed | -| Route Accepted / Programmed | Controller/proxy reports the named resource state | A particular operation passed Governance and authorization | -| Service endpoint becomes ready | Endpoint is a candidate within an admitted backend scope | Endpoint inherits secrets/capabilities from any matching label | -| xDS ACK or push completes | Delivery/acceptance observation for a resource version | All dependent closures or all replicas are active and current | -| Metrics show low token spend | An observed usage sample exists | Global budget has free capacity or unknown requests were uncharged | -| Pod rescheduled | A new worker may request its own scoped identity | Old claims, grants, history, or uncertain effects are reset | - -Kubernetes leader election is not a fencing protocol for arbitrary network -effects. Runtime claim/fence and the no-redispatch rule survive controller or Pod -replacement. Readiness must reflect actual qualified runtime dependencies; -it cannot override an expired issuer lease or incomplete recovery state. - -The concrete source/ledger/fencing contract is in -[[file:07-source-admission-ledger-fencing.org][Source admission, durable ledger, and fencing contracts]]. Go requests a -supervised replacement under its delegated role; it does not choose the ledger -fence, recreate owner-issued source handles, or clear a spent dispatch claim. -It reports quiescing/unknown when physical retirement is unproven, rather than -turning controller convergence into a stopped-old-worker assertion. - -RBAC and workload identities should be role-specific. Separate discovery reads, -status writes, publication proposals, publication signing, runtime admission, -and credential access. A controller that watches Secrets or mutates Deployments -has a material trust role; minimize that scope and include it in the compromise -model. Preserve namespace/tenant provenance across translations, label selectors, -ReferenceGrant handling, service discovery, and workload identity validation. - -* Performance and validation implications - -Keep resource watching, large joins, translation, and status publication outside -the request's admission/dispatch critical section. Coalesce safe update work, -but never merge away a revocation or report old state as current. Bound queues, -staging memory, fanout, stale watch intervals, and resynchronization after loss. - -Evaluate Go's value along two independent dimensions: - -- Integration quality: correctness under watch restart, version skew, secret - rotation, endpoint churn, permissions, status generation, and tenant isolation. -- Network-path quality, when selected: full protocol conformance, equal strict - authorization/coordination semantics, streaming behavior, resource use, and - failure containment compared with the Rust candidate. - -Source inspection does not yet choose an upstream library embedding API, a -specific Kubernetes version, an Agent SDK, or a Go proxy implementation. Record -the actual benefit and maintenance owner before adding those dependencies. - -* Embedded architecture views - -** 14-adapter-broker-boundary.svg - -[[file:diagrams/14-adapter-broker-boundary.svg]] +#+date: 2026-11-10 +#+property: STATUS R1-R2-locally-verified-later-stages-planned +#+options: toc:2 + +* Architecture decision + +The production target is Rust + Scheme/POO/gerbil-ascent. Rust owns network I/O, +bounded queues, durable state and final effects. Scheme owns higher-order +configuration, object composition, rule inference and Workflow semantics. Go +is optional for concrete integration/development reuse; it is not a required +planning hop in the target architecture. R2's default source-preparation command +exits before fixed or catalog-selected operations reach Rust directly. Only +explicit =serve= retains the Go relay for reference controls and R5 retirement. + +The model authority is [[file:../../dev/sysml/ArchitectureEvolution.sysml][ArchitectureEvolution::RustSchemeAllocation]], +linked to [[file:../../dev/sysml/WeaverExecution.sysml][WeaverExecution]] and the existing source, ledger and object-lifecycle +contracts. The [[file:../50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org][delivery plan]] records the implementation matrix, finite acceptance, +failed evidence and retirement order. R1 does not qualify the outstanding 1 ms +latency gate or establish exact-head GitHub CI. + +* Current ownership after R1 + +| Responsibility | Owner and existing mechanism | +|----------------+------------------------------| +| Decode external JSON/YAML syntax and copy typed data | Existing Go file adapter; no semantic selection | +| Candidate eligibility, exact rounded cost/latency/digest ranking | Scheme POO records and gerbil-ascent on the existing affine owner | +| Session topology, nested choice/parallel/join and ready-node derivation | Existing Scheme Session/Funflow/Governor and ASCENT | +| Canonical plan/body commitments and request/profile/endpoint guards | Rust contracts and shared HTTPS transport guard | +| Configuration/source proposal delivery | Existing authenticated source gRPC; Go currently transports the data | +| Catalog observation and typed fact projection | Existing Rust source owner and ledger; no second database | +| Immutable projection reuse | Existing version/record cache and bounded coalescing; no cached permission | +| Publication, exact source/currentness, claim, reservation, hard-fact barriers | Existing Rust deciding transactions | +| Credentialed request, streamed response release, fallback and uncertain outcomes | Existing Rust broker/runtime; R2 fixed/catalog callers connect directly, retained relay callers use serve | +| Independently issued SPEC review and terminal usage signatures | Existing separate issuer custody; language migration cannot merge keys | +| OpenSysML analysis, model rendering and development drivers | Go, retained for direct existing SDK reuse | + +The Go routing/Bundle algorithms still have development/reference callers. +Deployment bootstrap and dynamic request materialization no longer invoke them. +Their later physical removal follows consumer migration; there is no second +production selector or Workflow runtime in Go. + +* Composition and authority are different boundaries + +Startup catalogs can declare an already composed original or a bounded source +composition, never both. The existing Scheme owner composes the latter, Rust +validates it, and only then seals the exact original. Later CompileSource calls +still compare the candidate against independently retained original data with +SourceExpectation equality. No request can replace an installed producer. + +File-source and dynamic catalog inputs use source-only ComposeSource. The RPC +returns inert data; it cannot publish, install a catalog, enroll a source, +resolve a hard-fact barrier or produce a consumed permit. Source authority is +checked before and after derivation. Catalog-backed requests require the exact +observed version and recheck it afterward. Full source assessment remains in +CompileSource; pure composition does not delay listener readiness with module +source evaluation. Rust keeps fresh deciding checks at actual use. + +The Go adapter copies independent SPEC review data without regenerating it. +A new candidate or source response cannot self-approve the publication it +suggests. See [[file:09-code-as-policy.org][Code as Policy]], [[file:05-authorization-execution-protocol.org][authorization-to-execution coordination]] and +[[file:13-go-adapter-broker-boundary.org][adapter-to-broker custody]]. + +* Request and cloud-adapter separation + +Target request path: +client -> Rust ingress/admission -> prepared projection or necessary bounded +Scheme derivation -> Rust ledger/Cedar/claim/reservation -> broker -> response +release. Complete released receipts drive the existing Governor progression; +a pending queue entry or a historical receipt is not permission to send. + +Target configuration/fact path: +file or authenticated cloud observation -> Rust source adapter -> existing +persisted intent -> Scheme/POO/ASCENT impact/reconciliation -> existing Rust +prepare/publish/activate transactions -> observed status. Scheme derivation +cannot release a barrier; the deciding transaction checks exact source revision +and intent prefix. There is no Kubernetes API access in response forwarding. + +Cloud observations retain cluster/resource identity, UID, opaque resourceVersion +and generation separately from ledger revisions. Duplicate/reordered watch +notifications, relist, deletion/recreation and reconnect cannot revive revoked +facts. Coalesce recomputation demand, never accepted intent or unknown holds. +Kubernetes leader election, Programmed status and xDS ACK are observations; +they do not fence old workers, resolve uncertain effects or free shared quota. + +Use separate bounded adapter queues, concurrency and credentials even when an +adapter and runtime share Rust/Tokio. A slow controller, collector or control-plane +outage cannot consume the frame writer's execution budget. See the existing +[[file:14-stream-message-authorization.org][stream-message contract]] for immutable messages, credits and complete release. + +* Long-term cloud-native reuse + +Language choice follows the required integration and its existing evidence: + +| Existing evidence | Allocation decision | +|-------------------+---------------------| +| kube-rs client/controller/CRD interfaces and Praxis Grid's Rust dependency set | Rust is a viable default for Kubernetes; implementing it does not require a Go controller | +| Agentgateway's Go controller dependencies include Kubernetes, Gateway API, Istio, Helm and xDS | Go can aggregate substantial integration machinery when those exact capabilities are required | +| Helm pkg/action provides release lifecycle APIs | An embedded Helm lifecycle can justify a separate Go deployment adapter; ordinary chart installation need not be embedded | +| containerd exposes a rich Go client and remote service APIs | Choose protocol access or a Go SDK by required lifecycle behavior; do not turn the gateway into a container orchestrator by default | +| OpenTelemetry Collector is independently deployed and Rust has an SDK | Reuse the Collector through its interface; its Go implementation does not require embedding Go | + +These decisions use upstream source/interfaces and maintenance evidence. Weaver +need not implement both ecosystems or rerun generic ecosystem benchmarks to +justify them. Local tests check our integration's authority, behavior, failure +handling and actual runtime gates. No speculative Go adapter or generic plugin +host is added solely to retain a language. + +References: +- https://github.com/kube-rs/kube +- https://github.com/praxis-proxy/grid/blob/main/Cargo.toml +- https://github.com/agentgateway/agentgateway/blob/main/go.mod +- https://agentgateway.dev/docs/kubernetes/latest/documentation/about/architecture/ +- https://github.com/helm/helm/blob/main/pkg/action/action.go +- https://github.com/containerd/containerd/blob/main/client/client.go +- https://opentelemetry.io/docs/collector/ +- https://opentelemetry.io/docs/languages/rust/ + +* Delivery and retirement order + +1. R1: consolidate deployed source selection/composition in Scheme and Rust; + retain OpenSysML and finite existing reference controls. +2. R2: replace the Go request/frame relay with direct authenticated Rust ingress, + preserving OAuth first-hop binding, trailers, cancellation and complete release. +3. R3: finish startup/source lifecycle consolidation through existing owners and + ledger transactions; preserve restart, withdrawal and A-to-B-to-A behavior. +4. R4: add the first required cloud integration, Rust by default, with an isolated + Go adapter only where upstream SDK evidence selects it. +5. R5: remove obsolete production Go packaging and reference algorithms after all + consumers migrate; decide development tooling and independent issuers separately. + +Finite R1 evidence and remaining gates live in the delivery plan. Compile, +listener readiness, first source assessment, hot execution and drain are separate +measurements. The same release and original acceptance thresholds apply; a +language-placement change alone does not satisfy the outstanding 1 ms target. diff --git a/go/api/gateway/v1/gateway.pb.go b/go/api/gateway/v1/gateway.pb.go index f58dde43..f3540b94 100644 --- a/go/api/gateway/v1/gateway.pb.go +++ b/go/api/gateway/v1/gateway.pb.go @@ -917,6 +917,302 @@ func (x *SourceArtifact) GetPublication() *PublishRequest { return nil } +type RoutingCandidate struct { + state protoimpl.MessageState `protogen:"open.v1"` + Module string `protobuf:"bytes,1,opt,name=module,proto3" json:"module,omitempty"` + Capabilities []string `protobuf:"bytes,2,rep,name=capabilities,proto3" json:"capabilities,omitempty"` + LatencyMs uint64 `protobuf:"varint,3,opt,name=latency_ms,json=latencyMs,proto3" json:"latency_ms,omitempty"` + ProcurementRates []uint64 `protobuf:"varint,4,rep,packed,name=procurement_rates,json=procurementRates,proto3" json:"procurement_rates,omitempty"` + TokenBounds []uint64 `protobuf:"varint,5,rep,packed,name=token_bounds,json=tokenBounds,proto3" json:"token_bounds,omitempty"` + Plan *ProviderPlan `protobuf:"bytes,6,opt,name=plan,proto3" json:"plan,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RoutingCandidate) Reset() { + *x = RoutingCandidate{} + mi := &file_gateway_v1_gateway_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoutingCandidate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoutingCandidate) ProtoMessage() {} + +func (x *RoutingCandidate) ProtoReflect() protoreflect.Message { + mi := &file_gateway_v1_gateway_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RoutingCandidate.ProtoReflect.Descriptor instead. +func (*RoutingCandidate) Descriptor() ([]byte, []int) { + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{10} +} + +func (x *RoutingCandidate) GetModule() string { + if x != nil { + return x.Module + } + return "" +} + +func (x *RoutingCandidate) GetCapabilities() []string { + if x != nil { + return x.Capabilities + } + return nil +} + +func (x *RoutingCandidate) GetLatencyMs() uint64 { + if x != nil { + return x.LatencyMs + } + return 0 +} + +func (x *RoutingCandidate) GetProcurementRates() []uint64 { + if x != nil { + return x.ProcurementRates + } + return nil +} + +func (x *RoutingCandidate) GetTokenBounds() []uint64 { + if x != nil { + return x.TokenBounds + } + return nil +} + +func (x *RoutingCandidate) GetPlan() *ProviderPlan { + if x != nil { + return x.Plan + } + return nil +} + +type RoutingSelection struct { + state protoimpl.MessageState `protogen:"open.v1"` + Node string `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` + AllowedModules []string `protobuf:"bytes,2,rep,name=allowed_modules,json=allowedModules,proto3" json:"allowed_modules,omitempty"` + Required []string `protobuf:"bytes,3,rep,name=required,proto3" json:"required,omitempty"` + MaxLatencyMs uint64 `protobuf:"varint,4,opt,name=max_latency_ms,json=maxLatencyMs,proto3" json:"max_latency_ms,omitempty"` + MaxProcurementCost uint64 `protobuf:"varint,5,opt,name=max_procurement_cost,json=maxProcurementCost,proto3" json:"max_procurement_cost,omitempty"` + UserTokenRates []uint64 `protobuf:"varint,6,rep,packed,name=user_token_rates,json=userTokenRates,proto3" json:"user_token_rates,omitempty"` + Candidates []*RoutingCandidate `protobuf:"bytes,7,rep,name=candidates,proto3" json:"candidates,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RoutingSelection) Reset() { + *x = RoutingSelection{} + mi := &file_gateway_v1_gateway_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoutingSelection) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoutingSelection) ProtoMessage() {} + +func (x *RoutingSelection) ProtoReflect() protoreflect.Message { + mi := &file_gateway_v1_gateway_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RoutingSelection.ProtoReflect.Descriptor instead. +func (*RoutingSelection) Descriptor() ([]byte, []int) { + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{11} +} + +func (x *RoutingSelection) GetNode() string { + if x != nil { + return x.Node + } + return "" +} + +func (x *RoutingSelection) GetAllowedModules() []string { + if x != nil { + return x.AllowedModules + } + return nil +} + +func (x *RoutingSelection) GetRequired() []string { + if x != nil { + return x.Required + } + return nil +} + +func (x *RoutingSelection) GetMaxLatencyMs() uint64 { + if x != nil { + return x.MaxLatencyMs + } + return 0 +} + +func (x *RoutingSelection) GetMaxProcurementCost() uint64 { + if x != nil { + return x.MaxProcurementCost + } + return 0 +} + +func (x *RoutingSelection) GetUserTokenRates() []uint64 { + if x != nil { + return x.UserTokenRates + } + return nil +} + +func (x *RoutingSelection) GetCandidates() []*RoutingCandidate { + if x != nil { + return x.Candidates + } + return nil +} + +type SourceCompositionRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Source *SourceArtifact `protobuf:"bytes,1,opt,name=source,proto3" json:"source,omitempty"` + Routing []*RoutingSelection `protobuf:"bytes,2,rep,name=routing,proto3" json:"routing,omitempty"` + UseCatalog bool `protobuf:"varint,3,opt,name=use_catalog,json=useCatalog,proto3" json:"use_catalog,omitempty"` + ExpectedCatalogVersion string `protobuf:"bytes,4,opt,name=expected_catalog_version,json=expectedCatalogVersion,proto3" json:"expected_catalog_version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SourceCompositionRequest) Reset() { + *x = SourceCompositionRequest{} + mi := &file_gateway_v1_gateway_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SourceCompositionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SourceCompositionRequest) ProtoMessage() {} + +func (x *SourceCompositionRequest) ProtoReflect() protoreflect.Message { + mi := &file_gateway_v1_gateway_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SourceCompositionRequest.ProtoReflect.Descriptor instead. +func (*SourceCompositionRequest) Descriptor() ([]byte, []int) { + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{12} +} + +func (x *SourceCompositionRequest) GetSource() *SourceArtifact { + if x != nil { + return x.Source + } + return nil +} + +func (x *SourceCompositionRequest) GetRouting() []*RoutingSelection { + if x != nil { + return x.Routing + } + return nil +} + +func (x *SourceCompositionRequest) GetUseCatalog() bool { + if x != nil { + return x.UseCatalog + } + return false +} + +func (x *SourceCompositionRequest) GetExpectedCatalogVersion() string { + if x != nil { + return x.ExpectedCatalogVersion + } + return "" +} + +type SourceCompositionReply struct { + state protoimpl.MessageState `protogen:"open.v1"` + Artifact *SourceArtifact `protobuf:"bytes,1,opt,name=artifact,proto3" json:"artifact,omitempty"` + CatalogVersion string `protobuf:"bytes,2,opt,name=catalog_version,json=catalogVersion,proto3" json:"catalog_version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SourceCompositionReply) Reset() { + *x = SourceCompositionReply{} + mi := &file_gateway_v1_gateway_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SourceCompositionReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SourceCompositionReply) ProtoMessage() {} + +func (x *SourceCompositionReply) ProtoReflect() protoreflect.Message { + mi := &file_gateway_v1_gateway_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SourceCompositionReply.ProtoReflect.Descriptor instead. +func (*SourceCompositionReply) Descriptor() ([]byte, []int) { + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{13} +} + +func (x *SourceCompositionReply) GetArtifact() *SourceArtifact { + if x != nil { + return x.Artifact + } + return nil +} + +func (x *SourceCompositionReply) GetCatalogVersion() string { + if x != nil { + return x.CatalogVersion + } + return "" +} + // Source authority here is knowledge at response admission, never a later permit. type CompiledSource struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -929,7 +1225,7 @@ type CompiledSource struct { func (x *CompiledSource) Reset() { *x = CompiledSource{} - mi := &file_gateway_v1_gateway_proto_msgTypes[10] + mi := &file_gateway_v1_gateway_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -941,7 +1237,7 @@ func (x *CompiledSource) String() string { func (*CompiledSource) ProtoMessage() {} func (x *CompiledSource) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[10] + mi := &file_gateway_v1_gateway_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -954,7 +1250,7 @@ func (x *CompiledSource) ProtoReflect() protoreflect.Message { // Deprecated: Use CompiledSource.ProtoReflect.Descriptor instead. func (*CompiledSource) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{10} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{14} } func (x *CompiledSource) GetProducer() string { @@ -988,7 +1284,7 @@ type OperationKey struct { func (x *OperationKey) Reset() { *x = OperationKey{} - mi := &file_gateway_v1_gateway_proto_msgTypes[11] + mi := &file_gateway_v1_gateway_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1000,7 +1296,7 @@ func (x *OperationKey) String() string { func (*OperationKey) ProtoMessage() {} func (x *OperationKey) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[11] + mi := &file_gateway_v1_gateway_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1013,7 +1309,7 @@ func (x *OperationKey) ProtoReflect() protoreflect.Message { // Deprecated: Use OperationKey.ProtoReflect.Descriptor instead. func (*OperationKey) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{11} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{15} } func (x *OperationKey) GetFamily() string { @@ -1040,7 +1336,7 @@ type Route struct { func (x *Route) Reset() { *x = Route{} - mi := &file_gateway_v1_gateway_proto_msgTypes[12] + mi := &file_gateway_v1_gateway_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1052,7 +1348,7 @@ func (x *Route) String() string { func (*Route) ProtoMessage() {} func (x *Route) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[12] + mi := &file_gateway_v1_gateway_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1065,7 +1361,7 @@ func (x *Route) ProtoReflect() protoreflect.Message { // Deprecated: Use Route.ProtoReflect.Descriptor instead. func (*Route) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{12} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{16} } func (x *Route) GetTarget() string { @@ -1100,7 +1396,7 @@ type ProviderPlan struct { func (x *ProviderPlan) Reset() { *x = ProviderPlan{} - mi := &file_gateway_v1_gateway_proto_msgTypes[13] + mi := &file_gateway_v1_gateway_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1112,7 +1408,7 @@ func (x *ProviderPlan) String() string { func (*ProviderPlan) ProtoMessage() {} func (x *ProviderPlan) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[13] + mi := &file_gateway_v1_gateway_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1125,7 +1421,7 @@ func (x *ProviderPlan) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderPlan.ProtoReflect.Descriptor instead. func (*ProviderPlan) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{13} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{17} } func (x *ProviderPlan) GetFamily() string { @@ -1210,7 +1506,7 @@ type ProviderRequest struct { func (x *ProviderRequest) Reset() { *x = ProviderRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[14] + mi := &file_gateway_v1_gateway_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1222,7 +1518,7 @@ func (x *ProviderRequest) String() string { func (*ProviderRequest) ProtoMessage() {} func (x *ProviderRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[14] + mi := &file_gateway_v1_gateway_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1235,7 +1531,7 @@ func (x *ProviderRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderRequest.ProtoReflect.Descriptor instead. func (*ProviderRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{14} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{18} } func (x *ProviderRequest) GetPlan() *ProviderPlan { @@ -1276,7 +1572,7 @@ type ProviderCatalogSnapshot struct { func (x *ProviderCatalogSnapshot) Reset() { *x = ProviderCatalogSnapshot{} - mi := &file_gateway_v1_gateway_proto_msgTypes[15] + mi := &file_gateway_v1_gateway_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1288,7 +1584,7 @@ func (x *ProviderCatalogSnapshot) String() string { func (*ProviderCatalogSnapshot) ProtoMessage() {} func (x *ProviderCatalogSnapshot) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[15] + mi := &file_gateway_v1_gateway_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1301,7 +1597,7 @@ func (x *ProviderCatalogSnapshot) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderCatalogSnapshot.ProtoReflect.Descriptor instead. func (*ProviderCatalogSnapshot) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{15} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{19} } func (x *ProviderCatalogSnapshot) GetVersion() string { @@ -1327,7 +1623,7 @@ type ProviderCatalogChange struct { func (x *ProviderCatalogChange) Reset() { *x = ProviderCatalogChange{} - mi := &file_gateway_v1_gateway_proto_msgTypes[16] + mi := &file_gateway_v1_gateway_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1339,7 +1635,7 @@ func (x *ProviderCatalogChange) String() string { func (*ProviderCatalogChange) ProtoMessage() {} func (x *ProviderCatalogChange) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[16] + mi := &file_gateway_v1_gateway_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1352,7 +1648,7 @@ func (x *ProviderCatalogChange) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderCatalogChange.ProtoReflect.Descriptor instead. func (*ProviderCatalogChange) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{16} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{20} } func (x *ProviderCatalogChange) GetRecord() []byte { @@ -1374,7 +1670,7 @@ type Event struct { func (x *Event) Reset() { *x = Event{} - mi := &file_gateway_v1_gateway_proto_msgTypes[17] + mi := &file_gateway_v1_gateway_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1386,7 +1682,7 @@ func (x *Event) String() string { func (*Event) ProtoMessage() {} func (x *Event) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[17] + mi := &file_gateway_v1_gateway_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1399,7 +1695,7 @@ func (x *Event) ProtoReflect() protoreflect.Message { // Deprecated: Use Event.ProtoReflect.Descriptor instead. func (*Event) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{17} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{21} } func (x *Event) GetSequence() uint64 { @@ -1441,7 +1737,7 @@ type ArrowBatch struct { func (x *ArrowBatch) Reset() { *x = ArrowBatch{} - mi := &file_gateway_v1_gateway_proto_msgTypes[18] + mi := &file_gateway_v1_gateway_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1453,7 +1749,7 @@ func (x *ArrowBatch) String() string { func (*ArrowBatch) ProtoMessage() {} func (x *ArrowBatch) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[18] + mi := &file_gateway_v1_gateway_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1466,7 +1762,7 @@ func (x *ArrowBatch) ProtoReflect() protoreflect.Message { // Deprecated: Use ArrowBatch.ProtoReflect.Descriptor instead. func (*ArrowBatch) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{18} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{22} } func (x *ArrowBatch) GetIpc() []byte { @@ -1505,7 +1801,7 @@ type ProviderFrame struct { func (x *ProviderFrame) Reset() { *x = ProviderFrame{} - mi := &file_gateway_v1_gateway_proto_msgTypes[19] + mi := &file_gateway_v1_gateway_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1517,7 +1813,7 @@ func (x *ProviderFrame) String() string { func (*ProviderFrame) ProtoMessage() {} func (x *ProviderFrame) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[19] + mi := &file_gateway_v1_gateway_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1530,7 +1826,7 @@ func (x *ProviderFrame) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderFrame.ProtoReflect.Descriptor instead. func (*ProviderFrame) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{19} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{23} } func (x *ProviderFrame) GetTarget() string { @@ -1604,7 +1900,7 @@ type ProviderReceipt struct { func (x *ProviderReceipt) Reset() { *x = ProviderReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[20] + mi := &file_gateway_v1_gateway_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1616,7 +1912,7 @@ func (x *ProviderReceipt) String() string { func (*ProviderReceipt) ProtoMessage() {} func (x *ProviderReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[20] + mi := &file_gateway_v1_gateway_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1629,7 +1925,7 @@ func (x *ProviderReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderReceipt.ProtoReflect.Descriptor instead. func (*ProviderReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{20} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{24} } func (x *ProviderReceipt) GetFamily() string { @@ -1708,7 +2004,7 @@ type Task struct { func (x *Task) Reset() { *x = Task{} - mi := &file_gateway_v1_gateway_proto_msgTypes[21] + mi := &file_gateway_v1_gateway_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1720,7 +2016,7 @@ func (x *Task) String() string { func (*Task) ProtoMessage() {} func (x *Task) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[21] + mi := &file_gateway_v1_gateway_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1733,7 +2029,7 @@ func (x *Task) ProtoReflect() protoreflect.Message { // Deprecated: Use Task.ProtoReflect.Descriptor instead. func (*Task) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{21} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{25} } func (x *Task) GetFamily() string { @@ -1833,7 +2129,7 @@ type ProviderProfile struct { func (x *ProviderProfile) Reset() { *x = ProviderProfile{} - mi := &file_gateway_v1_gateway_proto_msgTypes[22] + mi := &file_gateway_v1_gateway_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1845,7 +2141,7 @@ func (x *ProviderProfile) String() string { func (*ProviderProfile) ProtoMessage() {} func (x *ProviderProfile) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[22] + mi := &file_gateway_v1_gateway_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1858,7 +2154,7 @@ func (x *ProviderProfile) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderProfile.ProtoReflect.Descriptor instead. func (*ProviderProfile) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{22} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{26} } func (x *ProviderProfile) GetId() string { @@ -1905,7 +2201,7 @@ type RegisterTaskRequest struct { func (x *RegisterTaskRequest) Reset() { *x = RegisterTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[23] + mi := &file_gateway_v1_gateway_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1917,7 +2213,7 @@ func (x *RegisterTaskRequest) String() string { func (*RegisterTaskRequest) ProtoMessage() {} func (x *RegisterTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[23] + mi := &file_gateway_v1_gateway_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1930,7 +2226,7 @@ func (x *RegisterTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{23} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{27} } func (x *RegisterTaskRequest) GetTask() *Task { @@ -1952,7 +2248,7 @@ type DomainBinding struct { func (x *DomainBinding) Reset() { *x = DomainBinding{} - mi := &file_gateway_v1_gateway_proto_msgTypes[24] + mi := &file_gateway_v1_gateway_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1964,7 +2260,7 @@ func (x *DomainBinding) String() string { func (*DomainBinding) ProtoMessage() {} func (x *DomainBinding) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[24] + mi := &file_gateway_v1_gateway_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1977,7 +2273,7 @@ func (x *DomainBinding) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainBinding.ProtoReflect.Descriptor instead. func (*DomainBinding) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{24} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{28} } func (x *DomainBinding) GetOrigin() string { @@ -2022,7 +2318,7 @@ type DomainStamp struct { func (x *DomainStamp) Reset() { *x = DomainStamp{} - mi := &file_gateway_v1_gateway_proto_msgTypes[25] + mi := &file_gateway_v1_gateway_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2034,7 +2330,7 @@ func (x *DomainStamp) String() string { func (*DomainStamp) ProtoMessage() {} func (x *DomainStamp) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[25] + mi := &file_gateway_v1_gateway_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2047,7 +2343,7 @@ func (x *DomainStamp) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainStamp.ProtoReflect.Descriptor instead. func (*DomainStamp) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{25} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{29} } func (x *DomainStamp) GetOrigin() string { @@ -2106,7 +2402,7 @@ type DomainView struct { func (x *DomainView) Reset() { *x = DomainView{} - mi := &file_gateway_v1_gateway_proto_msgTypes[26] + mi := &file_gateway_v1_gateway_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2118,7 +2414,7 @@ func (x *DomainView) String() string { func (*DomainView) ProtoMessage() {} func (x *DomainView) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[26] + mi := &file_gateway_v1_gateway_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2131,7 +2427,7 @@ func (x *DomainView) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainView.ProtoReflect.Descriptor instead. func (*DomainView) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{26} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{30} } func (x *DomainView) GetFamily() string { @@ -2187,7 +2483,7 @@ type RegisterDomainTaskRequest struct { func (x *RegisterDomainTaskRequest) Reset() { *x = RegisterDomainTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[27] + mi := &file_gateway_v1_gateway_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2199,7 +2495,7 @@ func (x *RegisterDomainTaskRequest) String() string { func (*RegisterDomainTaskRequest) ProtoMessage() {} func (x *RegisterDomainTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[27] + mi := &file_gateway_v1_gateway_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2212,7 +2508,7 @@ func (x *RegisterDomainTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterDomainTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterDomainTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{27} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{31} } func (x *RegisterDomainTaskRequest) GetTask() *Task { @@ -2247,7 +2543,7 @@ type TaskAdmission struct { func (x *TaskAdmission) Reset() { *x = TaskAdmission{} - mi := &file_gateway_v1_gateway_proto_msgTypes[28] + mi := &file_gateway_v1_gateway_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2259,7 +2555,7 @@ func (x *TaskAdmission) String() string { func (*TaskAdmission) ProtoMessage() {} func (x *TaskAdmission) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[28] + mi := &file_gateway_v1_gateway_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2272,7 +2568,7 @@ func (x *TaskAdmission) ProtoReflect() protoreflect.Message { // Deprecated: Use TaskAdmission.ProtoReflect.Descriptor instead. func (*TaskAdmission) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{28} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{32} } func (x *TaskAdmission) GetTaskKey() string { @@ -2308,7 +2604,7 @@ type RegisterOriginalTaskRequest struct { func (x *RegisterOriginalTaskRequest) Reset() { *x = RegisterOriginalTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[29] + mi := &file_gateway_v1_gateway_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2320,7 +2616,7 @@ func (x *RegisterOriginalTaskRequest) String() string { func (*RegisterOriginalTaskRequest) ProtoMessage() {} func (x *RegisterOriginalTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[29] + mi := &file_gateway_v1_gateway_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2333,7 +2629,7 @@ func (x *RegisterOriginalTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterOriginalTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterOriginalTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{29} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{33} } func (x *RegisterOriginalTaskRequest) GetTask() *Task { @@ -2378,7 +2674,7 @@ type TaskAdmissionReceipt struct { func (x *TaskAdmissionReceipt) Reset() { *x = TaskAdmissionReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[30] + mi := &file_gateway_v1_gateway_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2390,7 +2686,7 @@ func (x *TaskAdmissionReceipt) String() string { func (*TaskAdmissionReceipt) ProtoMessage() {} func (x *TaskAdmissionReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[30] + mi := &file_gateway_v1_gateway_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2403,7 +2699,7 @@ func (x *TaskAdmissionReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use TaskAdmissionReceipt.ProtoReflect.Descriptor instead. func (*TaskAdmissionReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{30} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{34} } func (x *TaskAdmissionReceipt) GetOperationId() string { @@ -2458,7 +2754,7 @@ type FamilyAliasRequest struct { func (x *FamilyAliasRequest) Reset() { *x = FamilyAliasRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[31] + mi := &file_gateway_v1_gateway_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2470,7 +2766,7 @@ func (x *FamilyAliasRequest) String() string { func (*FamilyAliasRequest) ProtoMessage() {} func (x *FamilyAliasRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[31] + mi := &file_gateway_v1_gateway_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2483,7 +2779,7 @@ func (x *FamilyAliasRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FamilyAliasRequest.ProtoReflect.Descriptor instead. func (*FamilyAliasRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{31} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{35} } func (x *FamilyAliasRequest) GetFamily() string { @@ -2517,7 +2813,7 @@ type DomainMigration struct { func (x *DomainMigration) Reset() { *x = DomainMigration{} - mi := &file_gateway_v1_gateway_proto_msgTypes[32] + mi := &file_gateway_v1_gateway_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2529,7 +2825,7 @@ func (x *DomainMigration) String() string { func (*DomainMigration) ProtoMessage() {} func (x *DomainMigration) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[32] + mi := &file_gateway_v1_gateway_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2542,7 +2838,7 @@ func (x *DomainMigration) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainMigration.ProtoReflect.Descriptor instead. func (*DomainMigration) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{32} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{36} } func (x *DomainMigration) GetOperationId() string { @@ -2623,7 +2919,7 @@ type DomainMigrationReceipt struct { func (x *DomainMigrationReceipt) Reset() { *x = DomainMigrationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[33] + mi := &file_gateway_v1_gateway_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2635,7 +2931,7 @@ func (x *DomainMigrationReceipt) String() string { func (*DomainMigrationReceipt) ProtoMessage() {} func (x *DomainMigrationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[33] + mi := &file_gateway_v1_gateway_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2648,7 +2944,7 @@ func (x *DomainMigrationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainMigrationReceipt.ProtoReflect.Descriptor instead. func (*DomainMigrationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{33} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{37} } func (x *DomainMigrationReceipt) GetOperationId() string { @@ -2701,17 +2997,20 @@ func (x *DomainMigrationReceipt) GetHistoryEpoch() uint64 { } // Distinct source capability: both fields are required by the server. No fallback. +// Exactly one of task or source_scope. The latter declares a bounded deferred +// selection or immutable original under authenticated source custody; never an operation permit. type RegisterPublishedTaskRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Task *Task `protobuf:"bytes,1,opt,name=task,proto3" json:"task,omitempty"` - Publication *PublicationKey `protobuf:"bytes,2,opt,name=publication,proto3" json:"publication,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Task *Task `protobuf:"bytes,1,opt,name=task,proto3" json:"task,omitempty"` + Publication *PublicationKey `protobuf:"bytes,2,opt,name=publication,proto3" json:"publication,omitempty"` + SourceScope *SourceCompositionRequest `protobuf:"bytes,3,opt,name=source_scope,json=sourceScope,proto3" json:"source_scope,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *RegisterPublishedTaskRequest) Reset() { *x = RegisterPublishedTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[34] + mi := &file_gateway_v1_gateway_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2723,7 +3022,7 @@ func (x *RegisterPublishedTaskRequest) String() string { func (*RegisterPublishedTaskRequest) ProtoMessage() {} func (x *RegisterPublishedTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[34] + mi := &file_gateway_v1_gateway_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2736,7 +3035,7 @@ func (x *RegisterPublishedTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterPublishedTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterPublishedTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{34} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{38} } func (x *RegisterPublishedTaskRequest) GetTask() *Task { @@ -2753,6 +3052,13 @@ func (x *RegisterPublishedTaskRequest) GetPublication() *PublicationKey { return nil } +func (x *RegisterPublishedTaskRequest) GetSourceScope() *SourceCompositionRequest { + if x != nil { + return x.SourceScope + } + return nil +} + type PublishRequest struct { state protoimpl.MessageState `protogen:"open.v1"` ExpectedRevision *uint64 `protobuf:"varint,1,opt,name=expected_revision,json=expectedRevision,proto3,oneof" json:"expected_revision,omitempty"` @@ -2766,7 +3072,7 @@ type PublishRequest struct { func (x *PublishRequest) Reset() { *x = PublishRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[35] + mi := &file_gateway_v1_gateway_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2778,7 +3084,7 @@ func (x *PublishRequest) String() string { func (*PublishRequest) ProtoMessage() {} func (x *PublishRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[35] + mi := &file_gateway_v1_gateway_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2791,7 +3097,7 @@ func (x *PublishRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PublishRequest.ProtoReflect.Descriptor instead. func (*PublishRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{35} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{39} } func (x *PublishRequest) GetExpectedRevision() uint64 { @@ -2842,7 +3148,7 @@ type PublicationReceipt struct { func (x *PublicationReceipt) Reset() { *x = PublicationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[36] + mi := &file_gateway_v1_gateway_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2854,7 +3160,7 @@ func (x *PublicationReceipt) String() string { func (*PublicationReceipt) ProtoMessage() {} func (x *PublicationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[36] + mi := &file_gateway_v1_gateway_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2867,7 +3173,7 @@ func (x *PublicationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationReceipt.ProtoReflect.Descriptor instead. func (*PublicationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{36} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{40} } func (x *PublicationReceipt) GetOperationId() string { @@ -2915,7 +3221,7 @@ type PublicationKey struct { func (x *PublicationKey) Reset() { *x = PublicationKey{} - mi := &file_gateway_v1_gateway_proto_msgTypes[37] + mi := &file_gateway_v1_gateway_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2927,7 +3233,7 @@ func (x *PublicationKey) String() string { func (*PublicationKey) ProtoMessage() {} func (x *PublicationKey) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[37] + mi := &file_gateway_v1_gateway_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2940,7 +3246,7 @@ func (x *PublicationKey) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationKey.ProtoReflect.Descriptor instead. func (*PublicationKey) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{37} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{41} } func (x *PublicationKey) GetOperationId() string { @@ -2967,7 +3273,7 @@ type SourceAuthorityView struct { func (x *SourceAuthorityView) Reset() { *x = SourceAuthorityView{} - mi := &file_gateway_v1_gateway_proto_msgTypes[38] + mi := &file_gateway_v1_gateway_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2979,7 +3285,7 @@ func (x *SourceAuthorityView) String() string { func (*SourceAuthorityView) ProtoMessage() {} func (x *SourceAuthorityView) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[38] + mi := &file_gateway_v1_gateway_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2992,7 +3298,7 @@ func (x *SourceAuthorityView) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceAuthorityView.ProtoReflect.Descriptor instead. func (*SourceAuthorityView) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{38} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{42} } func (x *SourceAuthorityView) GetEpoch() uint64 { @@ -3022,7 +3328,7 @@ type SourceRotationRequest struct { func (x *SourceRotationRequest) Reset() { *x = SourceRotationRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[39] + mi := &file_gateway_v1_gateway_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3034,7 +3340,7 @@ func (x *SourceRotationRequest) String() string { func (*SourceRotationRequest) ProtoMessage() {} func (x *SourceRotationRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[39] + mi := &file_gateway_v1_gateway_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3047,7 +3353,7 @@ func (x *SourceRotationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceRotationRequest.ProtoReflect.Descriptor instead. func (*SourceRotationRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{39} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{43} } func (x *SourceRotationRequest) GetOperationId() string { @@ -3090,7 +3396,7 @@ type SourceRotationReceipt struct { func (x *SourceRotationReceipt) Reset() { *x = SourceRotationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[40] + mi := &file_gateway_v1_gateway_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3102,7 +3408,7 @@ func (x *SourceRotationReceipt) String() string { func (*SourceRotationReceipt) ProtoMessage() {} func (x *SourceRotationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[40] + mi := &file_gateway_v1_gateway_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3115,7 +3421,7 @@ func (x *SourceRotationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceRotationReceipt.ProtoReflect.Descriptor instead. func (*SourceRotationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{40} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{44} } func (x *SourceRotationReceipt) GetOperationId() string { @@ -3159,7 +3465,7 @@ type AuthorityParent struct { func (x *AuthorityParent) Reset() { *x = AuthorityParent{} - mi := &file_gateway_v1_gateway_proto_msgTypes[41] + mi := &file_gateway_v1_gateway_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3171,7 +3477,7 @@ func (x *AuthorityParent) String() string { func (*AuthorityParent) ProtoMessage() {} func (x *AuthorityParent) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[41] + mi := &file_gateway_v1_gateway_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3184,7 +3490,7 @@ func (x *AuthorityParent) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthorityParent.ProtoReflect.Descriptor instead. func (*AuthorityParent) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{41} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{45} } func (x *AuthorityParent) GetRevision() uint64 { @@ -3228,7 +3534,7 @@ type ReviewAuthority struct { func (x *ReviewAuthority) Reset() { *x = ReviewAuthority{} - mi := &file_gateway_v1_gateway_proto_msgTypes[42] + mi := &file_gateway_v1_gateway_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3240,7 +3546,7 @@ func (x *ReviewAuthority) String() string { func (*ReviewAuthority) ProtoMessage() {} func (x *ReviewAuthority) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[42] + mi := &file_gateway_v1_gateway_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3253,7 +3559,7 @@ func (x *ReviewAuthority) ProtoReflect() protoreflect.Message { // Deprecated: Use ReviewAuthority.ProtoReflect.Descriptor instead. func (*ReviewAuthority) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{42} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{46} } func (x *ReviewAuthority) GetAudience() string { @@ -3302,7 +3608,7 @@ type PublicationReview struct { func (x *PublicationReview) Reset() { *x = PublicationReview{} - mi := &file_gateway_v1_gateway_proto_msgTypes[43] + mi := &file_gateway_v1_gateway_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3314,7 +3620,7 @@ func (x *PublicationReview) String() string { func (*PublicationReview) ProtoMessage() {} func (x *PublicationReview) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[43] + mi := &file_gateway_v1_gateway_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3327,7 +3633,7 @@ func (x *PublicationReview) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationReview.ProtoReflect.Descriptor instead. func (*PublicationReview) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{43} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{47} } func (x *PublicationReview) GetPublication() *PublicationKey { @@ -3367,7 +3673,7 @@ type DeltaReview struct { func (x *DeltaReview) Reset() { *x = DeltaReview{} - mi := &file_gateway_v1_gateway_proto_msgTypes[44] + mi := &file_gateway_v1_gateway_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3379,7 +3685,7 @@ func (x *DeltaReview) String() string { func (*DeltaReview) ProtoMessage() {} func (x *DeltaReview) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[44] + mi := &file_gateway_v1_gateway_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3392,7 +3698,7 @@ func (x *DeltaReview) ProtoReflect() protoreflect.Message { // Deprecated: Use DeltaReview.ProtoReflect.Descriptor instead. func (*DeltaReview) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{44} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{48} } func (x *DeltaReview) GetReview() *PublicationReview { @@ -3463,7 +3769,7 @@ type PublicationReviewContext struct { func (x *PublicationReviewContext) Reset() { *x = PublicationReviewContext{} - mi := &file_gateway_v1_gateway_proto_msgTypes[45] + mi := &file_gateway_v1_gateway_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3475,7 +3781,7 @@ func (x *PublicationReviewContext) String() string { func (*PublicationReviewContext) ProtoMessage() {} func (x *PublicationReviewContext) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[45] + mi := &file_gateway_v1_gateway_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3488,7 +3794,7 @@ func (x *PublicationReviewContext) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationReviewContext.ProtoReflect.Descriptor instead. func (*PublicationReviewContext) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{45} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{49} } func (x *PublicationReviewContext) GetPublication() *PublicationKey { @@ -3529,7 +3835,7 @@ type ReviewRegistrationReceipt struct { func (x *ReviewRegistrationReceipt) Reset() { *x = ReviewRegistrationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[46] + mi := &file_gateway_v1_gateway_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3541,7 +3847,7 @@ func (x *ReviewRegistrationReceipt) String() string { func (*ReviewRegistrationReceipt) ProtoMessage() {} func (x *ReviewRegistrationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[46] + mi := &file_gateway_v1_gateway_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3554,7 +3860,7 @@ func (x *ReviewRegistrationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use ReviewRegistrationReceipt.ProtoReflect.Descriptor instead. func (*ReviewRegistrationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{46} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{50} } func (x *ReviewRegistrationReceipt) GetPublication() *PublicationKey { @@ -3584,7 +3890,7 @@ type MeterCredentialRotation struct { func (x *MeterCredentialRotation) Reset() { *x = MeterCredentialRotation{} - mi := &file_gateway_v1_gateway_proto_msgTypes[47] + mi := &file_gateway_v1_gateway_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3596,7 +3902,7 @@ func (x *MeterCredentialRotation) String() string { func (*MeterCredentialRotation) ProtoMessage() {} func (x *MeterCredentialRotation) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[47] + mi := &file_gateway_v1_gateway_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3609,7 +3915,7 @@ func (x *MeterCredentialRotation) ProtoReflect() protoreflect.Message { // Deprecated: Use MeterCredentialRotation.ProtoReflect.Descriptor instead. func (*MeterCredentialRotation) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{47} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{51} } func (x *MeterCredentialRotation) GetTenant() string { @@ -3656,7 +3962,7 @@ type MeterCredentialEpoch struct { func (x *MeterCredentialEpoch) Reset() { *x = MeterCredentialEpoch{} - mi := &file_gateway_v1_gateway_proto_msgTypes[48] + mi := &file_gateway_v1_gateway_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3668,7 +3974,7 @@ func (x *MeterCredentialEpoch) String() string { func (*MeterCredentialEpoch) ProtoMessage() {} func (x *MeterCredentialEpoch) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[48] + mi := &file_gateway_v1_gateway_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3681,7 +3987,7 @@ func (x *MeterCredentialEpoch) ProtoReflect() protoreflect.Message { // Deprecated: Use MeterCredentialEpoch.ProtoReflect.Descriptor instead. func (*MeterCredentialEpoch) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{48} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{52} } func (x *MeterCredentialEpoch) GetEpoch() uint64 { @@ -3712,7 +4018,7 @@ type MeteringReceipt struct { func (x *MeteringReceipt) Reset() { *x = MeteringReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[49] + mi := &file_gateway_v1_gateway_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3724,7 +4030,7 @@ func (x *MeteringReceipt) String() string { func (*MeteringReceipt) ProtoMessage() {} func (x *MeteringReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[49] + mi := &file_gateway_v1_gateway_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3737,7 +4043,7 @@ func (x *MeteringReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use MeteringReceipt.ProtoReflect.Descriptor instead. func (*MeteringReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{49} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{53} } func (x *MeteringReceipt) GetAudience() string { @@ -3842,7 +4148,7 @@ type MeteringApplication struct { func (x *MeteringApplication) Reset() { *x = MeteringApplication{} - mi := &file_gateway_v1_gateway_proto_msgTypes[50] + mi := &file_gateway_v1_gateway_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3854,7 +4160,7 @@ func (x *MeteringApplication) String() string { func (*MeteringApplication) ProtoMessage() {} func (x *MeteringApplication) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[50] + mi := &file_gateway_v1_gateway_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3867,7 +4173,7 @@ func (x *MeteringApplication) ProtoReflect() protoreflect.Message { // Deprecated: Use MeteringApplication.ProtoReflect.Descriptor instead. func (*MeteringApplication) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{50} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{54} } func (x *MeteringApplication) GetApplication() string { @@ -3905,7 +4211,7 @@ type ProviderOAuthChange struct { func (x *ProviderOAuthChange) Reset() { *x = ProviderOAuthChange{} - mi := &file_gateway_v1_gateway_proto_msgTypes[51] + mi := &file_gateway_v1_gateway_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3917,7 +4223,7 @@ func (x *ProviderOAuthChange) String() string { func (*ProviderOAuthChange) ProtoMessage() {} func (x *ProviderOAuthChange) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[51] + mi := &file_gateway_v1_gateway_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3930,7 +4236,7 @@ func (x *ProviderOAuthChange) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderOAuthChange.ProtoReflect.Descriptor instead. func (*ProviderOAuthChange) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{51} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{55} } func (x *ProviderOAuthChange) GetAction() isProviderOAuthChange_Action { @@ -4009,7 +4315,7 @@ type ProviderOAuthGrant struct { func (x *ProviderOAuthGrant) Reset() { *x = ProviderOAuthGrant{} - mi := &file_gateway_v1_gateway_proto_msgTypes[52] + mi := &file_gateway_v1_gateway_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4021,7 +4327,7 @@ func (x *ProviderOAuthGrant) String() string { func (*ProviderOAuthGrant) ProtoMessage() {} func (x *ProviderOAuthGrant) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[52] + mi := &file_gateway_v1_gateway_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4034,7 +4340,7 @@ func (x *ProviderOAuthGrant) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderOAuthGrant.ProtoReflect.Descriptor instead. func (*ProviderOAuthGrant) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{52} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{56} } func (x *ProviderOAuthGrant) GetIssuer() string { @@ -4132,7 +4438,7 @@ type ProviderOAuthIssuerRotation struct { func (x *ProviderOAuthIssuerRotation) Reset() { *x = ProviderOAuthIssuerRotation{} - mi := &file_gateway_v1_gateway_proto_msgTypes[53] + mi := &file_gateway_v1_gateway_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4144,7 +4450,7 @@ func (x *ProviderOAuthIssuerRotation) String() string { func (*ProviderOAuthIssuerRotation) ProtoMessage() {} func (x *ProviderOAuthIssuerRotation) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[53] + mi := &file_gateway_v1_gateway_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4157,7 +4463,7 @@ func (x *ProviderOAuthIssuerRotation) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderOAuthIssuerRotation.ProtoReflect.Descriptor instead. func (*ProviderOAuthIssuerRotation) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{53} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{57} } func (x *ProviderOAuthIssuerRotation) GetExpectedEpoch() uint64 { @@ -4245,7 +4551,34 @@ const file_gateway_v1_gateway_proto_rawDesc = "" + "governance\x12-\n" + "\x05tasks\x18\x02 \x03(\v2\x17.weaver.gateway.v1.TaskR\x05tasks\x125\n" + "\x05plans\x18\x03 \x03(\v2\x1f.weaver.gateway.v1.ProviderPlanR\x05plans\x12C\n" + - "\vpublication\x18\x04 \x01(\v2!.weaver.gateway.v1.PublishRequestR\vpublication\"\xb1\x01\n" + + "\vpublication\x18\x04 \x01(\v2!.weaver.gateway.v1.PublishRequestR\vpublication\"\xf2\x01\n" + + "\x10RoutingCandidate\x12\x16\n" + + "\x06module\x18\x01 \x01(\tR\x06module\x12\"\n" + + "\fcapabilities\x18\x02 \x03(\tR\fcapabilities\x12\x1d\n" + + "\n" + + "latency_ms\x18\x03 \x01(\x04R\tlatencyMs\x12+\n" + + "\x11procurement_rates\x18\x04 \x03(\x04R\x10procurementRates\x12!\n" + + "\ftoken_bounds\x18\x05 \x03(\x04R\vtokenBounds\x123\n" + + "\x04plan\x18\x06 \x01(\v2\x1f.weaver.gateway.v1.ProviderPlanR\x04plan\"\xb2\x02\n" + + "\x10RoutingSelection\x12\x12\n" + + "\x04node\x18\x01 \x01(\tR\x04node\x12'\n" + + "\x0fallowed_modules\x18\x02 \x03(\tR\x0eallowedModules\x12\x1a\n" + + "\brequired\x18\x03 \x03(\tR\brequired\x12$\n" + + "\x0emax_latency_ms\x18\x04 \x01(\x04R\fmaxLatencyMs\x120\n" + + "\x14max_procurement_cost\x18\x05 \x01(\x04R\x12maxProcurementCost\x12(\n" + + "\x10user_token_rates\x18\x06 \x03(\x04R\x0euserTokenRates\x12C\n" + + "\n" + + "candidates\x18\a \x03(\v2#.weaver.gateway.v1.RoutingCandidateR\n" + + "candidates\"\xef\x01\n" + + "\x18SourceCompositionRequest\x129\n" + + "\x06source\x18\x01 \x01(\v2!.weaver.gateway.v1.SourceArtifactR\x06source\x12=\n" + + "\arouting\x18\x02 \x03(\v2#.weaver.gateway.v1.RoutingSelectionR\arouting\x12\x1f\n" + + "\vuse_catalog\x18\x03 \x01(\bR\n" + + "useCatalog\x128\n" + + "\x18expected_catalog_version\x18\x04 \x01(\tR\x16expectedCatalogVersion\"\x80\x01\n" + + "\x16SourceCompositionReply\x12=\n" + + "\bartifact\x18\x01 \x01(\v2!.weaver.gateway.v1.SourceArtifactR\bartifact\x12'\n" + + "\x0fcatalog_version\x18\x02 \x01(\tR\x0ecatalogVersion\"\xb1\x01\n" + "\x0eCompiledSource\x12\x1a\n" + "\bproducer\x18\x01 \x01(\tR\bproducer\x12D\n" + "\tauthority\x18\x02 \x01(\v2&.weaver.gateway.v1.SourceAuthorityViewR\tauthority\x12=\n" + @@ -4402,10 +4735,11 @@ const file_gateway_v1_gateway_proto_rawDesc = "" + "budgetRoot\x12!\n" + "\fhistory_root\x18\x05 \x01(\tR\vhistoryRoot\x12!\n" + "\fbudget_epoch\x18\x06 \x01(\x04R\vbudgetEpoch\x12#\n" + - "\rhistory_epoch\x18\a \x01(\x04R\fhistoryEpoch\"\x90\x01\n" + + "\rhistory_epoch\x18\a \x01(\x04R\fhistoryEpoch\"\xe0\x01\n" + "\x1cRegisterPublishedTaskRequest\x12+\n" + "\x04task\x18\x01 \x01(\v2\x17.weaver.gateway.v1.TaskR\x04task\x12C\n" + - "\vpublication\x18\x02 \x01(\v2!.weaver.gateway.v1.PublicationKeyR\vpublication\"\xc1\x01\n" + + "\vpublication\x18\x02 \x01(\v2!.weaver.gateway.v1.PublicationKeyR\vpublication\x12N\n" + + "\fsource_scope\x18\x03 \x01(\v2+.weaver.gateway.v1.SourceCompositionRequestR\vsourceScope\"\xc1\x01\n" + "\x0ePublishRequest\x120\n" + "\x11expected_revision\x18\x01 \x01(\x04H\x00R\x10expectedRevision\x88\x01\x01\x12\x14\n" + "\x05fence\x18\x02 \x01(\x04R\x05fence\x12\x16\n" + @@ -4542,7 +4876,7 @@ const file_gateway_v1_gateway_proto_rawDesc = "" + "\x1dDELTA_DISPOSITION_UNSPECIFIED\x10\x00\x12\r\n" + "\tBOOTSTRAP\x10\x01\x12\x15\n" + "\x11NO_EXECUTION_GAIN\x10\x02\x12\x15\n" + - "\x11EXPLICIT_APPROVAL\x10\x032\xa7\x14\n" + + "\x11EXPLICIT_APPROVAL\x10\x032\x90\x15\n" + "\aGateway\x12Y\n" + "\x0fExecuteProvider\x12\".weaver.gateway.v1.ProviderRequest\x1a .weaver.gateway.v1.ProviderFrame0\x01\x12N\n" + "\aInspect\x12\x1f.weaver.gateway.v1.OperationKey\x1a\".weaver.gateway.v1.ProviderReceipt\x12l\n" + @@ -4566,7 +4900,8 @@ const file_gateway_v1_gateway_proto_rawDesc = "" + "\x15RotateSourceAuthority\x12(.weaver.gateway.v1.SourceRotationRequest\x1a(.weaver.gateway.v1.SourceRotationReceipt\x12V\n" + "\rStageHardFact\x12!.weaver.gateway.v1.HardFactIntent\x1a\".weaver.gateway.v1.HardFactBarrier\x12_\n" + "\x0fResolveHardFact\x12\".weaver.gateway.v1.HardFactBarrier\x1a(.weaver.gateway.v1.FactBarrierResolution\x12V\n" + - "\rCompileSource\x12\".weaver.gateway.v1.ProducerRequest\x1a!.weaver.gateway.v1.CompiledSource\x12^\n" + + "\rCompileSource\x12\".weaver.gateway.v1.ProducerRequest\x1a!.weaver.gateway.v1.CompiledSource\x12g\n" + + "\rComposeSource\x12+.weaver.gateway.v1.SourceCompositionRequest\x1a).weaver.gateway.v1.SourceCompositionReply\x12^\n" + "\x16InspectProviderCatalog\x12\x18.weaver.gateway.v1.Empty\x1a*.weaver.gateway.v1.ProviderCatalogSnapshot\x12n\n" + "\x16PublishProviderCatalog\x12(.weaver.gateway.v1.ProviderCatalogChange\x1a*.weaver.gateway.v1.ProviderCatalogSnapshot\x12R\n" + "\x10InspectTelemetry\x12\x18.weaver.gateway.v1.Empty\x1a$.weaver.gateway.v1.TelemetrySnapshot\x12W\n" + @@ -4585,7 +4920,7 @@ func file_gateway_v1_gateway_proto_rawDescGZIP() []byte { } var file_gateway_v1_gateway_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_gateway_v1_gateway_proto_msgTypes = make([]protoimpl.MessageInfo, 58) +var file_gateway_v1_gateway_proto_msgTypes = make([]protoimpl.MessageInfo, 62) var file_gateway_v1_gateway_proto_goTypes = []any{ (Encoding)(0), // 0: weaver.gateway.v1.Encoding (PublicationOutcome)(0), // 1: weaver.gateway.v1.PublicationOutcome @@ -4601,159 +4936,171 @@ var file_gateway_v1_gateway_proto_goTypes = []any{ (*WorkflowSelector)(nil), // 11: weaver.gateway.v1.WorkflowSelector (*GovernanceSelection)(nil), // 12: weaver.gateway.v1.GovernanceSelection (*SourceArtifact)(nil), // 13: weaver.gateway.v1.SourceArtifact - (*CompiledSource)(nil), // 14: weaver.gateway.v1.CompiledSource - (*OperationKey)(nil), // 15: weaver.gateway.v1.OperationKey - (*Route)(nil), // 16: weaver.gateway.v1.Route - (*ProviderPlan)(nil), // 17: weaver.gateway.v1.ProviderPlan - (*ProviderRequest)(nil), // 18: weaver.gateway.v1.ProviderRequest - (*ProviderCatalogSnapshot)(nil), // 19: weaver.gateway.v1.ProviderCatalogSnapshot - (*ProviderCatalogChange)(nil), // 20: weaver.gateway.v1.ProviderCatalogChange - (*Event)(nil), // 21: weaver.gateway.v1.Event - (*ArrowBatch)(nil), // 22: weaver.gateway.v1.ArrowBatch - (*ProviderFrame)(nil), // 23: weaver.gateway.v1.ProviderFrame - (*ProviderReceipt)(nil), // 24: weaver.gateway.v1.ProviderReceipt - (*Task)(nil), // 25: weaver.gateway.v1.Task - (*ProviderProfile)(nil), // 26: weaver.gateway.v1.ProviderProfile - (*RegisterTaskRequest)(nil), // 27: weaver.gateway.v1.RegisterTaskRequest - (*DomainBinding)(nil), // 28: weaver.gateway.v1.DomainBinding - (*DomainStamp)(nil), // 29: weaver.gateway.v1.DomainStamp - (*DomainView)(nil), // 30: weaver.gateway.v1.DomainView - (*RegisterDomainTaskRequest)(nil), // 31: weaver.gateway.v1.RegisterDomainTaskRequest - (*TaskAdmission)(nil), // 32: weaver.gateway.v1.TaskAdmission - (*RegisterOriginalTaskRequest)(nil), // 33: weaver.gateway.v1.RegisterOriginalTaskRequest - (*TaskAdmissionReceipt)(nil), // 34: weaver.gateway.v1.TaskAdmissionReceipt - (*FamilyAliasRequest)(nil), // 35: weaver.gateway.v1.FamilyAliasRequest - (*DomainMigration)(nil), // 36: weaver.gateway.v1.DomainMigration - (*DomainMigrationReceipt)(nil), // 37: weaver.gateway.v1.DomainMigrationReceipt - (*RegisterPublishedTaskRequest)(nil), // 38: weaver.gateway.v1.RegisterPublishedTaskRequest - (*PublishRequest)(nil), // 39: weaver.gateway.v1.PublishRequest - (*PublicationReceipt)(nil), // 40: weaver.gateway.v1.PublicationReceipt - (*PublicationKey)(nil), // 41: weaver.gateway.v1.PublicationKey - (*SourceAuthorityView)(nil), // 42: weaver.gateway.v1.SourceAuthorityView - (*SourceRotationRequest)(nil), // 43: weaver.gateway.v1.SourceRotationRequest - (*SourceRotationReceipt)(nil), // 44: weaver.gateway.v1.SourceRotationReceipt - (*AuthorityParent)(nil), // 45: weaver.gateway.v1.AuthorityParent - (*ReviewAuthority)(nil), // 46: weaver.gateway.v1.ReviewAuthority - (*PublicationReview)(nil), // 47: weaver.gateway.v1.PublicationReview - (*DeltaReview)(nil), // 48: weaver.gateway.v1.DeltaReview - (*PublicationReviewContext)(nil), // 49: weaver.gateway.v1.PublicationReviewContext - (*ReviewRegistrationReceipt)(nil), // 50: weaver.gateway.v1.ReviewRegistrationReceipt - (*MeterCredentialRotation)(nil), // 51: weaver.gateway.v1.MeterCredentialRotation - (*MeterCredentialEpoch)(nil), // 52: weaver.gateway.v1.MeterCredentialEpoch - (*MeteringReceipt)(nil), // 53: weaver.gateway.v1.MeteringReceipt - (*MeteringApplication)(nil), // 54: weaver.gateway.v1.MeteringApplication - (*ProviderOAuthChange)(nil), // 55: weaver.gateway.v1.ProviderOAuthChange - (*ProviderOAuthGrant)(nil), // 56: weaver.gateway.v1.ProviderOAuthGrant - (*ProviderOAuthIssuerRotation)(nil), // 57: weaver.gateway.v1.ProviderOAuthIssuerRotation - nil, // 58: weaver.gateway.v1.Task.EndpointsEntry - nil, // 59: weaver.gateway.v1.Task.BodyDigestsEntry - nil, // 60: weaver.gateway.v1.Task.NodeCostBoundsEntry - nil, // 61: weaver.gateway.v1.Task.StreamContractsEntry + (*RoutingCandidate)(nil), // 14: weaver.gateway.v1.RoutingCandidate + (*RoutingSelection)(nil), // 15: weaver.gateway.v1.RoutingSelection + (*SourceCompositionRequest)(nil), // 16: weaver.gateway.v1.SourceCompositionRequest + (*SourceCompositionReply)(nil), // 17: weaver.gateway.v1.SourceCompositionReply + (*CompiledSource)(nil), // 18: weaver.gateway.v1.CompiledSource + (*OperationKey)(nil), // 19: weaver.gateway.v1.OperationKey + (*Route)(nil), // 20: weaver.gateway.v1.Route + (*ProviderPlan)(nil), // 21: weaver.gateway.v1.ProviderPlan + (*ProviderRequest)(nil), // 22: weaver.gateway.v1.ProviderRequest + (*ProviderCatalogSnapshot)(nil), // 23: weaver.gateway.v1.ProviderCatalogSnapshot + (*ProviderCatalogChange)(nil), // 24: weaver.gateway.v1.ProviderCatalogChange + (*Event)(nil), // 25: weaver.gateway.v1.Event + (*ArrowBatch)(nil), // 26: weaver.gateway.v1.ArrowBatch + (*ProviderFrame)(nil), // 27: weaver.gateway.v1.ProviderFrame + (*ProviderReceipt)(nil), // 28: weaver.gateway.v1.ProviderReceipt + (*Task)(nil), // 29: weaver.gateway.v1.Task + (*ProviderProfile)(nil), // 30: weaver.gateway.v1.ProviderProfile + (*RegisterTaskRequest)(nil), // 31: weaver.gateway.v1.RegisterTaskRequest + (*DomainBinding)(nil), // 32: weaver.gateway.v1.DomainBinding + (*DomainStamp)(nil), // 33: weaver.gateway.v1.DomainStamp + (*DomainView)(nil), // 34: weaver.gateway.v1.DomainView + (*RegisterDomainTaskRequest)(nil), // 35: weaver.gateway.v1.RegisterDomainTaskRequest + (*TaskAdmission)(nil), // 36: weaver.gateway.v1.TaskAdmission + (*RegisterOriginalTaskRequest)(nil), // 37: weaver.gateway.v1.RegisterOriginalTaskRequest + (*TaskAdmissionReceipt)(nil), // 38: weaver.gateway.v1.TaskAdmissionReceipt + (*FamilyAliasRequest)(nil), // 39: weaver.gateway.v1.FamilyAliasRequest + (*DomainMigration)(nil), // 40: weaver.gateway.v1.DomainMigration + (*DomainMigrationReceipt)(nil), // 41: weaver.gateway.v1.DomainMigrationReceipt + (*RegisterPublishedTaskRequest)(nil), // 42: weaver.gateway.v1.RegisterPublishedTaskRequest + (*PublishRequest)(nil), // 43: weaver.gateway.v1.PublishRequest + (*PublicationReceipt)(nil), // 44: weaver.gateway.v1.PublicationReceipt + (*PublicationKey)(nil), // 45: weaver.gateway.v1.PublicationKey + (*SourceAuthorityView)(nil), // 46: weaver.gateway.v1.SourceAuthorityView + (*SourceRotationRequest)(nil), // 47: weaver.gateway.v1.SourceRotationRequest + (*SourceRotationReceipt)(nil), // 48: weaver.gateway.v1.SourceRotationReceipt + (*AuthorityParent)(nil), // 49: weaver.gateway.v1.AuthorityParent + (*ReviewAuthority)(nil), // 50: weaver.gateway.v1.ReviewAuthority + (*PublicationReview)(nil), // 51: weaver.gateway.v1.PublicationReview + (*DeltaReview)(nil), // 52: weaver.gateway.v1.DeltaReview + (*PublicationReviewContext)(nil), // 53: weaver.gateway.v1.PublicationReviewContext + (*ReviewRegistrationReceipt)(nil), // 54: weaver.gateway.v1.ReviewRegistrationReceipt + (*MeterCredentialRotation)(nil), // 55: weaver.gateway.v1.MeterCredentialRotation + (*MeterCredentialEpoch)(nil), // 56: weaver.gateway.v1.MeterCredentialEpoch + (*MeteringReceipt)(nil), // 57: weaver.gateway.v1.MeteringReceipt + (*MeteringApplication)(nil), // 58: weaver.gateway.v1.MeteringApplication + (*ProviderOAuthChange)(nil), // 59: weaver.gateway.v1.ProviderOAuthChange + (*ProviderOAuthGrant)(nil), // 60: weaver.gateway.v1.ProviderOAuthGrant + (*ProviderOAuthIssuerRotation)(nil), // 61: weaver.gateway.v1.ProviderOAuthIssuerRotation + nil, // 62: weaver.gateway.v1.Task.EndpointsEntry + nil, // 63: weaver.gateway.v1.Task.BodyDigestsEntry + nil, // 64: weaver.gateway.v1.Task.NodeCostBoundsEntry + nil, // 65: weaver.gateway.v1.Task.StreamContractsEntry } var file_gateway_v1_gateway_proto_depIdxs = []int32{ 8, // 0: weaver.gateway.v1.FactBarrierResolution.barrier:type_name -> weaver.gateway.v1.HardFactBarrier 10, // 1: weaver.gateway.v1.GovernanceSelection.workflow_edges:type_name -> weaver.gateway.v1.WorkflowEdge 11, // 2: weaver.gateway.v1.GovernanceSelection.workflow_selectors:type_name -> weaver.gateway.v1.WorkflowSelector 12, // 3: weaver.gateway.v1.SourceArtifact.governance:type_name -> weaver.gateway.v1.GovernanceSelection - 25, // 4: weaver.gateway.v1.SourceArtifact.tasks:type_name -> weaver.gateway.v1.Task - 17, // 5: weaver.gateway.v1.SourceArtifact.plans:type_name -> weaver.gateway.v1.ProviderPlan - 39, // 6: weaver.gateway.v1.SourceArtifact.publication:type_name -> weaver.gateway.v1.PublishRequest - 42, // 7: weaver.gateway.v1.CompiledSource.authority:type_name -> weaver.gateway.v1.SourceAuthorityView - 13, // 8: weaver.gateway.v1.CompiledSource.artifact:type_name -> weaver.gateway.v1.SourceArtifact - 16, // 9: weaver.gateway.v1.ProviderPlan.routes:type_name -> weaver.gateway.v1.Route - 17, // 10: weaver.gateway.v1.ProviderRequest.plan:type_name -> weaver.gateway.v1.ProviderPlan - 0, // 11: weaver.gateway.v1.ProviderRequest.encoding:type_name -> weaver.gateway.v1.Encoding - 21, // 12: weaver.gateway.v1.ProviderFrame.event:type_name -> weaver.gateway.v1.Event - 22, // 13: weaver.gateway.v1.ProviderFrame.arrow:type_name -> weaver.gateway.v1.ArrowBatch - 58, // 14: weaver.gateway.v1.Task.endpoints:type_name -> weaver.gateway.v1.Task.EndpointsEntry - 59, // 15: weaver.gateway.v1.Task.body_digests:type_name -> weaver.gateway.v1.Task.BodyDigestsEntry - 60, // 16: weaver.gateway.v1.Task.node_cost_bounds:type_name -> weaver.gateway.v1.Task.NodeCostBoundsEntry - 61, // 17: weaver.gateway.v1.Task.stream_contracts:type_name -> weaver.gateway.v1.Task.StreamContractsEntry - 26, // 18: weaver.gateway.v1.Task.provider_profile:type_name -> weaver.gateway.v1.ProviderProfile - 25, // 19: weaver.gateway.v1.RegisterTaskRequest.task:type_name -> weaver.gateway.v1.Task - 29, // 20: weaver.gateway.v1.DomainView.stamp:type_name -> weaver.gateway.v1.DomainStamp - 25, // 21: weaver.gateway.v1.RegisterDomainTaskRequest.task:type_name -> weaver.gateway.v1.Task - 28, // 22: weaver.gateway.v1.RegisterDomainTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding - 41, // 23: weaver.gateway.v1.RegisterDomainTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey - 25, // 24: weaver.gateway.v1.RegisterOriginalTaskRequest.task:type_name -> weaver.gateway.v1.Task - 28, // 25: weaver.gateway.v1.RegisterOriginalTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding - 32, // 26: weaver.gateway.v1.RegisterOriginalTaskRequest.admission:type_name -> weaver.gateway.v1.TaskAdmission - 41, // 27: weaver.gateway.v1.RegisterOriginalTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey - 25, // 28: weaver.gateway.v1.RegisterPublishedTaskRequest.task:type_name -> weaver.gateway.v1.Task - 41, // 29: weaver.gateway.v1.RegisterPublishedTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey - 1, // 30: weaver.gateway.v1.PublicationReceipt.outcome:type_name -> weaver.gateway.v1.PublicationOutcome - 2, // 31: weaver.gateway.v1.SourceRotationReceipt.outcome:type_name -> weaver.gateway.v1.SourceRotationOutcome - 42, // 32: weaver.gateway.v1.SourceRotationReceipt.authority:type_name -> weaver.gateway.v1.SourceAuthorityView - 41, // 33: weaver.gateway.v1.PublicationReview.publication:type_name -> weaver.gateway.v1.PublicationKey - 45, // 34: weaver.gateway.v1.PublicationReview.parent:type_name -> weaver.gateway.v1.AuthorityParent - 47, // 35: weaver.gateway.v1.DeltaReview.review:type_name -> weaver.gateway.v1.PublicationReview - 3, // 36: weaver.gateway.v1.DeltaReview.disposition:type_name -> weaver.gateway.v1.DeltaDisposition - 41, // 37: weaver.gateway.v1.PublicationReviewContext.publication:type_name -> weaver.gateway.v1.PublicationKey - 45, // 38: weaver.gateway.v1.PublicationReviewContext.parent:type_name -> weaver.gateway.v1.AuthorityParent - 46, // 39: weaver.gateway.v1.PublicationReviewContext.reviewer:type_name -> weaver.gateway.v1.ReviewAuthority - 42, // 40: weaver.gateway.v1.PublicationReviewContext.source:type_name -> weaver.gateway.v1.SourceAuthorityView - 41, // 41: weaver.gateway.v1.ReviewRegistrationReceipt.publication:type_name -> weaver.gateway.v1.PublicationKey - 56, // 42: weaver.gateway.v1.ProviderOAuthChange.grant:type_name -> weaver.gateway.v1.ProviderOAuthGrant - 57, // 43: weaver.gateway.v1.ProviderOAuthChange.rotate_issuer:type_name -> weaver.gateway.v1.ProviderOAuthIssuerRotation - 18, // 44: weaver.gateway.v1.Gateway.ExecuteProvider:input_type -> weaver.gateway.v1.ProviderRequest - 15, // 45: weaver.gateway.v1.Gateway.Inspect:input_type -> weaver.gateway.v1.OperationKey - 51, // 46: weaver.gateway.v1.Gateway.RotateMeterCredential:input_type -> weaver.gateway.v1.MeterCredentialRotation - 15, // 47: weaver.gateway.v1.Gateway.InspectTerminalUsage:input_type -> weaver.gateway.v1.OperationKey - 53, // 48: weaver.gateway.v1.Gateway.ApplyMetering:input_type -> weaver.gateway.v1.MeteringReceipt - 27, // 49: weaver.gateway.v1.Gateway.RegisterTask:input_type -> weaver.gateway.v1.RegisterTaskRequest - 38, // 50: weaver.gateway.v1.Gateway.RegisterPublishedTask:input_type -> weaver.gateway.v1.RegisterPublishedTaskRequest - 31, // 51: weaver.gateway.v1.Gateway.RegisterDomainTask:input_type -> weaver.gateway.v1.RegisterDomainTaskRequest - 33, // 52: weaver.gateway.v1.Gateway.RegisterOriginalTask:input_type -> weaver.gateway.v1.RegisterOriginalTaskRequest - 35, // 53: weaver.gateway.v1.Gateway.RegisterFamilyAlias:input_type -> weaver.gateway.v1.FamilyAliasRequest - 36, // 54: weaver.gateway.v1.Gateway.MigrateExecutionDomains:input_type -> weaver.gateway.v1.DomainMigration - 15, // 55: weaver.gateway.v1.Gateway.InspectExecutionDomains:input_type -> weaver.gateway.v1.OperationKey - 39, // 56: weaver.gateway.v1.Gateway.PublishAuthority:input_type -> weaver.gateway.v1.PublishRequest - 39, // 57: weaver.gateway.v1.Gateway.StageAuthority:input_type -> weaver.gateway.v1.PublishRequest - 41, // 58: weaver.gateway.v1.Gateway.InspectPublication:input_type -> weaver.gateway.v1.PublicationKey - 39, // 59: weaver.gateway.v1.Gateway.StageReviewedAuthority:input_type -> weaver.gateway.v1.PublishRequest - 41, // 60: weaver.gateway.v1.Gateway.InspectPublicationReview:input_type -> weaver.gateway.v1.PublicationKey - 48, // 61: weaver.gateway.v1.Gateway.RegisterPublicationReview:input_type -> weaver.gateway.v1.DeltaReview - 5, // 62: weaver.gateway.v1.Gateway.InspectSourceAuthority:input_type -> weaver.gateway.v1.Empty - 43, // 63: weaver.gateway.v1.Gateway.RotateSourceAuthority:input_type -> weaver.gateway.v1.SourceRotationRequest - 7, // 64: weaver.gateway.v1.Gateway.StageHardFact:input_type -> weaver.gateway.v1.HardFactIntent - 8, // 65: weaver.gateway.v1.Gateway.ResolveHardFact:input_type -> weaver.gateway.v1.HardFactBarrier - 6, // 66: weaver.gateway.v1.Gateway.CompileSource:input_type -> weaver.gateway.v1.ProducerRequest - 5, // 67: weaver.gateway.v1.Gateway.InspectProviderCatalog:input_type -> weaver.gateway.v1.Empty - 20, // 68: weaver.gateway.v1.Gateway.PublishProviderCatalog:input_type -> weaver.gateway.v1.ProviderCatalogChange - 5, // 69: weaver.gateway.v1.Gateway.InspectTelemetry:input_type -> weaver.gateway.v1.Empty - 55, // 70: weaver.gateway.v1.Gateway.ChangeProviderOAuth:input_type -> weaver.gateway.v1.ProviderOAuthChange - 23, // 71: weaver.gateway.v1.Gateway.ExecuteProvider:output_type -> weaver.gateway.v1.ProviderFrame - 24, // 72: weaver.gateway.v1.Gateway.Inspect:output_type -> weaver.gateway.v1.ProviderReceipt - 52, // 73: weaver.gateway.v1.Gateway.RotateMeterCredential:output_type -> weaver.gateway.v1.MeterCredentialEpoch - 53, // 74: weaver.gateway.v1.Gateway.InspectTerminalUsage:output_type -> weaver.gateway.v1.MeteringReceipt - 54, // 75: weaver.gateway.v1.Gateway.ApplyMetering:output_type -> weaver.gateway.v1.MeteringApplication - 5, // 76: weaver.gateway.v1.Gateway.RegisterTask:output_type -> weaver.gateway.v1.Empty - 5, // 77: weaver.gateway.v1.Gateway.RegisterPublishedTask:output_type -> weaver.gateway.v1.Empty - 5, // 78: weaver.gateway.v1.Gateway.RegisterDomainTask:output_type -> weaver.gateway.v1.Empty - 34, // 79: weaver.gateway.v1.Gateway.RegisterOriginalTask:output_type -> weaver.gateway.v1.TaskAdmissionReceipt - 30, // 80: weaver.gateway.v1.Gateway.RegisterFamilyAlias:output_type -> weaver.gateway.v1.DomainView - 37, // 81: weaver.gateway.v1.Gateway.MigrateExecutionDomains:output_type -> weaver.gateway.v1.DomainMigrationReceipt - 30, // 82: weaver.gateway.v1.Gateway.InspectExecutionDomains:output_type -> weaver.gateway.v1.DomainView - 40, // 83: weaver.gateway.v1.Gateway.PublishAuthority:output_type -> weaver.gateway.v1.PublicationReceipt - 41, // 84: weaver.gateway.v1.Gateway.StageAuthority:output_type -> weaver.gateway.v1.PublicationKey - 40, // 85: weaver.gateway.v1.Gateway.InspectPublication:output_type -> weaver.gateway.v1.PublicationReceipt - 41, // 86: weaver.gateway.v1.Gateway.StageReviewedAuthority:output_type -> weaver.gateway.v1.PublicationKey - 49, // 87: weaver.gateway.v1.Gateway.InspectPublicationReview:output_type -> weaver.gateway.v1.PublicationReviewContext - 50, // 88: weaver.gateway.v1.Gateway.RegisterPublicationReview:output_type -> weaver.gateway.v1.ReviewRegistrationReceipt - 42, // 89: weaver.gateway.v1.Gateway.InspectSourceAuthority:output_type -> weaver.gateway.v1.SourceAuthorityView - 44, // 90: weaver.gateway.v1.Gateway.RotateSourceAuthority:output_type -> weaver.gateway.v1.SourceRotationReceipt - 8, // 91: weaver.gateway.v1.Gateway.StageHardFact:output_type -> weaver.gateway.v1.HardFactBarrier - 9, // 92: weaver.gateway.v1.Gateway.ResolveHardFact:output_type -> weaver.gateway.v1.FactBarrierResolution - 14, // 93: weaver.gateway.v1.Gateway.CompileSource:output_type -> weaver.gateway.v1.CompiledSource - 19, // 94: weaver.gateway.v1.Gateway.InspectProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot - 19, // 95: weaver.gateway.v1.Gateway.PublishProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot - 4, // 96: weaver.gateway.v1.Gateway.InspectTelemetry:output_type -> weaver.gateway.v1.TelemetrySnapshot - 5, // 97: weaver.gateway.v1.Gateway.ChangeProviderOAuth:output_type -> weaver.gateway.v1.Empty - 71, // [71:98] is the sub-list for method output_type - 44, // [44:71] is the sub-list for method input_type - 44, // [44:44] is the sub-list for extension type_name - 44, // [44:44] is the sub-list for extension extendee - 0, // [0:44] is the sub-list for field type_name + 29, // 4: weaver.gateway.v1.SourceArtifact.tasks:type_name -> weaver.gateway.v1.Task + 21, // 5: weaver.gateway.v1.SourceArtifact.plans:type_name -> weaver.gateway.v1.ProviderPlan + 43, // 6: weaver.gateway.v1.SourceArtifact.publication:type_name -> weaver.gateway.v1.PublishRequest + 21, // 7: weaver.gateway.v1.RoutingCandidate.plan:type_name -> weaver.gateway.v1.ProviderPlan + 14, // 8: weaver.gateway.v1.RoutingSelection.candidates:type_name -> weaver.gateway.v1.RoutingCandidate + 13, // 9: weaver.gateway.v1.SourceCompositionRequest.source:type_name -> weaver.gateway.v1.SourceArtifact + 15, // 10: weaver.gateway.v1.SourceCompositionRequest.routing:type_name -> weaver.gateway.v1.RoutingSelection + 13, // 11: weaver.gateway.v1.SourceCompositionReply.artifact:type_name -> weaver.gateway.v1.SourceArtifact + 46, // 12: weaver.gateway.v1.CompiledSource.authority:type_name -> weaver.gateway.v1.SourceAuthorityView + 13, // 13: weaver.gateway.v1.CompiledSource.artifact:type_name -> weaver.gateway.v1.SourceArtifact + 20, // 14: weaver.gateway.v1.ProviderPlan.routes:type_name -> weaver.gateway.v1.Route + 21, // 15: weaver.gateway.v1.ProviderRequest.plan:type_name -> weaver.gateway.v1.ProviderPlan + 0, // 16: weaver.gateway.v1.ProviderRequest.encoding:type_name -> weaver.gateway.v1.Encoding + 25, // 17: weaver.gateway.v1.ProviderFrame.event:type_name -> weaver.gateway.v1.Event + 26, // 18: weaver.gateway.v1.ProviderFrame.arrow:type_name -> weaver.gateway.v1.ArrowBatch + 62, // 19: weaver.gateway.v1.Task.endpoints:type_name -> weaver.gateway.v1.Task.EndpointsEntry + 63, // 20: weaver.gateway.v1.Task.body_digests:type_name -> weaver.gateway.v1.Task.BodyDigestsEntry + 64, // 21: weaver.gateway.v1.Task.node_cost_bounds:type_name -> weaver.gateway.v1.Task.NodeCostBoundsEntry + 65, // 22: weaver.gateway.v1.Task.stream_contracts:type_name -> weaver.gateway.v1.Task.StreamContractsEntry + 30, // 23: weaver.gateway.v1.Task.provider_profile:type_name -> weaver.gateway.v1.ProviderProfile + 29, // 24: weaver.gateway.v1.RegisterTaskRequest.task:type_name -> weaver.gateway.v1.Task + 33, // 25: weaver.gateway.v1.DomainView.stamp:type_name -> weaver.gateway.v1.DomainStamp + 29, // 26: weaver.gateway.v1.RegisterDomainTaskRequest.task:type_name -> weaver.gateway.v1.Task + 32, // 27: weaver.gateway.v1.RegisterDomainTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding + 45, // 28: weaver.gateway.v1.RegisterDomainTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey + 29, // 29: weaver.gateway.v1.RegisterOriginalTaskRequest.task:type_name -> weaver.gateway.v1.Task + 32, // 30: weaver.gateway.v1.RegisterOriginalTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding + 36, // 31: weaver.gateway.v1.RegisterOriginalTaskRequest.admission:type_name -> weaver.gateway.v1.TaskAdmission + 45, // 32: weaver.gateway.v1.RegisterOriginalTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey + 29, // 33: weaver.gateway.v1.RegisterPublishedTaskRequest.task:type_name -> weaver.gateway.v1.Task + 45, // 34: weaver.gateway.v1.RegisterPublishedTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey + 16, // 35: weaver.gateway.v1.RegisterPublishedTaskRequest.source_scope:type_name -> weaver.gateway.v1.SourceCompositionRequest + 1, // 36: weaver.gateway.v1.PublicationReceipt.outcome:type_name -> weaver.gateway.v1.PublicationOutcome + 2, // 37: weaver.gateway.v1.SourceRotationReceipt.outcome:type_name -> weaver.gateway.v1.SourceRotationOutcome + 46, // 38: weaver.gateway.v1.SourceRotationReceipt.authority:type_name -> weaver.gateway.v1.SourceAuthorityView + 45, // 39: weaver.gateway.v1.PublicationReview.publication:type_name -> weaver.gateway.v1.PublicationKey + 49, // 40: weaver.gateway.v1.PublicationReview.parent:type_name -> weaver.gateway.v1.AuthorityParent + 51, // 41: weaver.gateway.v1.DeltaReview.review:type_name -> weaver.gateway.v1.PublicationReview + 3, // 42: weaver.gateway.v1.DeltaReview.disposition:type_name -> weaver.gateway.v1.DeltaDisposition + 45, // 43: weaver.gateway.v1.PublicationReviewContext.publication:type_name -> weaver.gateway.v1.PublicationKey + 49, // 44: weaver.gateway.v1.PublicationReviewContext.parent:type_name -> weaver.gateway.v1.AuthorityParent + 50, // 45: weaver.gateway.v1.PublicationReviewContext.reviewer:type_name -> weaver.gateway.v1.ReviewAuthority + 46, // 46: weaver.gateway.v1.PublicationReviewContext.source:type_name -> weaver.gateway.v1.SourceAuthorityView + 45, // 47: weaver.gateway.v1.ReviewRegistrationReceipt.publication:type_name -> weaver.gateway.v1.PublicationKey + 60, // 48: weaver.gateway.v1.ProviderOAuthChange.grant:type_name -> weaver.gateway.v1.ProviderOAuthGrant + 61, // 49: weaver.gateway.v1.ProviderOAuthChange.rotate_issuer:type_name -> weaver.gateway.v1.ProviderOAuthIssuerRotation + 22, // 50: weaver.gateway.v1.Gateway.ExecuteProvider:input_type -> weaver.gateway.v1.ProviderRequest + 19, // 51: weaver.gateway.v1.Gateway.Inspect:input_type -> weaver.gateway.v1.OperationKey + 55, // 52: weaver.gateway.v1.Gateway.RotateMeterCredential:input_type -> weaver.gateway.v1.MeterCredentialRotation + 19, // 53: weaver.gateway.v1.Gateway.InspectTerminalUsage:input_type -> weaver.gateway.v1.OperationKey + 57, // 54: weaver.gateway.v1.Gateway.ApplyMetering:input_type -> weaver.gateway.v1.MeteringReceipt + 31, // 55: weaver.gateway.v1.Gateway.RegisterTask:input_type -> weaver.gateway.v1.RegisterTaskRequest + 42, // 56: weaver.gateway.v1.Gateway.RegisterPublishedTask:input_type -> weaver.gateway.v1.RegisterPublishedTaskRequest + 35, // 57: weaver.gateway.v1.Gateway.RegisterDomainTask:input_type -> weaver.gateway.v1.RegisterDomainTaskRequest + 37, // 58: weaver.gateway.v1.Gateway.RegisterOriginalTask:input_type -> weaver.gateway.v1.RegisterOriginalTaskRequest + 39, // 59: weaver.gateway.v1.Gateway.RegisterFamilyAlias:input_type -> weaver.gateway.v1.FamilyAliasRequest + 40, // 60: weaver.gateway.v1.Gateway.MigrateExecutionDomains:input_type -> weaver.gateway.v1.DomainMigration + 19, // 61: weaver.gateway.v1.Gateway.InspectExecutionDomains:input_type -> weaver.gateway.v1.OperationKey + 43, // 62: weaver.gateway.v1.Gateway.PublishAuthority:input_type -> weaver.gateway.v1.PublishRequest + 43, // 63: weaver.gateway.v1.Gateway.StageAuthority:input_type -> weaver.gateway.v1.PublishRequest + 45, // 64: weaver.gateway.v1.Gateway.InspectPublication:input_type -> weaver.gateway.v1.PublicationKey + 43, // 65: weaver.gateway.v1.Gateway.StageReviewedAuthority:input_type -> weaver.gateway.v1.PublishRequest + 45, // 66: weaver.gateway.v1.Gateway.InspectPublicationReview:input_type -> weaver.gateway.v1.PublicationKey + 52, // 67: weaver.gateway.v1.Gateway.RegisterPublicationReview:input_type -> weaver.gateway.v1.DeltaReview + 5, // 68: weaver.gateway.v1.Gateway.InspectSourceAuthority:input_type -> weaver.gateway.v1.Empty + 47, // 69: weaver.gateway.v1.Gateway.RotateSourceAuthority:input_type -> weaver.gateway.v1.SourceRotationRequest + 7, // 70: weaver.gateway.v1.Gateway.StageHardFact:input_type -> weaver.gateway.v1.HardFactIntent + 8, // 71: weaver.gateway.v1.Gateway.ResolveHardFact:input_type -> weaver.gateway.v1.HardFactBarrier + 6, // 72: weaver.gateway.v1.Gateway.CompileSource:input_type -> weaver.gateway.v1.ProducerRequest + 16, // 73: weaver.gateway.v1.Gateway.ComposeSource:input_type -> weaver.gateway.v1.SourceCompositionRequest + 5, // 74: weaver.gateway.v1.Gateway.InspectProviderCatalog:input_type -> weaver.gateway.v1.Empty + 24, // 75: weaver.gateway.v1.Gateway.PublishProviderCatalog:input_type -> weaver.gateway.v1.ProviderCatalogChange + 5, // 76: weaver.gateway.v1.Gateway.InspectTelemetry:input_type -> weaver.gateway.v1.Empty + 59, // 77: weaver.gateway.v1.Gateway.ChangeProviderOAuth:input_type -> weaver.gateway.v1.ProviderOAuthChange + 27, // 78: weaver.gateway.v1.Gateway.ExecuteProvider:output_type -> weaver.gateway.v1.ProviderFrame + 28, // 79: weaver.gateway.v1.Gateway.Inspect:output_type -> weaver.gateway.v1.ProviderReceipt + 56, // 80: weaver.gateway.v1.Gateway.RotateMeterCredential:output_type -> weaver.gateway.v1.MeterCredentialEpoch + 57, // 81: weaver.gateway.v1.Gateway.InspectTerminalUsage:output_type -> weaver.gateway.v1.MeteringReceipt + 58, // 82: weaver.gateway.v1.Gateway.ApplyMetering:output_type -> weaver.gateway.v1.MeteringApplication + 5, // 83: weaver.gateway.v1.Gateway.RegisterTask:output_type -> weaver.gateway.v1.Empty + 5, // 84: weaver.gateway.v1.Gateway.RegisterPublishedTask:output_type -> weaver.gateway.v1.Empty + 5, // 85: weaver.gateway.v1.Gateway.RegisterDomainTask:output_type -> weaver.gateway.v1.Empty + 38, // 86: weaver.gateway.v1.Gateway.RegisterOriginalTask:output_type -> weaver.gateway.v1.TaskAdmissionReceipt + 34, // 87: weaver.gateway.v1.Gateway.RegisterFamilyAlias:output_type -> weaver.gateway.v1.DomainView + 41, // 88: weaver.gateway.v1.Gateway.MigrateExecutionDomains:output_type -> weaver.gateway.v1.DomainMigrationReceipt + 34, // 89: weaver.gateway.v1.Gateway.InspectExecutionDomains:output_type -> weaver.gateway.v1.DomainView + 44, // 90: weaver.gateway.v1.Gateway.PublishAuthority:output_type -> weaver.gateway.v1.PublicationReceipt + 45, // 91: weaver.gateway.v1.Gateway.StageAuthority:output_type -> weaver.gateway.v1.PublicationKey + 44, // 92: weaver.gateway.v1.Gateway.InspectPublication:output_type -> weaver.gateway.v1.PublicationReceipt + 45, // 93: weaver.gateway.v1.Gateway.StageReviewedAuthority:output_type -> weaver.gateway.v1.PublicationKey + 53, // 94: weaver.gateway.v1.Gateway.InspectPublicationReview:output_type -> weaver.gateway.v1.PublicationReviewContext + 54, // 95: weaver.gateway.v1.Gateway.RegisterPublicationReview:output_type -> weaver.gateway.v1.ReviewRegistrationReceipt + 46, // 96: weaver.gateway.v1.Gateway.InspectSourceAuthority:output_type -> weaver.gateway.v1.SourceAuthorityView + 48, // 97: weaver.gateway.v1.Gateway.RotateSourceAuthority:output_type -> weaver.gateway.v1.SourceRotationReceipt + 8, // 98: weaver.gateway.v1.Gateway.StageHardFact:output_type -> weaver.gateway.v1.HardFactBarrier + 9, // 99: weaver.gateway.v1.Gateway.ResolveHardFact:output_type -> weaver.gateway.v1.FactBarrierResolution + 18, // 100: weaver.gateway.v1.Gateway.CompileSource:output_type -> weaver.gateway.v1.CompiledSource + 17, // 101: weaver.gateway.v1.Gateway.ComposeSource:output_type -> weaver.gateway.v1.SourceCompositionReply + 23, // 102: weaver.gateway.v1.Gateway.InspectProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot + 23, // 103: weaver.gateway.v1.Gateway.PublishProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot + 4, // 104: weaver.gateway.v1.Gateway.InspectTelemetry:output_type -> weaver.gateway.v1.TelemetrySnapshot + 5, // 105: weaver.gateway.v1.Gateway.ChangeProviderOAuth:output_type -> weaver.gateway.v1.Empty + 78, // [78:106] is the sub-list for method output_type + 50, // [50:78] is the sub-list for method input_type + 50, // [50:50] is the sub-list for extension type_name + 50, // [50:50] is the sub-list for extension extendee + 0, // [0:50] is the sub-list for field type_name } func init() { file_gateway_v1_gateway_proto_init() } @@ -4763,15 +5110,15 @@ func file_gateway_v1_gateway_proto_init() { } file_gateway_v1_gateway_proto_msgTypes[3].OneofWrappers = []any{} file_gateway_v1_gateway_proto_msgTypes[5].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[19].OneofWrappers = []any{ + file_gateway_v1_gateway_proto_msgTypes[23].OneofWrappers = []any{ (*ProviderFrame_Event)(nil), (*ProviderFrame_Arrow)(nil), } - file_gateway_v1_gateway_proto_msgTypes[35].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[36].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[41].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[42].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[51].OneofWrappers = []any{ + file_gateway_v1_gateway_proto_msgTypes[39].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[40].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[45].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[46].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[55].OneofWrappers = []any{ (*ProviderOAuthChange_Grant)(nil), (*ProviderOAuthChange_RevokeTokenHash)(nil), (*ProviderOAuthChange_RotateIssuer)(nil), @@ -4782,7 +5129,7 @@ func file_gateway_v1_gateway_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_gateway_v1_gateway_proto_rawDesc), len(file_gateway_v1_gateway_proto_rawDesc)), NumEnums: 4, - NumMessages: 58, + NumMessages: 62, NumExtensions: 0, NumServices: 1, }, diff --git a/go/api/gateway/v1/gateway_grpc.pb.go b/go/api/gateway/v1/gateway_grpc.pb.go index da788127..75de8746 100644 --- a/go/api/gateway/v1/gateway_grpc.pb.go +++ b/go/api/gateway/v1/gateway_grpc.pb.go @@ -46,6 +46,7 @@ const ( Gateway_StageHardFact_FullMethodName = "/weaver.gateway.v1.Gateway/StageHardFact" Gateway_ResolveHardFact_FullMethodName = "/weaver.gateway.v1.Gateway/ResolveHardFact" Gateway_CompileSource_FullMethodName = "/weaver.gateway.v1.Gateway/CompileSource" + Gateway_ComposeSource_FullMethodName = "/weaver.gateway.v1.Gateway/ComposeSource" Gateway_InspectProviderCatalog_FullMethodName = "/weaver.gateway.v1.Gateway/InspectProviderCatalog" Gateway_PublishProviderCatalog_FullMethodName = "/weaver.gateway.v1.Gateway/PublishProviderCatalog" Gateway_InspectTelemetry_FullMethodName = "/weaver.gateway.v1.Gateway/InspectTelemetry" @@ -85,6 +86,8 @@ type GatewayClient interface { // Preparation only. Actual ingress/source state selects an installed original; // request labels cannot supply authority, replacement source or module paths. CompileSource(ctx context.Context, in *ProducerRequest, opts ...grpc.CallOption) (*CompiledSource, error) + // Authenticated source-only advisory composition; never publishes or installs an original. + ComposeSource(ctx context.Context, in *SourceCompositionRequest, opts ...grpc.CallOption) (*SourceCompositionReply, error) InspectProviderCatalog(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ProviderCatalogSnapshot, error) PublishProviderCatalog(ctx context.Context, in *ProviderCatalogChange, opts ...grpc.CallOption) (*ProviderCatalogSnapshot, error) // Statistical process-local counters only; never durable execution evidence. @@ -354,6 +357,16 @@ func (c *gatewayClient) CompileSource(ctx context.Context, in *ProducerRequest, return out, nil } +func (c *gatewayClient) ComposeSource(ctx context.Context, in *SourceCompositionRequest, opts ...grpc.CallOption) (*SourceCompositionReply, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(SourceCompositionReply) + err := c.cc.Invoke(ctx, Gateway_ComposeSource_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *gatewayClient) InspectProviderCatalog(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ProviderCatalogSnapshot, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ProviderCatalogSnapshot) @@ -427,6 +440,8 @@ type GatewayServer interface { // Preparation only. Actual ingress/source state selects an installed original; // request labels cannot supply authority, replacement source or module paths. CompileSource(context.Context, *ProducerRequest) (*CompiledSource, error) + // Authenticated source-only advisory composition; never publishes or installs an original. + ComposeSource(context.Context, *SourceCompositionRequest) (*SourceCompositionReply, error) InspectProviderCatalog(context.Context, *Empty) (*ProviderCatalogSnapshot, error) PublishProviderCatalog(context.Context, *ProviderCatalogChange) (*ProviderCatalogSnapshot, error) // Statistical process-local counters only; never durable execution evidence. @@ -509,6 +524,9 @@ func (UnimplementedGatewayServer) ResolveHardFact(context.Context, *HardFactBarr func (UnimplementedGatewayServer) CompileSource(context.Context, *ProducerRequest) (*CompiledSource, error) { return nil, status.Errorf(codes.Unimplemented, "method CompileSource not implemented") } +func (UnimplementedGatewayServer) ComposeSource(context.Context, *SourceCompositionRequest) (*SourceCompositionReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method ComposeSource not implemented") +} func (UnimplementedGatewayServer) InspectProviderCatalog(context.Context, *Empty) (*ProviderCatalogSnapshot, error) { return nil, status.Errorf(codes.Unimplemented, "method InspectProviderCatalog not implemented") } @@ -951,6 +969,24 @@ func _Gateway_CompileSource_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _Gateway_ComposeSource_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SourceCompositionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GatewayServer).ComposeSource(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Gateway_ComposeSource_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GatewayServer).ComposeSource(ctx, req.(*SourceCompositionRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Gateway_InspectProviderCatalog_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(Empty) if err := dec(in); err != nil { @@ -1118,6 +1154,10 @@ var Gateway_ServiceDesc = grpc.ServiceDesc{ MethodName: "CompileSource", Handler: _Gateway_CompileSource_Handler, }, + { + MethodName: "ComposeSource", + Handler: _Gateway_ComposeSource_Handler, + }, { MethodName: "InspectProviderCatalog", Handler: _Gateway_InspectProviderCatalog_Handler, diff --git a/go/cmd/weaver-control/main.go b/go/cmd/weaver-control/main.go index 00b5d9b5..f0d38194 100644 --- a/go/cmd/weaver-control/main.go +++ b/go/cmd/weaver-control/main.go @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 -// Command weaver-control serves authenticated routing over gRPC to the Rust broker. +// Command weaver-control prepares source state; serve retains the reference relay. package main import ( @@ -17,7 +17,15 @@ import ( func main() { ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer cancel() - if err := controlplane.RunFromEnv(ctx); err != nil { + action := controlplane.PrepareFromEnv + if len(os.Args) > 2 || (len(os.Args) == 2 && os.Args[1] != "prepare" && os.Args[1] != "serve") { + fmt.Fprintln(os.Stderr, "usage: weaver-control [prepare|serve]") + os.Exit(2) + } + if len(os.Args) == 2 && os.Args[1] == "serve" { + action = controlplane.RunFromEnv + } + if err := action(ctx); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } diff --git a/go/dev/provider_control_test.go b/go/dev/provider_control_test.go index 24a5a09c..1feb4f25 100644 --- a/go/dev/provider_control_test.go +++ b/go/dev/provider_control_test.go @@ -108,6 +108,28 @@ func newControlProcess(t testing.TB, f *fixture, path string) *controlProcess { t.Cleanup(func() { c.stop(t) }) return c } + +// Source preparation needs no operation credential or Go ingress socket. +func (c *controlProcess) prepare(t testing.TB) { + t.Helper() + ctx, cancel := context.WithTimeout(t.Context(), 15*time.Second) + defer cancel() + command := exec.CommandContext(ctx, c.image) + for _, value := range os.Environ() { + if !strings.HasPrefix(value, "WEAVER_CONTROL_") { + command.Env = append(command.Env, value) + } + } + for _, value := range c.env { + name, _, _ := strings.Cut(value, "=") + if strings.HasPrefix(name, "WEAVER_CONTROL_AUTHORITY_SOURCE_") || name == "WEAVER_CONTROL_AUTHORITY_CA" || name == "WEAVER_CONTROL_AUTHORITY_SERVER_NAME" || name == "WEAVER_CONTROL_CONFIG" || name == "WEAVER_CONTROL_PRODUCER" { + command.Env = append(command.Env, value) + } + } + if output, err := command.CombinedOutput(); err != nil { + t.Fatalf("source-only preparation: %v: %s", err, output) + } +} func (c *controlProcess) start(t testing.TB) { t.Helper() log, err := os.OpenFile(filepath.Join(c.directory, "control.log"), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600) @@ -119,7 +141,7 @@ func (c *controlProcess) start(t testing.TB) { log.Close() t.Fatal(err) } - child := exec.Command(c.image) + child := exec.Command(c.image, "serve") child.Env = append(os.Environ(), c.env...) child.Stdout, child.Stderr = log, log if os.Getenv("WEAVER_TEST_CONTROL_HEAP") == "1" { @@ -534,7 +556,7 @@ func exerciseControlSourceReplyLoss(t *testing.T, source func(*testing.T, *fixtu go func() { exited <- server.Serve(listener) }() t.Cleanup(func() { server.Stop(); <-exited }) c.env = append(c.env, "WEAVER_CONTROL_AUTHORITY_SOURCE_ADDRESS="+listener.Addr().String()) - child := exec.Command(controlBinary) + child := exec.Command(controlBinary, "serve") child.Env = append(os.Environ(), c.env...) log, err := os.Create(filepath.Join(c.directory, "lost-publication.log")) if err != nil { diff --git a/go/dev/provider_grpc_test.go b/go/dev/provider_grpc_test.go index 6da6a349..3f694bad 100644 --- a/go/dev/provider_grpc_test.go +++ b/go/dev/provider_grpc_test.go @@ -127,9 +127,15 @@ func TestProviderFailuresNeverRetryOrFallback(t *testing.T) { for name, handler := range cases { t.Run(name, func(t *testing.T) { f := newFixture(t, handler, false) - if _, _, err := execute(t, f, pb.Encoding_PROTOBUF, 1); err == nil { + _, _, failure := execute(t, f, pb.Encoding_PROTOBUF, 1) + if failure == nil { t.Fatal("indeterminate provider call succeeded") } + // The partial upstream response must terminate with Rust's gRPC + // failure status, rather than clean EOF or a client decode error. + if name == "partial-sse" && status.Code(failure) != codes.FailedPrecondition { + t.Fatalf("terminal gRPC status lost: %v", failure) + } if f.primary.Load() != 1 || f.backup.Load() != 0 || f.denied.Load() != 0 { t.Fatal("failure caused a retry or fallback") } diff --git a/go/dev/provider_module_routing_test.go b/go/dev/provider_module_routing_test.go index 82d179d4..b453c135 100644 --- a/go/dev/provider_module_routing_test.go +++ b/go/dev/provider_module_routing_test.go @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 -//go:build integration && !windows +//go:build integration && schemeintegration && !windows package dev @@ -41,12 +41,19 @@ func (c lostCatalogReply) PublishProviderCatalog(ctx context.Context, req *pb.Pr func TestProviderModuleSelectionBindsOriginal(t *testing.T) { t.Setenv("WEAVER_STORAGE_JOURNAL", "mvcc") for _, mode := range []string{"complete", "partial", "deny"} { - t.Run(mode, func(t *testing.T) { checkImportedProvider(t, mode) }) + t.Run(mode, func(t *testing.T) { checkImportedProvider(t, mode, false) }) } } -func checkImportedProvider(t *testing.T, mode string) { +func TestProviderRustDirectCatalogSelection(t *testing.T) { + t.Setenv("WEAVER_STORAGE_JOURNAL", "mvcc") + for _, mode := range []string{"complete", "alternate", "partial", "deny"} { + t.Run(mode, func(t *testing.T) { checkImportedProvider(t, mode, true) }) + } +} +func checkImportedProvider(t *testing.T, mode string, direct bool) { t.Helper() handler := completeSSE + if mode == "partial" { handler = func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "text/event-stream") @@ -76,6 +83,17 @@ func checkImportedProvider(t *testing.T, mode string) { } return "WEAVER_METERING=" + string(data) }) + if _, err := f.client.RPC.ComposeSource(f.client.Context(t.Context()), &pb.SourceCompositionRequest{}); status.Code(err) != codes.PermissionDenied { + t.Fatalf("operation caller entered semantic composition: %v", err) + } + if _, err := f.admin.RPC.ComposeSource(f.admin.Context(t.Context()), &pb.SourceCompositionRequest{UseCatalog: true, ExpectedCatalogVersion: "unexpected"}); status.Code(err) != codes.FailedPrecondition { + t.Fatalf("stale catalog coordinate entered composition: %v", err) + } + if direct { + if _, err := f.client.RPC.RegisterPublishedTask(f.client.Context(t.Context()), &pb.RegisterPublishedTaskRequest{SourceScope: &pb.SourceCompositionRequest{}}); status.Code(err) != codes.PermissionDenied { + t.Fatalf("operation caller declared source scope: %v", err) + } + } bundle := controlBundle(t, f) selected := append([]string(nil), bundle.Governance.OpenNodes[:1]...) bundle.Governance.OpenNodes = selected @@ -94,22 +112,36 @@ func checkImportedProvider(t *testing.T, mode string) { bundle.Publication.Policy += ` forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { context.family == "control" };` } + invalid := qualified + invalid.Body = `{}` // Ineligible offer must not suppress the valid module. cheap := qualified cheap.Model = "model-b" cheap.Body = strings.Replace(cheap.Body, "model-a", "model-b", 1) + chosen := qualified + if mode == "alternate" { + cheap = qualified + cheap.Body = strings.Replace(cheap.Body, "hello", "alternate", 1) + chosen = cheap + } bundle.Plans = nil bundle.SelectOnRequest = true bundle.Routing = []routing.Selection{{ Node: qualified.Node, AllowedModules: []string{"basic", "premium"}, Required: []string{"quality"}, MaxLatencyMillis: 100, MaxProcurementCost: 100, UserTokenRates: [4]uint64{0, 0, 0, 100000}, Candidates: []routing.Candidate{ + {Module: "premium", Capabilities: []string{"quality"}, LatencyMillis: 1, TokenBounds: [4]uint64{64, 0, 0, 32}, Plan: invalid}, {Module: "basic", LatencyMillis: 10, TokenBounds: [4]uint64{64, 0, 0, 32}, Plan: cheap}, {Module: "premium", Capabilities: []string{"quality"}, LatencyMillis: 40, ProcurementRates: [4]uint64{1_000_000}, TokenBounds: [4]uint64{64, 0, 0, 32}, Plan: qualified}, }, }} control := newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")) - control.start(t) - t.Cleanup(func() { control.stop(t) }) + if direct { + control.prepare(t) + control.client = f.client + } else { + control.start(t) + t.Cleanup(func() { control.stop(t) }) + } ctx, cancel := context.WithTimeout(t.Context(), 12*time.Second) defer cancel() source := f.admin @@ -129,7 +161,7 @@ forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { c "procurement_rates": [4]uint64{rate}, "token_bounds": [4]uint64{64, 0, 0, 32}}, } } - chosenDigest, _ := qualified.Digest() + chosenDigest, _ := chosen.Digest() change := func(parent string, rate uint64) *pb.ProviderCatalogChange { metadata, err := json.Marshal(entry(rate)) if err != nil { @@ -137,7 +169,7 @@ forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { c } litellm, err := json.Marshal(map[string]any{"model_list": []any{ map[string]any{"model_name": "premium", "litellm_params": map[string]string{ - "model": "openai/" + qualified.Model, "api_base": strings.TrimSuffix(qualified.Routes[0].Endpoint, "/chat/completions"), + "model": "openai/" + chosen.Model, "api_base": strings.TrimSuffix(chosen.Routes[0].Endpoint, "/chat/completions"), "api_key": "os.environ/WEAVER_TEST_KEY", }}, }}) @@ -146,7 +178,7 @@ forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { c } record, err := config.ImportProviderCatalog(litellm, config.ProfileJSON, config.ProviderImportReview{ Parent: parent, Bindings: map[string]config.ProviderImportBinding{ - "premium": {Plan: qualified, Credential: "os.environ/WEAVER_TEST_KEY", Entry: metadata}, + "premium": {Plan: chosen, Credential: "os.environ/WEAVER_TEST_KEY", Entry: metadata}, }, }) if err != nil { @@ -189,7 +221,15 @@ forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { c if status.Code(err) != codes.FailedPrecondition || f.primary.Load() != 0 { t.Fatalf("stale quote admitted: %v", err) } - if _, err := control.client.Execute(ctx, cheap, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }); status.Code(err) != codes.InvalidArgument || f.primary.Load() != 0 { + expectedCode := codes.InvalidArgument + if direct { + expectedCode = codes.FailedPrecondition + } + unselected := cheap + if mode == "alternate" { + unselected = qualified + } + if _, err := control.client.Execute(ctx, unselected, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }); status.Code(err) != expectedCode || f.primary.Load() != 0 { t.Fatalf("unselected model reached provider: %v", err) } execute := func(ctx context.Context, wantFrames bool) error { @@ -208,7 +248,7 @@ forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { c if err != nil { return err } - if !wantFrames || frame.GetModel() != qualified.Model { + if !wantFrames || frame.GetModel() != chosen.Model { return errors.New("unexpected provider frame") } seen = true @@ -231,9 +271,28 @@ forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { c if successes != 0 || f.primary.Load() != 0 { t.Fatalf("import bypassed Cedar invocation: successes=%d calls=%d", successes, f.primary.Load()) } + if direct { + next := secondaryClient(t, f.pki) + token := sha256.Sum256([]byte(f.admin.Token)) + if _, err := f.admin.RotateSource(ctx, v1.SourceRotation{OperationID: "retire-routing-source", ExpectedEpoch: 0, NextCertificate: next.Certificate[0], NextCredentialSHA256: hex.EncodeToString(token[:])}); err != nil { + t.Fatal(err) + } + if err := execute(ctx, false); status.Code(err) != codes.FailedPrecondition { + t.Fatalf("retired source reused cached projection: %v", err) + } + f.stop(t) + f.start(t) + control.client = f.client + if err := execute(ctx, false); status.Code(err) != codes.FailedPrecondition { + t.Fatalf("restart restored retired source: %v", err) + } + if f.primary.Load() != 0 { + t.Fatal("retired source sent provider traffic") + } + } return } - if (mode == "complete" && successes != 1) || (mode == "partial" && successes != 0) || f.primary.Load() != 1 { + if ((mode == "complete" || mode == "alternate") && successes != 1) || (mode == "partial" && successes != 0) || f.primary.Load() != 1 { t.Fatalf("expected a single provider dispatch: successes=%d calls=%d", successes, f.primary.Load()) } withdrawal, err := json.Marshal(map[string]any{"parent": current.Version, "entries": map[string]any{}}) @@ -241,16 +300,22 @@ forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { c t.Fatal(err) } withdrawn := current - if mode == "complete" { + if mode == "complete" || mode == "alternate" { withdrawn, err = publish(&pb.ProviderCatalogChange{Record: withdrawal}) if err != nil { t.Fatal(err) } } - control.stop(t) + if !direct { + control.stop(t) + } f.stop(t) f.start(t) - control.start(t) + if direct { + control.client = f.client + } else { + control.start(t) + } retry, stop := context.WithTimeout(t.Context(), 12*time.Second) defer stop() if err := execute(retry, false); status.Code(err) != codes.FailedPrecondition { diff --git a/go/dev/provider_program_deployment_test.go b/go/dev/provider_program_deployment_test.go index 1ca39b61..e8ab67ee 100644 --- a/go/dev/provider_program_deployment_test.go +++ b/go/dev/provider_program_deployment_test.go @@ -27,6 +27,7 @@ import ( v1 "github.com/HardenedLinux/weaver/go/api/v1" "github.com/HardenedLinux/weaver/go/internal/config" "github.com/HardenedLinux/weaver/go/internal/gatewayclient" + "github.com/HardenedLinux/weaver/go/internal/routing" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" @@ -631,8 +632,54 @@ func TestProviderControlCompiledAssetsRevocationAndRestart(t *testing.T) { } func compiledControlSources(assets bool) controlPolicySources { + return composedControlSources(assets, false) +} + +func TestProviderControlSchemeCompositionRevocationAndRestart(t *testing.T) { + exerciseControlPolicies(t, "json", nil, composedControlSources(false, true)) +} + +func composedControlSources(assets, compose bool) controlPolicySources { return controlPolicySources{producer: "approved-control", configure: func(t *testing.T, f *fixture, bundle config.Bundle) { path := configuredCatalogPath(t, f, bundle) + if compose { + data, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + var catalog struct { + Producers []map[string]any `json:"producers"` + } + if err := json.Unmarshal(data, &catalog); err != nil { + t.Fatal(err) + } + raw := bundle + raw.Tasks = append([]v1.Task(nil), bundle.Tasks...) + raw.Tasks[0].BodyDigests = map[string]string{} + raw.Tasks[0].StreamContracts = map[string]string{} + raw.Plans = []v1.ProviderPlan{} + choices := make([]routing.Selection, 0, len(bundle.Plans)) + for _, plan := range bundle.Plans { + invalid := plan + invalid.Body = `{}` + choices = append(choices, routing.Selection{Node: plan.Node, + AllowedModules: []string{"approved"}, Required: []string{"text"}, + MaxLatencyMillis: 100, MaxProcurementCost: 4, + Candidates: []routing.Candidate{{Module: "approved", Capabilities: []string{"text"}, + LatencyMillis: 10, TokenBounds: [4]uint64{0, 0, 0, 32}, Plan: plan}, + {Module: "approved", Capabilities: []string{"text"}, LatencyMillis: 1, TokenBounds: [4]uint64{0, 0, 0, 32}, Plan: invalid}}, + }) + } + delete(catalog.Producers[0], "original") + catalog.Producers[0]["composition"] = map[string]any{"source": raw, "routing": choices} + data, err = json.Marshal(catalog) + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(path, data, 0600); err != nil { + t.Fatal(err) + } + } f.stop(t) f.env = append(f.env, "WEAVER_GOVERNANCE_CATALOG="+path) if assets { @@ -806,3 +853,145 @@ func TestProviderControlCompiledCatalogRequiresExactSourceEpoch(t *testing.T) { } t.Log("exact epoch and producer compiled after restart, with zero provider sends") } + +// The preparation command has source credentials only and exits before any +// operation request. All frames then travel directly from the Rust listener. +func TestProviderRustDirectPreparedOperationWithoutGoRelay(t *testing.T) { + f := newFixture(t, completeSSE, false) + bundle := controlBundle(t, f) + f.env = append(f.env, "WEAVER_GOVERNANCE_RETIRE_ON_ACTIVATION=1") + policy := compiledControlSources(false) + policy.configure(t, f, bundle) + control := newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")) + control.useProducer(policy.producer) + ctx, cancel := context.WithTimeout(t.Context(), 15*time.Second) + defer cancel() + command := exec.CommandContext(ctx, control.image, "prepare") + for _, value := range os.Environ() { + if !strings.HasPrefix(value, "WEAVER_CONTROL_") { + command.Env = append(command.Env, value) + } + } + for _, value := range control.env { + name, _, _ := strings.Cut(value, "=") + if strings.HasPrefix(name, "WEAVER_CONTROL_AUTHORITY_SOURCE_") || name == "WEAVER_CONTROL_AUTHORITY_CA" || + name == "WEAVER_CONTROL_AUTHORITY_SERVER_NAME" || name == "WEAVER_CONTROL_CONFIG" || name == "WEAVER_CONTROL_PRODUCER" { + command.Env = append(command.Env, value) + } + } + if output, err := command.CombinedOutput(); err != nil { + t.Fatalf("source-only preparation: %v: %s", err, output) + } + // A dangling modification must not be interpreted as an operation-key call. + stream, err := f.client.RPC.ExecuteProvider(f.client.Context(ctx), &pb.ProviderRequest{Plan: &pb.ProviderPlan{Family: "control", Node: "infer", Profile: "changed"}, Encoding: pb.Encoding_PROTOBUF, BatchRows: 1}) + if err == nil { + _, err = stream.Recv() + } + if err == nil || f.primary.Load() != 0 || f.backup.Load() != 0 { + t.Fatal("modified original admitted", err) + } + stream, err = f.client.RPC.ExecuteProvider(f.client.Context(ctx), &pb.ProviderRequest{Plan: &pb.ProviderPlan{Family: "control", Node: "infer"}, Encoding: pb.Encoding_PROTOBUF, BatchRows: 1}) + if err != nil { + t.Fatal(err) + } + frames := 0 + text := "" + for { + frame, err := stream.Recv() + if err == io.EOF { + break + } + if err != nil { + t.Fatal(err) + } + if frame.GetEvent() == nil { + t.Fatal("empty released frame") + } + text += frame.GetEvent().Text + frames++ + } + if frames != 5 || text != "hello world" || f.primary.Load()+f.backup.Load() != 1 { + t.Fatal("direct operation incomplete", frames) + } + if control.child != nil { + t.Fatal("Go service remained in the request path") + } + f.stop(t) + f.start(t) + stream, err = f.client.RPC.ExecuteProvider(f.client.Context(ctx), &pb.ProviderRequest{Plan: &pb.ProviderPlan{Family: "control", Node: "infer"}, Encoding: pb.Encoding_PROTOBUF, BatchRows: 1}) + if err == nil { + _, err = stream.Recv() + } + if err == nil || f.primary.Load()+f.backup.Load() != 1 { + t.Fatal("restart replayed completed original", err) + } +} + +// JSON source preparation also retains exact plans for direct operation keys; +// it does not rely on the optional compiled single-provider retirement profile. +func TestProviderRustDirectFilePreparation(t *testing.T) { + f := newFixture(t, completeSSE, false) + bundle := controlBundle(t, f) + originalPolicy := bundle.Publication.Policy + bundle.Publication.Policy += ` +forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { context.family == "control" && context.node == "next" };` + control := newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")) + control.prepare(t) + ctx, cancel := context.WithTimeout(t.Context(), 12*time.Second) + defer cancel() + run := func() error { + stream, err := f.client.RPC.ExecuteProvider(f.client.Context(ctx), &pb.ProviderRequest{Plan: &pb.ProviderPlan{Family: "control", Node: "infer"}, Encoding: pb.Encoding_PROTOBUF, BatchRows: 1}) + if err != nil { + return err + } + count := 0 + text := "" + for { + frame, err := stream.Recv() + if err == io.EOF { + if count != 5 || text != "hello world" { + t.Fatalf("incomplete direct file stream: count=%d text=%q", count, text) + } + return nil + } + if err != nil { + return err + } + count++ + text += frame.GetEvent().GetText() + } + } + if err := run(); err != nil { + t.Fatal(err) + } + if f.primary.Load() != 1 || control.child != nil { + t.Fatal("direct file operation path", f.primary.Load()) + } + deniedNext := func() { + stream, err := f.client.RPC.ExecuteProvider(f.client.Context(ctx), &pb.ProviderRequest{Plan: &pb.ProviderPlan{Family: "control", Node: "next"}, Encoding: pb.Encoding_PROTOBUF, BatchRows: 1}) + if err == nil { + _, err = stream.Recv() + } + if status.Code(err) != codes.FailedPrecondition || f.primary.Load() != 1 { + t.Fatalf("fixed projection used stale authority: %v", err) + } + } + deniedNext() // Warm exact immutable data while Cedar denies execution. + for index, policy := range []string{originalPolicy, bundle.Publication.Policy} { + publication := bundle.Publication.Clone() + revision := uint64(index + 1) + publication.OperationID = "fixed-policy-" + strconv.Itoa(index) + publication.ExpectedRevision = &revision + publication.Fence = uint64(index + 2) + publication.Policy = policy + if _, err := f.admin.Publish(ctx, publication); err != nil { + t.Fatal(err) + } + deniedNext() // Even newly allowing Cedar cannot rebase the old plan. + } + f.stop(t) + f.start(t) + if err := run(); err == nil || f.primary.Load() != 1 { + t.Fatal("restart replayed file original", err) + } +} diff --git a/go/internal/config/bundle.go b/go/internal/config/bundle.go index 439fc58b..ff2af1cf 100644 --- a/go/internal/config/bundle.go +++ b/go/internal/config/bundle.go @@ -43,6 +43,22 @@ const SessionDAGSchema = "weaver.session-dag.v1" const SessionWorkflowSchema = "weaver.session-workflow.v1" +// DecodeConfiguration handles external syntax only. Rust/Scheme composes its meaning. +func DecodeConfiguration(data []byte, format ProfileFormat) (Bundle, error) { + if len(data) == 0 || len(data) > 8<<20 { + return Bundle{}, errors.New("source bundle bound") + } + source, err := sourceJSON(data, format) + if err != nil { + return Bundle{}, err + } + bundle, err := v1.DecodeSource[Bundle](source) + if err != nil { + return Bundle{}, err + } + return CloneConfiguration(bundle) +} + func DecodeBundle(data []byte, format ProfileFormat) (Bundle, error) { var zero Bundle if len(data) == 0 || len(data) > 8<<20 { diff --git a/go/internal/config/freeze.go b/go/internal/config/freeze.go index 1cf72c3d..233efdbc 100644 --- a/go/internal/config/freeze.go +++ b/go/internal/config/freeze.go @@ -14,15 +14,70 @@ import ( "slices" ) -// FreezeBundle takes an independent validated copy for private control-plane -// ownership. JSON/YAML remain ingress formats, not an internal cloning protocol. +// FreezeBundle is the existing development/reference oracle. Deployment parsing +// uses DecodeConfiguration and delegates semantic composition to Rust/Scheme. func FreezeBundle(input Bundle) (Bundle, error) { + result, err := cloneBundle(input) + if err != nil { + return Bundle{}, err + } + if result.SelectOnRequest { + if len(input.Tasks) != 1 || len(input.Routing) != 1 || len(input.Tasks[0].Nodes) != 1 { + return Bundle{}, errors.New("request routing requires one original task and node") + } + choice := input.Routing[0] + choice.Required = slices.Clone(choice.Required) + choice.AllowedModules = slices.Clone(choice.AllowedModules) + choice.Candidates = slices.Clone(choice.Candidates) + for i := range choice.Candidates { + candidate := &choice.Candidates[i] + candidate.Capabilities = slices.Clone(candidate.Capabilities) + candidate.Plan.Routes = slices.Clone(candidate.Plan.Routes) + } + result.Routing = []routing.Selection{choice} + if _, err := result.MaterializeRequest(); err != nil { + return Bundle{}, err + } + return result, nil + } + if err := result.chooseRoutes(); err != nil { + return Bundle{}, err + } + if err := result.Validate(); err != nil { + return Bundle{}, err + } + return result, nil +} + +// CloneConfiguration copies bounded source data without selecting or interpreting it. +func CloneConfiguration(input Bundle) (Bundle, error) { return cloneBundle(input) } + +// CloneArtifact owns an already composed Rust/Scheme projection. It performs no +// routing selection or Workflow interpretation; Rust remains the final validator. +func CloneArtifact(input Bundle) (Bundle, error) { + if input.SelectOnRequest || len(input.Routing) != 0 { + return Bundle{}, errors.New("artifact must already be composed by Scheme") + } + return cloneBundle(input) +} +func cloneBundle(input Bundle) (Bundle, error) { // Copy only bounded input, then validate the independent image once. // Callers must keep input stable during this synchronous copy. if !sourceTextBound(input) { return Bundle{}, errors.New("typed source text bound") } result := input + result.Routing = slices.Clone(input.Routing) + for index := range result.Routing { + choice := &result.Routing[index] + choice.Required = slices.Clone(choice.Required) + choice.AllowedModules = slices.Clone(choice.AllowedModules) + choice.Candidates = slices.Clone(choice.Candidates) + for i := range choice.Candidates { + choice.Candidates[i].Capabilities = slices.Clone(choice.Candidates[i].Capabilities) + choice.Candidates[i].Plan.Routes = slices.Clone(choice.Candidates[i].Plan.Routes) + } + } result.Governance.OpenNodes = slices.Clone(input.Governance.OpenNodes) result.Governance.WorkflowEdges = slices.Clone(input.Governance.WorkflowEdges) result.Governance.WorkflowSelectors = slices.Clone(input.Governance.WorkflowSelectors) @@ -49,31 +104,6 @@ func FreezeBundle(input Bundle) (Bundle, error) { copy.Routes = slices.Clone(p.Routes) result.Plans[index] = copy } - if result.SelectOnRequest { - if len(input.Tasks) != 1 || len(input.Routing) != 1 || len(input.Tasks[0].Nodes) != 1 { - return Bundle{}, errors.New("request routing requires one original task and node") - } - choice := input.Routing[0] - choice.Required = slices.Clone(choice.Required) - choice.AllowedModules = slices.Clone(choice.AllowedModules) - choice.Candidates = slices.Clone(choice.Candidates) - for i := range choice.Candidates { - candidate := &choice.Candidates[i] - candidate.Capabilities = slices.Clone(candidate.Capabilities) - candidate.Plan.Routes = slices.Clone(candidate.Plan.Routes) - } - result.Routing = []routing.Selection{choice} - if _, err := result.MaterializeRequest(); err != nil { - return Bundle{}, err - } - return result, nil - } - if err := result.chooseRoutes(); err != nil { - return Bundle{}, err - } - if err := result.Validate(); err != nil { - return Bundle{}, err - } return result, nil } diff --git a/go/internal/controlplane/deployment.go b/go/internal/controlplane/deployment.go index b30ddda9..8ef2db17 100644 --- a/go/internal/controlplane/deployment.go +++ b/go/internal/controlplane/deployment.go @@ -12,15 +12,12 @@ import ( "encoding/hex" "errors" "fmt" - "github.com/HardenedLinux/weaver/go/internal/config" "github.com/HardenedLinux/weaver/go/internal/gatewayclient" "google.golang.org/grpc" "io" "log/slog" "net" "os" - "path/filepath" - "strings" "time" ) @@ -120,24 +117,10 @@ func RunFromEnv(ctx context.Context) error { } bounded := BoundListener(listener) defer bounded.Close() - input, err := selectDeploymentSource(os.LookupEnv) + input, err := loadDeploymentSource() if err != nil { return err } - if input.producer == "" { - data, err := readBoundFile(input.path) - if err != nil { - return err - } - format := config.ProfileJSON - if ext := strings.ToLower(filepath.Ext(input.path)); ext == ".yaml" || ext == ".yml" { - format = config.ProfileYAML - } - input.bundle, err = config.DecodeBundle(data, format) - if err != nil { - return err - } - } trace("configuration-ready") authorityRoots, err := roots("WEAVER_CONTROL_AUTHORITY_CA") if err != nil { @@ -234,3 +217,41 @@ func RunFromEnv(ctx context.Context) error { return errors.New("control drain exceeded bound") } } + +// PrepareFromEnv activates source state and exits. It opens no operation listener, +// needs no operation credential, and cannot forward any provider frame. +func PrepareFromEnv(ctx context.Context) error { + startup, cancel := context.WithTimeout(ctx, 15*time.Second) + defer cancel() + input, err := loadDeploymentSource() + if err != nil { + return err + } + ca, err := roots("WEAVER_CONTROL_AUTHORITY_CA") + if err != nil { + return err + } + key, err := pair("WEAVER_CONTROL_AUTHORITY_SOURCE") + if err != nil { + return err + } + address, err := required("WEAVER_CONTROL_AUTHORITY_SOURCE_ADDRESS") + if err != nil { + return err + } + token, err := required("WEAVER_CONTROL_AUTHORITY_SOURCE_TOKEN") + if err != nil { + return err + } + name, err := required("WEAVER_CONTROL_AUTHORITY_SERVER_NAME") + if err != nil { + return err + } + source, err := gatewayclient.Dial(startup, address, token, &tls.Config{RootCAs: ca, Certificates: []tls.Certificate{key}, ServerName: name, MinVersion: tls.VersionTLS13}) + if err != nil { + return err + } + defer source.Connection.Close() + _, err = input.bootstrap(startup, source, nil, nil) + return err +} diff --git a/go/internal/controlplane/deployment_source.go b/go/internal/controlplane/deployment_source.go index 7d408b36..2883b810 100644 --- a/go/internal/controlplane/deployment_source.go +++ b/go/internal/controlplane/deployment_source.go @@ -7,6 +7,7 @@ package controlplane import ( "context" "errors" + "os" "path/filepath" "strings" @@ -49,3 +50,20 @@ func (input deploymentSource) bootstrap(ctx context.Context, source, operation * } return bootstrap(ctx, source, operation, input.bundle, trace) } + +func loadDeploymentSource() (deploymentSource, error) { + input, err := selectDeploymentSource(os.LookupEnv) + if err != nil || input.producer != "" { + return input, err + } + data, err := readBoundFile(input.path) + if err != nil { + return deploymentSource{}, err + } + format := config.ProfileJSON + if ext := strings.ToLower(filepath.Ext(input.path)); ext == ".yaml" || ext == ".yml" { + format = config.ProfileYAML + } + input.bundle, err = config.DecodeConfiguration(data, format) + return input, err +} diff --git a/go/internal/controlplane/gateway.go b/go/internal/controlplane/gateway.go index 9bd5abaf..e2870e68 100644 --- a/go/internal/controlplane/gateway.go +++ b/go/internal/controlplane/gateway.go @@ -39,6 +39,9 @@ type Gateway struct { // Bootstrap has no execution API calls. Unknown publication outcomes never activate ingress. // Task registration is persistent and idempotent, not an atomic multi-task transaction. func Bootstrap(ctx context.Context, source, owner *gatewayclient.Client, bundle config.Bundle) (*Gateway, error) { + if owner == nil { + return nil, errors.New("operation authority role required") + } return bootstrap(ctx, source, owner, bundle, nil) } @@ -51,13 +54,22 @@ func (trace bootstrapTrace) phase(name string) { } func bootstrap(ctx context.Context, source, owner *gatewayclient.Client, bundle config.Bundle, trace bootstrapTrace) (*Gateway, error) { - if source == nil || owner == nil { + if source == nil { return nil, errors.New("source and operation authority roles required") } - frozen, err := config.FreezeBundle(bundle) + frozen, err := config.CloneConfiguration(bundle) if err != nil { return nil, err } + selected, err := composeSourceBundle(ctx, source, frozen, false, "") + if err != nil { + return nil, err + } + if !frozen.SelectOnRequest { + frozen = selected + } else if len(frozen.Tasks) != 1 || len(frozen.Routing) != 1 || len(frozen.Tasks[0].Nodes) != 1 { + return nil, errors.New("request routing requires one original task and node") + } return bootstrapFrozen(ctx, source, owner, frozen, trace) } @@ -83,13 +95,10 @@ func bootstrapFrozen(ctx context.Context, source, owner *gatewayclient.Client, f if err != nil { return nil, err } - if !frozen.SelectOnRequest { - trace.phase("task-registration-start") - for _, task := range frozen.Tasks { - if _, err = source.RPC.RegisterPublishedTask(source.Context(ctx), &pb.RegisterPublishedTaskRequest{Task: gatewayclient.Task(task), Publication: &pb.PublicationKey{OperationId: frozen.Publication.OperationID, Digest: digest}}); err != nil { - return nil, err - } - } + trace.phase("task-registration-start") + _, err = source.RPC.RegisterPublishedTask(source.Context(ctx), &pb.RegisterPublishedTaskRequest{Publication: &pb.PublicationKey{OperationId: frozen.Publication.OperationID, Digest: digest}, SourceScope: sourceCompositionRequest(frozen, false, "")}) + if err != nil { + return nil, err } if receipt == nil { trace.phase("publication-finalize-start") diff --git a/go/internal/controlplane/provider_catalog.go b/go/internal/controlplane/provider_catalog.go index 67c92160..8b2fb1fb 100644 --- a/go/internal/controlplane/provider_catalog.go +++ b/go/internal/controlplane/provider_catalog.go @@ -7,27 +7,12 @@ package controlplane import ( "bytes" "context" - "encoding/json" - "errors" pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" "github.com/HardenedLinux/weaver/go/internal/config" "github.com/HardenedLinux/weaver/go/internal/gatewayclient" - "github.com/HardenedLinux/weaver/go/internal/routing" ) -type catalogEntry struct { - Module string `json:"module"` - Capabilities []string `json:"capabilities"` - Latency uint64 `json:"latency_millis"` - UserRates [4]uint64 `json:"user_rates"` - Quote struct { - Tenant string `json:"tenant"` - ProcurementRates [4]uint64 `json:"procurement_rates"` - TokenBounds [4]uint64 `json:"token_bounds"` - } `json:"quote"` -} - // A projection owns its input and selected bundle. It carries no authority. type catalogProjection struct { version string @@ -41,36 +26,26 @@ func (g *Gateway) materializeProvider(ctx context.Context) (*catalogProjection, if err != nil { return nil, "", err } - selected, err := g.projectCatalog(snapshot) + selected, err := g.composeCatalog(ctx, snapshot) return selected, snapshot.Version, err } -func (g *Gateway) projectCatalog(snapshot *pb.ProviderCatalogSnapshot) (*catalogProjection, error) { - if snapshot.Version == "" { - selected, err := g.deferred.MaterializeRequest() - if err != nil { - return nil, err - } - return &catalogProjection{bundle: selected, registration: g.catalogRegistration(selected)}, nil - } +// Cache only immutable composition for the freshly observed exact catalog version. +func (g *Gateway) composeCatalog(ctx context.Context, snapshot *pb.ProviderCatalogSnapshot) (*catalogProjection, error) { if current := g.cachedCatalog(snapshot); current != nil { return current, nil } - // Requests still read the catalog independently. Share the projection - // work when they arrive together with the same new snapshot. g.catalogBuildMu.Lock() defer g.catalogBuildMu.Unlock() if current := g.cachedCatalog(snapshot); current != nil { return current, nil } - selected, err := projectCatalog(*g.deferred, snapshot.Record) + selected, err := composeSourceBundle(ctx, g.source, *g.deferred, true, snapshot.Version) if err != nil { return nil, err } - projection := &catalogProjection{ - version: snapshot.Version, record: bytes.Clone(snapshot.Record), bundle: selected, - registration: g.catalogRegistration(selected), - } + projection := &catalogProjection{version: snapshot.Version, record: bytes.Clone(snapshot.Record), + bundle: selected, registration: g.catalogRegistration(selected)} g.catalog.Store(projection) return projection, nil } @@ -89,45 +64,3 @@ func (g *Gateway) cachedCatalog(snapshot *pb.ProviderCatalogSnapshot) *catalogPr } return nil } - -func projectCatalog(bundle config.Bundle, record []byte) (config.Bundle, error) { - var catalog struct { - Entries map[string]catalogEntry `json:"entries"` - } - if len(record) > 262144 || json.Unmarshal(record, &catalog) != nil { - return config.Bundle{}, errors.New("invalid provider catalog") - } - selection, err := catalogSelection(bundle.Routing[0], catalog.Entries) - if err != nil { - return config.Bundle{}, err - } - bundle.Routing = []routing.Selection{selection} - return bundle.MaterializeRequest() -} - -func catalogSelection(source routing.Selection, entries map[string]catalogEntry) (routing.Selection, error) { - selection := source - selection.Candidates = nil - tenant := "" - for _, candidate := range source.Candidates { - digest, err := candidate.Plan.Digest() - if err != nil { - return routing.Selection{}, err - } - entry, ok := entries[digest] - if !ok { - continue - } - // All concrete candidates for one original must use its tenant tariff. - if len(selection.Candidates) != 0 && (entry.UserRates != selection.UserTokenRates || entry.Quote.Tenant != tenant) { - return routing.Selection{}, errors.New("mixed catalog tariffs for original operation") - } - tenant = entry.Quote.Tenant - selection.UserTokenRates = entry.UserRates - candidate.Module, candidate.Capabilities = entry.Module, entry.Capabilities - candidate.LatencyMillis = entry.Latency - candidate.ProcurementRates, candidate.TokenBounds = entry.Quote.ProcurementRates, entry.Quote.TokenBounds - selection.Candidates = append(selection.Candidates, candidate) - } - return selection, nil -} diff --git a/go/internal/controlplane/provider_catalog_test.go b/go/internal/controlplane/provider_catalog_test.go index 9440d26a..902b5f9c 100644 --- a/go/internal/controlplane/provider_catalog_test.go +++ b/go/internal/controlplane/provider_catalog_test.go @@ -8,6 +8,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "strings" "sync" "testing" @@ -91,11 +92,21 @@ func catalogProjectionFixture(t testing.TB) (config.Bundle, []byte, v1.ProviderP } type catalogRPC struct { + configuration config.Bundle sourceRPC snapshot *pb.ProviderCatalogSnapshot readErr error } +func (r *catalogRPC) ComposeSource(_ context.Context, request *pb.SourceCompositionRequest, _ ...grpc.CallOption) (*pb.SourceCompositionReply, error) { + r.calls = append(r.calls, "compose") + selected, err := projectCatalog(r.configuration, r.snapshot.Record) + if err != nil { + return nil, err + } + return &pb.SourceCompositionReply{Artifact: sourceCompositionRequest(selected, false, "").Source, CatalogVersion: request.ExpectedCatalogVersion}, nil +} + func (r *catalogRPC) InspectProviderCatalog(context.Context, *pb.Empty, ...grpc.CallOption) (*pb.ProviderCatalogSnapshot, error) { r.calls = append(r.calls, "catalog") return r.snapshot, r.readErr @@ -103,7 +114,7 @@ func (r *catalogRPC) InspectProviderCatalog(context.Context, *pb.Empty, ...grpc. func TestCatalogProjectionRequiresExactSnapshotAndLiveAuthority(t *testing.T) { bundle, record, key := catalogProjectionFixture(t) - rpc := &catalogRPC{snapshot: &pb.ProviderCatalogSnapshot{Version: "a", Record: bytes.Clone(record)}} + rpc := &catalogRPC{configuration: bundle, snapshot: &pb.ProviderCatalogSnapshot{Version: "a", Record: bytes.Clone(record)}} gateway := &Gateway{deferred: &bundle, source: &gatewayclient.Client{RPC: rpc}} check := func(version string, code codes.Code, wantCalls string) { t.Helper() @@ -113,7 +124,7 @@ func TestCatalogProjectionRequiresExactSnapshotAndLiveAuthority(t *testing.T) { t.Fatalf("catalog version=%q status=%v calls=%v", got, err, rpc.calls) } } - check("a", codes.OK, "catalog,register") + check("a", codes.OK, "catalog,compose,register") a := gateway.catalog.Load() check("a", codes.OK, "catalog,register") if gateway.catalog.Load() != a { @@ -128,14 +139,14 @@ func TestCatalogProjectionRequiresExactSnapshotAndLiveAuthority(t *testing.T) { // The snapshot buffer can be reused by its caller. An invalid replacement // with the same version must miss the cache and fail closed. rpc.snapshot.Record[0] = '[' - check("", codes.FailedPrecondition, "catalog") + check("", codes.FailedPrecondition, "catalog,compose") rpc.snapshot = &pb.ProviderCatalogSnapshot{Version: "b", Record: record} - check("b", codes.OK, "catalog,register") + check("b", codes.OK, "catalog,compose,register") if gateway.catalog.Load() == a || gateway.catalog.Load().version != "b" { t.Fatal("a different version reused the original projection") } rpc.snapshot = &pb.ProviderCatalogSnapshot{Version: "withdrawn", Record: []byte(`{"entries":{}}`)} - check("", codes.FailedPrecondition, "catalog") + check("", codes.FailedPrecondition, "catalog,compose") } func projectCatalogWave(t testing.TB, gateway *Gateway, snapshots [4]*pb.ProviderCatalogSnapshot) [4]config.Bundle { @@ -224,3 +235,116 @@ func BenchmarkProviderCatalogProjection(b *testing.B) { }) } } + +// Frozen reference behavior for existing fixture/oracle controls only. The +// deployed path calls composeCatalog and delegates semantic work to Rust/Scheme. +type catalogEntry struct { + Module string `json:"module"` + Capabilities []string `json:"capabilities"` + Latency uint64 `json:"latency_millis"` + UserRates [4]uint64 `json:"user_rates"` + Quote struct { + Tenant string `json:"tenant"` + ProcurementRates [4]uint64 `json:"procurement_rates"` + TokenBounds [4]uint64 `json:"token_bounds"` + } `json:"quote"` +} + +func (g *Gateway) projectCatalog(snapshot *pb.ProviderCatalogSnapshot) (*catalogProjection, error) { + if snapshot.Version == "" { + selected, err := g.deferred.MaterializeRequest() + if err != nil { + return nil, err + } + return &catalogProjection{bundle: selected, registration: g.catalogRegistration(selected)}, nil + } + if current := g.cachedCatalog(snapshot); current != nil { + return current, nil + } + // Requests still read the catalog independently. Share the projection + // work when they arrive together with the same new snapshot. + g.catalogBuildMu.Lock() + defer g.catalogBuildMu.Unlock() + if current := g.cachedCatalog(snapshot); current != nil { + return current, nil + } + selected, err := projectCatalog(*g.deferred, snapshot.Record) + if err != nil { + return nil, err + } + projection := &catalogProjection{ + version: snapshot.Version, record: bytes.Clone(snapshot.Record), bundle: selected, + registration: g.catalogRegistration(selected), + } + g.catalog.Store(projection) + return projection, nil +} + +func projectCatalog(bundle config.Bundle, record []byte) (config.Bundle, error) { + var catalog struct { + Entries map[string]catalogEntry `json:"entries"` + } + if len(record) > 262144 || json.Unmarshal(record, &catalog) != nil { + return config.Bundle{}, errors.New("invalid provider catalog") + } + selection, err := catalogSelection(bundle.Routing[0], catalog.Entries) + if err != nil { + return config.Bundle{}, err + } + bundle.Routing = []routing.Selection{selection} + return bundle.MaterializeRequest() +} + +func catalogSelection(source routing.Selection, entries map[string]catalogEntry) (routing.Selection, error) { + selection := source + selection.Candidates = nil + tenant := "" + for _, candidate := range source.Candidates { + digest, err := candidate.Plan.Digest() + if err != nil { + return routing.Selection{}, err + } + entry, ok := entries[digest] + if !ok { + continue + } + // All concrete candidates for one original must use its tenant tariff. + if len(selection.Candidates) != 0 && (entry.UserRates != selection.UserTokenRates || entry.Quote.Tenant != tenant) { + return routing.Selection{}, errors.New("mixed catalog tariffs for original operation") + } + tenant = entry.Quote.Tenant + selection.UserTokenRates = entry.UserRates + candidate.Module, candidate.Capabilities = entry.Module, entry.Capabilities + candidate.LatencyMillis = entry.Latency + candidate.ProcurementRates, candidate.TokenBounds = entry.Quote.ProcurementRates, entry.Quote.TokenBounds + selection.Candidates = append(selection.Candidates, candidate) + } + return selection, nil +} + +func TestCatalogCompositionCoalescesFourRequests(t *testing.T) { + bundle, record, _ := catalogProjectionFixture(t) + snapshot := &pb.ProviderCatalogSnapshot{Version: "same", Record: record} + rpc := &catalogRPC{configuration: bundle, snapshot: snapshot} + gateway := &Gateway{deferred: &bundle, source: &gatewayclient.Client{RPC: rpc}} + var results [4]*catalogProjection + var failures [4]error + var workers sync.WaitGroup + start := make(chan struct{}) + for i := range results { + workers.Go(func() { + <-start + results[i], failures[i] = gateway.composeCatalog(t.Context(), snapshot) + }) + } + close(start) + workers.Wait() + for i := range results { + if failures[i] != nil || results[i] == nil || results[i] != results[0] { + t.Fatalf("composition was not shared: %v", failures) + } + } + if strings.Join(rpc.calls, ",") != "compose" { + t.Fatal("duplicate semantic work", rpc.calls) + } +} diff --git a/go/internal/controlplane/source_compile.go b/go/internal/controlplane/source_compile.go index f0c99ddc..397b61c7 100644 --- a/go/internal/controlplane/source_compile.go +++ b/go/internal/controlplane/source_compile.go @@ -18,11 +18,14 @@ import ( // BootstrapProducer joins native registered compilation to the existing exact // source reconciliation/publication and routing path. Compilation never sends. func BootstrapProducer(ctx context.Context, source, owner *gatewayclient.Client, producer string) (*Gateway, error) { + if owner == nil { + return nil, errors.New("operation authority role required") + } return bootstrapProducer(ctx, source, owner, producer, nil) } func bootstrapProducer(ctx context.Context, source, owner *gatewayclient.Client, producer string, trace bootstrapTrace) (*Gateway, error) { - if source == nil || owner == nil { + if source == nil { return nil, errors.New("source and operation authority roles required") } trace.phase("source-compile-start") @@ -95,7 +98,7 @@ func compiledBundle(input *pb.SourceArtifact) (config.Bundle, error) { } bundle.Plans = append(bundle.Plans, plan) } - return config.FreezeBundle(bundle) + return config.CloneArtifact(bundle) } func unknownFields(message proto.Message) bool { return len(message.ProtoReflect().GetUnknown()) != 0 } func cloneRevision(value *uint64) *uint64 { diff --git a/go/internal/controlplane/source_compile_test.go b/go/internal/controlplane/source_compile_test.go index 3b3d0d88..55bc8bd5 100644 --- a/go/internal/controlplane/source_compile_test.go +++ b/go/internal/controlplane/source_compile_test.go @@ -82,15 +82,11 @@ func FuzzCompiledSourceOwnershipAndBinding(f *testing.F) { if !reflect.DeepEqual(owned, expected) { t.Fatal("source followed protobuf-owned storage") } - _, err = compiledBundle(wire) - // A different expected revision is still consistent proposal data. - // Original provenance comes from the authenticated server's catalog; - // only the final publication CAS decides whether that parent is current. - if field%7 != 6 && err == nil { - t.Fatal("malformed binding accepted") - } - if field%7 == 6 && err != nil { - t.Fatal("valid proposal was mistaken for authority", err) + // The adapter owns the projection but does not reinterpret Workflow or + // recompute semantic commitments. Rust's source binding rejects changes. + // A changed revision remains a proposal for the final publication CAS. + if _, err = compiledBundle(wire); err != nil { + t.Fatal("bounded projection was mistaken for semantic authority", err) } }) } @@ -114,6 +110,11 @@ type sourceRPC struct { failRegister bool } +func (r *sourceRPC) ComposeSource(_ context.Context, request *pb.SourceCompositionRequest, _ ...grpc.CallOption) (*pb.SourceCompositionReply, error) { + // This test double projects the supplied artifact; real Rust/Scheme semantics + // are covered by the native owner and authenticated integration tests. + return &pb.SourceCompositionReply{Artifact: request.Source, CatalogVersion: request.ExpectedCatalogVersion}, nil +} func (r *sourceRPC) CompileSource(context.Context, *pb.ProducerRequest, ...grpc.CallOption) (*pb.CompiledSource, error) { r.calls = append(r.calls, "compile") if r.failCompile { diff --git a/go/internal/controlplane/source_composition.go b/go/internal/controlplane/source_composition.go new file mode 100644 index 00000000..4171426f --- /dev/null +++ b/go/internal/controlplane/source_composition.go @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +package controlplane + +import ( + "context" + "errors" + pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" + "github.com/HardenedLinux/weaver/go/internal/config" + "github.com/HardenedLinux/weaver/go/internal/gatewayclient" +) + +// Pure wire projection. Selection, topology and canonical checks belong to Scheme/Rust. +func sourceCompositionRequest(bundle config.Bundle, catalog bool, version string) *pb.SourceCompositionRequest { + g := bundle.Governance + selection := &pb.GovernanceSelection{Schema: g.Schema, Family: g.Family, OpenNodes: g.OpenNodes} + for _, edge := range g.WorkflowEdges { + selection.WorkflowEdges = append(selection.WorkflowEdges, &pb.WorkflowEdge{Dependent: edge[0], Dependency: edge[1]}) + } + for _, row := range g.WorkflowSelectors { + selection.WorkflowSelectors = append(selection.WorkflowSelectors, &pb.WorkflowSelector{Selector: row[0], Left: row[1], Right: row[2]}) + } + source := &pb.SourceArtifact{Governance: selection, Publication: gatewayclient.Publication(bundle.Publication)} + for _, task := range bundle.Tasks { + source.Tasks = append(source.Tasks, gatewayclient.Task(task)) + } + for _, plan := range bundle.Plans { + source.Plans = append(source.Plans, gatewayclient.Plan(plan)) + } + request := &pb.SourceCompositionRequest{Source: source, UseCatalog: catalog, ExpectedCatalogVersion: version} + for _, row := range bundle.Routing { + selection := &pb.RoutingSelection{Node: row.Node, AllowedModules: row.AllowedModules, Required: row.Required, + MaxLatencyMs: row.MaxLatencyMillis, MaxProcurementCost: row.MaxProcurementCost, UserTokenRates: row.UserTokenRates[:]} + for _, candidate := range row.Candidates { + selection.Candidates = append(selection.Candidates, &pb.RoutingCandidate{Module: candidate.Module, + Capabilities: candidate.Capabilities, LatencyMs: candidate.LatencyMillis, + ProcurementRates: candidate.ProcurementRates[:], TokenBounds: candidate.TokenBounds[:], Plan: gatewayclient.Plan(candidate.Plan)}) + } + request.Routing = append(request.Routing, selection) + } + return request +} +func composeSourceBundle(ctx context.Context, source *gatewayclient.Client, bundle config.Bundle, catalog bool, version string) (config.Bundle, error) { + reply, err := source.RPC.ComposeSource(source.Context(ctx), sourceCompositionRequest(bundle, catalog, version)) + if err != nil { + return config.Bundle{}, err + } + if reply == nil || reply.CatalogVersion != version { + return config.Bundle{}, errors.New("composition version changed") + } + selected, err := compiledBundle(reply.Artifact) + if err != nil { + return config.Bundle{}, err + } + // Independently issued review custody is transport data, never recomputed by + // the semantic planner. Rust still verifies its exact publication binding. + selected.Publication.Review = bundle.Publication.Clone().Review + return selected, nil +} diff --git a/go/internal/devrunner/plan.go b/go/internal/devrunner/plan.go index 279e564e..a6099fae 100644 --- a/go/internal/devrunner/plan.go +++ b/go/internal/devrunner/plan.go @@ -253,7 +253,7 @@ func stagesForMode(mode, goBinary string) ([]Stage, error) { {"scheme-source-integration-tests", schemeTool(), []string{"test", "-g", "-v", "5", "t/integration"}}, {"scheme-provider-server-build", "cargo", append(SchemeQualificationCargoArgs(), "--no-run", "-vv")}, {"scheme-rooted-sdk-integration", "cargo", append(SchemeQualificationCargoArgs(), "--", "--test-threads=4")}, - {"scheme-grpc-stream-integration", goBinary, []string{"-C", "go", "test", "-json", "-count=1", "-race", "-tags=integration,schemeintegration", "-timeout=10m", "./dev", "-run", "^TestProviderControl", "-skip", "^TestProviderControlGovernorPerformance$"}}, + {"scheme-grpc-stream-integration", goBinary, []string{"-C", "go", "test", "-json", "-count=1", "-race", "-tags=integration,schemeintegration", "-timeout=10m", "./dev", "-run", "^TestProvider(Control|ModuleSelectionBindsOriginal|RustDirect)", "-skip", "^TestProviderControlGovernorPerformance$"}}, }, nil case "bench-execution": return []Stage{ diff --git a/proto/gateway/v1/gateway.proto b/proto/gateway/v1/gateway.proto index 0948499f..b173d5d8 100644 --- a/proto/gateway/v1/gateway.proto +++ b/proto/gateway/v1/gateway.proto @@ -35,6 +35,8 @@ service Gateway { // Preparation only. Actual ingress/source state selects an installed original; // request labels cannot supply authority, replacement source or module paths. rpc CompileSource(ProducerRequest) returns (CompiledSource); + // Authenticated source-only advisory composition; never publishes or installs an original. + rpc ComposeSource(SourceCompositionRequest) returns (SourceCompositionReply); rpc InspectProviderCatalog(Empty) returns (ProviderCatalogSnapshot); rpc PublishProviderCatalog(ProviderCatalogChange) returns (ProviderCatalogSnapshot); // Statistical process-local counters only; never durable execution evidence. @@ -83,6 +85,21 @@ message WorkflowEdge { string dependent = 1; string dependency = 2; } message WorkflowSelector { string selector = 1; string left = 2; string right = 3; } message GovernanceSelection { string schema = 1; string family = 2; repeated string open_nodes = 3; repeated WorkflowEdge workflow_edges = 4; repeated WorkflowSelector workflow_selectors = 5; } message SourceArtifact { GovernanceSelection governance = 1; repeated Task tasks = 2; repeated ProviderPlan plans = 3; PublishRequest publication = 4; } +message RoutingCandidate { + string module = 1; repeated string capabilities = 2; uint64 latency_ms = 3; + repeated uint64 procurement_rates = 4; repeated uint64 token_bounds = 5; + ProviderPlan plan = 6; +} +message RoutingSelection { + string node = 1; repeated string allowed_modules = 2; repeated string required = 3; + uint64 max_latency_ms = 4; uint64 max_procurement_cost = 5; + repeated uint64 user_token_rates = 6; repeated RoutingCandidate candidates = 7; +} +message SourceCompositionRequest { + SourceArtifact source = 1; repeated RoutingSelection routing = 2; + bool use_catalog = 3; string expected_catalog_version = 4; +} +message SourceCompositionReply { SourceArtifact artifact = 1; string catalog_version = 2; } // Source authority here is knowledge at response admission, never a later permit. message CompiledSource { string producer = 1; SourceAuthorityView authority = 2; SourceArtifact artifact = 3; } message OperationKey { string family = 1; string node = 2; } @@ -120,7 +137,9 @@ message FamilyAliasRequest { string family = 1; string origin = 2; } message DomainMigration { string operation_id = 1; string budget_from = 2; string budget_to = 3; string history_from = 4; string history_to = 5; uint64 budget_from_epoch = 6; uint64 budget_to_epoch = 7; uint64 history_from_epoch = 8; uint64 history_to_epoch = 9; } message DomainMigrationReceipt { string operation_id = 1; string digest = 2; bool committed = 3; string budget_root = 4; string history_root = 5; uint64 budget_epoch = 6; uint64 history_epoch = 7; } // Distinct source capability: both fields are required by the server. No fallback. -message RegisterPublishedTaskRequest { Task task = 1; PublicationKey publication = 2; } +// Exactly one of task or source_scope. The latter declares a bounded deferred +// selection or immutable original under authenticated source custody; never an operation permit. +message RegisterPublishedTaskRequest { Task task = 1; PublicationKey publication = 2; SourceCompositionRequest source_scope = 3; } message PublishRequest { optional uint64 expected_revision = 1; uint64 fence = 2; string policy = 3; string schema = 4; string operation_id = 5; } enum PublicationOutcome { PUBLICATION_OUTCOME_UNSPECIFIED = 0; COMMITTED = 1; REJECTED = 2; } message PublicationReceipt { string operation_id = 1; string digest = 2; PublicationOutcome outcome = 3; optional uint64 revision = 4; optional uint64 fence = 5; } diff --git a/scheme/gateway/compiled.ss b/scheme/gateway/compiled.ss index 2419fa11..b7d9b775 100644 --- a/scheme/gateway/compiled.ss +++ b/scheme/gateway/compiled.ss @@ -8,6 +8,7 @@ (only-in :clan/poo/object .get .o) :gerbil-scheme-rust/scheme/runtime (only-in "./func.ss" governor-ready-steps make-retained-governor gateway-source-cancelled?) + (only-in "./provider-source.ss" compose-provider-configuration) (only-in "./program.ss" make-gateway-program hard-fact-affected) (only-in "./snapshot.ss" scheme-value->source-data source-data->scheme-value)) (export install-gateway-producer!) @@ -48,6 +49,10 @@ indexed_result: (table-ref value 'indexed_result)) packed)) (derive-governor (scheme-value->source-data value)))))))) +(def (compose-request value) + (with-catch (lambda (_) #f) + (lambda () (source-data->scheme-value + (compose-provider-configuration (scheme-value->source-data value)))))) (def (fact-impact-request value) (with-catch (lambda (_) #f) (lambda () @@ -64,6 +69,9 @@ (c-define (fact-impact-root root) (int64) int64 "weaver_hard_fact_impact_v1" "extern" (gerbil-scheme-rust/scheme/runtime#gerbil-rs-rooted-call root hardenedlinux/weaver/scheme/gateway/compiled#fact-impact-request)) + (c-define (compose-root root) (int64) int64 "weaver_compose_source_v1" "extern" + (gerbil-scheme-rust/scheme/runtime#gerbil-rs-rooted-call root + hardenedlinux/weaver/scheme/gateway/compiled#compose-request)) (c-define (capture-root root) (int64) int64 "weaver_capture_source_v1" "extern" (gerbil-scheme-rust/scheme/runtime#gerbil-rs-rooted-call root hardenedlinux/weaver/scheme/gateway/compiled#capture-request)) diff --git a/scheme/gateway/contracts.ss b/scheme/gateway/contracts.ss index a7797e19..9cd1230c 100644 --- a/scheme/gateway/contracts.ss +++ b/scheme/gateway/contracts.ss @@ -9,7 +9,7 @@ (only-in :clan/poo/number UIntN) (only-in :hardenedlinux/weaver/scheme/policy/types CedarPolicySource CedarSchemaSource)) (export GatewayArtifact GatewaySourceInput TaskContract ProviderPlanContract PublicationContract - ProviderProfileContract ProviderRouteContract Identifier Counter Credits Digest) + ProviderProfileContract ProviderRouteContract Identifier Counter Credits Digest ProviderComposition) ;;; Preserve exact JSON integer tokens above 2^53; the default Integer JSON ;;; encoder intentionally uses strings there, which this wire schema forbids. @@ -87,3 +87,20 @@ (.cc (Record governance: (list GovernorHandoff) tasks: (list (List TaskContract)) plans: (list (List ProviderPlanContract)) publication: (list PublicationContract)) identity: 'weaver/gateway-artifact sealed: #t)) + +;;; Bounded host facts for source composition, not an authorization receipt. +(def ProviderCandidateFacts + (.cc (Record module: (list Identifier) capabilities: (list (List String)) + latency_ms: (list Counter) procurement_rates: (list (List Counter)) + token_bounds: (list (List Counter)) plan: (list ProviderPlanContract) + digest: (list Digest) body_digest: (list Digest)) + identity: 'weaver/provider-candidate-facts sealed: #t)) +(def ProviderSelectionFacts + (.cc (Record node: (list Identifier) allowed_modules: (list (List Identifier)) + required: (list (List String)) max_latency_ms: (list Counter) + max_procurement_cost: (list Counter) user_token_rates: (list (List Counter)) + candidates: (list (List ProviderCandidateFacts))) + identity: 'weaver/provider-selection-facts sealed: #t)) +(def ProviderComposition + (.cc (Record source: (list GatewayArtifact) routing: (list (List ProviderSelectionFacts))) + identity: 'weaver/provider-composition sealed: #t)) diff --git a/scheme/gateway/func.ss b/scheme/gateway/func.ss index 5758e4d9..073d7c46 100644 --- a/scheme/gateway/func.ss +++ b/scheme/gateway/func.ss @@ -26,7 +26,7 @@ (only-in "./derivation.ss" derive-gateway-source) (only-in "./derivation-types.ss" GatewayPreparation) "./contracts.ss") -(export compile-gateway prepare-gateway prepare-governed-gateway emit-gateway emit-governed-gateway capture-governed-gateway make-gateway-program governor-open-nodes governor-ready-steps) +(export compile-gateway prepare-gateway prepare-governed-gateway emit-gateway emit-governed-gateway capture-governed-gateway make-gateway-program governor-open-nodes governor-ready-steps compose-governor-selection) (export gateway-source-phase-observer gateway-source-cancelled? make-retained-governor trace-gateway-source-phase) ;;; Each source-loaded role has its own parameter. Enable the same numeric @@ -127,6 +127,24 @@ conditional? (list-sort (lambda (a b) (stringvector (.get selection candidates))) + (unless (and (member node (.get task nodes)) (not (member node chosen-nodes)) + (< 0 (.get selection max_latency_ms)) (<= (vector-length candidates) 8)) + (error "Routing node or candidate bound")) + (def offers '()) + (def allowed '()) + (def capable '()) + (for-each + (lambda (id) + (def candidate (vector-ref candidates id)) + (def plan (.get candidate plan)) + (def price (charge (.get candidate procurement_rates) (.get candidate token_bounds))) + (def debit (charge (.get selection user_token_rates) (.get candidate token_bounds))) + (when (and (equal? (.get plan family) (.get task family)) + (equal? (.get plan node) node) price debit + (< 0 (.get candidate latency_ms)) + (<= (.get candidate latency_ms) (.get selection max_latency_ms)) + (<= price (.get selection max_procurement_cost)) + (<= debit (.get plan ceiling))) + (set! offers (cons (list id price (.get candidate latency_ms)) offers))) + (when (member (.get candidate module) (.get selection allowed_modules)) + (set! allowed (cons (list id) allowed))) + (when (andmap (lambda (capability) (member capability (.get candidate capabilities))) + (.get selection required)) + (set! capable (cons (list id) capable)))) + (iota (vector-length candidates))) + (def program + (relational-program + (relation offer (id price latency) offers) + (relation allowed (id) allowed) + (relation capable (id) capable) + (relation eligible (id price latency) '()) + (rule (eligible ?id ?price ?latency) (offer ?id ?price ?latency) + (allowed ?id) (capable ?id)) + (limits 24 8 32))) + (def result (gerbil-ascent-session-run (gerbil-ascent-open-session program))) + (unless (eq? (.ref result 'finished) #t) (error "Routing derivation incomplete")) + (def eligible ((.ref result 'rows-of) 'eligible)) + (when (null? eligible) (error "No eligible model candidate")) + (def (before? a b) + (or (< (cadr a) (cadr b)) + (and (= (cadr a) (cadr b)) + (or (< (caddr a) (caddr b)) + (and (= (caddr a) (caddr b)) + (stringsymbol node) (.get chosen body_digest)) bodies)) + (set! streams (cons (cons (string->symbol node) (.get chosen digest)) streams))) routing) + (def schema (.get (.get original governance) schema)) + (def topology + (if (equal? schema "agentic-ai-lab.loop-governor.v1") + (.get original governance) + (let (controls (provider-source-controls schema)) + (compose-governor-selection (car controls) (cadr controls) '() (.get task family))))) + (validate GatewayArtifact + (copy-source-data + (.o (:: @ original) governance: topology + tasks: (list (.o (:: @ task) body_digests: (object<-alist bodies) + stream_contracts: (object<-alist streams))) + plans: (reverse selected-plans))))) diff --git a/scheme/gateway/types.ss b/scheme/gateway/types.ss index 528ea35b..73a6af6e 100644 --- a/scheme/gateway/types.ss +++ b/scheme/gateway/types.ss @@ -2,7 +2,7 @@ ;;; ;;; SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 -;;; Gateway configuration operations; actual routing compilation remains in Go. +;;; Gateway semantic operations; Rust retains final validation and authority. (import (only-in :clan/poo/object .cc) (only-in :clan/poo/mop Function Bool) (only-in :clan/poo/type Record List Pair Or Symbol String Enum) diff --git a/t/gateway-source-test.ss b/t/gateway-source-test.ss index c0cae6cc..fc66492d 100644 --- a/t/gateway-source-test.ss +++ b/t/gateway-source-test.ss @@ -5,7 +5,7 @@ ;;; Source compilation checks stay in the native Scheme test suite. (import :std/test (only-in :std/error Error? Error-message) - (only-in :clan/poo/object .o .get .slot? object-slots-set!) + (only-in :clan/poo/object .o .get .ref .slot? object-slots-set!) (only-in :clan/poo/mop TypeError? validate sexp<-) (only-in ../scheme/gateway/contracts GatewayArtifact) (only-in :agentic-ai-lab/modules/governance/interface AgenticAILabGovernanceProfile. agentic-ai-lab-governance-source) @@ -20,6 +20,7 @@ (prefix-in :clan/poo/testing/property/generator generator.) (prefix-in :clan/poo/testing/property property.) (only-in :clan/poo/testing/property/test check-property) + (only-in ../scheme/gateway/provider-source compose-provider-configuration) ../scheme/gateway/func) (export gateway-source-test) @@ -57,6 +58,29 @@ (def gateway-source-test (test-suite "Stable source assessment projection" + (test-case "ASCENT routing filters modules and ranks exact cost then latency then digest" + (def source-plan plan) + (def (candidate module-name latency price digest-value) + (.o module: module-name capabilities: '("text") latency_ms: latency + procurement_rates: (list price 0 0 0) token_bounds: '(1000000 0 0 32) + plan: source-plan digest: digest-value body_digest: commitment)) + (def (compose candidate-values (maximum 100)) + (compose-provider-configuration + (.o source: (.o (:: @ bundle) tasks: (list (.o (:: @ task) body_digests: (.o) stream_contracts: (.o))) plans: '()) + routing: (list (.o node: "infer" allowed_modules: '("allowed") required: '("text") + max_latency_ms: maximum max_procurement_cost: 4 user_token_rates: '(0 0 0 0) + candidates: candidate-values))))) + (def a (candidate "allowed" 10 2 (make-string 64 #\b))) + (def b (candidate "allowed" 10 2 commitment)) + (def disallowed (candidate "other" 1 1 (make-string 64 #\0))) + (for-each + (lambda (candidates) + (check-equal? (.ref (.get (car (.get (compose candidates) tasks)) stream_contracts) 'infer) commitment)) + (list (list a disallowed b) (list b a disallowed))) + (check-exception (compose (list disallowed)) Error?) + (check-exception (compose (list a) 9) Error?) + (check-exception (compose (list (candidate "allowed" 1 9223372036854775807 + commitment))) Error?)) (test-case "program returns independent typed data without borrowing an ambient sink" (let* ((program (make-gateway-program)) (held #f) (text (string-copy (.get source-publication policy))) (original (string-copy text)) From fd782458db81c3c2e2e77e9728c7d49bb42b9ba5 Mon Sep 17 00:00:00 2001 From: guangtao Date: Tue, 10 Nov 2026 18:24:14 +0800 Subject: [PATCH 102/105] Move Weaver source preparation and verification to Rust Version the source, Kubernetes fixture, acceptance controls and SysML allocation. Keep generated run outputs in the local verification cache. Final Scheme release qualification remains pending after the prepared SDK was removed. --- Cargo.lock | 495 +++++++++- Project.sysml | 16 +- README.org | 2 +- crates/contracts/src/json.rs | 7 +- crates/contracts/src/lib.rs | 2 +- crates/ledger/src/hard_fact.rs | 87 +- crates/ledger/src/lib.rs | 2 +- crates/ledger/src/provider_routing.rs | 22 +- crates/ledger/src/schema.rs | 2 + crates/server/Cargo.toml | 8 + crates/server/build.rs | 2 +- crates/server/src/entrypoint.rs | 33 + crates/server/src/grpc.rs | 9 + crates/server/src/grpc_config.rs | 4 +- crates/server/src/grpc_hard_fact.rs | 19 + crates/server/src/kubernetes.rs | 286 ++++++ crates/server/src/lib.rs | 5 + crates/server/src/main.rs | 51 +- crates/server/src/provider_import.rs | 121 +++ crates/server/src/review_wire.rs | 30 + crates/server/src/source_artifact.rs | 32 +- crates/server/src/source_file.rs | 205 +++++ crates/server/src/source_owner.rs | 32 +- crates/server/src/source_prepare.rs | 327 +++++++ dev/sysml/ArchitectureEvolution.sysml | 18 +- dev/sysml/ArchitectureReaderViews.sysml | 8 +- dev/sysml/ControlActivation.sysml | 2 +- dev/sysml/ControllerObjectLifecycle.sysml | 2 +- dev/sysml/ProviderRpc.sysml | 2 +- dev/sysml/ResearchReaderViews.sysml | 2 +- dev/sysml/WeaverExecution.sysml | 24 +- dev/sysml/runtime-trace.json | 2 +- .../10.01-llm-gateway-and-routing.org | 2 +- .../59-provider-rpc/59.00-index.org | 2 +- .../59.03-provider-rpc-core.d2 | 44 +- .../59.03-provider-rpc-core.png | Bin 114628 -> 114620 bytes .../59.03-provider-rpc-core.svg | 24 +- .../59.19-governance-control.org | 24 +- ....82-semantic-responsibility-allocation.org | 2 +- .../59.87-spec-upgrade-and-delivery-plan.org | 84 +- docs/architecture/00-system-design.org | 12 +- .../architecture/06-go-control-plane-role.org | 72 +- .../diagrams/01-system-boundaries.d2 | 46 +- .../diagrams/01-system-boundaries.png | Bin 110872 -> 112842 bytes .../diagrams/01-system-boundaries.svg | 30 +- go/api/gateway/v1/gateway.pb.go | 844 +++++++++++------- go/api/gateway/v1/gateway_grpc.pb.go | 38 + go/cmd/weaver-import-provider/main.go | 54 -- .../weaver-control => dev/controlref}/main.go | 4 +- go/dev/provider_control_test.go | 58 +- go/dev/provider_fixture_test.go | 2 +- go/dev/provider_hard_fact_test.go | 26 +- go/dev/provider_import_test.go | 83 ++ go/dev/provider_kubernetes_test.go | 235 +++++ go/dev/provider_module_routing_test.go | 2 +- go/dev/provider_program_deployment_test.go | 164 +++- go/dev/publication_recovery_test.go | 15 +- go/dev/runtime_boundary_test.go | 57 +- prod/kubernetes/provideravailability.crd.yaml | 50 ++ .../kubernetes/provideravailability.rbac.yaml | 36 + proto/gateway/v1/gateway.proto | 15 + 61 files changed, 3281 insertions(+), 603 deletions(-) create mode 100644 crates/server/src/kubernetes.rs create mode 100644 crates/server/src/provider_import.rs create mode 100644 crates/server/src/source_file.rs create mode 100644 crates/server/src/source_prepare.rs delete mode 100644 go/cmd/weaver-import-provider/main.go rename go/{cmd/weaver-control => dev/controlref}/main.go (82%) create mode 100644 go/dev/provider_import_test.go create mode 100644 go/dev/provider_kubernetes_test.go create mode 100644 prod/kubernetes/provideravailability.crd.yaml create mode 100644 prod/kubernetes/provideravailability.rbac.yaml diff --git a/Cargo.lock b/Cargo.lock index e2f23a22..882542fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,6 +79,12 @@ dependencies = [ "cc", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "allocator-api2" version = "0.4.0" @@ -100,6 +106,17 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "annotate-snippets" +version = "0.12.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a5b0a5ab8561c603f16c3b78c24a386b1f70e7fc1b1b1e8c15738828e4a176" +dependencies = [ + "anstyle", + "memchr", + "unicode-width 0.2.2", +] + [[package]] name = "anstream" version = "1.0.0" @@ -210,6 +227,12 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + [[package]] name = "arrayvec" version = "0.5.2" @@ -382,6 +405,40 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfdc70193dadb9d7287fa4b633f15f90c876915b31f6af17da307fc59c9859a8" +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "async-trait" version = "0.1.92" @@ -471,6 +528,17 @@ dependencies = [ "tower-service", ] +[[package]] +name = "backon" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" +dependencies = [ + "fastrand", + "gloo-timers", + "tokio", +] + [[package]] name = "base-x" version = "0.2.11" @@ -822,7 +890,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84f39a1d02e72014885b6c33d5ec4fbd0c7ede5ed1069b3a9e5775874bca066b" dependencies = [ "chrono", - "educe", + "educe 0.8.1", "either", "itertools 0.15.0", "lalrpop", @@ -1115,6 +1183,12 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "core_detect" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -1398,6 +1472,27 @@ dependencies = [ "serde_core", ] +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.119", +] + [[package]] name = "digest" version = "0.10.7" @@ -1481,6 +1576,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "educe" version = "0.8.1" @@ -1526,6 +1633,29 @@ dependencies = [ "log", ] +[[package]] +name = "encoding_rs" +version = "0.8.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89253175e704ab869b04f9db224d38630e0211a53841a79181deae0889e169f5" +dependencies = [ + "cfg-if", + "core_detect", + "multiversion_no_op", + "rustversion", + "scopeguard", + "simdutf8", +] + +[[package]] +name = "encoding_rs_io" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba3fe847045ecff794b9c138293a80db914678c453ad63fbf0c6a9eb6e00b22" +dependencies = [ + "encoding_rs", +] + [[package]] name = "enum-ordinalize" version = "4.4.2" @@ -1582,6 +1712,26 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "event-listener" +version = "5.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +dependencies = [ + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "fallible-iterator" version = "0.3.0" @@ -1682,6 +1832,20 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "futures" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.34" @@ -1744,6 +1908,7 @@ version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -1925,6 +2090,28 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "granit-parser" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d03f81ad4732830d85cfd417a9f62cde6dadda4354d37d078a6084a19560aa2d" +dependencies = [ + "arraydeque", + "smallvec", +] + [[package]] name = "group" version = "0.13.0" @@ -1982,6 +2169,17 @@ dependencies = [ "foldhash 0.1.5", ] +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2 0.2.21", + "equivalent", + "foldhash 0.2.0", +] + [[package]] name = "hashbrown" version = "0.17.1" @@ -2024,6 +2222,17 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "hostname" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617aaa3557aef3810a6369d0a99fac8a080891b68bd9f9812a1eeda0c0730cbd" +dependencies = [ + "cfg-if", + "libc", + "windows-link", +] + [[package]] name = "http" version = "1.5.0" @@ -2109,7 +2318,9 @@ dependencies = [ "http", "hyper", "hyper-util", + "log", "rustls", + "rustls-native-certs", "tokio", "tokio-rustls", "tower-service", @@ -2598,6 +2809,53 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json-patch" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7421438de105a0827e44fadd05377727847d717c80ce29a229f85fd04c427b72" +dependencies = [ + "jsonptr", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "jsonpath-rust" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c4668c489390e66d586fe2238ee8568473f7ac1607b411342f787c5e1bedd7" +dependencies = [ + "pest", + "pest_derive", + "regex", + "serde_json", + "thiserror", +] + +[[package]] +name = "jsonptr" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5a3cc660ba5d72bce0b3bb295bf20847ccbb40fd423f3f05b61273672e561fe" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "k8s-openapi" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c6922f6afe80418dd6019818af5d0d34584c371780ff09b9752370c25b4abb" +dependencies = [ + "base64 0.22.1", + "jiff", + "serde", + "serde_json", +] + [[package]] name = "keccak" version = "0.1.6" @@ -2617,6 +2875,99 @@ dependencies = [ "cpufeatures 0.3.1", ] +[[package]] +name = "kube" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "208d7fe1380066abb194812a8a8e303cb896a33bb3d7b3177b71bd03ff39bf18" +dependencies = [ + "k8s-openapi", + "kube-client", + "kube-core", + "kube-runtime", +] + +[[package]] +name = "kube-client" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e940a73033a7c5c7918b5ece7851d84571b58be25e937198da37fa13f116d3" +dependencies = [ + "base64 0.22.1", + "bytes", + "either", + "futures", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-timeout", + "hyper-util", + "jiff", + "jsonpath-rust", + "k8s-openapi", + "kube-core", + "pem", + "rustls", + "rustls-platform-verifier", + "secrecy", + "serde", + "serde-saphyr", + "serde_json", + "thiserror", + "tokio", + "tokio-util", + "tower", + "tower-http", + "tracing", +] + +[[package]] +name = "kube-core" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d2353c118cf3462c352ee0b5bd5b0cf17990af456dfd8662d136ff9812eeb4" +dependencies = [ + "derive_more", + "form_urlencoded", + "http", + "jiff", + "json-patch", + "k8s-openapi", + "serde", + "serde-value", + "serde_json", + "thiserror", +] + +[[package]] +name = "kube-runtime" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb064ef71c7bea55e934a443960da9e9ec31fbb2ba63e47e4aeca32603d5cc7" +dependencies = [ + "ahash", + "async-broadcast", + "async-stream", + "backon", + "educe 0.6.0", + "futures", + "hashbrown 0.16.1", + "hostname", + "json-patch", + "k8s-openapi", + "kube-client", + "parking_lot", + "pin-project", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "lalrpop" version = "0.22.2" @@ -3139,12 +3490,24 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" +[[package]] +name = "multiversion_no_op" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743fb55ba31b18fb1ecef6bdc9aa2743314978ac084044301a7eee33fb99a20d" + [[package]] name = "new_debug_unreachable" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + [[package]] name = "nom" version = "7.1.3" @@ -3265,6 +3628,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + [[package]] name = "owo-colors" version = "3.5.0" @@ -3302,6 +3674,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.5" @@ -3347,6 +3725,59 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pest" +version = "2.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ec53fd1d256900a9a771bf2720d42cef6f8bc91b4e25065fbd291e3e7222576" +dependencies = [ + "memchr", + "pest_stack_guard", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf794fd301ddc20818a6b4de85ed507f4b45300245cec948982e69e12e3bd7" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3073afae5db334c25dea9fc3e230a4f191e920c1df080cb9c0b37c9ce1dbb41" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "pest_meta" +version = "2.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bc7f614b3742541642af1685faaa910bf6333e3cd3729c2cccd118146a57327" +dependencies = [ + "pest", +] + +[[package]] +name = "pest_stack_guard" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac6154fd4418b8f0b82532c59c26f303f9ca59a64c883e8ce3971fd82733439" +dependencies = [ + "psm", + "stacker", +] + [[package]] name = "petgraph" version = "0.7.1" @@ -4242,6 +4673,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secrecy" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" +dependencies = [ + "zeroize", +] + [[package]] name = "security-framework" version = "3.7.0" @@ -4285,6 +4725,35 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-saphyr" +version = "0.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd22781911de0ca6debda95f073c8f18bec65d1a94f1fa9573f3102e514cea4" +dependencies = [ + "ahash", + "annotate-snippets", + "base64 0.22.1", + "encoding_rs_io", + "getrandom 0.3.4", + "granit-parser", + "nohash-hasher", + "num-traits", + "serde_core", + "smallvec", + "zmij", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + [[package]] name = "serde_bytes" version = "0.11.19" @@ -4543,9 +5012,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.16.3" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "smol_str" @@ -4891,6 +5360,7 @@ dependencies = [ "futures-util", "libc", "pin-project-lite", + "slab", "tokio", ] @@ -5063,15 +5533,18 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ + "base64 0.22.1", "bitflags 2.13.2", "bytes", "futures-util", "http", "http-body", + "mime", "pin-project-lite", "tower", "tower-layer", "tower-service", + "tracing", "url", ] @@ -5093,6 +5566,7 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -5190,7 +5664,7 @@ dependencies = [ "aegis", "aes", "aes-gcm", - "allocator-api2", + "allocator-api2 0.4.0", "antithesis_sdk", "arc-swap", "aristo", @@ -5382,6 +5856,12 @@ version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + [[package]] name = "unarray" version = "0.1.4" @@ -5761,20 +6241,27 @@ dependencies = [ "arrow-schema", "asp-rust", "criterion", + "futures-util", "gerbil-scheme", "gerbil-scheme-sys", "hex", + "k8s-openapi", + "kube", "proptest", "prost", "rcgen", "ring", "rustls", + "serde", + "serde-saphyr", + "serde_json", "sha2 0.10.9", "subtle", "tempfile", "tokio", "tokio-stream", "tokio-util", + "toml 1.1.8+spec-1.1.0", "tonic", "tonic-prost", "tonic-prost-build", diff --git a/Project.sysml b/Project.sysml index eb7b2622..026a0b1a 100644 --- a/Project.sysml +++ b/Project.sysml @@ -103,8 +103,7 @@ package WeaverProject { part 'go/dev' : ForbiddenRuntimeRoot; part 'go/internal/devrunner' : ForbiddenRuntimeRoot; part prod : RuntimeAssetRoot; - part 'go/cmd/weaver-control' : RuntimeGoEntry; - part 'go/cmd/weaver-import-provider' : RuntimeGoEntry; + part 'go/dev/controlref' : DevelopmentGoEntry; part 'go/cmd/weaver-meter' : RuntimeGoEntry; part 'go/cmd/weaver-dev' : DevelopmentGoEntry; part 'scheme' : RuntimeSourceRoot; @@ -474,9 +473,9 @@ package WeaverProject { execution, durable CAS and qualified storage/transport adapters. */ part cedarLibrary : WeaverExecution::CedarSecurityFrameworks; part semantics : WeaverExecution::SchemeSemanticPublisher; - part control : WeaverExecution::GoControlAdapter; - doc /* Go deployment chooses an authenticated approved-producer RPC or - a JSON/YAML data file, exclusively. It never launches Scheme. Rust's + part control : WeaverExecution::SourceControlAdapter; + doc /* Rust preparation chooses an authenticated approved-producer RPC or + a JSON/YAML data file, exclusively. Rust's default production program installation remains a delivery gate; qualification graphs do not silently become production semantics. */ part policy : WeaverExecution::RustPolicy; @@ -755,9 +754,8 @@ package WeaverProject { part 'go/api/v1' : GoPackage; part 'go/api/gateway/v1' : GoPackage; - part 'go/cmd/weaver-control' : GoPackage; + part 'go/dev/controlref' : GoPackage; part 'go/cmd/weaver-dev' : GoPackage; - part 'go/cmd/weaver-import-provider' : GoPackage; part 'go/cmd/weaver-meter' : GoPackage; part 'go/dev' : GoPackage; part 'go/internal/config' : GoPackage; @@ -791,6 +789,8 @@ package WeaverProject { or production Governance capability is introduced. */ } + part 'prod/kubernetes/provideravailability.crd.yaml' : File; + part 'prod/kubernetes/provideravailability.rbac.yaml' : File; part 'prod/policies/provider/ProviderReview.lean' : File; part 'prod/policies/provider/schema.json' : File; part 'prod/policies/provider/provider.cedar' : File; @@ -844,7 +844,7 @@ package WeaverProject { allocation governanceCode allocate Architecture::semantics to Layout::'scheme/governance'; allocation configurationCode allocate Architecture::semantics to Layout::'scheme/gateway'; - allocation controlCode allocate Architecture::control to Layout::'go/internal/controlplane'; + allocation controlCode allocate Architecture::control to Layout::'crates/server'; allocation cedarCode allocate Architecture::policy to Layout::'crates/policy'; allocation cedarBridgeCode allocate Architecture::policy to Layout::'crates/policy-ffi'; allocation ledgerCode allocate Architecture::ledger to Layout::'crates/ledger'; diff --git a/README.org b/README.org index 7f91b2cd..f0a18da0 100644 --- a/README.org +++ b/README.org @@ -143,7 +143,7 @@ checked through the in-process OpenSysML SDK. | Path | Contents | |------+----------| | =crates/= | Rust workspace libraries, server and per-crate benchmarks | -| =go/= | Go control plane, gRPC clients and development tooling | +| =go/= | OpenSysML tools, gRPC clients, reference controls and independent metering issuer | | =proto/= | Shared versioned Protobuf service definitions | | =scheme/= | Governance, Policy and Gateway modules | | =t/= | Scheme-owned tests and fixtures | diff --git a/crates/contracts/src/json.rs b/crates/contracts/src/json.rs index 74cbd1bc..6c2e5fad 100644 --- a/crates/contracts/src/json.rs +++ b/crates/contracts/src/json.rs @@ -70,7 +70,12 @@ impl<'de> Deserialize<'de> for Unique { } /// Decode bounded JSON after rejecting duplicate keys at every depth. pub fn decode(bytes: &[u8]) -> Result { - if bytes.len() > MAX_BODY_BYTES * 2 { + decode_bounded(bytes, MAX_BODY_BYTES * 2) +} + +/// Use the caller's explicit input bound with the same strict JSON decoder. +pub fn decode_bounded(bytes: &[u8], limit: usize) -> Result { + if bytes.len() > limit { return Err(Error::Invalid("JSON input size")); } let Unique(value) = serde_json::from_slice(bytes)?; diff --git a/crates/contracts/src/lib.rs b/crates/contracts/src/lib.rs index 2cdab829..234af021 100644 --- a/crates/contracts/src/lib.rs +++ b/crates/contracts/src/lib.rs @@ -54,7 +54,7 @@ pub use source_authority::{ SourceAuthority, SourceIdentity, SourceRotation, SourceRotationOutcome, SourceRotationReceipt, }; mod stream; -pub use json::decode; +pub use json::{decode, decode_bounded}; pub use model::{ Error, MAX_BODY_BYTES, MAX_CREDITS, Outcome, Proposal, Receipt, Result, Task, body_digest, identifier, diff --git a/crates/ledger/src/hard_fact.rs b/crates/ledger/src/hard_fact.rs index d141e581..58f79dc5 100644 --- a/crates/ledger/src/hard_fact.rs +++ b/crates/ledger/src/hard_fact.rs @@ -6,7 +6,7 @@ use std::collections::BTreeSet; use crate::{ Ledger, - persistence::{begin, driver::Connection, exec, maybe_current, params}, + persistence::{begin, driver::Connection, exec, maybe_current, params, read_all_current}, source_authority, store::{db, integer}, }; @@ -24,6 +24,16 @@ pub enum FactPreparation { Resolved(FactResolution), } +pub struct FactFeedState { + pub domain: String, + pub source_epoch: u64, + pub floor: u64, + pub revision: u64, + pub snapshot: String, + pub available: Option, + pub pending: Vec<(FactBarrier, bool)>, +} + struct Head { feed: FactFeed, floor: u64, @@ -432,6 +442,81 @@ impl Ledger { tx.commit().map_err(db) } + /// Observe the installed cut and the exact ordered barriers for source recovery. + pub fn inspect_fact_feed(&mut self) -> Result { + let tx = begin(&mut self.connection).map_err(db)?; + let head = head(&tx)?.ok_or(Error::Denied)?; + authorize(&tx, self.source.as_ref(), &head.feed)?; + let available = if head.revision == 0 { + None + } else { + Some( + crate::persistence::one_current( + &tx, + "SELECT NOT EXISTS(SELECT 1 FROM json_each(unavailable) WHERE value=?1) + FROM main.hard_fact_feed WHERE singleton=1", + params![head.feed.root.clone()], + |row| row.get::(0), + ) + .map_err(db)?, + ) + }; + let mut pending = Vec::new(); + if let Some(tail) = tail(&tx, &head)? { + let rows = read_all_current( + &tx, + "SELECT original,barrier FROM main.hard_fact_intents + WHERE resolution IS NULL LIMIT ?1", + params![(MAX_PENDING + 1) as i64], + |row| Ok((row.get::(0)?, row.get::(1)?)), + ) + .map_err(db)?; + let mut entries = rows + .into_iter() + .map(|(intent, barrier)| { + Ok(( + decode::(intent.as_bytes())?, + decode::(barrier.as_bytes())?, + )) + }) + .collect::>>()?; + entries.sort_unstable_by_key(|(_, barrier)| barrier.revision); + if entries.len() as u64 != tail.revision - head.revision + || entries.last().map(|(_, barrier)| barrier) != Some(&tail) + { + return Err(Error::Conflict("hard fact pending sequence changed")); + } + let mut revision = head.revision; + let mut snapshot = head.snapshot.as_str(); + for (intent, barrier) in &entries { + if revision.checked_add(1) != Some(barrier.revision) + || snapshot != intent.previous_snapshot + || intent.snapshot()? != barrier.snapshot + || intent.operation_id != barrier.operation_id + || intent.revision != barrier.revision + || intent.source_epoch != head.feed.authority.epoch + || intent.source_epoch != barrier.source_epoch + || intent.domain != head.feed.domain + { + return Err(Error::Conflict("hard fact pending sequence changed")); + } + revision = barrier.revision; + snapshot = &barrier.snapshot; + pending.push((barrier.clone(), intent.available)); + } + } + tx.commit().map_err(db)?; + Ok(FactFeedState { + domain: head.feed.domain, + source_epoch: head.feed.authority.epoch, + floor: head.floor, + revision: head.revision, + snapshot: head.snapshot, + available, + pending, + }) + } + /// Stage the exact original and install the pending barrier before a worker sees the intent. pub fn stage_fact_intent(&mut self, intent: &FactIntent) -> Result { let snapshot = intent.snapshot()?; diff --git a/crates/ledger/src/lib.rs b/crates/ledger/src/lib.rs index 6caa8ae3..b76c13b5 100644 --- a/crates/ledger/src/lib.rs +++ b/crates/ledger/src/lib.rs @@ -17,7 +17,7 @@ mod delta_registration; mod domains; mod execution_exposure; mod hard_fact; -pub use hard_fact::FactPreparation; +pub use hard_fact::{FactFeedState, FactPreparation}; mod exposure_manifest; #[cfg(feature = "commit-observer")] pub use exposure_manifest::use_prepared_manifest_programs; diff --git a/crates/ledger/src/provider_routing.rs b/crates/ledger/src/provider_routing.rs index a7228e20..84202778 100644 --- a/crates/ledger/src/provider_routing.rs +++ b/crates/ledger/src/provider_routing.rs @@ -50,7 +50,12 @@ fn binding( } fn cut(connection: &Connection, bound: ProviderOperationBinding) -> Result { - if crate::source_authority::current(connection)?.as_ref() != Some(&bound.authority) { + let catalog_scope = matches!(&bound.scope, ProviderOperationScope::Catalog { .. }); + // A fixed task already belongs to its committed publication. A catalog + // scope can register a new task, so its declaring source must still be current. + if catalog_scope + && crate::source_authority::current(connection)?.as_ref() != Some(&bound.authority) + { return Err(Error::Denied); } let publication = bound.scope.publication(); @@ -71,14 +76,13 @@ fn cut(connection: &Connection, bound: ProviderOperationBinding) -> Result Result<(), Box> { println!("cargo:rerun-if-changed=../../proto/gateway/v1/gateway.proto"); tonic_prost_build::configure() - .build_client(false) + .build_client(true) .compile_protos(&["../../proto/gateway/v1/gateway.proto"], &["../../proto"])?; Ok(()) } diff --git a/crates/server/src/entrypoint.rs b/crates/server/src/entrypoint.rs index 13b8e517..61f60b60 100644 --- a/crates/server/src/entrypoint.rs +++ b/crates/server/src/entrypoint.rs @@ -10,6 +10,39 @@ pub async fn run() -> weaver_contracts::Result<()> { run_on_runtime().await } +/// Prepare the approved source over the separate authenticated source listener. +#[tokio::main(flavor = "current_thread")] +pub async fn prepare(config: Option) -> weaver_contracts::Result<()> { + tokio::time::timeout( + std::time::Duration::from_secs(15), + crate::source_prepare::run(config.as_deref()), + ) + .await + .map_err(|_| weaver_contracts::Error::Conflict("source preparation deadline"))? +} + +/// Emit an inert reviewed catalog proposal using the existing wire record. +pub fn import_provider( + source: &std::path::Path, + yaml: bool, + review: &std::path::Path, +) -> weaver_contracts::Result<()> { + use std::io::Write; + let record = crate::provider_import::proposal(source, yaml, review)?; + let mut output = std::io::stdout().lock(); + output + .write_all(&record) + .and_then(|_| output.write_all(b"\n")) + .map_err(|_| weaver_contracts::Error::Invalid("provider import output")) +} + +/// Reconcile the deployment-bound Kubernetes resource through the source listener. +#[cfg(feature = "kubernetes")] +#[tokio::main(flavor = "current_thread")] +pub async fn reconcile_kubernetes(config: std::path::PathBuf) -> weaver_contracts::Result<()> { + crate::kubernetes::run(&config).await +} + pub(crate) async fn run_on_runtime() -> weaver_contracts::Result<()> { use weaver_ledger::{Journal, LedgerCustody}; let journal = match std::env::var("WEAVER_STORAGE_JOURNAL").as_deref() { diff --git a/crates/server/src/grpc.rs b/crates/server/src/grpc.rs index 1aee4812..9303e870 100644 --- a/crates/server/src/grpc.rs +++ b/crates/server/src/grpc.rs @@ -319,6 +319,15 @@ impl Gateway { } #[tonic::async_trait] impl pb::gateway_server::Gateway for Gateway { + async fn inspect_hard_fact( + &self, + request: Request, + ) -> Result, Status> { + let caller = self.source_identity(&request)?; + let state = self.ingress.source()?.inspect_fact(caller).await?; + Ok(Response::new(Self::fact_feed_state(state))) + } + async fn stage_hard_fact( &self, request: Request, diff --git a/crates/server/src/grpc_config.rs b/crates/server/src/grpc_config.rs index 856fde7a..19c5b79f 100644 --- a/crates/server/src/grpc_config.rs +++ b/crates/server/src/grpc_config.rs @@ -8,10 +8,10 @@ use std::{collections::BTreeMap, io::Read}; use tonic::transport::{Certificate, Identity, ServerTlsConfig}; use weaver_broker::ProviderTransport; use weaver_contracts::{Error, Result}; -fn required(name: &str) -> Result { +pub(crate) fn required(name: &str) -> Result { std::env::var(name).map_err(|_| Error::Invalid("required gRPC configuration missing")) } -fn read_path(path: impl AsRef) -> Result> { +pub(crate) fn read_path(path: impl AsRef) -> Result> { let mut bytes = Vec::new(); std::fs::File::open(path) .map_err(|_| Error::Invalid("RPC configuration file"))? diff --git a/crates/server/src/grpc_hard_fact.rs b/crates/server/src/grpc_hard_fact.rs index 7de2729a..10da87e3 100644 --- a/crates/server/src/grpc_hard_fact.rs +++ b/crates/server/src/grpc_hard_fact.rs @@ -7,6 +7,25 @@ use tonic::{Response, Status}; use weaver_contracts::SourceIdentity; impl Gateway { + pub(crate) fn fact_feed_state(state: weaver_ledger::FactFeedState) -> pb::HardFactFeedState { + pb::HardFactFeedState { + domain: state.domain, + source_epoch: state.source_epoch, + floor: state.floor, + revision: state.revision, + snapshot: state.snapshot, + available: state.available, + pending: state + .pending + .into_iter() + .map(|(barrier, available)| pb::PendingHardFact { + barrier: Some(Self::fact_barrier(barrier)), + available, + }) + .collect(), + } + } + fn fact_barrier(barrier: weaver_contracts::FactBarrier) -> pb::HardFactBarrier { pb::HardFactBarrier { operation_id: barrier.operation_id, diff --git a/crates/server/src/kubernetes.rs b/crates/server/src/kubernetes.rs new file mode 100644 index 00000000..53746c05 --- /dev/null +++ b/crates/server/src/kubernetes.rs @@ -0,0 +1,286 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! The cluster supplies observations. The source owner retains the authoritative cut. +use crate::{grpc_config::read_path, pb, source_prepare}; +use futures_util::StreamExt; +use kube::{ + Api, + api::{ApiResource, DynamicObject, GroupVersionKind, Patch, PatchParams}, + runtime::{WatchStreamExt, watcher}, +}; +use serde::Deserialize; +use serde_json::json; +use std::{path::Path, time::Duration}; +use weaver_contracts::{Error, Result, body_digest}; + +const RECONCILE_TIMEOUT: Duration = Duration::from_secs(12); +const RESYNC_INTERVAL: Duration = Duration::from_secs(15); + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct Config { + source: source_prepare::SourceConnection, + kubernetes: Binding, +} + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct Binding { + namespace: String, + name: String, + uid: String, + domain: String, +} + +impl Binding { + fn matches(&self, object: &DynamicObject) -> bool { + object.metadata.namespace.as_deref() == Some(&self.namespace) + && object.metadata.name.as_deref() == Some(&self.name) + && object.metadata.uid.as_deref() == Some(&self.uid) + && object.metadata.deletion_timestamp.is_none() + } +} + +async fn reconcile( + binding: &Binding, + api: &Api, + source: &mut source_prepare::Client, +) -> Result<()> { + // Capture the ledger predecessor before reading the desired state. A competing + // write after that capture invalidates the exact floor used for any new intent. + let state = source + .inspect_hard_fact(pb::Empty {}) + .await + .map_err(|_| Error::Conflict("hard fact feed observation failed"))? + .into_inner(); + if state.domain != binding.domain { + return Err(Error::Conflict("Kubernetes hard fact feed binding")); + } + let object = api + .get_opt(&binding.name) + .await + .map_err(|_| Error::Conflict("Kubernetes resource observation failed"))?; + let matching = object.as_ref().filter(|object| binding.matches(object)); + let (available, generation) = match matching { + Some(object) => ( + object + .data + .pointer("/spec/available") + .and_then(serde_json::Value::as_bool) + .ok_or(Error::Invalid("ProviderAvailability spec"))?, + Some( + object + .metadata + .generation + .filter(|value| *value > 0) + .ok_or(Error::Invalid("ProviderAvailability generation"))?, + ), + ), + None => (false, None), + }; + + let mut pending = state.pending; + let (effective, prior_revision, previous_snapshot) = match pending.last() { + Some(tail) => { + let barrier = tail + .barrier + .as_ref() + .ok_or(Error::Invalid("hard fact tail missing"))?; + ( + Some(tail.available), + barrier.revision, + barrier.snapshot.as_str(), + ) + } + None => (state.available, state.revision, state.snapshot.as_str()), + }; + + // Install the currently observed intent before resolving any older pending + // work. Thus resolving a stale available intent cannot open a withdrawn cut. + if effective != Some(available) { + let revision = prior_revision + .checked_add(1) + .ok_or(Error::Invalid("hard fact revision"))?; + let encoded = serde_json::to_string(&( + "weaver.kubernetes.provider-availability.v1", + &binding.namespace, + &binding.name, + &binding.uid, + generation, + &state.domain, + state.source_epoch, + revision, + previous_snapshot, + state.floor, + available, + ))?; + let intent = weaver_contracts::FactIntent { + operation_id: body_digest(&encoded), + domain: state.domain, + source_epoch: state.source_epoch, + revision, + previous_snapshot: previous_snapshot.to_owned(), + expected_floor: state.floor, + available, + }; + let snapshot = intent.snapshot()?; + let barrier = source + .stage_hard_fact(pb::HardFactIntent { + operation_id: intent.operation_id.clone(), + domain: intent.domain, + source_epoch: intent.source_epoch, + revision: intent.revision, + previous_snapshot: intent.previous_snapshot, + expected_floor: intent.expected_floor, + available: Some(intent.available), + }) + .await + .map_err(|_| Error::Conflict("Kubernetes hard fact staging result unknown"))? + .into_inner(); + if barrier.operation_id != intent.operation_id + || barrier.revision != intent.revision + || barrier.source_epoch != intent.source_epoch + || barrier.snapshot != snapshot + || Some(barrier.floor) != intent.expected_floor.checked_add(1) + { + return Err(Error::Conflict( + "Kubernetes hard fact staging receipt binding", + )); + } + pending.push(pb::PendingHardFact { + barrier: Some(barrier), + available, + }); + } + + let mut cut = (state.revision, state.snapshot); + for item in pending { + let barrier = item + .barrier + .ok_or(Error::Invalid("hard fact barrier missing"))?; + let receipt = source + .resolve_hard_fact(barrier.clone()) + .await + .map_err(|_| Error::Conflict("Kubernetes hard fact resolution result unknown"))? + .into_inner(); + if receipt.barrier.as_ref() != Some(&barrier) { + return Err(Error::Conflict( + "Kubernetes hard fact resolution receipt binding", + )); + } + cut = (barrier.revision, barrier.snapshot); + } + + // Observe the ledger after all attempts. A concurrent staging or resolution + // supersedes the status update even if an earlier exact receipt still exists. + if cut.0 != state.revision { + let installed = source + .inspect_hard_fact(pb::Empty {}) + .await + .map_err(|_| Error::Conflict("hard fact installation observation failed"))? + .into_inner(); + if !installed.pending.is_empty() + || installed.source_epoch != state.source_epoch + || installed.revision != cut.0 + || installed.snapshot != cut.1 + || installed.available != Some(available) + { + return Err(Error::Conflict("Kubernetes hard fact cut superseded")); + } + } + if let (Some(object), Some(generation)) = (matching, generation) { + let status = json!({ + "observedGeneration": generation, + "sourceEpoch": state.source_epoch, + "revision": cut.0, + "snapshot": cut.1, + }); + if object.data.get("status") != Some(&status) { + let resource_version = object + .metadata + .resource_version + .as_deref() + .ok_or(Error::Invalid("ProviderAvailability resource version"))?; + let patch = json!({ + "metadata": {"resourceVersion": resource_version}, + "status": status, + }); + api.patch_status( + &binding.name, + &PatchParams::default(), + &Patch::Merge(&patch), + ) + .await + .map_err(|_| Error::Conflict("ProviderAvailability status write rejected"))?; + } + } + Ok(()) +} + +pub(crate) async fn run(path: &Path) -> Result<()> { + let bytes = read_path(path)?; + let text = std::str::from_utf8(&bytes).map_err(|_| Error::Invalid("weaver.toml encoding"))?; + let mut config = toml::from_str::(text) + .map_err(|_| Error::Invalid("weaver.toml Kubernetes configuration"))?; + let binding = config.kubernetes; + for identity in [ + &binding.namespace, + &binding.name, + &binding.uid, + &binding.domain, + ] { + weaver_contracts::identifier(identity)?; + } + if config.source.producer.is_some() || config.source.file.is_some() { + return Err(Error::Invalid("Kubernetes hard fact source configuration")); + } + config.source.resolve_paths(path)?; + let mut source = + tokio::time::timeout(RECONCILE_TIMEOUT, source_prepare::connect(&config.source)) + .await + .map_err(|_| Error::Conflict("source listener connection deadline"))??; + let cluster = kube::Client::try_default() + .await + .map_err(|_| Error::Invalid("Kubernetes client configuration"))?; + let resource = ApiResource::from_gvk_with_plural( + &GroupVersionKind::gvk( + "weaver.hardenedlinux.org", + "v1alpha1", + "ProviderAvailability", + ), + "provideravailabilities", + ); + let api = Api::::namespaced_with(cluster, &binding.namespace, &resource); + let events = watcher( + api.clone(), + watcher::Config::default().fields(&format!("metadata.name={}", binding.name)), + ) + .default_backoff(); + tokio::pin!(events); + let mut resync = tokio::time::interval(RESYNC_INTERVAL); + resync.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay); + let stop = crate::shutdown::signal()?; + tokio::pin!(stop); + loop { + tokio::select! { + _ = &mut stop => return Ok(()), + _ = resync.tick() => {} + event = events.next() => match event { + Some(Ok(watcher::Event::Apply(_) | watcher::Event::Delete(_) | watcher::Event::InitDone)) => {} + Some(Ok(_)) => continue, + Some(Err(_)) => { + eprintln!("weaver Kubernetes watch interrupted; kube-rs will recover"); + continue; + } + None => return Err(Error::Conflict("Kubernetes watch closed")), + }, + } + match tokio::time::timeout(RECONCILE_TIMEOUT, reconcile(&binding, &api, &mut source)).await + { + Ok(Ok(())) => {} + Ok(Err(error)) => eprintln!("weaver Kubernetes reconciliation: {error}"), + Err(_) => eprintln!("weaver Kubernetes reconciliation deadline"), + } + } +} diff --git a/crates/server/src/lib.rs b/crates/server/src/lib.rs index a7e7423b..3ebad7db 100644 --- a/crates/server/src/lib.rs +++ b/crates/server/src/lib.rs @@ -20,10 +20,13 @@ mod grpc_hard_fact; mod grpc_listeners; mod grpc_output; mod grpc_provider; +#[cfg(feature = "kubernetes")] +mod kubernetes; pub mod pb; #[cfg(all(test, unix))] #[path = "../tests/unit/provider_commit.rs"] mod provider_commit_tests; +mod provider_import; mod provider_oauth; mod review_wire; mod rpc_security; @@ -33,8 +36,10 @@ mod shutdown; mod single_provider; mod source_artifact; mod source_composition; +mod source_file; mod source_identity; mod source_owner; +mod source_prepare; mod telemetry; #[cfg(test)] #[path = "../tests/unit/fixtures.rs"] diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs index eaa0103e..0b7cf46b 100644 --- a/crates/server/src/main.rs +++ b/crates/server/src/main.rs @@ -9,7 +9,56 @@ fn main() { "weaver startup stage=process-main clock={:?}", std::time::SystemTime::now() ); - if let Err(error) = weaver_server::entrypoint::run() { + let mut args = std::env::args_os().skip(1); + let usage = || { + weaver_contracts::Error::Invalid(concat!( + "usage: weaver-server [prepare [--config path]", + " | reconcile-kubernetes --config path (kubernetes feature)", + " | import-provider json|yaml source review]" + )) + }; + let result = match args.next().as_deref() { + None => weaver_server::entrypoint::run(), + Some(command) if command == "prepare" => { + match (args.next().as_deref(), args.next(), args.next()) { + (None, None, None) => weaver_server::entrypoint::prepare(None), + (Some(flag), Some(path), None) if flag == "--config" => { + weaver_server::entrypoint::prepare(Some(path.into())) + } + _ => Err(usage()), + } + } + Some(command) if command == "import-provider" => { + match ( + args.next().as_deref(), + args.next(), + args.next(), + args.next(), + ) { + (Some(format), Some(source), Some(review), None) + if format == "json" || format == "yaml" => + { + weaver_server::entrypoint::import_provider( + std::path::Path::new(&source), + format == "yaml", + std::path::Path::new(&review), + ) + } + _ => Err(usage()), + } + } + #[cfg(feature = "kubernetes")] + Some(command) if command == "reconcile-kubernetes" => { + match (args.next().as_deref(), args.next(), args.next()) { + (Some(flag), Some(path), None) if flag == "--config" => { + weaver_server::entrypoint::reconcile_kubernetes(path.into()) + } + _ => Err(usage()), + } + } + _ => Err(usage()), + }; + if let Err(error) = result { eprintln!("{error}"); std::process::exit(1); } diff --git a/crates/server/src/provider_import.rs b/crates/server/src/provider_import.rs new file mode 100644 index 00000000..61b1dd7c --- /dev/null +++ b/crates/server/src/provider_import.rs @@ -0,0 +1,121 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Offline projection of reviewed LiteLLM inputs into the existing catalog record. +use crate::source_file::read_document; +use serde::Deserialize; +use std::{collections::BTreeMap, path::Path}; +use weaver_contracts::{CatalogEntry, Error, ProviderCatalog, ProviderPlan, Result}; + +const MAX_IMPORT_BYTES: usize = 262_144; + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct Review { + #[serde(default)] + parent: String, + bindings: BTreeMap, +} + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct Binding { + plan: ProviderPlan, + credential_reference: String, + entry: CatalogEntry, +} + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct LiteLlm { + model_list: Vec, +} + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct Model { + model_name: String, + litellm_params: Parameters, +} + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct Parameters { + model: String, + api_base: String, + api_key: String, +} + +fn credential_reference(value: &str) -> bool { + let Some(name) = value.strip_prefix("os.environ/") else { + return false; + }; + let mut bytes = name.bytes(); + name.len() <= 128 + && bytes + .next() + .is_some_and(|byte| byte.is_ascii_uppercase() || byte == b'_') + && bytes.all(|byte| byte.is_ascii_uppercase() || byte.is_ascii_digit() || byte == b'_') +} + +pub(crate) fn proposal(source: &Path, yaml: bool, review: &Path) -> Result> { + let source: LiteLlm = read_document(source, yaml, MAX_IMPORT_BYTES)?; + let mut review: Review = read_document(review, false, weaver_contracts::MAX_BODY_BYTES * 2)?; + if !review.parent.is_empty() + && (review.parent.len() != 64 + || !review + .parent + .bytes() + .all(|byte| byte.is_ascii_hexdigit() && !byte.is_ascii_uppercase())) + { + return Err(Error::Invalid("provider import parent digest")); + } + if source.model_list.is_empty() + || source.model_list.len() > 256 + || source.model_list.len() != review.bindings.len() + { + return Err(Error::Invalid("provider import inventory")); + } + + let mut entries = BTreeMap::new(); + for model in source.model_list { + let binding = review + .bindings + .remove(&model.model_name) + .filter(|_| !model.model_name.is_empty()) + .ok_or(Error::Invalid("provider import alias binding"))?; + let parameters = model.litellm_params; + let endpoint = format!( + "{}/chat/completions", + parameters + .api_base + .strip_suffix('/') + .unwrap_or(¶meters.api_base) + ); + if binding.plan.routes.len() != 1 + || binding.plan.routes[0].endpoint != endpoint + || parameters.api_base.contains(['?', '#']) + || parameters.model.strip_prefix("openai/") != Some(binding.plan.model.as_str()) + || parameters.api_key != binding.credential_reference + || !credential_reference(¶meters.api_key) + { + return Err(Error::Invalid("provider import reviewed binding")); + } + weaver_broker::HttpsTransport::validate_endpoint(&endpoint)?; + if entries + .insert(binding.plan.digest()?, binding.entry) + .is_some() + { + return Err(Error::Invalid("duplicate imported plan")); + } + } + let record = ProviderCatalog { + parent: review.parent, + entries, + } + .record()?; + if record.len() > MAX_IMPORT_BYTES { + return Err(Error::Invalid("provider import output bound")); + } + Ok(record) +} diff --git a/crates/server/src/review_wire.rs b/crates/server/src/review_wire.rs index ff514be9..7fd9c21f 100644 --- a/crates/server/src/review_wire.rs +++ b/crates/server/src/review_wire.rs @@ -69,3 +69,33 @@ pub(crate) fn evidence(e: pb::DeltaReview) -> Result { .map_err(|_| Status::invalid_argument("review evidence bounds"))?; Ok(evidence) } + +pub(crate) fn evidence_message(e: DeltaReview) -> pb::DeltaReview { + let disposition = match e.disposition { + DeltaDisposition::Bootstrap => pb::DeltaDisposition::Bootstrap, + DeltaDisposition::NoExecutionGain => pb::DeltaDisposition::NoExecutionGain, + DeltaDisposition::ExplicitApproval => pb::DeltaDisposition::ExplicitApproval, + }; + pb::DeltaReview { + review: Some(pb::PublicationReview { + publication: Some(pb::PublicationKey { + operation_id: e.review.publication.operation_id, + digest: e.review.publication.digest, + }), + parent: e.review.parent.map(|p| pb::AuthorityParent { + revision: p.revision, + fence: p.fence, + policy_digest: p.policy_digest, + schema_digest: p.schema_digest, + }), + artifact: e.review.artifact, + }), + audience: e.audience, + reviewer_epoch: e.reviewer_epoch, + source_epoch: e.source_epoch, + source_identity_digest: e.source_identity_digest, + disposition: disposition as i32, + delta: e.delta, + signature: e.signature, + } +} diff --git a/crates/server/src/source_artifact.rs b/crates/server/src/source_artifact.rs index b7133efa..2ff3514e 100644 --- a/crates/server/src/source_artifact.rs +++ b/crates/server/src/source_artifact.rs @@ -5,10 +5,40 @@ //! Concrete protobuf projection of bound source data, never a new execution permit. use crate::pb; use weaver_contracts::{ProviderPlan, ProviderProfile, ProviderRoute, Publication, Task}; -use weaver_governance::{BoundSource, SourceData, SourceSelection}; +use weaver_governance::{BoundSource, SourceComposition, SourceData, SourceSelection}; pub(crate) fn artifact(bound: &BoundSource) -> pb::SourceArtifact { artifact_data(bound.source().data()) } +pub(crate) fn composition(input: &SourceComposition) -> pb::SourceCompositionRequest { + pb::SourceCompositionRequest { + source: Some(artifact_data(&input.source)), + routing: input + .routing + .iter() + .map(|row| pb::RoutingSelection { + node: row.node.clone(), + allowed_modules: row.allowed_modules.clone(), + required: row.required.clone(), + max_latency_ms: row.max_latency_ms, + max_procurement_cost: row.max_procurement_cost, + user_token_rates: row.user_token_rates.to_vec(), + candidates: row + .candidates + .iter() + .map(|candidate| pb::RoutingCandidate { + module: candidate.module.clone(), + capabilities: candidate.capabilities.clone(), + latency_ms: candidate.latency_ms, + procurement_rates: candidate.procurement_rates.to_vec(), + token_bounds: candidate.token_bounds.to_vec(), + plan: Some(plan(&candidate.plan)), + }) + .collect(), + }) + .collect(), + ..Default::default() + } +} /// Typed projection only; the caller retains source provenance and authority checks. pub(crate) fn artifact_data(data: &SourceData) -> pb::SourceArtifact { let SourceData { diff --git a/crates/server/src/source_file.rs b/crates/server/src/source_file.rs new file mode 100644 index 00000000..c6062d58 --- /dev/null +++ b/crates/server/src/source_file.rs @@ -0,0 +1,205 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! Decode the deployed source bundle into the existing Scheme input. +use serde::Deserialize; +use serde_json::Value; +use std::{io::Read, path::Path}; +use weaver_contracts::{DeltaReview, Error, ProviderPlan, Publication, Result, Task}; +use weaver_governance::{RoutingSelection, SourceComposition, SourceData, SourceSelection}; + +const MAX_FILE_BYTES: usize = weaver_governance::MAX_SOURCE_BYTES; + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct Bundle { + #[serde(default)] + select_on_request: bool, + routing: Option>, + governance: SourceSelection, + tasks: Vec, + plans: Option>, + publication: FilePublication, +} + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct FilePublication { + operation_id: String, + expected_revision: Option, + fence: u64, + policy: String, + schema: String, + review: Option, +} + +pub(crate) struct FileSource { + pub(crate) input: SourceComposition, + pub(crate) select_on_request: bool, + pub(crate) review: Option, +} + +pub(crate) fn load(path: &Path) -> Result { + let format = path.extension().and_then(|extension| extension.to_str()); + if format.is_some_and(|extension| { + ["ss", "scm"] + .iter() + .any(|name| extension.eq_ignore_ascii_case(name)) + }) { + return Err(Error::Invalid( + "Scheme deployment requires an approved producer", + )); + } + let yaml = format.is_some_and(|extension| { + extension.eq_ignore_ascii_case("yaml") || extension.eq_ignore_ascii_case("yml") + }); + let mut document: Value = read_document(path, yaml, MAX_FILE_BYTES)?; + // The old Go wire emits null for unmaterialized commitment maps and empty + // capability sets. Preserve those meanings before decoding the Rust DTOs. + if let Some(tasks) = document.get_mut("tasks").and_then(Value::as_array_mut) { + for task in tasks { + normalize_null(task, "body_digests", Value::Object(Default::default())); + normalize_null(task, "stream_contracts", Value::Object(Default::default())); + } + } + if let Some(routing) = document.get_mut("routing").and_then(Value::as_array_mut) { + for row in routing { + normalize_null(row, "required", Value::Array(Vec::new())); + if let Some(candidates) = row.get_mut("candidates").and_then(Value::as_array_mut) { + for candidate in candidates { + normalize_null(candidate, "capabilities", Value::Array(Vec::new())); + } + } + } + } + let bundle: Bundle = + serde_json::from_value(document).map_err(|_| Error::Invalid("source bundle fields"))?; + let FilePublication { + operation_id, + expected_revision, + fence, + policy, + schema, + review, + } = bundle.publication; + let publication = Publication { + operation_id, + expected_revision, + fence, + policy, + schema, + }; + if let Some(evidence) = &review { + evidence.validate()?; + if evidence.review.publication.operation_id != publication.operation_id + || evidence.review.publication.digest != publication.digest()? + { + return Err(Error::Invalid("source review binding")); + } + } + let input = SourceComposition { + source: SourceData { + governance: bundle.governance, + tasks: bundle.tasks, + plans: bundle.plans.unwrap_or_default(), + publication, + }, + routing: bundle.routing.unwrap_or_default(), + }; + Ok(FileSource { + input, + select_on_request: bundle.select_on_request, + review, + }) +} + +pub(crate) fn read_document( + path: &Path, + yaml: bool, + limit: usize, +) -> Result { + let mut data = Vec::new(); + std::fs::File::open(path) + .map_err(|_| Error::Invalid("source data file"))? + .take((limit + 1) as u64) + .read_to_end(&mut data) + .map_err(|_| Error::Invalid("source data read"))?; + if data.is_empty() || data.len() > limit { + return Err(Error::Invalid("source data bound")); + } + if !yaml { + return weaver_contracts::decode_bounded(&data, limit) + .map_err(|_| Error::Invalid("source data JSON")); + } + let text = std::str::from_utf8(&data).map_err(|_| Error::Invalid("source YAML encoding"))?; + require_source_yaml_shape(text)?; + let options = serde_saphyr::options! { + merge_keys: serde_saphyr::MergeKeyPolicy::Error, + duplicate_keys: serde_saphyr::DuplicateKeyPolicy::Error, + strict_booleans: true, + no_schema: true, + budget: serde_saphyr::budget! { + max_anchors: 0, + max_aliases: 0, + max_documents: 1, + max_depth: 32, + max_inclusion_depth: 0, + }, + }; + serde_saphyr::from_str_with_options(text, options) + .map_err(|_| Error::Invalid("source data YAML")) +} + +fn require_source_yaml_shape(text: &str) -> Result<()> { + use serde_saphyr::granit_parser::{Event, Parser}; + let mut document = false; + let mut depth = 0; + // The typed deserializer reads the first document and can interpret + // non-core tags. Check the same parser's events before decoding data. + for event in Parser::new_from_str(text) { + let (event, _) = event.map_err(|_| Error::Invalid("source data YAML"))?; + match event { + Event::DocumentStart(..) if document => { + return Err(Error::Invalid("one source YAML document required")); + } + Event::DocumentStart(..) => document = true, + Event::Scalar(_, _, anchor, tag) + if anchor != 0 + || tag.as_ref().is_some_and(|tag| { + !matches!(tag.core_suffix(), Some("str" | "null" | "bool" | "int")) + }) => + { + return Err(Error::Invalid("unsupported source YAML scalar")); + } + Event::SequenceStart(_, anchor, ref tag) | Event::MappingStart(_, anchor, ref tag) => { + let expected_tag = if matches!(event, Event::SequenceStart(..)) { + "seq" + } else { + "map" + }; + depth += 1; + if depth > 32 + || anchor != 0 + || tag + .as_ref() + .is_some_and(|tag| tag.core_suffix() != Some(expected_tag)) + { + return Err(Error::Invalid("source YAML structure")); + } + } + Event::SequenceEnd | Event::MappingEnd => depth -= 1, + Event::Alias(_) => return Err(Error::Invalid("source YAML alias")), + _ => {} + } + } + if !document { + return Err(Error::Invalid("one source YAML document required")); + } + Ok(()) +} + +fn normalize_null(value: &mut Value, field: &str, empty: Value) { + if let Some(entry) = value.get_mut(field).filter(|entry| entry.is_null()) { + *entry = empty; + } +} diff --git a/crates/server/src/source_owner.rs b/crates/server/src/source_owner.rs index 9af64fce..c1210adf 100644 --- a/crates/server/src/source_owner.rs +++ b/crates/server/src/source_owner.rs @@ -126,6 +126,10 @@ enum Command { slot: OwnedSemaphorePermit, }, + InspectFact { + reply: oneshot::Sender>, + slot: OwnedSemaphorePermit, + }, StageFact { intent: FactIntent, reply: oneshot::Sender>, @@ -266,6 +270,14 @@ impl SourceWorker { } } impl SourceOwner { + pub(crate) async fn inspect_fact( + &self, + caller: SourceIdentity, + ) -> std::result::Result { + self.submit_priority(caller, |reply, slot| Command::InspectFact { reply, slot }) + .await + } + pub(crate) async fn stage_fact( &self, caller: SourceIdentity, @@ -669,11 +681,6 @@ impl SourceOwner { } }; if let Some(plan) = cached { - if !expected.is_empty() { - return Err(Status::failed_precondition( - "fixed original has no selected catalog coordinate", - )); - } return Ok((plan.as_ref().clone(), String::new())); } let observed = self @@ -687,11 +694,6 @@ impl SourceOwner { .ok_or(Status::failed_precondition( "source routing scope unavailable", ))?; - if !expected.is_empty() && expected != observed.catalog_version { - return Err(Status::failed_precondition( - "provider catalog coordinate changed", - )); - } if let weaver_contracts::ProviderOperationScope::Fixed { plan, .. } = &observed.binding.scope { @@ -701,6 +703,11 @@ impl SourceOwner { *self.routing.lock().await = Some(OperationProjection::Fixed(Arc::new(plan.clone()))); return Ok((plan, String::new())); } + if !expected.is_empty() && expected != observed.catalog_version { + return Err(Status::failed_precondition( + "provider catalog coordinate changed", + )); + } let mut projection = self.routing.lock().await; let reusable = match projection.as_ref() { Some(OperationProjection::Catalog(p)) @@ -1004,6 +1011,11 @@ fn process( }); answer(ledger, reply, result, slot)?; } + Command::InspectFact { reply, slot } => { + let result = + ledger.with_authenticated_source(&caller, |ledger| ledger.inspect_fact_feed()); + answer(ledger, reply, result, slot)?; + } Command::StageFact { intent, reply, diff --git a/crates/server/src/source_prepare.rs b/crates/server/src/source_prepare.rs new file mode 100644 index 00000000..c8103302 --- /dev/null +++ b/crates/server/src/source_prepare.rs @@ -0,0 +1,327 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//! One-shot source publication using the existing authenticated owner. +use crate::{ + grpc_config::{read_path, required}, + pb, +}; +use std::{ + path::{Path, PathBuf}, + time::Duration, +}; +use tonic::{ + Code, Request, Status, + metadata::{Ascii, MetadataValue}, + service::{Interceptor, interceptor::InterceptedService}, + transport::{Certificate, Channel, ClientTlsConfig, Endpoint, Identity}, +}; +use weaver_contracts::{Error, Result}; + +pub(crate) type Client = pb::gateway_client::GatewayClient>; + +#[derive(Clone)] +pub(crate) struct Bearer(MetadataValue); + +impl Interceptor for Bearer { + fn call(&mut self, mut request: Request<()>) -> std::result::Result, Status> { + request + .metadata_mut() + .insert("authorization", self.0.clone()); + Ok(request) + } +} + +#[derive(serde::Deserialize)] +#[serde(deny_unknown_fields)] +struct PreparationFile { + source: SourceConnection, +} + +#[derive(serde::Deserialize)] +#[serde(deny_unknown_fields)] +pub(crate) struct SourceConnection { + pub(crate) producer: Option, + pub(crate) file: Option, + address: String, + server_name: String, + ca: PathBuf, + certificate: PathBuf, + key: PathBuf, + token_env: String, +} + +enum SourceInput { + Producer(String), + File(Box), +} + +impl SourceConnection { + fn load(config: Option<&Path>) -> Result { + match config { + Some(path) => { + let bytes = read_path(path)?; + let text = std::str::from_utf8(&bytes) + .map_err(|_| Error::Invalid("weaver.toml encoding"))?; + let mut source = toml::from_str::(text) + .map_err(|_| Error::Invalid("weaver.toml source configuration"))? + .source; + source.resolve_paths(path)?; + Ok(source) + } + None => Ok(Self { + producer: std::env::var_os("WEAVER_CONTROL_PRODUCER") + .map(|name| { + name.into_string() + .map_err(|_| Error::Invalid("source producer encoding")) + }) + .transpose()?, + file: std::env::var_os("WEAVER_CONTROL_CONFIG").map(PathBuf::from), + address: required("WEAVER_CONTROL_AUTHORITY_SOURCE_ADDRESS")?, + server_name: required("WEAVER_CONTROL_AUTHORITY_SERVER_NAME")?, + ca: required("WEAVER_CONTROL_AUTHORITY_CA")?.into(), + certificate: required("WEAVER_CONTROL_AUTHORITY_SOURCE_CERT")?.into(), + key: required("WEAVER_CONTROL_AUTHORITY_SOURCE_KEY")?.into(), + token_env: "WEAVER_CONTROL_AUTHORITY_SOURCE_TOKEN".into(), + }), + } + } +} + +impl SourceConnection { + pub(crate) fn resolve_paths(&mut self, path: &Path) -> Result<()> { + let directory = path + .parent() + .ok_or(Error::Invalid("weaver.toml directory"))?; + self.ca = directory.join(&self.ca); + self.certificate = directory.join(&self.certificate); + self.key = directory.join(&self.key); + if let Some(file) = &mut self.file { + *file = directory.join(&file); + } + Ok(()) + } +} + +pub(crate) async fn connect(settings: &SourceConnection) -> Result { + let _ = rustls::crypto::ring::default_provider().install_default(); + let secret = required(&settings.token_env)?; + if secret.is_empty() { + return Err(Error::Invalid("source bearer")); + } + let mut token: MetadataValue = format!("Bearer {secret}") + .parse() + .map_err(|_| Error::Invalid("source bearer"))?; + token.set_sensitive(true); + let tls = ClientTlsConfig::new() + .domain_name(&settings.server_name) + .ca_certificate(Certificate::from_pem(read_path(&settings.ca)?)) + .identity(Identity::from_pem( + read_path(&settings.certificate)?, + read_path(&settings.key)?, + )); + let channel = Endpoint::from_shared(format!("https://{}", settings.address)) + .and_then(|endpoint| endpoint.timeout(Duration::from_secs(10)).tls_config(tls)) + .map_err(|_| Error::Invalid("source listener configuration"))? + .connect() + .await + .map_err(|_| Error::Conflict("source listener unavailable"))?; + Ok( + pb::gateway_client::GatewayClient::with_interceptor(channel, Bearer(token)) + .max_decoding_message_size(4 * 1024 * 1024) + .max_encoding_message_size(2 * 1024 * 1024), + ) +} + +async fn compile(client: &mut Client, producer: String) -> Result { + let reply = client + .compile_source(pb::ProducerRequest { + producer: producer.clone(), + }) + .await + .map_err(|_| Error::Conflict("approved source compilation failed"))? + .into_inner(); + let authority = client + .inspect_source_authority(pb::Empty {}) + .await + .map_err(|_| Error::Conflict("source authority observation failed"))? + .into_inner(); + if reply.producer != producer || reply.authority.as_ref() != Some(&authority) { + return Err(Error::Conflict("compiled source authority changed")); + } + Ok(pb::SourceCompositionRequest { + source: reply.artifact, + ..Default::default() + }) +} + +fn verify_receipt( + receipt: pb::PublicationReceipt, + key: &pb::PublicationKey, + publication: &weaver_contracts::Publication, +) -> Result<()> { + let revision = match publication.expected_revision { + Some(parent) => parent + .checked_add(1) + .filter(|next| *next <= weaver_contracts::MAX_CREDITS) + .ok_or(Error::Invalid("source activation revision"))?, + None => 0, + }; + if receipt.operation_id != key.operation_id + || receipt.digest != key.digest + || receipt.outcome != pb::PublicationOutcome::Committed as i32 + || receipt.revision != Some(revision) + || receipt.fence != Some(publication.fence) + { + return Err(Error::Conflict("source activation receipt binding")); + } + Ok(()) +} + +fn validated_original(artifact: pb::SourceArtifact) -> Result { + let original = crate::source_composition::decode(pb::SourceCompositionRequest { + source: Some(artifact), + ..Default::default() + }) + .map_err(|_| Error::Invalid("prepared source data"))?; + weaver_governance::OwnedSource::from_source(original.source) + .map_err(|_| Error::Invalid("prepared source binding")) +} + +async fn compose( + client: &mut Client, + input: crate::source_file::FileSource, +) -> Result { + if input.select_on_request + && (input.input.source.tasks.len() != 1 + || input.input.source.tasks[0].nodes.len() != 1 + || input.input.routing.len() != 1) + { + return Err(Error::Invalid("deferred source scope")); + } + let request = crate::source_artifact::composition(&input.input); + let response = client + .compose_source(request.clone()) + .await + .map_err(|_| Error::Conflict("source bundle composition failed"))? + .into_inner(); + let selected = response + .artifact + .ok_or(Error::Invalid("selected source missing"))?; + if !response.catalog_version.is_empty() + || validated_original(selected.clone())?.publication() != &input.input.source.publication + { + return Err(Error::Conflict("composed source publication changed")); + } + let scope = if input.select_on_request { + request + } else { + pb::SourceCompositionRequest { + source: Some(selected), + ..Default::default() + } + }; + Ok(scope) +} + +async fn publish( + client: &mut Client, + scope: pb::SourceCompositionRequest, + publication: &weaver_contracts::Publication, + review: Option, +) -> Result<()> { + let wire = scope + .source + .as_ref() + .and_then(|artifact| artifact.publication.clone()) + .ok_or(Error::Invalid("prepared source publication"))?; + let key = pb::PublicationKey { + operation_id: publication.operation_id.clone(), + digest: publication.digest()?, + }; + let committed = match client.inspect_publication(key.clone()).await { + Ok(response) => { + verify_receipt(response.into_inner(), &key, publication)?; + true + } + Err(status) if status.code() == Code::NotFound => { + let staged = client + .stage_authority(wire.clone()) + .await + .map_err(|_| Error::Conflict("source staging result unknown"))? + .into_inner(); + if staged != key { + return Err(Error::Conflict("source staging receipt binding")); + } + false + } + Err(_) => return Err(Error::Conflict("source publication observation failed")), + }; + client + .register_published_task(pb::RegisterPublishedTaskRequest { + task: None, + publication: Some(key.clone()), + source_scope: Some(scope), + }) + .await + .map_err(|_| Error::Conflict("source registration result unknown"))?; + if !committed { + if let Some(review) = review { + let expected_digest = review.review.digest()?; + let registered = client + .register_publication_review(crate::review_wire::evidence_message(review)) + .await + .map_err(|_| Error::Conflict("source review registration result unknown"))? + .into_inner(); + if registered.publication.as_ref() != Some(&key) + || registered.review_digest != expected_digest + { + return Err(Error::Conflict("source review receipt binding")); + } + } + let receipt = client + .publish_authority(wire) + .await + .map_err(|_| Error::Conflict("source publication result unknown"))? + .into_inner(); + verify_receipt(receipt, &key, publication)?; + } + Ok(()) +} + +pub(crate) async fn run(config: Option<&Path>) -> Result<()> { + let mut settings = SourceConnection::load(config)?; + let source = match (settings.producer.take(), settings.file.take()) { + (Some(producer), None) => { + weaver_contracts::identifier(&producer)?; + SourceInput::Producer(producer) + } + (None, Some(path)) => SourceInput::File(Box::new(crate::source_file::load(&path)?)), + _ => { + return Err(Error::Invalid( + "exactly one source producer or file required", + )); + } + }; + let mut client = connect(&settings).await?; + match source { + SourceInput::Producer(producer) => { + let scope = compile(&mut client, producer).await?; + let original = validated_original( + scope + .source + .clone() + .ok_or(Error::Invalid("compiled source missing"))?, + )?; + publish(&mut client, scope, original.publication(), None).await + } + SourceInput::File(input) => { + let publication = input.input.source.publication.clone(); + let mut input = *input; + let review = input.review.take(); + let scope = compose(&mut client, input).await?; + publish(&mut client, scope, &publication, review).await + } + } +} diff --git a/dev/sysml/ArchitectureEvolution.sysml b/dev/sysml/ArchitectureEvolution.sysml index 0103fd06..acbacf6f 100644 --- a/dev/sysml/ArchitectureEvolution.sysml +++ b/dev/sysml/ArchitectureEvolution.sysml @@ -507,7 +507,11 @@ package ArchitectureEvolution { listener receives a narrow resolver, never a source credential. Fixed plans are inert original data; reuse their sealed projection without a source-lane transaction on each hit. All fresh execution - guards remain broker/ledger decisions. Catalog derivation uses the + guards remain broker/ledger decisions. Publisher credential rotation + retires the old mutation identity. An already registered fixed task + stays bound to its committed publication, with the same outcome on + cache hit, cold lookup or restart. Object withdrawal changes deciding + authority through publication or the hard-fact barrier. Catalog derivation uses the existing affine Scheme/POO/gerbil-ascent owner. Coalesce identical immutable projections; never cache permission. Before registering a selected task, one existing ledger transaction rejoins the exact @@ -583,10 +587,20 @@ package ArchitectureEvolution { attribute retirementCondition : String; item evidence : EvidenceAxis[0..*]; } + item def ProviderAvailabilityObservation :> CloudResourceObservation { + attribute available : Boolean; + doc /* The namespaced ProviderAvailability resource exposes one desired + fact. Deployment binds its namespace, name and UID to one admitted + hard-fact feed. Kubernetes status reflects a resolved ledger cut. + A replacement UID needs an explicit binding. A watch event triggers + a fresh read before the adapter stages withdrawal. The source-only + recovery view returns pending barriers in ledger order. Stage the + newly observed intent before resolving older pending work. */ + } action def IngestCloudObservation { in item observation : CloudResourceObservation; out item cut : ReconciliationCut; - doc /* Target Rust kube-rs or protocol adapter feeds existing source lane. + doc /* The Rust kube-rs adapter feeds the existing source lane. Observation admission precedes Scheme ReconcileObjectSet. No watch callback directly publishes or executes an effect. */ } diff --git a/dev/sysml/ArchitectureReaderViews.sysml b/dev/sysml/ArchitectureReaderViews.sysml index 9f82b48b..28809280 100644 --- a/dev/sysml/ArchitectureReaderViews.sysml +++ b/dev/sysml/ArchitectureReaderViews.sysml @@ -21,8 +21,8 @@ package WeaverArchitectureReaderViews { attribute illustration : String = "task-contract"; } part def boundaries_control :> ReaderNode { - attribute displayName : String = "Go control"; - attribute responsibility : String = "Route and publish intent"; + attribute displayName : String = "Rust source lane"; + attribute responsibility : String = "Prepare and publish intent"; attribute glyph : String = "routing"; attribute illustration : String = "route-choice"; } @@ -57,12 +57,12 @@ package WeaverArchitectureReaderViews { view boundaries { attribute mappedFile : String = "docs/architecture/diagrams/01-system-boundaries.d2"; attribute displayTitle : String = "Trace authority to the final writer"; - attribute displaySubtitle : String = "Scheme supplies semantics. Go coordinates. Rust owns actual effects."; + attribute displaySubtitle : String = "Scheme supplies semantics. Rust coordinates publication and owns effects."; attribute displayEyebrow : String = "WEAVER / SCOPED READER VIEW"; attribute readerQuestion : String = "Who owns meaning, coordination and actual effects?"; attribute designAudience : String = "Gateway design and runtime reviewers"; attribute designMedium : String = "GitHub at 830 CSS pixels"; - attribute designMessage : String = "Scheme supplies semantics. Go coordinates. Rust owns actual effects."; + attribute designMessage : String = "Scheme supplies semantics. Rust coordinates publication and owns effects."; attribute designFocus : String = "p_writer"; attribute visualThemes : String = "sketchbook,ocean,compact,reading"; attribute visualOptions : String = "{\"elk.algorithm\":\"layered\",\"elk.direction\":\"DOWN\",\"elk.edgeRouting\":\"ORTHOGONAL\",\"elk.spacing.nodeNode\":\"16\",\"elk.layered.spacing.nodeNodeBetweenLayers\":\"27\"}"; diff --git a/dev/sysml/ControlActivation.sysml b/dev/sysml/ControlActivation.sysml index bad8c65a..e04af366 100644 --- a/dev/sysml/ControlActivation.sysml +++ b/dev/sysml/ControlActivation.sysml @@ -90,7 +90,7 @@ package ControlActivation { requirement def GovernorSourceHandoff { doc /* Allocate original semantics and derivation constraints to WeaverExecution::SchemeSemanticPublisher, authenticated publication - orchestration to GoControlAdapter, Cedar evaluation to RustPolicy, + orchestration to SourceControlAdapter, Cedar evaluation to RustPolicy, durable assignment/consumption to RustLedger and external bytes to RustFinalBroker/HttpsExecutor. SourceCommand remains the shared lane. Independent original identity is a premise still requiring runtime diff --git a/dev/sysml/ControllerObjectLifecycle.sysml b/dev/sysml/ControllerObjectLifecycle.sysml index 1f61d73c..50cbeecf 100644 --- a/dev/sysml/ControllerObjectLifecycle.sysml +++ b/dev/sysml/ControllerObjectLifecycle.sysml @@ -143,7 +143,7 @@ package ControllerObjectLifecycle { part def Publication :> Assessment { attribute :>> phase = Phase::publication; attribute :>> runtimeMechanism = Mechanism::authorityImplemented; - attribute :>> sourceOwner = "WeaverExecution::GoControlAdapter;WeaverExecution::RustLedger"; + attribute :>> sourceOwner = "WeaverExecution::SourceControlAdapter;WeaverExecution::RustLedger"; attribute :>> displayName = "Publish"; attribute :>> responsibility = "Exists: durable CAS\nMissing: fact projection"; attribute :>> currentSource = "go/internal/controlplane/gateway.go;crates/ledger/src/publication.rs;crates/ledger/src/task_origins.rs"; diff --git a/dev/sysml/ProviderRpc.sysml b/dev/sysml/ProviderRpc.sysml index c2074ba9..5f27858e 100644 --- a/dev/sysml/ProviderRpc.sysml +++ b/dev/sysml/ProviderRpc.sysml @@ -71,7 +71,7 @@ package ProviderRpc { } requirement def TransportAndExecutionLatencySeparation { doc /* The direct client sends authenticated Protobuf requests to Rust. - The retained Go relay forwards authenticated Protobuf envelopes over + The Go reference relay forwards authenticated Protobuf envelopes over gRPC. The streaming response carries either a Protobuf event or an Arrow IPC batch inside each Protobuf frame. The Go relay forwards frames unchanged. The Go client decodes Arrow only diff --git a/dev/sysml/ResearchReaderViews.sysml b/dev/sysml/ResearchReaderViews.sysml index e5ab8ce2..94e74df8 100644 --- a/dev/sysml/ResearchReaderViews.sysml +++ b/dev/sysml/ResearchReaderViews.sysml @@ -252,7 +252,7 @@ package WeaverResearchReaderViews { attribute glyph : String = "routine"; } part def rpcCore_control :> ReaderNode { - attribute displayName : String = "Go control RPC"; + attribute displayName : String = "Rust source RPC"; attribute responsibility : String = "Carry the bound proposal"; attribute glyph : String = "routing"; attribute illustration : String = "route-choice"; diff --git a/dev/sysml/WeaverExecution.sysml b/dev/sysml/WeaverExecution.sysml index 28957157..d9e6b917 100644 --- a/dev/sysml/WeaverExecution.sysml +++ b/dev/sysml/WeaverExecution.sysml @@ -871,7 +871,7 @@ package WeaverExecution { port derivedFacts : ~PolicyEvidenceDesign::DerivedFactsPort; port effectObservations : ~PolicyEvidenceDesign::EffectObservationPort; } - part def GoControlAdapter { + part def SourceControlAdapter { attribute overviewName : String = "Source transport"; attribute overviewSummary : String = "Carry prepared source data"; attribute overviewGlyph : String = "route-choice"; @@ -883,44 +883,44 @@ package WeaverExecution { } action publishCandidate : OrchestrateSourcePublication; doc /* The Scheme catalog path copies an already composed projection; - it does not run Go routing or interpret Workflow. File-source and dynamic + using the Rust source client. File-source and dynamic catalog requests now delegate composition through the same source-only RPC. Remaining Go Bundle algorithms serve development/reference callers. Preserve the semantic original through configuration normalization, protocol aliasing and authenticated publication. JSON/YAML populates the same admitted contracts; it cannot define another authorization language. Routing, retries and fallback select candidates within that - original. Go neither invents original task keys from session labels + original. The adapter never invents original task keys from session labels nor treats compile/publication acknowledgments as final-use permits. */ - attribute displayName : String = "Go / Configuration transport"; + attribute displayName : String = "Rust / Configuration transport"; attribute leanDeclaration : String = "CedarPooSpec.Gateway.Context"; attribute leanFields : String = "scope,policyRevision,ownerEpoch,historyRevision,factFloor"; - attribute securityName : String = "Go / Source publication"; + attribute securityName : String = "Rust / Source publication"; attribute securityGlyph : String = "publication"; attribute securityResponsibility : String = "Carry the original context\nPublish over authenticated gRPC\nUnknown replies stay unresolved"; attribute responsibility : String = "Source preparation + optional adapters\nOne owned source image\nNo default response forwarding"; attribute glyph : String = "routing"; attribute visualRole : String = "selection"; - doc /* BootstrapProducer receives the server's typed CompileSource + doc /* Rust prepare receives the server's typed CompileSource artifact over authenticated gRPC and reobserves source authority. Its bounded typed projection copies one already composed owned image, then shares the private publication implementation with file configuration. It neither JSON-roundtrips nor repeats normalization across these internal functions. No borrowed protobuf container escapes. Source staging, task registration and publication still use existing CAS; - response admission is not permission for a later send. RunFromEnv + response admission is not permission for a later send. The source client selects exactly one approved producer or JSON/YAML data file; Scheme files cannot launch a compiler, and producer failure cannot fall back to a file. The Rust deployment still must install its approved graph. */ - doc /* R2 default/explicit prepare reuses source bootstrap without an + doc /* Rust prepare reuses source bootstrap without an operation credential, frontend listener or response forwarding, then exits. Fixed and catalog-selected clients use the existing Rust operation listener. Source-owned typed declarations persist in the existing ledger; the narrow operation resolver cannot publish source authority. Catalog derivation rejoins current source, publication and catalog in the registration transaction. Fixed plans and selected - originals retain their exact activation coordinates. Explicit serve - remains for reference controls until R5. */ + originals retain their exact activation coordinates. The Go relay + lives under the development boundary for reference controls. */ doc /* Carry routine node and routing preference data without selecting candidates or interpreting Workflow; emit typed data with no send capability. Carry configuration/capture commitments and authenticated original source identity over gRPC. Reconcile ambiguity; @@ -1305,7 +1305,7 @@ package WeaverExecution { action def Consume; action def GuardAndSend; action def RecoverOutcome { - doc /* Go observes the Rust-owned durable result under the frozen + doc /* The source client observes the durable result under the frozen publication identity and digest before submitting an absent decision. A known result is read-only recovery. Unknown or rejected results do not activate ingress. A historical receipt never replaces current @@ -1318,7 +1318,7 @@ package WeaverExecution { } part gateway : Gateway { part semanticPublisher : SchemeSemanticPublisher; - part controlAdapter : GoControlAdapter; + part controlAdapter : SourceControlAdapter; part policy : RustPolicy; part ledger : RustLedger; part broker : RustFinalBroker; diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index 8a64dbdb..26ae3a7d 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -1 +1 @@ -[{"id":"ProviderAdmissionTurn","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let selected_admission"},{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn begin_driver_counters_follow_their_admission_grant"},{"file":"crates/ledger/src/persistence/driver_observer.rs","pattern":"fn observe_read"},{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct AdmissionRequest"},{"file":"crates/ledger/tests/unit/provider_admission_turn.rs","pattern":"fn queued_unaccepted_admission_preserves_old_frame_and_original_hold"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionTurnProperty"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionCommitRecovery"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderAdmissionTurn"},{"file":"crates/broker/src/provider/request.rs","pattern":"Stage::Tls"},{"file":"go/dev/provider_transport_phases_test.go","pattern":"func reportProviderTransport"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run eagerQueueBlocksOldFrameCounterexampleTest"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem queue_preserves_arbitrary_requirement","declaration":"Weaver.ProviderAdmissionTurn.queue_preserves_arbitrary_requirement"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem finite_queue_preserves_final_offer","declaration":"Weaver.ProviderAdmissionTurn.finite_queue_preserves_final_offer"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem open_writer_cannot_mutate","declaration":"Weaver.ProviderAdmissionTurn.open_writer_cannot_mutate"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem accepted_hard_intent_blocks","declaration":"Weaver.ProviderAdmissionTurn.accepted_hard_intent_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_outcome_blocks","declaration":"Weaver.ProviderAdmissionTurn.unknown_outcome_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem changed_image_blocks","declaration":"Weaver.ProviderAdmissionTurn.changed_image_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem queued_admission_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.queued_admission_preserves_spec_final_use"},{"file":"go/internal/controlplane/deployment.go","pattern":"if gateway.source == nil"},{"file":"go/dev/provider_control_bench_test.go","pattern":"func TestProviderGoControlMeasuredChain"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem runtime_catalog_requires_source","declaration":"Weaver.ProviderAdmissionTurn.runtime_catalog_requires_source"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_activation_blocks_source_handoff","declaration":"Weaver.ProviderAdmissionTurn.unknown_activation_blocks_source_handoff"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem bootstrap_source_close_preserves_actual","declaration":"Weaver.ProviderAdmissionTurn.bootstrap_source_close_preserves_actual"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run failedBootstrapCleanupDoesNotActivateIngressTest"},{"file":"go/dev/provider_admission_overlap_bench_test.go","pattern":"func BenchmarkProviderAdmissionOverlap"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn collect_buffered"},{"file":"go/dev/provider_control_bench_test.go","pattern":"image := serverBinary"},{"file":"go/dev/provider_fixture_test.go","pattern":"test-owned Go control image sha256"},{"file":"crates/ledger/src/persistence/scope_trace.rs","pattern":"pub\\(super\\) fn observe_release"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"observed_release_covers_lease_removal_without_retaining_a_grant"},{"file":"crates/ledger/src/persistence/driver_observer.rs","pattern":"pub\\(super\\) fn observe_commit"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"commit_io_observes_native_spans_after_unobserved_setup"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"maybe_prepared\\(c, PREPARE"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn review_program_reuse_reads_replacement_and_rejects_projection_loss"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn review_program_reuse_preserves_native_receipts_and_currentness"},{"file":"go/dev/provider_control_bench_test.go","pattern":"both arms use Go forwarding"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"valid_review!\\(\"CROSS JOIN\"\\)"},{"file":"crates/ledger/src/domains/view.rs","pattern":"require_view\\(persistence::maybe_prepared"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn manifest_programs_rebind_current_members_and_reject_divergence"}]},{"id":"ProviderReadCustody","witnesses":[{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn conflicts"},{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn acquire_origin"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let shared_reads"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn compatible_origins_share_reads_but_an_older_writer_blocks_younger_readers"},{"file":"crates/ledger/tests/unit/provider_read_custody.rs","pattern":"fn shared_reads_keep_distinct_origin_native_writes_concurrent"},{"file":"go/dev/provider_read_custody_test.go","pattern":"func TestProviderReadCustodyProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderReadCustody"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem arbitrary_policy_preserved","declaration":"Weaver.ProviderReadCustody.arbitrary_policy_preserved"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem finite_interleaving_preserves_policy","declaration":"Weaver.ProviderReadCustody.finite_interleaving_preserves_policy"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem overlapping_writes_conflict","declaration":"Weaver.ProviderReadCustody.overlapping_writes_conflict"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessRetainsWriterAndSameOriginBarriers"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_binding_blocks","declaration":"Weaver.ProviderReadCustody.changed_binding_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_shared_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_shared_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_origin_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_origin_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_owner_blocks","declaration":"Weaver.ProviderReadCustody.changed_owner_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem shared_writer_conflicts","declaration":"Weaver.ProviderReadCustody.shared_writer_conflicts"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem older_conflicting_writer_blocks","declaration":"Weaver.ProviderReadCustody.older_conflicting_writer_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem read_custody_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.read_custody_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderReadCustody.qnt","pattern":"run unsafeSharedMutationCounterexampleTest"}]},{"id":"ProviderLifecycleFootprint","witnesses":[{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct OriginLifecycle"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"enum Impact"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_lifecycle"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_provider_lifecycle"},{"file":"crates/ledger/tests/unit/provider_lifecycle.rs","pattern":"fn peer_lifecycle_preserves_complete_view_but_shared_admission_does_not"},{"file":"go/dev/provider_lifecycle_test.go","pattern":"func TestProviderLifecycleCommitRecovery"},{"file":"crates/ledger/tests/unit/authority_footprint.rs","pattern":"fn local_commit_retires_whole_and_own_but_preserves_peer"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem origin_commit_retires_whole_reader","declaration":"Weaver.ProviderLifecycleFootprint.origin_commit_retires_whole_reader"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem arbitrary_cedar_predicate_preserved","declaration":"Weaver.ProviderLifecycleFootprint.arbitrary_cedar_predicate_preserved"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem shared_admission_requires_shared_invalidation","declaration":"Weaver.ProviderLifecycleFootprint.shared_admission_requires_shared_invalidation"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem peer_lifecycle_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.peer_lifecycle_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderLifecycleFootprint.qnt","pattern":"run unsafeNarrowAdmissionCounterexampleTest"}]},{"id":"ProviderSnapshotPublication","witnesses":[{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn release_provider_group_for_delivery"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"struct Snapshot"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn share_qualification"},{"file":"crates/ledger/src/provider.rs","pattern":"fn begin_snapshot_validation"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn take_refresh"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem pending_close_defers_renewal","declaration":"Weaver.ProviderSnapshotPublication.pending_close_defers_renewal"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn a_request_arriving_during_qualification_cannot_trigger_a_second_native_read"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn one_snapshot_requalification_covers_every_exact_frame"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn post_staging_native_failure_cannot_publish_a_partial_snapshot"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn queue_snapshot"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func awaitDeliveryCuts"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem final_use_joins_snapshot","declaration":"Weaver.ProviderSnapshotPublication.final_use_joins_snapshot"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem published_snapshot_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.published_snapshot_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSnapshotPublication.qnt","pattern":"run ungatedArcLoadIsCounterexampleTest"}]},{"id":"ProviderSemanticProgress","witnesses":[{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct RangeProgress"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_progress"},{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn stage_group"},{"file":"crates/ledger/tests/unit/provider_delivery.rs","pattern":"fn exact_range_progress_preserves_queued_authorization"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderSemanticProgressProperty"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_released_binding","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_released_binding"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_image","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_image"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem range_progress_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.range_progress_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSemanticProgress.qnt","pattern":"run hiddenSemanticEditIsCounterexampleTest"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"}]},{"id":"ProviderDeliveryJoin","witnesses":[{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn bounded_trace_retains_every_requalification"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeTraceChunksPreserveAllRecords"},{"file":"crates/ledger/tests/unit/persistence_owner.rs","pattern":"fn descriptor_copy_is_not_a_retained_execution_owner"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem retained_role_blocks_custody_retirement","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.retained_role_blocks_custody_retirement"},{"file":"dev/proofs/quint/ProviderDeliveryPipeline.qnt","pattern":"run threeInertFramesNeedNoStopAndWaitTest"},{"file":"crates/server/src/grpc_delivery_producer.rs","pattern":"fn reserve_guarded"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"pub fn poll"},{"file":"crates/server/src/grpc_delivery.rs","pattern":"impl Stream for ResponseStream"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryCommitAndReceiverRecovery"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryReceiverProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem orphaned_witness_cannot_activate","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.orphaned_witness_cannot_activate"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem acknowledged_delivery_preserves_same_actual_view","declaration":"Weaver.DomainMigrationComposition.acknowledged_delivery_preserves_same_actual_view"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run committedWithoutAcknowledgmentCannotAcceptTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run rollbackCannotEraseIndependentWitnessTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run oldOwnerCannotRequalifyAfterRestartTest"}]},{"id":"ProviderEgressPromotion","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_close_receipt_cannot_resolve_new_intent","declaration":"Weaver.ProviderEgressWindow.Promotion.old_close_receipt_cannot_resolve_new_intent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem expired_clock_blocks_receiver","declaration":"Weaver.ProviderEgressWindow.Promotion.expired_clock_blocks_receiver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem every_effect_writer_needs_mediation","declaration":"Weaver.ProviderEgressWindow.Promotion.every_effect_writer_needs_mediation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem other_writer_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.other_writer_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem uncertain_effect_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.uncertain_effect_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem unchanged_database_does_not_revalidate_old_read","declaration":"Weaver.ProviderEgressWindow.Promotion.unchanged_database_does_not_revalidate_old_read"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem witness_ahead_blocks_old_image","declaration":"Weaver.ProviderEgressWindow.Promotion.witness_ahead_blocks_old_image"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem only_current_owner_can_deliver","declaration":"Weaver.ProviderEgressWindow.Promotion.only_current_owner_can_deliver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_queued_frame_cannot_follow_replacement","declaration":"Weaver.ProviderEgressWindow.Promotion.old_queued_frame_cannot_follow_replacement"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem delivered_frame_cannot_be_delivered_twice","declaration":"Weaver.ProviderEgressWindow.Promotion.delivered_frame_cannot_be_delivered_twice"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem receiver_promotion_refines_interval_admission","declaration":"Weaver.ProviderEgressWindow.Promotion.receiver_promotion_refines_interval_admission"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run firstCommitCannotDeliverAnotherPendingWriterTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run independentWitnessBeforeDatabaseBlocksDeliveryTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run oldWorkerDeliveryCounterexampleTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run allWriterClassesUseTheSameCutTest"}]},{"id":"BoundedProviderEgressWindow","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem any_accepted_trace_keeps_disjoint_prefix","declaration":"Weaver.ProviderEgressWindow.any_accepted_trace_keeps_disjoint_prefix"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem loss_and_restart_close_old_window","declaration":"Weaver.ProviderEgressWindow.loss_and_restart_close_old_window"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem matching_image_does_not_reopen_old_cut","declaration":"Weaver.ProviderEgressWindow.matching_image_does_not_reopen_old_cut"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem connected_roots_cannot_use_distinct_lanes","declaration":"Weaver.ProviderEgressWindow.connected_roots_cannot_use_distinct_lanes"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem admitted_four_turn_envelope","declaration":"Weaver.ProviderEgressWindow.admitted_four_turn_envelope"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem settlement_is_idempotent","declaration":"Weaver.ProviderEgressWindow.settlement_is_idempotent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem holder_stage_overlap_cannot_exceed_ticket_wait","declaration":"Weaver.ProviderEgressWindow.holder_stage_overlap_cannot_exceed_ticket_wait"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run coherentStoreRollbackActuallyDuplicatesOfferTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run pendingRevocationStopsActualOfferTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run lostBurnAckSealsOriginalTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run rehydratingOldWindowActuallyDuplicatesOfferTest"}]},{"id":"OriginalFloorDecision","witnesses":[{"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run lostCommitResponseResolvesSameOperationTest"},{"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run unknownCommitCannotActivateTest"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"}]},{"id":"ProviderCurrentnessPerformance","witnesses":[{"file":"go/dev/provider_domain_program_test.go","pattern":"func BenchmarkProviderDomainProgram"},{"file":"go/dev/provider_domain_tail_test.go","pattern":"func BenchmarkProviderSharedLongTail"},{"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem prepared_domain_program_preserves_live_decision"}]},{"id":"ProviderSchedulerOwnership","witnesses":[{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn waiting_multi_root_range_precedes_younger_conflicts"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessCountsArrivalGrantInversions"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"}]},{"id":"SenderBoundProviderOAuth","witnesses":[{"file":"go/dev/provider_oauth_relay_test.go","pattern":"func TestProviderOAuthTwoHopRevocationAndRecovery"},{"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem retained_root_revocation_blocks_child"}]},{"id":"TransportAndExecutionLatencySeparation","witnesses":[{"file":"go/dev/provider_scheduler_bench_test.go","pattern":"func BenchmarkProviderScheduledEncoding"},{"file":"go/dev/provider_range_group_test.go","pattern":"func BenchmarkProviderRangePreparationGroup"}]},{"id":"TelemetryNoninterference","witnesses":[{"file":"crates/telemetry/tests/unit/metrics.rs","pattern":"fn observations_are_monotone_and_restart_local"},{"file":"go/internal/telemetry/metrics_test.go","pattern":"func TestPropertyCountersAreBoundedMonotoneAndRestartLocal"},{"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderTelemetryCannotRefundOrRedispatchUnknownSend"},{"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderControlTelemetryObservesBothServices"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryReadsAndRestartCannotRefundTest"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryAsRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem arbitrary_observations_keep_execution","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.arbitrary_observations_keep_execution"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem telemetry_reset_keeps_unknown_hold","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.telemetry_reset_keeps_unknown_hold"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem observations_preserve_effect_safety","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.observations_preserve_effect_safety"}]},{"id":"SharedDomainAuthority","witnesses":[{"file":"crates/ledger/src/domains/binding.rs","pattern":"fn bind"},{"file":"crates/ledger/src/domains/migration.rs","pattern":"fn migrate_execution_domains"},{"file":"crates/ledger/src/domains/view.rs","pattern":"fn require_stamp"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_cross_family_shared_history_serializes_final_use"},{"file":"crates/ledger/tests/unit/shared_domains.rs","pattern":"fn finite_families_never_split_a_shared_cap"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsProperty"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsCedarReadsCurrentAuthority"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run overCapacityUnionKeepsOriginalDecisionTest"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run domainSplitCounterexampleTest"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_cannot_split_any_shared_pair","declaration":"Weaver.SharedDomains.union_cannot_split_any_shared_pair"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem admitted_union_conserves_capacity","declaration":"Weaver.SharedDomains.admitted_union_conserves_capacity"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_retains_history","declaration":"Weaver.SharedDomains.union_retains_history"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_fences_both_old_permits","declaration":"Weaver.SharedDomains.union_fences_both_old_permits"}]},{"id":"TursoMvccCustody","witnesses":[{"file":"crates/ledger/src/persistence/owner.rs","pattern":"fn open"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_family"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_final_domains_overlap_including_new_executor_connection"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_same_budget_and_history_family_keeps_final_order"},{"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn mvcc_effect_before_failed_observation_never_releases_or_replays"},{"file":"go/dev/provider_final_domains_test.go","pattern":"func TestProviderMVCCIndependentFinalSendsAndRevocation"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run postSendCommitConflictKeepsPhysicalEffectTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem shared_final_readers_keep_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.shared_final_readers_keep_current_fence"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem failed_observation_after_send_keeps_spent_hold","declaration":"Weaver.RuntimeAdmission.MVCC.failed_observation_after_send_keeps_spent_hold"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_disjoint_admissions_have_overlapping_turso_writes"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_process_custody_refuses_a_second_process"},{"file":"crates/ledger/tests/unit/mvcc.rs","pattern":"fn mvcc_concurrent_family_budget_has_one_original_reservation"},{"file":"go/dev/provider_mvcc_test.go","pattern":"func TestProviderMVCCExecutionBoundary"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run snapshotWriteSkewCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem disjoint_domain_commits_commute","declaration":"Weaver.RuntimeAdmission.MVCC.disjoint_domain_commits_commute"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem family_step_preserves_all_budgets","declaration":"Weaver.RuntimeAdmission.MVCC.family_step_preserves_all_budgets"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exclusive_final_use_keeps_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.exclusive_final_use_keeps_current_fence"}]},{"id":"ArchitectureViewGrammar","witnesses":[{"file":"dev/sysml/ArchitectureViews.sysml","pattern":"view zeroTrust"},{"file":"go/internal/devrunner/model_views.go","pattern":"func CaptureModelViews"},{"file":"go/internal/devrunner/model_views_test.go","pattern":"func TestModelViewsUseActualSDK"},{"file":"go/internal/devrunner/model_views_test.go","pattern":"func FuzzModelViewCaptureTracksSource"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestArchitectureDiagramsUseDifferentViewProfiles"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramProfilesAreExplicitAndLocal"},{"file":"go/internal/devrunner/diagrams.go","pattern":"func RenderDiagrams"},{"file":"dev/d2/src/render.ts","pattern":"composeFigure[(]input,composer[)]"},{"file":"dev/d2/test/model-view.test.ts","pattern":"public Library binds SDK SysML identity"},{"file":"dev/d2/src/objects.ts","pattern":"export const composeObjects"},{"file":"dev/d2/test/model-view.test.ts","pattern":"missing captured views and unsupported source ports refuse"},{"file":"dev/d2/test/vector-readability.test.ts","pattern":"Preserve the original ordered-sequence line-overlap check"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramEvidenceRejectsLostNodesAndRelationships"}]},{"id":"ProductionAssetBoundary","witnesses":[{"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRuntimeAssetBoundary"},{"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRejectsRuntimeDevReferences"}]},{"id":"OriginalTaskBinding","witnesses":[{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem first_birth_seal_cannot_broaden","declaration":"Weaver.TaskOrigin.first_birth_seal_cannot_broaden"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem sealed_birth_cannot_be_replaced","declaration":"Weaver.TaskOrigin.sealed_birth_cannot_be_replaced"},{"file":"crates/ledger/tests/unit/task_publication.rs","pattern":"fn lost_birth_projection_cannot_authorize_or_be_silently_repaired"},{"file":"crates/ledger/src/task_origins.rs","pattern":"fn register_original_task"},{"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn source_rotation_cannot_reallocate_task_and_lost_reply_recovers_original_commit"},{"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn trusted_issuer_relabeling_every_identity_is_outside_local_deduplication"},{"file":"go/dev/provider_task_origin_test.go","pattern":"func TestProviderOriginalTaskOriginLostReplySourceSwitchAndRestart"},{"file":"dev/proofs/quint/TaskOrigin.qnt","pattern":"run issuerTrustCounterexampleTest"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem assigned_task_cannot_rebind","declaration":"Weaver.TaskOrigin.assigned_task_cannot_rebind"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem source_epoch_does_not_change_task_scope","declaration":"Weaver.TaskOrigin.source_epoch_does_not_change_task_scope"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem stale_source_command_cannot_commit","declaration":"Weaver.TaskOrigin.stale_source_command_cannot_commit"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn original_task_body_and_profile_cannot_be_replaced"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalBindingTest"}]},{"id":"SharedBudget","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn finite_manifest_siblings_cannot_mask_a_missing_original_member"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn maximum_manifest_cannot_replace_a_lost_sibling_after_restart"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityRecoveryGuardTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityFinalUseGuardTest"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn selected_message_binding_must_match_its_committed_digest_at_final_write"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn concurrent_message_admission_preserves_both_manifest_members"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exhausted_budget_cannot_publish_a_manifest_member_without_its_row"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem manifest_bound_runtime_step"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn surviving_stream_message_cannot_hide_a_lost_unknown_reservation"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exact_message_manifest_guards_recovery_and_existing_write_handles"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialMessageLossCounterexampleTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run digestSubstitutionFinalUseGuardTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exact_manifest_admission_covers_original_exposure"},{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn balanced_provider_projection_never_funds_a_different_original_plan"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_stream_projection_never_funds_the_next_logical_message"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem admission_covers_original_exposure"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run balancedProjectionCounterexampleTest"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_shrink_never_admits_a_different_node"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn require_family"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn mixed_request_and_stream_exposure_cannot_be_checked_in_separate_domains"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem orphaned_hold_blocks_new_admission"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run separateEffectDomainsCounterexampleTest"},{"file":"crates/ledger/tests/unit/properties.rs","pattern":"fn arbitrary_replays_restarts_and_consumption_preserve_claims"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run sharedBudgetTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalCostBoundTest"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn authored_ceiling_cannot_underreserve_the_original_wire_cost"}]},{"id":"ZeroTrustContractRefinement","witnesses":[{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem final_use_on_committed_union","declaration":"Weaver.DomainMigrationComposition.final_use_on_committed_union"},{"file":"crates/ledger/src/provider.rs","pattern":"actual.stamp != p.domains"},{"file":"crates/ledger/tests/unit/provider_domains.rs","pattern":"fn same_actual_domains_fence_original_provider_capability"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"actual migration committed; response discarded"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run committedUnionLostReplyKeepsBothOriginalsTest"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem gateway_final_use_preserves_domain_contract","declaration":"Weaver.DomainMigrationComposition.gateway_final_use_preserves_domain_contract"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem head_cas_preserves_original_obligations","declaration":"Weaver.DomainMigrationComposition.head_cas_preserves_original_obligations"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem overbooked_actual_view_cannot_supply_final_run","declaration":"Weaver.DomainMigrationComposition.overbooked_actual_view_cannot_supply_final_run"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureResearchModels"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainCommitRestartPositiveTest"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainRevocationKeepsOriginalExposureTest"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run detachedLogicalLedgerCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget","declaration":"Weaver.ProviderRpc.shared_exposure_keeps_original_budget"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework","declaration":"Weaver.ZeroTrustEnrichment.gateway_specialization_retains_generic_framework"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway","declaration":"Weaver.ZeroTrustEnrichment.retained_parent_and_selected_object_reach_gateway"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption","declaration":"Weaver.ZeroTrustEnrichment.usage_control_keeps_current_consumption"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use","declaration":"Weaver.ZeroTrustEnrichment.pending_policy_blocks_ongoing_use"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"}]},{"id":"ConsumeBeforeSend","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn final_write_requires_exact_durable_range"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run stateOnlyRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem inexact_cannot_refine_execution","declaration":"Weaver.StreamingExecution.RangeReceipt.inexact_cannot_refine_execution"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn crash_after_consumption_never_reopens_or_refunds"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run consumeBeforeSendTest"}]},{"id":"CurrentFinalGuard","witnesses":[{"file":"crates/ledger/tests/unit/serialization.rs","pattern":"fn effective_publication_cannot_overtake_the_locked_send_boundary"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run stalePermitTest"}]},{"id":"UnknownRetainsHold","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restart_never_backfills_request_claims_from_operations"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn orphaned_request_claim_cannot_admit_a_replacement_operation"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn next_stream_message_cannot_recreate_a_lost_node_claim"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn lost_message_projection_cannot_recycle_original_unknown_hold"},{"file":"crates/broker/tests/unit/https_transport.rs","pattern":"fn partial_transport_failure_is_unknown_and_never_retried"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run unknownRefundCounterexampleTest"}]},{"id":"NoImplicitRetry","witnesses":[{"file":"crates/ledger/tests/unit/concurrency.rs","pattern":"fn concurrent_consumers_invoke_once"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run duplicateRetryCounterexampleTest"}]},{"id":"DevelopmentPolicy","witnesses":[{"file":"crates/contracts/src/lib.rs","pattern":"mode = deny"}]},{"id":"MessageScopedAuthority","witnesses":[{"file":"crates/ledger/tests/unit/stream_properties.rs","pattern":"fn unknown_range_after_restart_blocks_new_nonce_and_authority"},{"file":"crates/policy/tests/unit/stream_policy.rs","pattern":"fn specification_derived_policy_is_typed_and_constrains_actual_range_facts"}]},{"id":"RangeFinalGuard","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn effective_revocation_stops_actual_next_range_and_prefix_reconnect"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run revokedBetweenBurnAndWriteTest"}]},{"id":"UnknownPrefixRecovery","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn rust_partial_write_freezes_tail_and_never_refunds"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unknown_cannot_resume"}]},{"id":"PrivateBufferCustody","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn tls_flush_cannot_release_a_tail_after_effective_revocation"},{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn recovered_old_worker_socket_cannot_use_new_custody"}]},{"id":"BoundedPerformanceWork","witnesses":[{"file":"crates/policy/tests/unit/cache_storage.rs","pattern":"fn compiled_storage_caps_slots_and_exact_hits_do_not_allocate_new_entries"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem bounded_range_copy_work"}]},{"id":"TrackedWriterDrain","witnesses":[{"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"async fn detached_executor_writer_keeps_slot_until_drain_acknowledges_completion"},{"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"fn arbitrary_disconnect_shutdown_and_drain_schedules_keep_executor_custody"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"},{"file":"dev/proofs/quint/RuntimeLifecycle.qnt","pattern":"run prematureAckCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem execution_and_drain_composition"}]},{"id":"GrpcCallerBinding","witnesses":[{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderRPCIdentityAndCancellation"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_name_is_not_key_authority"}]},{"id":"TransportSetupIsolation","witnesses":[{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run reconnectCannotUncancelOriginalStreamTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem crash_cannot_recreate_unknown_release"},{"file":"go/internal/gatewayclient/connection_test.go","pattern":"func TestConnectionSetupRetainsCallerDeadlineAndCancellation"},{"file":"go/dev/provider_startup_test.go","pattern":"func TestProviderFreshImageAndRestartStartup"},{"file":"dev/proofs/quint/GatewayComposition.qnt","pattern":"run reconnectRetainsSpentRootTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem gateway_run_preserves_original_execution_and_custody"}]},{"id":"CommittedProviderRouting","witnesses":[{"file":"go/internal/routing/provider_test.go","pattern":"func TestProviderRoutingCannotRewriteOriginalContract"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderGRPCStreamingAndArrowOption"}]},{"id":"UnambiguousProviderRequestBounds","witnesses":[{"file":"crates/contracts/tests/unit/provider_bounds.rs","pattern":"fn exactly_one_provider_cap_is_bounded"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn rejected_competing_caps_leave_no_claim_or_hold_after_restart"},{"file":"go/internal/routing/provider_test.go","pattern":"func FuzzProviderRequestBounds"},{"file":"go/dev/provider_bounds_test.go","pattern":"func TestProviderCompetingCapsCannotReachDispatch"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preferredCapPrecedenceCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem request_bounds_and_affine_execution_composition"}]},{"id":"SourceProviderProfileBinding","witnesses":[{"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceProfileAndCedarBindFinalSendAcrossRestart"},{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn concurrent_profile_registrations_cannot_fork_one_identity"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_task_registration_cannot_rebind"}]},{"id":"ClosedProviderRequestSchema","witnesses":[{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn provider_profile_cannot_fall_back_to_untyped_request_or_raw_stream"},{"file":"crates/contracts/tests/unit/provider_profiles.rs","pattern":"fn shared_closed_request_corpus_has_the_declared_semantics"},{"file":"go/api/v1/provider_profile_test.go","pattern":"func TestProviderProfileSharedClosedRequestCorpus"},{"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceCommittedExtensionsCannotBypassProfile"},{"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingSchemaGuardCounterexampleTest"}]},{"id":"RecoverableProfileFloor","witnesses":[{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn original_task_floor_prevents_missing_registry_from_rebinding_identity"},{"file":"crates/ledger/tests/unit/profile_floor_plan.rs","pattern":"fn semantic_floor_uses_two_composite_range_seeks"},{"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingFloorCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem missing_registry_cannot_erase_original_floor"}]},{"id":"CanonicalProfileConfiguration","witnesses":[{"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileJSONAndYAMLHaveOneCanonicalCommitment"},{"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileRejectsAmbiguousConfiguration"},{"file":"go/internal/config/provider_profile_test.go","pattern":"func FuzzProviderProfileConfiguration"}]},{"id":"AffineProviderAttempt","witnesses":[{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn arbitrary_provider_replays_restarts_and_release_batches_keep_original_claim"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run sdkRetryCannotConsumeAgainTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem consumed_unknown_retains_original_hold"}]},{"id":"EncodingAuthorityEquivalence","witnesses":[{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPolicyChangeDuringCapacityWait"},{"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowWireBoundDoesNotBoundDecodedText"},{"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowInvalidLaterRowReturnsNoPartialBatch"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preparedEncodingCannotSwitchTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem final_guard_checks_actual_owner_rows"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderArrowChecksEveryRow"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem arrow_cannot_weaken_row_authority"}]},{"id":"ProviderUnknownRetention","witnesses":[{"file":"crates/broker/src/provider/runtime.rs","pattern":"fn open_guarded"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn commit_provider"},{"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn failed_callback_never_enters_final_commit_and_retains_original_exposure"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn turso_applied_commit_without_ack_poison_is_not_reusable"},{"file":"go/dev/provider_commit_fault_test.go","pattern":"func TestProviderSealedTursoCommitRecovery"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run appliedLostAckPoisonsOldWorkerTest"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run durableCommitThenFenceThenLateAckTest"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run committingFailedCallbackCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem failed_callback_cannot_enter_commit","declaration":"Weaver.ProviderRpc.RequestWriteFence.failed_callback_cannot_enter_commit"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem applied_commit_without_ack_does_not_activate","declaration":"Weaver.ProviderRpc.RequestWriteFence.applied_commit_without_ack_does_not_activate"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem late_commit_ack_cannot_bypass_new_fence","declaration":"Weaver.ProviderRpc.RequestWriteFence.late_commit_ack_cannot_bypass_new_fence"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider[(]"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run individualHoldOnlyCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_provider_exposure_cannot_be_released"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem provider_exposure_strengthens_continuing_zero_trust"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerEnqueueBeforeCommitCrashCannotReplayPendingRange"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerCancellationAndReconnectRetainHistory"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run enqueueThenLostCommitRetainsUnknownTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem transport_history_preserves_original_hold"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderPartialRequestAndRestartRetainUnknownClaim"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run unknownRefundCounterexampleTest"}]},{"id":"ReservedAuthorityAdmission","witnesses":[{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run recoveryDoesNotRefreshUsageEvidenceTest"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn final_release_keeps_current_guard_and_unknown_commit_in_one_transaction"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run childOnlyPredicateDropsParentCounterexampleTest"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem continuing_uses_current_state_and_original_consumption"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem capacity_cannot_rebase_changed_floor"},{"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn waiting_capacity_does_not_hold_sql_or_authorize_after_publication"},{"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn pending_range_history_created_during_capacity_wait_cannot_be_replayed"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPositiveControlCompletesAfterCapacityReturns"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run returnedCapacityDoesNotAuthorizeStaleReleaseTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_backpressure_composition"},{"file":"crates/server/tests/unit/admission.rs","pattern":"async fn saturated_detached_execution_preserves_publication_and_observation_custody"},{"file":"go/dev/provider_capacity_test.go","pattern":"func TestProviderSaturatedExecutionPreservesRevocationAndObservation"},{"file":"dev/proofs/quint/AuthorityAdmission.qnt","pattern":"run sharedLaneStarvationCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_admission_composition"}]},{"id":"ConnectionCustodyBound","witnesses":[{"file":"crates/server/tests/unit/connections.rs","pattern":"async fn tcp_socket_owns_capacity_until_destruction_and_preserves_io_and_peer_identity"},{"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderPreTLSConnectionsAreBoundedAndExpire"},{"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderShutdownDestroysStalledTLSBeforeAcknowledgingExit"},{"file":"dev/proofs/quint/ConnectionAdmission.qnt","pattern":"run earlyReturnCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem provider_and_connection_composition"}]},{"id":"SourceIngressBinding","witnesses":[{"file":"go/dev/provider_source_test.go","pattern":"func TestProviderSourceIngressBindsCertificateCredentialAndMethod"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledCatalogRequiresExactSourceEpoch"},{"file":"go/dev/provider_capacity_test.go","pattern":"full operation ingress blocked new source session"},{"file":"crates/server/tests/unit/grpc_ingress.rs","pattern":"async fn aliased_or_empty_source_identity_is_rejected_before_serving"},{"file":"dev/proofs/quint/SourceIngress.qnt","pattern":"run forwardedCredentialCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem ingress_step_preserves_independent_custody"}]},{"id":"DurablePublicationDecision","witnesses":[{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn outcome_insert_failure_rolls_back_policy_schema_and_result_together"},{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn concurrent_same_identity_commits_only_one_revision"},{"file":"go/dev/publication_recovery_test.go","pattern":"func TestProviderPublicationLostReplyRestartAndHistoricalDecision"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run deletedOutcomeCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_and_provider_accounting_composition"}]},{"id":"OwnedSourceConnection","witnesses":[{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn cancelled_priority_wait_does_not_send_a_source_command"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn source_rotation_commits_before_queued_catalog_reads_recheck_identity"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run newCommandCanPrecedeOldReplyTest"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn completed_source_acknowledgment_returns_command_capacity"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run replyBeforeCapacityCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem command_ack_requires_returned_capacity"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn reused_source_connection_observes_other_writer_and_preserves_historical_result"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn disconnected_source_caller_keeps_capacity_until_original_sql_work_finishes"},{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn connection_reuse_rejects_an_unresolved_explicit_transaction"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run swallowedCloseErrorCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem owned_worker_and_publication_composition"}]},{"id":"FinalInvocationCancellation","witnesses":[{"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn cancellation_during_sql_wait_blocks_transport_and_keeps_spent_claim"},{"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn uncancelled_control_reaches_real_https_transport_once"},{"file":"dev/proofs/quint/DispatchCancellation.qnt","pattern":"run skippedRecheckCounterexampleTest"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run missingFinalCancellationCheckCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem cancellation_and_original_hold_composition"}]},{"id":"OriginalReleaseCapability","witnesses":[{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityBudgetHistoryChangeInvalidatesReleaseReadTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_plan_survives_batching"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn equal_batch_digests_cannot_transfer_release_between_original_nodes"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn release_encoding_cannot_change_after_preparation"},{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn release_capabilities_bind_plan_encoding_and_restart_session"},{"file":"dev/proofs/quint/ReleaseBinding.qnt","pattern":"run crossPlanCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem release_binding_and_execution_composition"}]},{"id":"SpecificSourceContracts","witnesses":[{"file":"crates/server/src/single_provider.rs","pattern":"bound: BoundSource"},{"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run governanceCannotReplaceGovernorTest"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run missingGovernorCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_cannot_replace_governor","declaration":"Weaver.PolicyBridge.governance_cannot_replace_governor"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governor_cannot_replace_governance","declaration":"Weaver.PolicyBridge.governor_cannot_replace_governance"},{"file":"scheme/governance/types.ss","pattern":"def GovernanceScopeContract\\s+\\(\\.cc \\(Record"},{"file":"scheme/gateway/contracts.ss","pattern":"def GatewayArtifact"},{"file":"t/gateway-contracts-test.ss","pattern":"def gateway-contracts-test"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityUncompiledSourceCannotRegisterTest"},{"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"},{"file":"t/gateway-contracts-test.ss","pattern":"module scopes use native POO Types and refuse evidence protocol hooks"}]},{"id":"GovernancePolicyProjection","witnesses":[{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrApprovalCannotOutliveExposureProjectionRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrCommitReplyLossAndReplayCannotMintAnotherTicketTest"},{"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn candidate_only_replay_cannot_register_for_a_real_predecessor"},{"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn replay_cannot_substitute_the_captured_predecessor"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem matched_replay_preserves_both_images"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run exactReplayPairSurvivesLostReplyAndCommitsOriginalTest"},{"file":"crates/ledger/tests/unit/source_authority.rs","pattern":"fn source_handoffs_and_old_workers_preserve_original_unknown_budget"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn consistent_whole_store_rollback_remains_a_local_authority_counterexample"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn residual_policy_schema_cannot_be_treated_as_an_empty_store_after_restart"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn first_enrollment_uses_all_durable_tables_without_temporary_aliases"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn committed_writer_before_enrollment_cannot_be_hidden_by_an_old_empty_read"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn callback_failure_after_enrollment_does_not_allow_a_replacement_identity"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem complete_catalog_refusal_preserves_original_state"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem source_enrollment_refusal_preserves_unknown_accounting"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run omittedProjectionEnrollmentCounterexampleTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateCatalogCommitMustReachDecidingGuardTest"},{"file":"go/dev/provider_source_authority_test.go","pattern":"func TestProviderPersistentSourceRotationLostReplyFencesExistingWorkerAndReissuedKey"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem retired_source_key_cannot_become_fresh"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_preserves_source_key_uniqueness"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run burnWithoutRetainedConfirmationCannotAdmitTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run cachedQualificationCannotAdmitWithZeroHeldProjectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run repairedProjectionDoesNotRecreateLostSendHandleTest"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_prefix_failure_atomically_rolls_back_burn"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_prefix_without_burn_projection_cannot_repeat_admission"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_burn_fenced_before_callback_keeps_original_unknown_exposure"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run confirmedRevocationAndHandoffRejectConsistentSourceRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run retainedRegistrationCannotReplaceAfterSnapshotRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run sameLengthArtifactReplacementCannotConfirmRetainedPrefixTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run wholeRetainedRootRollbackCanReplayQualificationCounterexampleTest"},{"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn identical_prefix_after_whole_store_restore_can_replay_dispatch_counterexample"},{"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn prefix_qualification_does_not_reconstruct_rolled_back_budget_counterexample"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run copiedRowsWithoutRecoveryQualificationCannotPublishTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateQualificationAfterRegistryAppendIsRefusedTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run recoveredNewOwnerRequalifiesOriginalArtifactTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run consistentAuthorityRollbackCanReplaySavedQualificationCounterexampleTest"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn stale_registry_read_and_reopened_worker_preserve_unknown_provider_exposure"},{"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn text_rendering_cannot_silently_replace_original_policy_ids"},{"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn actual_spec_replay_registration_persists_before_original_final_cas"},{"file":"go/dev/provider_policy_json_test.go","pattern":"func TestProviderControlNamedPolicyJSONRevocationAndRestart"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem finite_replay_does_not_certify_no_gain"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run observerRestartCannotRestoreReadCapabilityTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateRegistryReceiptAfterHandoffIsHistoricalTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run independentSnapshotRollbackResurrectsCredentialCounterexampleTest"},{"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn losing_verifier_metadata_cannot_downgrade_a_committed_served_profile"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem missing_verifier_cannot_downgrade"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run missingVerifierCannotDowngradeAfterRestartTest"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureComposition"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureRejectsFalseArithmetic"},{"file":"dev/proofs/cedar/SpecProofClosure.lean","pattern":"def proveClosedArithmetic"},{"file":"prod/policies/provider/ProviderReview.lean","pattern":"def entry"},{"file":"go/internal/specreview/producer.go","pattern":"Issue"},{"file":"crates/policy/src/qualified_delta.rs","pattern":"pub fn verify_qualified_delta"},{"file":"go/dev/provider_spec_review_test.go","pattern":"func TestProviderRealSPECReviewRevocationLostRepliesAndRestart"},{"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn historical_signature_only_nogain_is_not_semantic_qualification"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run signatureOnlyGainCounterexampleTest"},{"file":"dev/proofs/cedar/QualifiedReview.lean","pattern":"theorem qualified_execution_and_recovery_preserve_original","declaration":"Weaver.QualifiedReview.qualified_execution_and_recovery_preserve_original"},{"file":"crates/ledger/src/delta_registration.rs","pattern":"fn require_current"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"fn require"},{"file":"go/dev/provider_review_test.go","pattern":"func TestProviderReviewedPublicationLostRepliesAndRestart"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem reviewed_commit_composes_with_original_recovery"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run producerSignatureCannotReplaceQualificationTest"},{"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn consistent_snapshot_rollback_can_replace_local_registered_artifact_counterexample"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceLateCommitReplyAfterRotationRemainsHistorical"},{"file":"crates/ledger/tests/unit/publication_review.rs","pattern":"fn reviewed_prefixes_match_an_independent_model"},{"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn stage_review_requirement_and_legacy_final_cas_have_one_serial_order"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_registration_recovery_composes_without_releasing_unknown"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run latchedReviewCannotUseLegacyPublicationTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run configurationImageCannotErasePersistentRevocationTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registryAppendBetweenReadAndCASRequiresRejoinTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRollbackLostReplyRetainsUnknownConsumption"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem registrar_binding_reaches_final_cas"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run revocationBetweenValidationAndFinalCASTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run delayedIssuanceDecisionCannotReactivateOldEpochTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateRotationRecoversLostReplyAndPending"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateConfigRollbackReacceptsOldKeyCounterexample"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_recovery_keeps_original_constraints"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem durable_review_binding_survives_final_cas"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registrationLostReplyCannotPublishUnrecoveredProjectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run oldRegistrarCannotPublishAlreadyRegisteredArtifactTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderStagingLostReplyRetainsConcurrentPendingAcrossRestart"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRoleCredentialIsNotRegistrarIncarnationEvidence"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem reviewed_publication_keeps_recovery_contract"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run substitutedArtifactGetsOriginalRejectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run crossStoreReviewRollbackCounterexampleTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderPendingCommandSubstitutionAndHistoricalRecovery"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn typed_publication_does_not_yet_require_delta_evidence"},{"file":"scheme/policy/func.ss","pattern":"project-policy profile"},{"file":"scheme/policy/assets.ss","pattern":"read-policy-assets profile"},{"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"}]},{"id":"CompiledSourceStartup","witnesses":[{"file":"scheme/gateway/compiled.ss","pattern":"weaver_governance_ready_v1"},{"file":"crates/governance-build/src/application.rs","pattern":"pub fn approved"},{"file":"build.ss","pattern":"approved application root mismatch"},{"file":"crates/governance/src/program/compiler.rs","pattern":"pub fn initialize"},{"file":"crates/governance/src/catalog/configuration.rs","pattern":"pub fn from_configuration"},{"file":"crates/server/src/governance_deployment.rs","pattern":"async fn start_compiler"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRequiresRealInstallation"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"metadataAsInitializationCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem graph_membership_cannot_replace_initialization"}]},{"id":"GovernorSourceHandoff","witnesses":[{"file":"scheme/gateway/types.ss","pattern":"def GatewayProgram"},{"file":"scheme/gateway/program.ss","pattern":"def \\(make-gateway-program"},{"file":"t/gateway-source-test.ss","pattern":"program installation and close follow an irreversible lifecycle"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"caughtReentryPoisonsOuterDeliveryTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem program_result_composes_with_registered_original"},{"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"},{"file":"go/internal/controlplane/deployment_source_test.go","pattern":"func FuzzDeploymentSourceHasOneOwner"},{"file":"go/internal/controlplane/producer_deployment_test.go","pattern":"func exerciseProducerDeployment"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"deploymentCannotFallBackToFileTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem producer_deployment_keeps_registered_original"},{"file":"crates/server/src/grpc.rs","pattern":"async fn compile_source"},{"file":"go/internal/controlplane/source_compile.go","pattern":"func BootstrapProducer"},{"file":"go/internal/controlplane/approved_source_rpc_test.go","pattern":"func TestApprovedSourceMTLSBootstrap"},{"file":"go/internal/config/freeze_test.go","pattern":"func FuzzFrozenSourceDoesNotFollowCallerMutation"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem compilation_reply_keeps_registered_original"},{"file":"crates/governance/src/catalog/admission.rs","pattern":"pub struct ProducerCatalog"},{"file":"crates/governance/src/catalog/client.rs","pattern":"pub fn submit"},{"file":"crates/governance/tests/unit/catalog.rs","pattern":"changed_source_observations_and_fresh_names_cannot_select_original"},{"file":"crates/server/src/governance_owner.rs","pattern":"pub fn publish_producers"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"oldCatalogObservationStillCannotPublishThroughNewFenceTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"producer_selection_keeps_all_original_fields"},{"file":"crates/server/src/governance_owner.rs","pattern":"pub async fn start_governance"},{"file":"crates/server/src/grpc.rs","pattern":"pub async fn serve_grpc_with_runtime"},{"file":"crates/server/tests/unit/governance_owner.rs","pattern":"shared_owner_schedules_preserve_cleanup_and_terminal_admission"},{"file":"crates/server/tests/integration/governance_owner.rs","pattern":"actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"lateFactoryActivationCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_owner_join_preserves_cleanup"},{"file":"crates/governance/src/scheme_input/records.rs","pattern":"pub fn root_source"},{"file":"crates/governance/src/scheme_input/values.rs","pattern":"fn bytes"},{"file":"crates/governance/src/host/client.rs","pattern":"pub fn source_lane"},{"file":"crates/governance/src/host/owner.rs","pattern":"pub fn run"},{"file":"crates/governance/tests/unit/host.rs","pattern":"cancelled_running_work_keeps_its_slot_until_natural_return"},{"file":"crates/governance/tests/unit/host.rs","pattern":"active_compiler_observes_both_request_and_owner_cancellation"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSourceCancellationDrainsSchemeOwner"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"checkThenSendCloseRaceCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_host_delivery_requires_open_gate"},{"file":"crates/governance/src/binding.rs","pattern":"pub struct SourceExpectation"},{"file":"crates/governance/tests/unit/binding.rs","pattern":"coherent_replacements_cannot_change_original_content"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"unsafeSelfConsistentReplacementWitness"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"coherent_replacement_cannot_redefine_original"},{"file":"crates/governance/build.rs","pattern":"run_package_main"},{"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeQualificationStaysWithPreparedSchemeOwner"},{"file":"t/gateway-source-test.ss","pattern":"SDK field symbols and identifier strings cannot be interchanged"},{"file":"crates/governance/src/scheme.rs","pattern":"pub fn materialize_source"},{"file":"crates/governance/tests/integration/scheme_vm.rs","pattern":"actual_aa_capture_materializes_owned_data_before_vm_cleanup"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run unsafeEncodedBlobWitness"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem encoded_blob_cannot_claim_typed_capture"},{"file":"scheme/gateway/capture.ss","pattern":"Gateway capture requires one source emission"},{"file":"scheme/gateway/func.ss","pattern":"def \\(capture-governed-gateway"},{"file":"t/gateway-source-test.ss","pattern":"native PBT requires one completed emission"},{"file":"t/gateway-source-test.ss","pattern":"a late inherited sink cannot replace an active next capture"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run ignoredCaptureFuseCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem caught_duplicate_cannot_clear_capture_fuse"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"},{"file":"scheme/governance/capture.ss","pattern":"def \\(governance-profile-snapshot"},{"file":"t/governance-test.ss","pattern":"native PBT preserves every original assessment binding"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_assessment_snapshot_cannot_reuse_boundary"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run coordinatedLiveProfileLabelsCannotReplaceOriginalCaptureTest"},{"file":"scheme/gateway/func.ss","pattern":"assq 'open-patterns"},{"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"},{"file":"scheme/governance/types.ss","pattern":"def GovernanceAssessmentContext"},{"file":"scheme/gateway/func.ss","pattern":"same-node-set?"},{"file":"t/gateway-source-test.ss","pattern":"a false Governance assessment cannot emit a source handoff"},{"file":"t/governance-test.ss","pattern":"a typed ready assessment cannot omit an original blocking threat"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityChangedCompiledSourceCannotRecoverTest"},{"file":"scheme/policy/func.ss","pattern":"project-policy profile"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"},{"file":"t/integration/governed-control-test.ss","pattern":"def governed-control-test"},{"file":"go/internal/config/bundle_test.go","pattern":"func TestBundleRejectsSelectionAndCommitmentSubstitution"}]},{"id":"SourceStartupObservation","witnesses":[{"file":"scheme/gateway/provider-program.ss","pattern":"call-with-module-source-operation-measurement"},{"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeVerificationUsesOnlyPublicPackageEntries"},{"file":"crates/governance-build/src/program.rs","pattern":"build_program_archive_with_contract"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run releaseTagCannotRebaseCapturedSourceCounterexampleTest"},{"file":"go/internal/devrunner/retention_test.go","pattern":"func TestSchemePreparationFailureKeepsOriginalCutWithoutAmbientReceipt"},{"file":"go/internal/devrunner/retention_test.go","pattern":"func TestLateCleanupFailureCannotRetainPassingReceipt"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_preparation_cut_cannot_rebase_boundary","declaration":"Weaver.PolicyBridge.changed_preparation_cut_cannot_rebase_boundary"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run changedPackageMetadataCannotRebaseSnapshotTest"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run stalePreparationReceiptCounterexampleTest"},{"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"},{"file":"go/internal/controlplane/deployment.go","pattern":"trace\\(\"authority-reconciled\"\\)"},{"file":"scheme/gateway/func.ss","pattern":"source-selection-loaded"},{"file":"scheme/gateway/func.ss","pattern":"source-module-view-loaded"},{"file":"scheme/gateway/func.ss","pattern":"source-contracts-checked"},{"file":"scheme/gateway/func.ss","pattern":"source-advisory-derived"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"status=failed drain_ns"},{"file":"crates/governance/src/host/owner.rs","pattern":"scheme-owner-drop-begin"},{"file":"t/fixtures/governed-control.ss","pattern":"fixture-module-ready"},{"file":"go/dev/provider_control_test.go","pattern":"These unauthenticated diagnostics never replace readiness or exit checks"},{"file":"crates/governance-build/src/tooling.rs","pattern":"fn bind_package_sources"},{"file":"crates/governance-build/tests/unit/package_sources.rs","pattern":"fn native_package_inputs_follow_the_selected_store_without_overwriting_sources"}]},{"id":"PolicyCAbiIsInert","witnesses":[{"file":"scheme/policy/func.ss","pattern":"def \\(validate-policy-projection!"},{"file":"scheme/gateway/func.ss","pattern":"validate-policy-projection! projection"},{"file":"t/policy-test.ss","pattern":"real Rust preflight refuses cross-document syntax assembly"},{"file":"t/policy-projection-test.ss","pattern":"every named document precedes aggregate validation"},{"file":"crates/policy-ffi/tests/unit/validation.rs","pattern":"fn aggregate_validity_does_not_establish_complete_source_documents"},{"file":"crates/policy/tests/unit/decisions.rs","pattern":"fn default_deny_forbid_and_evaluation_error_are_fail_closed"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem incomplete_policy_document_cannot_admit"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run aggregateOnlyPolicyValidationCounterexampleTest"},{"file":"scheme/policy/source-bytes.ss","pattern":"def \\(cedar-source-utf8"},{"file":"t/policy-test.ss","pattern":"native PBT checks Unicode source bounds before the C ABI"},{"file":"crates/policy-ffi/tests/unit/abi.rs","pattern":"fn unicode_byte_limits_apply_to_each_actual_abi_region"},{"file":"crates/policy-ffi/src/abi.rs","pattern":"pub unsafe extern \"C\" fn weaver_policy_validate_v1"},{"file":"scheme/policy/cedar-ffi.ss","pattern":"def-C-lambda policy-validate/raw"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authoritySourceCommitNeverSendsTest"}]},{"id":"ControlActivationAcknowledgment","witnesses":[{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsStagingReplyLossAndRestart"},{"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlPublicationReplyLossCannotActivateOrRebase"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityLostReplyCannotActivateTest"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"}]},{"id":"ControlStreamRecoveryBinding","witnesses":[{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPartialRequestAndRestart"},{"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlCompleteStreamsShareBudgetAndRejectSDKRetry"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem profile_recovery_retains_original_hold"}]},{"id":"WorkspaceBenchmarkCoverage","witnesses":[{"file":"go/internal/devrunner/benchmark_test.go","pattern":"func TestBenchmarkEvidenceRequiresEveryCase"},{"file":"go/dev/workspace_test.go","pattern":"func TestCargoWorkspaceAndDevelopmentGates"},{"file":"crates/broker/benches/gateway.rs","pattern":"fn guarded_provider"},{"file":"go/dev/provider_bench_test.go","pattern":"func BenchmarkGatewayInspect"}]},{"id":"DurableRangeProgressJoin","witnesses":[{"file":"crates/ledger/src/stream_progress.rs","pattern":"fn message"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_message_cursor_cannot_hide_consumed_range"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_progress_cannot_release_old_writer_or_connection"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run restoredUnknownProjectionBlocksAdmissionTest"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run unknownResetDuplicatesRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unresolved_tail_blocks_admission","declaration":"Weaver.StreamingExecution.RangeProgress.unresolved_tail_blocks_admission"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem changed_progress_cannot_execute","declaration":"Weaver.StreamingExecution.RangeProgress.changed_progress_cannot_execute"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem joined_execution_preserves_safety","declaration":"Weaver.StreamingExecution.RangeProgress.joined_execution_preserves_safety"}]},{"id":"TursoAdmissionAtomicity","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"pub fn begin"},{"file":"crates/ledger/src/exposure_manifest.rs","pattern":"fn verified_members"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn failed_commit_releases_writer_and_poisoned_session_cannot_reenter"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn duplicate_claim_members_cannot_be_normalized_out_of_recovery"},{"file":"go/dev/workspace_test.go","pattern":"func TestProjectArchitectureStorageUsesMRRDataTursoOnly"},{"file":"dev/proofs/quint/TursoAdmission.qnt","pattern":"run tornCommitRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem storage_step_retains_admission_safety","declaration":"Weaver.RuntimeAdmission.Persistence.storage_step_retains_admission_safety"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem committed_consume_survives_reply_loss_and_restart","declaration":"Weaver.RuntimeAdmission.Persistence.committed_consume_survives_reply_loss_and_restart"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem commit_itself_does_not_send","declaration":"Weaver.RuntimeAdmission.Persistence.commit_itself_does_not_send"}]},{"id":"BoundedAdvisoryDerivation","witnesses":[{"file":"scheme/gateway/derivation.ss","pattern":"def \\(make-gateway-derivation"},{"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-gateway"},{"file":"t/gateway-derivation-test.ss","pattern":"generated source replacements agree with graph traversal and fresh results"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run derivedAdviceCannotChangeImageOrSpendTest"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run adviceAsOriginalCounterexampleTest"}]},{"id":"SessionWorkflowFrontier","witnesses":[{"file":"scheme/gateway/program.ss","pattern":"def \\(hard-fact-affected"},{"file":"go/dev/provider_hard_fact_test.go","pattern":"func TestProviderControlHardFactWithdrawalRestartAndABA"},{"file":"scheme/gateway/func.ss","pattern":"def \\(session-workflow-path"},{"file":"crates/server/src/governance_deployment.rs","pattern":"admits_session_workflow"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"fn bind_winner"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn provider_workflow_rechecks_prepared_floor_and_frontier_before_one_reservation"},{"file":"crates/server/src/session_workflow.rs","pattern":"async fn run_session_workflow"},{"file":"crates/server/src/single_provider.rs","pattern":"SessionTopology::prepare"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionWorkflowAutomaticallyResumes"},{"file":"scheme/gateway/func.ss","pattern":"def \\(governor-ready-steps"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"pub fn observe_workflow"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_workflow_observation"},{"file":"crates/governance/src/host/owner.rs","pattern":"cut_sha256=.*ready_sha256="},{"file":"crates/governance/src/program/compiler.rs","pattern":"topology_binding"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn governor_indices_reject_stale_binding_and_foreign_node"},{"file":"crates/server/src/session_workflow.rs","pattern":"DerivationOutput::Indices"},{"file":"crates/server/src/single_provider.rs","pattern":"topology.preopen"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn pack_governor_facts"},{"file":"t/gateway-governor-retained-test.ss","pattern":"packed facts are complete and bounded by the live binding"},{"file":"t/gateway-governor-retained-test.ss","pattern":"a compact cut must name the current binding"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"Governor transport %d expected"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched inner-join cut_sha256="},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched outer-join cut_sha256="},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionDAGConcurrentJoinAndRecovery"},{"file":"crates/ledger/src/provider_workflow_choice.rs","pattern":"fn record_result"},{"file":"go/dev/provider_workflow_choice_test.go","pattern":"func TestProviderControlSessionChoiceFromReleasedResult"},{"file":"crates/ledger/src/provider_workflow_nested.rs","pattern":"fn load"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn nested_workflow_rejects_stale_decision_and_keeps_winner_after_reopen"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSessionNestedChoiceAndParallelRecovery"},{"file":"scheme/gateway/func.ss","pattern":"WEAVER_TEST_GOVERNOR_CHANGED_SOURCES"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"unexpected Governor source replacement"},{"file":"crates/governance/src/host/client.rs","pattern":"weaver-governor-roundtrip"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"Governor roundtrip phases do not cover the call"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider_metering_with_deployment"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"a new frontier transaction must read the current deployment"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"prepare\\(tx, &proposal.predecessors, plan, current\\)"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn rooted_governor_indices_preserve_full_width_binding_and_all_64_candidates"},{"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-retained-governor-program"},{"file":"t/gateway-governor-retained-test.ss","pattern":"prepared nested rules agree with full fresh snapshots under replacement"},{"file":"t/gateway-governor-retained-test.ss","pattern":"prepared nested rules preserve source budget rejection and recovery"}]},{"id":"RustSchemeRuntimeBoundary","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"RustSchemeRuntimeBoundary"}]},{"id":"CloudAdapterAuthorityBoundary","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"CloudAdapterAuthorityBoundary"}]},{"id":"GoIntegrationLeverage","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"GoIntegrationLeverage"}]},{"id":"SchemeSourceComposition","witnesses":[{"file":"scheme/gateway/provider-source.ss","pattern":"def \\(compose-provider-configuration"},{"file":"scheme/gateway/compiled.ss","pattern":"weaver_compose_source_v1"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn composition_uses_scheme_then_rust_seals_the_exact_original"},{"file":"crates/server/src/governance_deployment.rs","pattern":"from_configuration_with"},{"file":"go/internal/controlplane/source_compile.go","pattern":"config.CloneArtifact"},{"file":"t/gateway-source-test.ss","pattern":"ASCENT routing filters modules"},{"file":"go/internal/controlplane/gateway.go","pattern":"composeSourceBundle"},{"file":"go/internal/controlplane/provider_catalog.go","pattern":"func \\(g \\*Gateway\\) composeCatalog"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSchemeCompositionRevocationAndRestart"},{"file":"crates/governance/src/composition.rs","pattern":"pub fn validate_selected"},{"file":"crates/governance/tests/unit/configuration.rs","pattern":"fn source_composition_cannot_seal_a_self_consistent_scope_substitution"}]},{"id":"AdvisorySourceComposition","witnesses":[{"file":"crates/server/src/grpc.rs","pattern":"async fn compose_source"},{"file":"crates/governance/src/host/client.rs","pattern":"pub async fn compose"},{"file":"go/dev/provider_module_routing_test.go","pattern":"operation caller entered semantic composition"},{"file":"go/internal/controlplane/provider_catalog_test.go","pattern":"func TestCatalogCompositionCoalescesFourRequests"},{"file":"crates/broker/tests/unit/https_transport.rs","pattern":"fn provider_endpoint_guard_preserves_anthropic_source_path_constraints"}]},{"id":"DirectRustOperationIngress","witnesses":[{"file":"go/internal/controlplane/deployment.go","pattern":"func PrepareFromEnv"},{"file":"go/cmd/weaver-control/main.go","pattern":"action := controlplane.PrepareFromEnv"},{"file":"crates/server/src/grpc_provider.rs","pattern":"operation_key_only"},{"file":"crates/server/src/single_provider.rs","pattern":"fn operation_plan"},{"file":"crates/server/src/provider_oauth.rs","pattern":"direct ingress cannot supply relay evidence"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderRustDirectPreparedOperationWithoutGoRelay"}]},{"id":"SourceBoundOperationPreparation","witnesses":[{"file":"crates/contracts/src/provider_routing.rs","pattern":"pub enum ProviderOperationScope"},{"file":"crates/ledger/src/provider_routing.rs","pattern":"pub fn register_provider_source"},{"file":"crates/ledger/src/provider_routing.rs","pattern":"pub fn register_routed_task"},{"file":"crates/server/src/source_owner.rs","pattern":"struct OperationResolver"},{"file":"go/dev/provider_module_routing_test.go","pattern":"func TestProviderRustDirectCatalogSelection"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderRustDirectFilePreparation"}]}] +[{"id":"ProviderAdmissionTurn","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let selected_admission"},{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn begin_driver_counters_follow_their_admission_grant"},{"file":"crates/ledger/src/persistence/driver_observer.rs","pattern":"fn observe_read"},{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct AdmissionRequest"},{"file":"crates/ledger/tests/unit/provider_admission_turn.rs","pattern":"fn queued_unaccepted_admission_preserves_old_frame_and_original_hold"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionTurnProperty"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionCommitRecovery"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderAdmissionTurn"},{"file":"crates/broker/src/provider/request.rs","pattern":"Stage::Tls"},{"file":"go/dev/provider_transport_phases_test.go","pattern":"func reportProviderTransport"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run eagerQueueBlocksOldFrameCounterexampleTest"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem queue_preserves_arbitrary_requirement","declaration":"Weaver.ProviderAdmissionTurn.queue_preserves_arbitrary_requirement"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem finite_queue_preserves_final_offer","declaration":"Weaver.ProviderAdmissionTurn.finite_queue_preserves_final_offer"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem open_writer_cannot_mutate","declaration":"Weaver.ProviderAdmissionTurn.open_writer_cannot_mutate"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem accepted_hard_intent_blocks","declaration":"Weaver.ProviderAdmissionTurn.accepted_hard_intent_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_outcome_blocks","declaration":"Weaver.ProviderAdmissionTurn.unknown_outcome_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem changed_image_blocks","declaration":"Weaver.ProviderAdmissionTurn.changed_image_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem queued_admission_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.queued_admission_preserves_spec_final_use"},{"file":"go/internal/controlplane/deployment.go","pattern":"if gateway.source == nil"},{"file":"go/dev/provider_control_bench_test.go","pattern":"func TestProviderGoControlMeasuredChain"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem runtime_catalog_requires_source","declaration":"Weaver.ProviderAdmissionTurn.runtime_catalog_requires_source"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_activation_blocks_source_handoff","declaration":"Weaver.ProviderAdmissionTurn.unknown_activation_blocks_source_handoff"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem bootstrap_source_close_preserves_actual","declaration":"Weaver.ProviderAdmissionTurn.bootstrap_source_close_preserves_actual"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run failedBootstrapCleanupDoesNotActivateIngressTest"},{"file":"go/dev/provider_admission_overlap_bench_test.go","pattern":"func BenchmarkProviderAdmissionOverlap"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn collect_buffered"},{"file":"go/dev/provider_control_bench_test.go","pattern":"image := serverBinary"},{"file":"go/dev/provider_fixture_test.go","pattern":"test-owned Go control image sha256"},{"file":"crates/ledger/src/persistence/scope_trace.rs","pattern":"pub\\(super\\) fn observe_release"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"observed_release_covers_lease_removal_without_retaining_a_grant"},{"file":"crates/ledger/src/persistence/driver_observer.rs","pattern":"pub\\(super\\) fn observe_commit"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"commit_io_observes_native_spans_after_unobserved_setup"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"maybe_prepared\\(c, PREPARE"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn review_program_reuse_reads_replacement_and_rejects_projection_loss"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn review_program_reuse_preserves_native_receipts_and_currentness"},{"file":"go/dev/provider_control_bench_test.go","pattern":"both arms use Go forwarding"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"valid_review!\\(\"CROSS JOIN\"\\)"},{"file":"crates/ledger/src/domains/view.rs","pattern":"require_view\\(persistence::maybe_prepared"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn manifest_programs_rebind_current_members_and_reject_divergence"}]},{"id":"ProviderReadCustody","witnesses":[{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn conflicts"},{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn acquire_origin"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let shared_reads"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn compatible_origins_share_reads_but_an_older_writer_blocks_younger_readers"},{"file":"crates/ledger/tests/unit/provider_read_custody.rs","pattern":"fn shared_reads_keep_distinct_origin_native_writes_concurrent"},{"file":"go/dev/provider_read_custody_test.go","pattern":"func TestProviderReadCustodyProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderReadCustody"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem arbitrary_policy_preserved","declaration":"Weaver.ProviderReadCustody.arbitrary_policy_preserved"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem finite_interleaving_preserves_policy","declaration":"Weaver.ProviderReadCustody.finite_interleaving_preserves_policy"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem overlapping_writes_conflict","declaration":"Weaver.ProviderReadCustody.overlapping_writes_conflict"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessRetainsWriterAndSameOriginBarriers"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_binding_blocks","declaration":"Weaver.ProviderReadCustody.changed_binding_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_shared_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_shared_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_origin_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_origin_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_owner_blocks","declaration":"Weaver.ProviderReadCustody.changed_owner_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem shared_writer_conflicts","declaration":"Weaver.ProviderReadCustody.shared_writer_conflicts"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem older_conflicting_writer_blocks","declaration":"Weaver.ProviderReadCustody.older_conflicting_writer_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem read_custody_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.read_custody_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderReadCustody.qnt","pattern":"run unsafeSharedMutationCounterexampleTest"}]},{"id":"ProviderLifecycleFootprint","witnesses":[{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct OriginLifecycle"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"enum Impact"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_lifecycle"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_provider_lifecycle"},{"file":"crates/ledger/tests/unit/provider_lifecycle.rs","pattern":"fn peer_lifecycle_preserves_complete_view_but_shared_admission_does_not"},{"file":"go/dev/provider_lifecycle_test.go","pattern":"func TestProviderLifecycleCommitRecovery"},{"file":"crates/ledger/tests/unit/authority_footprint.rs","pattern":"fn local_commit_retires_whole_and_own_but_preserves_peer"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem origin_commit_retires_whole_reader","declaration":"Weaver.ProviderLifecycleFootprint.origin_commit_retires_whole_reader"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem arbitrary_cedar_predicate_preserved","declaration":"Weaver.ProviderLifecycleFootprint.arbitrary_cedar_predicate_preserved"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem shared_admission_requires_shared_invalidation","declaration":"Weaver.ProviderLifecycleFootprint.shared_admission_requires_shared_invalidation"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem peer_lifecycle_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.peer_lifecycle_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderLifecycleFootprint.qnt","pattern":"run unsafeNarrowAdmissionCounterexampleTest"}]},{"id":"ProviderSnapshotPublication","witnesses":[{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn release_provider_group_for_delivery"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"struct Snapshot"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn share_qualification"},{"file":"crates/ledger/src/provider.rs","pattern":"fn begin_snapshot_validation"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn take_refresh"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem pending_close_defers_renewal","declaration":"Weaver.ProviderSnapshotPublication.pending_close_defers_renewal"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn a_request_arriving_during_qualification_cannot_trigger_a_second_native_read"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn one_snapshot_requalification_covers_every_exact_frame"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn post_staging_native_failure_cannot_publish_a_partial_snapshot"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn queue_snapshot"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func awaitDeliveryCuts"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem final_use_joins_snapshot","declaration":"Weaver.ProviderSnapshotPublication.final_use_joins_snapshot"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem published_snapshot_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.published_snapshot_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSnapshotPublication.qnt","pattern":"run ungatedArcLoadIsCounterexampleTest"}]},{"id":"ProviderSemanticProgress","witnesses":[{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct RangeProgress"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_progress"},{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn stage_group"},{"file":"crates/ledger/tests/unit/provider_delivery.rs","pattern":"fn exact_range_progress_preserves_queued_authorization"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderSemanticProgressProperty"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_released_binding","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_released_binding"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_image","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_image"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem range_progress_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.range_progress_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSemanticProgress.qnt","pattern":"run hiddenSemanticEditIsCounterexampleTest"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"}]},{"id":"ProviderDeliveryJoin","witnesses":[{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn bounded_trace_retains_every_requalification"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeTraceChunksPreserveAllRecords"},{"file":"crates/ledger/tests/unit/persistence_owner.rs","pattern":"fn descriptor_copy_is_not_a_retained_execution_owner"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem retained_role_blocks_custody_retirement","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.retained_role_blocks_custody_retirement"},{"file":"dev/proofs/quint/ProviderDeliveryPipeline.qnt","pattern":"run threeInertFramesNeedNoStopAndWaitTest"},{"file":"crates/server/src/grpc_delivery_producer.rs","pattern":"fn reserve_guarded"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"pub fn poll"},{"file":"crates/server/src/grpc_delivery.rs","pattern":"impl Stream for ResponseStream"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryCommitAndReceiverRecovery"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryReceiverProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem orphaned_witness_cannot_activate","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.orphaned_witness_cannot_activate"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem acknowledged_delivery_preserves_same_actual_view","declaration":"Weaver.DomainMigrationComposition.acknowledged_delivery_preserves_same_actual_view"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run committedWithoutAcknowledgmentCannotAcceptTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run rollbackCannotEraseIndependentWitnessTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run oldOwnerCannotRequalifyAfterRestartTest"}]},{"id":"ProviderEgressPromotion","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_close_receipt_cannot_resolve_new_intent","declaration":"Weaver.ProviderEgressWindow.Promotion.old_close_receipt_cannot_resolve_new_intent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem expired_clock_blocks_receiver","declaration":"Weaver.ProviderEgressWindow.Promotion.expired_clock_blocks_receiver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem every_effect_writer_needs_mediation","declaration":"Weaver.ProviderEgressWindow.Promotion.every_effect_writer_needs_mediation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem other_writer_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.other_writer_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem uncertain_effect_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.uncertain_effect_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem unchanged_database_does_not_revalidate_old_read","declaration":"Weaver.ProviderEgressWindow.Promotion.unchanged_database_does_not_revalidate_old_read"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem witness_ahead_blocks_old_image","declaration":"Weaver.ProviderEgressWindow.Promotion.witness_ahead_blocks_old_image"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem only_current_owner_can_deliver","declaration":"Weaver.ProviderEgressWindow.Promotion.only_current_owner_can_deliver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_queued_frame_cannot_follow_replacement","declaration":"Weaver.ProviderEgressWindow.Promotion.old_queued_frame_cannot_follow_replacement"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem delivered_frame_cannot_be_delivered_twice","declaration":"Weaver.ProviderEgressWindow.Promotion.delivered_frame_cannot_be_delivered_twice"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem receiver_promotion_refines_interval_admission","declaration":"Weaver.ProviderEgressWindow.Promotion.receiver_promotion_refines_interval_admission"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run firstCommitCannotDeliverAnotherPendingWriterTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run independentWitnessBeforeDatabaseBlocksDeliveryTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run oldWorkerDeliveryCounterexampleTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run allWriterClassesUseTheSameCutTest"}]},{"id":"BoundedProviderEgressWindow","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem any_accepted_trace_keeps_disjoint_prefix","declaration":"Weaver.ProviderEgressWindow.any_accepted_trace_keeps_disjoint_prefix"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem loss_and_restart_close_old_window","declaration":"Weaver.ProviderEgressWindow.loss_and_restart_close_old_window"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem matching_image_does_not_reopen_old_cut","declaration":"Weaver.ProviderEgressWindow.matching_image_does_not_reopen_old_cut"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem connected_roots_cannot_use_distinct_lanes","declaration":"Weaver.ProviderEgressWindow.connected_roots_cannot_use_distinct_lanes"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem admitted_four_turn_envelope","declaration":"Weaver.ProviderEgressWindow.admitted_four_turn_envelope"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem settlement_is_idempotent","declaration":"Weaver.ProviderEgressWindow.settlement_is_idempotent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem holder_stage_overlap_cannot_exceed_ticket_wait","declaration":"Weaver.ProviderEgressWindow.holder_stage_overlap_cannot_exceed_ticket_wait"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run coherentStoreRollbackActuallyDuplicatesOfferTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run pendingRevocationStopsActualOfferTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run lostBurnAckSealsOriginalTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run rehydratingOldWindowActuallyDuplicatesOfferTest"}]},{"id":"OriginalFloorDecision","witnesses":[{"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run lostCommitResponseResolvesSameOperationTest"},{"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run unknownCommitCannotActivateTest"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"}]},{"id":"ProviderCurrentnessPerformance","witnesses":[{"file":"go/dev/provider_domain_program_test.go","pattern":"func BenchmarkProviderDomainProgram"},{"file":"go/dev/provider_domain_tail_test.go","pattern":"func BenchmarkProviderSharedLongTail"},{"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem prepared_domain_program_preserves_live_decision"}]},{"id":"ProviderSchedulerOwnership","witnesses":[{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn waiting_multi_root_range_precedes_younger_conflicts"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessCountsArrivalGrantInversions"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"}]},{"id":"SenderBoundProviderOAuth","witnesses":[{"file":"go/dev/provider_oauth_relay_test.go","pattern":"func TestProviderOAuthTwoHopRevocationAndRecovery"},{"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem retained_root_revocation_blocks_child"}]},{"id":"TransportAndExecutionLatencySeparation","witnesses":[{"file":"go/dev/provider_scheduler_bench_test.go","pattern":"func BenchmarkProviderScheduledEncoding"},{"file":"go/dev/provider_range_group_test.go","pattern":"func BenchmarkProviderRangePreparationGroup"}]},{"id":"TelemetryNoninterference","witnesses":[{"file":"crates/telemetry/tests/unit/metrics.rs","pattern":"fn observations_are_monotone_and_restart_local"},{"file":"go/internal/telemetry/metrics_test.go","pattern":"func TestPropertyCountersAreBoundedMonotoneAndRestartLocal"},{"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderTelemetryCannotRefundOrRedispatchUnknownSend"},{"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderControlTelemetryObservesBothServices"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryReadsAndRestartCannotRefundTest"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryAsRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem arbitrary_observations_keep_execution","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.arbitrary_observations_keep_execution"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem telemetry_reset_keeps_unknown_hold","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.telemetry_reset_keeps_unknown_hold"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem observations_preserve_effect_safety","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.observations_preserve_effect_safety"}]},{"id":"SharedDomainAuthority","witnesses":[{"file":"crates/ledger/src/domains/binding.rs","pattern":"fn bind"},{"file":"crates/ledger/src/domains/migration.rs","pattern":"fn migrate_execution_domains"},{"file":"crates/ledger/src/domains/view.rs","pattern":"fn require_stamp"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_cross_family_shared_history_serializes_final_use"},{"file":"crates/ledger/tests/unit/shared_domains.rs","pattern":"fn finite_families_never_split_a_shared_cap"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsProperty"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsCedarReadsCurrentAuthority"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run overCapacityUnionKeepsOriginalDecisionTest"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run domainSplitCounterexampleTest"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_cannot_split_any_shared_pair","declaration":"Weaver.SharedDomains.union_cannot_split_any_shared_pair"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem admitted_union_conserves_capacity","declaration":"Weaver.SharedDomains.admitted_union_conserves_capacity"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_retains_history","declaration":"Weaver.SharedDomains.union_retains_history"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_fences_both_old_permits","declaration":"Weaver.SharedDomains.union_fences_both_old_permits"}]},{"id":"TursoMvccCustody","witnesses":[{"file":"crates/ledger/src/persistence/owner.rs","pattern":"fn open"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_family"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_final_domains_overlap_including_new_executor_connection"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_same_budget_and_history_family_keeps_final_order"},{"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn mvcc_effect_before_failed_observation_never_releases_or_replays"},{"file":"go/dev/provider_final_domains_test.go","pattern":"func TestProviderMVCCIndependentFinalSendsAndRevocation"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run postSendCommitConflictKeepsPhysicalEffectTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem shared_final_readers_keep_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.shared_final_readers_keep_current_fence"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem failed_observation_after_send_keeps_spent_hold","declaration":"Weaver.RuntimeAdmission.MVCC.failed_observation_after_send_keeps_spent_hold"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_disjoint_admissions_have_overlapping_turso_writes"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_process_custody_refuses_a_second_process"},{"file":"crates/ledger/tests/unit/mvcc.rs","pattern":"fn mvcc_concurrent_family_budget_has_one_original_reservation"},{"file":"go/dev/provider_mvcc_test.go","pattern":"func TestProviderMVCCExecutionBoundary"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run snapshotWriteSkewCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem disjoint_domain_commits_commute","declaration":"Weaver.RuntimeAdmission.MVCC.disjoint_domain_commits_commute"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem family_step_preserves_all_budgets","declaration":"Weaver.RuntimeAdmission.MVCC.family_step_preserves_all_budgets"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exclusive_final_use_keeps_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.exclusive_final_use_keeps_current_fence"}]},{"id":"ArchitectureViewGrammar","witnesses":[{"file":"dev/sysml/ArchitectureViews.sysml","pattern":"view zeroTrust"},{"file":"go/internal/devrunner/model_views.go","pattern":"func CaptureModelViews"},{"file":"go/internal/devrunner/model_views_test.go","pattern":"func TestModelViewsUseActualSDK"},{"file":"go/internal/devrunner/model_views_test.go","pattern":"func FuzzModelViewCaptureTracksSource"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestArchitectureDiagramsUseDifferentViewProfiles"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramProfilesAreExplicitAndLocal"},{"file":"go/internal/devrunner/diagrams.go","pattern":"func RenderDiagrams"},{"file":"dev/d2/src/render.ts","pattern":"composeFigure[(]input,composer[)]"},{"file":"dev/d2/test/model-view.test.ts","pattern":"public Library binds SDK SysML identity"},{"file":"dev/d2/src/objects.ts","pattern":"export const composeObjects"},{"file":"dev/d2/test/model-view.test.ts","pattern":"missing captured views and unsupported source ports refuse"},{"file":"dev/d2/test/vector-readability.test.ts","pattern":"Preserve the original ordered-sequence line-overlap check"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramEvidenceRejectsLostNodesAndRelationships"}]},{"id":"ProductionAssetBoundary","witnesses":[{"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRuntimeAssetBoundary"},{"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRejectsRuntimeDevReferences"}]},{"id":"OriginalTaskBinding","witnesses":[{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem first_birth_seal_cannot_broaden","declaration":"Weaver.TaskOrigin.first_birth_seal_cannot_broaden"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem sealed_birth_cannot_be_replaced","declaration":"Weaver.TaskOrigin.sealed_birth_cannot_be_replaced"},{"file":"crates/ledger/tests/unit/task_publication.rs","pattern":"fn lost_birth_projection_cannot_authorize_or_be_silently_repaired"},{"file":"crates/ledger/src/task_origins.rs","pattern":"fn register_original_task"},{"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn source_rotation_cannot_reallocate_task_and_lost_reply_recovers_original_commit"},{"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn trusted_issuer_relabeling_every_identity_is_outside_local_deduplication"},{"file":"go/dev/provider_task_origin_test.go","pattern":"func TestProviderOriginalTaskOriginLostReplySourceSwitchAndRestart"},{"file":"dev/proofs/quint/TaskOrigin.qnt","pattern":"run issuerTrustCounterexampleTest"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem assigned_task_cannot_rebind","declaration":"Weaver.TaskOrigin.assigned_task_cannot_rebind"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem source_epoch_does_not_change_task_scope","declaration":"Weaver.TaskOrigin.source_epoch_does_not_change_task_scope"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem stale_source_command_cannot_commit","declaration":"Weaver.TaskOrigin.stale_source_command_cannot_commit"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn original_task_body_and_profile_cannot_be_replaced"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalBindingTest"}]},{"id":"SharedBudget","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn finite_manifest_siblings_cannot_mask_a_missing_original_member"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn maximum_manifest_cannot_replace_a_lost_sibling_after_restart"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityRecoveryGuardTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityFinalUseGuardTest"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn selected_message_binding_must_match_its_committed_digest_at_final_write"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn concurrent_message_admission_preserves_both_manifest_members"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exhausted_budget_cannot_publish_a_manifest_member_without_its_row"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem manifest_bound_runtime_step"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn surviving_stream_message_cannot_hide_a_lost_unknown_reservation"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exact_message_manifest_guards_recovery_and_existing_write_handles"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialMessageLossCounterexampleTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run digestSubstitutionFinalUseGuardTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exact_manifest_admission_covers_original_exposure"},{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn balanced_provider_projection_never_funds_a_different_original_plan"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_stream_projection_never_funds_the_next_logical_message"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem admission_covers_original_exposure"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run balancedProjectionCounterexampleTest"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_shrink_never_admits_a_different_node"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn require_family"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn mixed_request_and_stream_exposure_cannot_be_checked_in_separate_domains"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem orphaned_hold_blocks_new_admission"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run separateEffectDomainsCounterexampleTest"},{"file":"crates/ledger/tests/unit/properties.rs","pattern":"fn arbitrary_replays_restarts_and_consumption_preserve_claims"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run sharedBudgetTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalCostBoundTest"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn authored_ceiling_cannot_underreserve_the_original_wire_cost"}]},{"id":"ZeroTrustContractRefinement","witnesses":[{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem final_use_on_committed_union","declaration":"Weaver.DomainMigrationComposition.final_use_on_committed_union"},{"file":"crates/ledger/src/provider.rs","pattern":"actual.stamp != p.domains"},{"file":"crates/ledger/tests/unit/provider_domains.rs","pattern":"fn same_actual_domains_fence_original_provider_capability"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"actual migration committed; response discarded"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run committedUnionLostReplyKeepsBothOriginalsTest"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem gateway_final_use_preserves_domain_contract","declaration":"Weaver.DomainMigrationComposition.gateway_final_use_preserves_domain_contract"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem head_cas_preserves_original_obligations","declaration":"Weaver.DomainMigrationComposition.head_cas_preserves_original_obligations"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem overbooked_actual_view_cannot_supply_final_run","declaration":"Weaver.DomainMigrationComposition.overbooked_actual_view_cannot_supply_final_run"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureResearchModels"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainCommitRestartPositiveTest"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainRevocationKeepsOriginalExposureTest"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run detachedLogicalLedgerCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget","declaration":"Weaver.ProviderRpc.shared_exposure_keeps_original_budget"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework","declaration":"Weaver.ZeroTrustEnrichment.gateway_specialization_retains_generic_framework"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway","declaration":"Weaver.ZeroTrustEnrichment.retained_parent_and_selected_object_reach_gateway"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption","declaration":"Weaver.ZeroTrustEnrichment.usage_control_keeps_current_consumption"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use","declaration":"Weaver.ZeroTrustEnrichment.pending_policy_blocks_ongoing_use"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"}]},{"id":"ConsumeBeforeSend","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn final_write_requires_exact_durable_range"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run stateOnlyRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem inexact_cannot_refine_execution","declaration":"Weaver.StreamingExecution.RangeReceipt.inexact_cannot_refine_execution"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn crash_after_consumption_never_reopens_or_refunds"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run consumeBeforeSendTest"}]},{"id":"CurrentFinalGuard","witnesses":[{"file":"crates/ledger/tests/unit/serialization.rs","pattern":"fn effective_publication_cannot_overtake_the_locked_send_boundary"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run stalePermitTest"}]},{"id":"UnknownRetainsHold","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restart_never_backfills_request_claims_from_operations"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn orphaned_request_claim_cannot_admit_a_replacement_operation"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn next_stream_message_cannot_recreate_a_lost_node_claim"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn lost_message_projection_cannot_recycle_original_unknown_hold"},{"file":"crates/broker/tests/unit/https_transport.rs","pattern":"fn partial_transport_failure_is_unknown_and_never_retried"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run unknownRefundCounterexampleTest"}]},{"id":"NoImplicitRetry","witnesses":[{"file":"crates/ledger/tests/unit/concurrency.rs","pattern":"fn concurrent_consumers_invoke_once"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run duplicateRetryCounterexampleTest"}]},{"id":"DevelopmentPolicy","witnesses":[{"file":"crates/contracts/src/lib.rs","pattern":"mode = deny"}]},{"id":"MessageScopedAuthority","witnesses":[{"file":"crates/ledger/tests/unit/stream_properties.rs","pattern":"fn unknown_range_after_restart_blocks_new_nonce_and_authority"},{"file":"crates/policy/tests/unit/stream_policy.rs","pattern":"fn specification_derived_policy_is_typed_and_constrains_actual_range_facts"}]},{"id":"RangeFinalGuard","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn effective_revocation_stops_actual_next_range_and_prefix_reconnect"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run revokedBetweenBurnAndWriteTest"}]},{"id":"UnknownPrefixRecovery","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn rust_partial_write_freezes_tail_and_never_refunds"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unknown_cannot_resume"}]},{"id":"PrivateBufferCustody","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn tls_flush_cannot_release_a_tail_after_effective_revocation"},{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn recovered_old_worker_socket_cannot_use_new_custody"}]},{"id":"BoundedPerformanceWork","witnesses":[{"file":"crates/policy/tests/unit/cache_storage.rs","pattern":"fn compiled_storage_caps_slots_and_exact_hits_do_not_allocate_new_entries"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem bounded_range_copy_work"}]},{"id":"TrackedWriterDrain","witnesses":[{"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"async fn detached_executor_writer_keeps_slot_until_drain_acknowledges_completion"},{"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"fn arbitrary_disconnect_shutdown_and_drain_schedules_keep_executor_custody"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"},{"file":"dev/proofs/quint/RuntimeLifecycle.qnt","pattern":"run prematureAckCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem execution_and_drain_composition"}]},{"id":"GrpcCallerBinding","witnesses":[{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderRPCIdentityAndCancellation"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_name_is_not_key_authority"}]},{"id":"TransportSetupIsolation","witnesses":[{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run reconnectCannotUncancelOriginalStreamTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem crash_cannot_recreate_unknown_release"},{"file":"go/internal/gatewayclient/connection_test.go","pattern":"func TestConnectionSetupRetainsCallerDeadlineAndCancellation"},{"file":"go/dev/provider_startup_test.go","pattern":"func TestProviderFreshImageAndRestartStartup"},{"file":"dev/proofs/quint/GatewayComposition.qnt","pattern":"run reconnectRetainsSpentRootTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem gateway_run_preserves_original_execution_and_custody"}]},{"id":"CommittedProviderRouting","witnesses":[{"file":"go/internal/routing/provider_test.go","pattern":"func TestProviderRoutingCannotRewriteOriginalContract"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderGRPCStreamingAndArrowOption"}]},{"id":"UnambiguousProviderRequestBounds","witnesses":[{"file":"crates/contracts/tests/unit/provider_bounds.rs","pattern":"fn exactly_one_provider_cap_is_bounded"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn rejected_competing_caps_leave_no_claim_or_hold_after_restart"},{"file":"go/internal/routing/provider_test.go","pattern":"func FuzzProviderRequestBounds"},{"file":"go/dev/provider_bounds_test.go","pattern":"func TestProviderCompetingCapsCannotReachDispatch"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preferredCapPrecedenceCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem request_bounds_and_affine_execution_composition"}]},{"id":"SourceProviderProfileBinding","witnesses":[{"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceProfileAndCedarBindFinalSendAcrossRestart"},{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn concurrent_profile_registrations_cannot_fork_one_identity"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_task_registration_cannot_rebind"}]},{"id":"ClosedProviderRequestSchema","witnesses":[{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn provider_profile_cannot_fall_back_to_untyped_request_or_raw_stream"},{"file":"crates/contracts/tests/unit/provider_profiles.rs","pattern":"fn shared_closed_request_corpus_has_the_declared_semantics"},{"file":"go/api/v1/provider_profile_test.go","pattern":"func TestProviderProfileSharedClosedRequestCorpus"},{"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceCommittedExtensionsCannotBypassProfile"},{"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingSchemaGuardCounterexampleTest"}]},{"id":"RecoverableProfileFloor","witnesses":[{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn original_task_floor_prevents_missing_registry_from_rebinding_identity"},{"file":"crates/ledger/tests/unit/profile_floor_plan.rs","pattern":"fn semantic_floor_uses_two_composite_range_seeks"},{"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingFloorCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem missing_registry_cannot_erase_original_floor"}]},{"id":"CanonicalProfileConfiguration","witnesses":[{"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileJSONAndYAMLHaveOneCanonicalCommitment"},{"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileRejectsAmbiguousConfiguration"},{"file":"go/internal/config/provider_profile_test.go","pattern":"func FuzzProviderProfileConfiguration"}]},{"id":"AffineProviderAttempt","witnesses":[{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn arbitrary_provider_replays_restarts_and_release_batches_keep_original_claim"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run sdkRetryCannotConsumeAgainTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem consumed_unknown_retains_original_hold"}]},{"id":"EncodingAuthorityEquivalence","witnesses":[{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPolicyChangeDuringCapacityWait"},{"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowWireBoundDoesNotBoundDecodedText"},{"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowInvalidLaterRowReturnsNoPartialBatch"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preparedEncodingCannotSwitchTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem final_guard_checks_actual_owner_rows"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderArrowChecksEveryRow"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem arrow_cannot_weaken_row_authority"}]},{"id":"ProviderUnknownRetention","witnesses":[{"file":"crates/broker/src/provider/runtime.rs","pattern":"fn open_guarded"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn commit_provider"},{"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn failed_callback_never_enters_final_commit_and_retains_original_exposure"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn turso_applied_commit_without_ack_poison_is_not_reusable"},{"file":"go/dev/provider_commit_fault_test.go","pattern":"func TestProviderSealedTursoCommitRecovery"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run appliedLostAckPoisonsOldWorkerTest"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run durableCommitThenFenceThenLateAckTest"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run committingFailedCallbackCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem failed_callback_cannot_enter_commit","declaration":"Weaver.ProviderRpc.RequestWriteFence.failed_callback_cannot_enter_commit"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem applied_commit_without_ack_does_not_activate","declaration":"Weaver.ProviderRpc.RequestWriteFence.applied_commit_without_ack_does_not_activate"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem late_commit_ack_cannot_bypass_new_fence","declaration":"Weaver.ProviderRpc.RequestWriteFence.late_commit_ack_cannot_bypass_new_fence"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider[(]"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run individualHoldOnlyCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_provider_exposure_cannot_be_released"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem provider_exposure_strengthens_continuing_zero_trust"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerEnqueueBeforeCommitCrashCannotReplayPendingRange"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerCancellationAndReconnectRetainHistory"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run enqueueThenLostCommitRetainsUnknownTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem transport_history_preserves_original_hold"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderPartialRequestAndRestartRetainUnknownClaim"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run unknownRefundCounterexampleTest"}]},{"id":"ReservedAuthorityAdmission","witnesses":[{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run recoveryDoesNotRefreshUsageEvidenceTest"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn final_release_keeps_current_guard_and_unknown_commit_in_one_transaction"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run childOnlyPredicateDropsParentCounterexampleTest"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem continuing_uses_current_state_and_original_consumption"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem capacity_cannot_rebase_changed_floor"},{"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn waiting_capacity_does_not_hold_sql_or_authorize_after_publication"},{"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn pending_range_history_created_during_capacity_wait_cannot_be_replayed"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPositiveControlCompletesAfterCapacityReturns"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run returnedCapacityDoesNotAuthorizeStaleReleaseTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_backpressure_composition"},{"file":"crates/server/tests/unit/admission.rs","pattern":"async fn saturated_detached_execution_preserves_publication_and_observation_custody"},{"file":"go/dev/provider_capacity_test.go","pattern":"func TestProviderSaturatedExecutionPreservesRevocationAndObservation"},{"file":"dev/proofs/quint/AuthorityAdmission.qnt","pattern":"run sharedLaneStarvationCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_admission_composition"}]},{"id":"ConnectionCustodyBound","witnesses":[{"file":"crates/server/tests/unit/connections.rs","pattern":"async fn tcp_socket_owns_capacity_until_destruction_and_preserves_io_and_peer_identity"},{"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderPreTLSConnectionsAreBoundedAndExpire"},{"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderShutdownDestroysStalledTLSBeforeAcknowledgingExit"},{"file":"dev/proofs/quint/ConnectionAdmission.qnt","pattern":"run earlyReturnCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem provider_and_connection_composition"}]},{"id":"SourceIngressBinding","witnesses":[{"file":"go/dev/provider_source_test.go","pattern":"func TestProviderSourceIngressBindsCertificateCredentialAndMethod"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledCatalogRequiresExactSourceEpoch"},{"file":"go/dev/provider_capacity_test.go","pattern":"full operation ingress blocked new source session"},{"file":"crates/server/tests/unit/grpc_ingress.rs","pattern":"async fn aliased_or_empty_source_identity_is_rejected_before_serving"},{"file":"dev/proofs/quint/SourceIngress.qnt","pattern":"run forwardedCredentialCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem ingress_step_preserves_independent_custody"}]},{"id":"DurablePublicationDecision","witnesses":[{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn outcome_insert_failure_rolls_back_policy_schema_and_result_together"},{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn concurrent_same_identity_commits_only_one_revision"},{"file":"go/dev/publication_recovery_test.go","pattern":"func TestProviderPublicationLostReplyRestartAndHistoricalDecision"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run deletedOutcomeCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_and_provider_accounting_composition"}]},{"id":"OwnedSourceConnection","witnesses":[{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn cancelled_priority_wait_does_not_send_a_source_command"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn source_rotation_commits_before_queued_catalog_reads_recheck_identity"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run newCommandCanPrecedeOldReplyTest"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn completed_source_acknowledgment_returns_command_capacity"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run replyBeforeCapacityCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem command_ack_requires_returned_capacity"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn reused_source_connection_observes_other_writer_and_preserves_historical_result"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn disconnected_source_caller_keeps_capacity_until_original_sql_work_finishes"},{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn connection_reuse_rejects_an_unresolved_explicit_transaction"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run swallowedCloseErrorCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem owned_worker_and_publication_composition"}]},{"id":"FinalInvocationCancellation","witnesses":[{"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn cancellation_during_sql_wait_blocks_transport_and_keeps_spent_claim"},{"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn uncancelled_control_reaches_real_https_transport_once"},{"file":"dev/proofs/quint/DispatchCancellation.qnt","pattern":"run skippedRecheckCounterexampleTest"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run missingFinalCancellationCheckCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem cancellation_and_original_hold_composition"}]},{"id":"OriginalReleaseCapability","witnesses":[{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityBudgetHistoryChangeInvalidatesReleaseReadTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_plan_survives_batching"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn equal_batch_digests_cannot_transfer_release_between_original_nodes"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn release_encoding_cannot_change_after_preparation"},{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn release_capabilities_bind_plan_encoding_and_restart_session"},{"file":"dev/proofs/quint/ReleaseBinding.qnt","pattern":"run crossPlanCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem release_binding_and_execution_composition"}]},{"id":"SpecificSourceContracts","witnesses":[{"file":"crates/server/src/single_provider.rs","pattern":"bound: BoundSource"},{"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run governanceCannotReplaceGovernorTest"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run missingGovernorCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_cannot_replace_governor","declaration":"Weaver.PolicyBridge.governance_cannot_replace_governor"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governor_cannot_replace_governance","declaration":"Weaver.PolicyBridge.governor_cannot_replace_governance"},{"file":"scheme/governance/types.ss","pattern":"def GovernanceScopeContract\\s+\\(\\.cc \\(Record"},{"file":"scheme/gateway/contracts.ss","pattern":"def GatewayArtifact"},{"file":"t/gateway-contracts-test.ss","pattern":"def gateway-contracts-test"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityUncompiledSourceCannotRegisterTest"},{"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"},{"file":"t/gateway-contracts-test.ss","pattern":"module scopes use native POO Types and refuse evidence protocol hooks"}]},{"id":"GovernancePolicyProjection","witnesses":[{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrApprovalCannotOutliveExposureProjectionRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrCommitReplyLossAndReplayCannotMintAnotherTicketTest"},{"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn candidate_only_replay_cannot_register_for_a_real_predecessor"},{"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn replay_cannot_substitute_the_captured_predecessor"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem matched_replay_preserves_both_images"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run exactReplayPairSurvivesLostReplyAndCommitsOriginalTest"},{"file":"crates/ledger/tests/unit/source_authority.rs","pattern":"fn source_handoffs_and_old_workers_preserve_original_unknown_budget"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn consistent_whole_store_rollback_remains_a_local_authority_counterexample"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn residual_policy_schema_cannot_be_treated_as_an_empty_store_after_restart"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn first_enrollment_uses_all_durable_tables_without_temporary_aliases"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn committed_writer_before_enrollment_cannot_be_hidden_by_an_old_empty_read"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn callback_failure_after_enrollment_does_not_allow_a_replacement_identity"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem complete_catalog_refusal_preserves_original_state"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem source_enrollment_refusal_preserves_unknown_accounting"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run omittedProjectionEnrollmentCounterexampleTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateCatalogCommitMustReachDecidingGuardTest"},{"file":"go/dev/provider_source_authority_test.go","pattern":"func TestProviderPersistentSourceRotationLostReplyFencesExistingWorkerAndReissuedKey"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem retired_source_key_cannot_become_fresh"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_preserves_source_key_uniqueness"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run burnWithoutRetainedConfirmationCannotAdmitTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run cachedQualificationCannotAdmitWithZeroHeldProjectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run repairedProjectionDoesNotRecreateLostSendHandleTest"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_prefix_failure_atomically_rolls_back_burn"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_prefix_without_burn_projection_cannot_repeat_admission"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_burn_fenced_before_callback_keeps_original_unknown_exposure"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run confirmedRevocationAndHandoffRejectConsistentSourceRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run retainedRegistrationCannotReplaceAfterSnapshotRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run sameLengthArtifactReplacementCannotConfirmRetainedPrefixTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run wholeRetainedRootRollbackCanReplayQualificationCounterexampleTest"},{"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn identical_prefix_after_whole_store_restore_can_replay_dispatch_counterexample"},{"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn prefix_qualification_does_not_reconstruct_rolled_back_budget_counterexample"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run copiedRowsWithoutRecoveryQualificationCannotPublishTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateQualificationAfterRegistryAppendIsRefusedTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run recoveredNewOwnerRequalifiesOriginalArtifactTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run consistentAuthorityRollbackCanReplaySavedQualificationCounterexampleTest"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn stale_registry_read_and_reopened_worker_preserve_unknown_provider_exposure"},{"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn text_rendering_cannot_silently_replace_original_policy_ids"},{"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn actual_spec_replay_registration_persists_before_original_final_cas"},{"file":"go/dev/provider_policy_json_test.go","pattern":"func TestProviderControlNamedPolicyJSONRevocationAndRestart"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem finite_replay_does_not_certify_no_gain"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run observerRestartCannotRestoreReadCapabilityTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateRegistryReceiptAfterHandoffIsHistoricalTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run independentSnapshotRollbackResurrectsCredentialCounterexampleTest"},{"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn losing_verifier_metadata_cannot_downgrade_a_committed_served_profile"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem missing_verifier_cannot_downgrade"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run missingVerifierCannotDowngradeAfterRestartTest"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureComposition"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureRejectsFalseArithmetic"},{"file":"dev/proofs/cedar/SpecProofClosure.lean","pattern":"def proveClosedArithmetic"},{"file":"prod/policies/provider/ProviderReview.lean","pattern":"def entry"},{"file":"go/internal/specreview/producer.go","pattern":"Issue"},{"file":"crates/policy/src/qualified_delta.rs","pattern":"pub fn verify_qualified_delta"},{"file":"go/dev/provider_spec_review_test.go","pattern":"func TestProviderRealSPECReviewRevocationLostRepliesAndRestart"},{"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn historical_signature_only_nogain_is_not_semantic_qualification"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run signatureOnlyGainCounterexampleTest"},{"file":"dev/proofs/cedar/QualifiedReview.lean","pattern":"theorem qualified_execution_and_recovery_preserve_original","declaration":"Weaver.QualifiedReview.qualified_execution_and_recovery_preserve_original"},{"file":"crates/ledger/src/delta_registration.rs","pattern":"fn require_current"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"fn require"},{"file":"go/dev/provider_review_test.go","pattern":"func TestProviderReviewedPublicationLostRepliesAndRestart"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem reviewed_commit_composes_with_original_recovery"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run producerSignatureCannotReplaceQualificationTest"},{"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn consistent_snapshot_rollback_can_replace_local_registered_artifact_counterexample"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceLateCommitReplyAfterRotationRemainsHistorical"},{"file":"crates/ledger/tests/unit/publication_review.rs","pattern":"fn reviewed_prefixes_match_an_independent_model"},{"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn stage_review_requirement_and_legacy_final_cas_have_one_serial_order"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_registration_recovery_composes_without_releasing_unknown"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run latchedReviewCannotUseLegacyPublicationTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run configurationImageCannotErasePersistentRevocationTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registryAppendBetweenReadAndCASRequiresRejoinTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRollbackLostReplyRetainsUnknownConsumption"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem registrar_binding_reaches_final_cas"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run revocationBetweenValidationAndFinalCASTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run delayedIssuanceDecisionCannotReactivateOldEpochTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateRotationRecoversLostReplyAndPending"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateConfigRollbackReacceptsOldKeyCounterexample"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_recovery_keeps_original_constraints"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem durable_review_binding_survives_final_cas"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registrationLostReplyCannotPublishUnrecoveredProjectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run oldRegistrarCannotPublishAlreadyRegisteredArtifactTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderStagingLostReplyRetainsConcurrentPendingAcrossRestart"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRoleCredentialIsNotRegistrarIncarnationEvidence"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem reviewed_publication_keeps_recovery_contract"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run substitutedArtifactGetsOriginalRejectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run crossStoreReviewRollbackCounterexampleTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderPendingCommandSubstitutionAndHistoricalRecovery"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn typed_publication_does_not_yet_require_delta_evidence"},{"file":"scheme/policy/func.ss","pattern":"project-policy profile"},{"file":"scheme/policy/assets.ss","pattern":"read-policy-assets profile"},{"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"}]},{"id":"CompiledSourceStartup","witnesses":[{"file":"scheme/gateway/compiled.ss","pattern":"weaver_governance_ready_v1"},{"file":"crates/governance-build/src/application.rs","pattern":"pub fn approved"},{"file":"build.ss","pattern":"approved application root mismatch"},{"file":"crates/governance/src/program/compiler.rs","pattern":"pub fn initialize"},{"file":"crates/governance/src/catalog/configuration.rs","pattern":"pub fn from_configuration"},{"file":"crates/server/src/governance_deployment.rs","pattern":"async fn start_compiler"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRequiresRealInstallation"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"metadataAsInitializationCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem graph_membership_cannot_replace_initialization"}]},{"id":"GovernorSourceHandoff","witnesses":[{"file":"scheme/gateway/types.ss","pattern":"def GatewayProgram"},{"file":"scheme/gateway/program.ss","pattern":"def \\(make-gateway-program"},{"file":"t/gateway-source-test.ss","pattern":"program installation and close follow an irreversible lifecycle"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"caughtReentryPoisonsOuterDeliveryTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem program_result_composes_with_registered_original"},{"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"},{"file":"go/internal/controlplane/deployment_source_test.go","pattern":"func FuzzDeploymentSourceHasOneOwner"},{"file":"go/internal/controlplane/producer_deployment_test.go","pattern":"func exerciseProducerDeployment"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"deploymentCannotFallBackToFileTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem producer_deployment_keeps_registered_original"},{"file":"crates/server/src/grpc.rs","pattern":"async fn compile_source"},{"file":"go/internal/controlplane/source_compile.go","pattern":"func BootstrapProducer"},{"file":"go/internal/controlplane/approved_source_rpc_test.go","pattern":"func TestApprovedSourceMTLSBootstrap"},{"file":"go/internal/config/freeze_test.go","pattern":"func FuzzFrozenSourceDoesNotFollowCallerMutation"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem compilation_reply_keeps_registered_original"},{"file":"crates/governance/src/catalog/admission.rs","pattern":"pub struct ProducerCatalog"},{"file":"crates/governance/src/catalog/client.rs","pattern":"pub fn submit"},{"file":"crates/governance/tests/unit/catalog.rs","pattern":"changed_source_observations_and_fresh_names_cannot_select_original"},{"file":"crates/server/src/governance_owner.rs","pattern":"pub fn publish_producers"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"oldCatalogObservationStillCannotPublishThroughNewFenceTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"producer_selection_keeps_all_original_fields"},{"file":"crates/server/src/governance_owner.rs","pattern":"pub async fn start_governance"},{"file":"crates/server/src/grpc.rs","pattern":"pub async fn serve_grpc_with_runtime"},{"file":"crates/server/tests/unit/governance_owner.rs","pattern":"shared_owner_schedules_preserve_cleanup_and_terminal_admission"},{"file":"crates/server/tests/integration/governance_owner.rs","pattern":"actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"lateFactoryActivationCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_owner_join_preserves_cleanup"},{"file":"crates/governance/src/scheme_input/records.rs","pattern":"pub fn root_source"},{"file":"crates/governance/src/scheme_input/values.rs","pattern":"fn bytes"},{"file":"crates/governance/src/host/client.rs","pattern":"pub fn source_lane"},{"file":"crates/governance/src/host/owner.rs","pattern":"pub fn run"},{"file":"crates/governance/tests/unit/host.rs","pattern":"cancelled_running_work_keeps_its_slot_until_natural_return"},{"file":"crates/governance/tests/unit/host.rs","pattern":"active_compiler_observes_both_request_and_owner_cancellation"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSourceCancellationDrainsSchemeOwner"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"checkThenSendCloseRaceCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_host_delivery_requires_open_gate"},{"file":"crates/governance/src/binding.rs","pattern":"pub struct SourceExpectation"},{"file":"crates/governance/tests/unit/binding.rs","pattern":"coherent_replacements_cannot_change_original_content"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"unsafeSelfConsistentReplacementWitness"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"coherent_replacement_cannot_redefine_original"},{"file":"crates/governance/build.rs","pattern":"run_package_main"},{"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeQualificationStaysWithPreparedSchemeOwner"},{"file":"t/gateway-source-test.ss","pattern":"SDK field symbols and identifier strings cannot be interchanged"},{"file":"crates/governance/src/scheme.rs","pattern":"pub fn materialize_source"},{"file":"crates/governance/tests/integration/scheme_vm.rs","pattern":"actual_aa_capture_materializes_owned_data_before_vm_cleanup"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run unsafeEncodedBlobWitness"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem encoded_blob_cannot_claim_typed_capture"},{"file":"scheme/gateway/capture.ss","pattern":"Gateway capture requires one source emission"},{"file":"scheme/gateway/func.ss","pattern":"def \\(capture-governed-gateway"},{"file":"t/gateway-source-test.ss","pattern":"native PBT requires one completed emission"},{"file":"t/gateway-source-test.ss","pattern":"a late inherited sink cannot replace an active next capture"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run ignoredCaptureFuseCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem caught_duplicate_cannot_clear_capture_fuse"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"},{"file":"scheme/governance/capture.ss","pattern":"def \\(governance-profile-snapshot"},{"file":"t/governance-test.ss","pattern":"native PBT preserves every original assessment binding"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_assessment_snapshot_cannot_reuse_boundary"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run coordinatedLiveProfileLabelsCannotReplaceOriginalCaptureTest"},{"file":"scheme/gateway/func.ss","pattern":"assq 'open-patterns"},{"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"},{"file":"scheme/governance/types.ss","pattern":"def GovernanceAssessmentContext"},{"file":"scheme/gateway/func.ss","pattern":"same-node-set?"},{"file":"t/gateway-source-test.ss","pattern":"a false Governance assessment cannot emit a source handoff"},{"file":"t/governance-test.ss","pattern":"a typed ready assessment cannot omit an original blocking threat"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityChangedCompiledSourceCannotRecoverTest"},{"file":"scheme/policy/func.ss","pattern":"project-policy profile"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"},{"file":"t/integration/governed-control-test.ss","pattern":"def governed-control-test"},{"file":"go/internal/config/bundle_test.go","pattern":"func TestBundleRejectsSelectionAndCommitmentSubstitution"}]},{"id":"SourceStartupObservation","witnesses":[{"file":"scheme/gateway/provider-program.ss","pattern":"call-with-module-source-operation-measurement"},{"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeVerificationUsesOnlyPublicPackageEntries"},{"file":"crates/governance-build/src/program.rs","pattern":"build_program_archive_with_contract"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run releaseTagCannotRebaseCapturedSourceCounterexampleTest"},{"file":"go/internal/devrunner/retention_test.go","pattern":"func TestSchemePreparationFailureKeepsOriginalCutWithoutAmbientReceipt"},{"file":"go/internal/devrunner/retention_test.go","pattern":"func TestLateCleanupFailureCannotRetainPassingReceipt"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_preparation_cut_cannot_rebase_boundary","declaration":"Weaver.PolicyBridge.changed_preparation_cut_cannot_rebase_boundary"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run changedPackageMetadataCannotRebaseSnapshotTest"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run stalePreparationReceiptCounterexampleTest"},{"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"},{"file":"go/internal/controlplane/deployment.go","pattern":"trace\\(\"authority-reconciled\"\\)"},{"file":"scheme/gateway/func.ss","pattern":"source-selection-loaded"},{"file":"scheme/gateway/func.ss","pattern":"source-module-view-loaded"},{"file":"scheme/gateway/func.ss","pattern":"source-contracts-checked"},{"file":"scheme/gateway/func.ss","pattern":"source-advisory-derived"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"status=failed drain_ns"},{"file":"crates/governance/src/host/owner.rs","pattern":"scheme-owner-drop-begin"},{"file":"t/fixtures/governed-control.ss","pattern":"fixture-module-ready"},{"file":"go/dev/provider_control_test.go","pattern":"These unauthenticated diagnostics never replace readiness or exit checks"},{"file":"crates/governance-build/src/tooling.rs","pattern":"fn bind_package_sources"},{"file":"crates/governance-build/tests/unit/package_sources.rs","pattern":"fn native_package_inputs_follow_the_selected_store_without_overwriting_sources"}]},{"id":"PolicyCAbiIsInert","witnesses":[{"file":"scheme/policy/func.ss","pattern":"def \\(validate-policy-projection!"},{"file":"scheme/gateway/func.ss","pattern":"validate-policy-projection! projection"},{"file":"t/policy-test.ss","pattern":"real Rust preflight refuses cross-document syntax assembly"},{"file":"t/policy-projection-test.ss","pattern":"every named document precedes aggregate validation"},{"file":"crates/policy-ffi/tests/unit/validation.rs","pattern":"fn aggregate_validity_does_not_establish_complete_source_documents"},{"file":"crates/policy/tests/unit/decisions.rs","pattern":"fn default_deny_forbid_and_evaluation_error_are_fail_closed"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem incomplete_policy_document_cannot_admit"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run aggregateOnlyPolicyValidationCounterexampleTest"},{"file":"scheme/policy/source-bytes.ss","pattern":"def \\(cedar-source-utf8"},{"file":"t/policy-test.ss","pattern":"native PBT checks Unicode source bounds before the C ABI"},{"file":"crates/policy-ffi/tests/unit/abi.rs","pattern":"fn unicode_byte_limits_apply_to_each_actual_abi_region"},{"file":"crates/policy-ffi/src/abi.rs","pattern":"pub unsafe extern \"C\" fn weaver_policy_validate_v1"},{"file":"scheme/policy/cedar-ffi.ss","pattern":"def-C-lambda policy-validate/raw"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authoritySourceCommitNeverSendsTest"}]},{"id":"ControlActivationAcknowledgment","witnesses":[{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsStagingReplyLossAndRestart"},{"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlPublicationReplyLossCannotActivateOrRebase"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityLostReplyCannotActivateTest"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"}]},{"id":"ControlStreamRecoveryBinding","witnesses":[{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPartialRequestAndRestart"},{"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlCompleteStreamsShareBudgetAndRejectSDKRetry"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem profile_recovery_retains_original_hold"}]},{"id":"WorkspaceBenchmarkCoverage","witnesses":[{"file":"go/internal/devrunner/benchmark_test.go","pattern":"func TestBenchmarkEvidenceRequiresEveryCase"},{"file":"go/dev/workspace_test.go","pattern":"func TestCargoWorkspaceAndDevelopmentGates"},{"file":"crates/broker/benches/gateway.rs","pattern":"fn guarded_provider"},{"file":"go/dev/provider_bench_test.go","pattern":"func BenchmarkGatewayInspect"}]},{"id":"DurableRangeProgressJoin","witnesses":[{"file":"crates/ledger/src/stream_progress.rs","pattern":"fn message"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_message_cursor_cannot_hide_consumed_range"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_progress_cannot_release_old_writer_or_connection"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run restoredUnknownProjectionBlocksAdmissionTest"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run unknownResetDuplicatesRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unresolved_tail_blocks_admission","declaration":"Weaver.StreamingExecution.RangeProgress.unresolved_tail_blocks_admission"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem changed_progress_cannot_execute","declaration":"Weaver.StreamingExecution.RangeProgress.changed_progress_cannot_execute"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem joined_execution_preserves_safety","declaration":"Weaver.StreamingExecution.RangeProgress.joined_execution_preserves_safety"}]},{"id":"TursoAdmissionAtomicity","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"pub fn begin"},{"file":"crates/ledger/src/exposure_manifest.rs","pattern":"fn verified_members"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn failed_commit_releases_writer_and_poisoned_session_cannot_reenter"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn duplicate_claim_members_cannot_be_normalized_out_of_recovery"},{"file":"go/dev/workspace_test.go","pattern":"func TestProjectArchitectureStorageUsesMRRDataTursoOnly"},{"file":"dev/proofs/quint/TursoAdmission.qnt","pattern":"run tornCommitRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem storage_step_retains_admission_safety","declaration":"Weaver.RuntimeAdmission.Persistence.storage_step_retains_admission_safety"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem committed_consume_survives_reply_loss_and_restart","declaration":"Weaver.RuntimeAdmission.Persistence.committed_consume_survives_reply_loss_and_restart"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem commit_itself_does_not_send","declaration":"Weaver.RuntimeAdmission.Persistence.commit_itself_does_not_send"}]},{"id":"BoundedAdvisoryDerivation","witnesses":[{"file":"scheme/gateway/derivation.ss","pattern":"def \\(make-gateway-derivation"},{"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-gateway"},{"file":"t/gateway-derivation-test.ss","pattern":"generated source replacements agree with graph traversal and fresh results"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run derivedAdviceCannotChangeImageOrSpendTest"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run adviceAsOriginalCounterexampleTest"}]},{"id":"SessionWorkflowFrontier","witnesses":[{"file":"scheme/gateway/program.ss","pattern":"def \\(hard-fact-affected"},{"file":"go/dev/provider_hard_fact_test.go","pattern":"func TestProviderControlHardFactWithdrawalRestartAndABA"},{"file":"scheme/gateway/func.ss","pattern":"def \\(session-workflow-path"},{"file":"crates/server/src/governance_deployment.rs","pattern":"admits_session_workflow"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"fn bind_winner"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn provider_workflow_rechecks_prepared_floor_and_frontier_before_one_reservation"},{"file":"crates/server/src/session_workflow.rs","pattern":"async fn run_session_workflow"},{"file":"crates/server/src/single_provider.rs","pattern":"SessionTopology::prepare"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionWorkflowAutomaticallyResumes"},{"file":"scheme/gateway/func.ss","pattern":"def \\(governor-ready-steps"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"pub fn observe_workflow"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_workflow_observation"},{"file":"crates/governance/src/host/owner.rs","pattern":"cut_sha256=.*ready_sha256="},{"file":"crates/governance/src/program/compiler.rs","pattern":"topology_binding"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn governor_indices_reject_stale_binding_and_foreign_node"},{"file":"crates/server/src/session_workflow.rs","pattern":"DerivationOutput::Indices"},{"file":"crates/server/src/single_provider.rs","pattern":"topology.preopen"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn pack_governor_facts"},{"file":"t/gateway-governor-retained-test.ss","pattern":"packed facts are complete and bounded by the live binding"},{"file":"t/gateway-governor-retained-test.ss","pattern":"a compact cut must name the current binding"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"Governor transport %d expected"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched inner-join cut_sha256="},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched outer-join cut_sha256="},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionDAGConcurrentJoinAndRecovery"},{"file":"crates/ledger/src/provider_workflow_choice.rs","pattern":"fn record_result"},{"file":"go/dev/provider_workflow_choice_test.go","pattern":"func TestProviderControlSessionChoiceFromReleasedResult"},{"file":"crates/ledger/src/provider_workflow_nested.rs","pattern":"fn load"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn nested_workflow_rejects_stale_decision_and_keeps_winner_after_reopen"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSessionNestedChoiceAndParallelRecovery"},{"file":"scheme/gateway/func.ss","pattern":"WEAVER_TEST_GOVERNOR_CHANGED_SOURCES"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"unexpected Governor source replacement"},{"file":"crates/governance/src/host/client.rs","pattern":"weaver-governor-roundtrip"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"Governor roundtrip phases do not cover the call"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider_metering_with_deployment"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"a new frontier transaction must read the current deployment"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"prepare\\(tx, &proposal.predecessors, plan, current\\)"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn rooted_governor_indices_preserve_full_width_binding_and_all_64_candidates"},{"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-retained-governor-program"},{"file":"t/gateway-governor-retained-test.ss","pattern":"prepared nested rules agree with full fresh snapshots under replacement"},{"file":"t/gateway-governor-retained-test.ss","pattern":"prepared nested rules preserve source budget rejection and recovery"}]},{"id":"RustSchemeRuntimeBoundary","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"RustSchemeRuntimeBoundary"}]},{"id":"CloudAdapterAuthorityBoundary","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"CloudAdapterAuthorityBoundary"},{"file":"prod/kubernetes/provideravailability.crd.yaml","pattern":"kind: ProviderAvailability"},{"file":"prod/kubernetes/provideravailability.rbac.yaml","pattern":"resources: \\[provideravailabilities/status\\]"},{"file":"crates/server/src/kubernetes.rs","pattern":"async fn reconcile\\("},{"file":"crates/ledger/src/hard_fact.rs","pattern":"pub fn inspect_fact_feed\\("},{"file":"go/dev/provider_kubernetes_test.go","pattern":"func TestProviderKubernetesAvailability\\("}]},{"id":"GoIntegrationLeverage","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"GoIntegrationLeverage"}]},{"id":"SchemeSourceComposition","witnesses":[{"file":"scheme/gateway/provider-source.ss","pattern":"def \\(compose-provider-configuration"},{"file":"scheme/gateway/compiled.ss","pattern":"weaver_compose_source_v1"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn composition_uses_scheme_then_rust_seals_the_exact_original"},{"file":"crates/server/src/governance_deployment.rs","pattern":"from_configuration_with"},{"file":"go/internal/controlplane/source_compile.go","pattern":"config.CloneArtifact"},{"file":"t/gateway-source-test.ss","pattern":"ASCENT routing filters modules"},{"file":"go/internal/controlplane/gateway.go","pattern":"composeSourceBundle"},{"file":"go/internal/controlplane/provider_catalog.go","pattern":"func \\(g \\*Gateway\\) composeCatalog"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSchemeCompositionRevocationAndRestart"},{"file":"crates/governance/src/composition.rs","pattern":"pub fn validate_selected"},{"file":"crates/governance/tests/unit/configuration.rs","pattern":"fn source_composition_cannot_seal_a_self_consistent_scope_substitution"}]},{"id":"AdvisorySourceComposition","witnesses":[{"file":"crates/server/src/grpc.rs","pattern":"async fn compose_source"},{"file":"crates/governance/src/host/client.rs","pattern":"pub async fn compose"},{"file":"go/dev/provider_module_routing_test.go","pattern":"operation caller entered semantic composition"},{"file":"go/internal/controlplane/provider_catalog_test.go","pattern":"func TestCatalogCompositionCoalescesFourRequests"},{"file":"crates/broker/tests/unit/https_transport.rs","pattern":"fn provider_endpoint_guard_preserves_anthropic_source_path_constraints"}]},{"id":"DirectRustOperationIngress","witnesses":[{"file":"go/internal/controlplane/deployment.go","pattern":"func PrepareFromEnv"},{"file":"go/dev/controlref/main.go","pattern":"action := controlplane.PrepareFromEnv"},{"file":"crates/server/src/grpc_provider.rs","pattern":"operation_key_only"},{"file":"crates/server/src/single_provider.rs","pattern":"fn operation_plan"},{"file":"crates/server/src/provider_oauth.rs","pattern":"direct ingress cannot supply relay evidence"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderRustDirectPreparedOperationWithoutGoRelay"}]},{"id":"SourceBoundOperationPreparation","witnesses":[{"file":"crates/contracts/src/provider_routing.rs","pattern":"pub enum ProviderOperationScope"},{"file":"crates/ledger/src/provider_routing.rs","pattern":"pub fn register_provider_source"},{"file":"crates/ledger/src/provider_routing.rs","pattern":"pub fn register_routed_task"},{"file":"crates/server/src/source_owner.rs","pattern":"struct OperationResolver"},{"file":"go/dev/provider_module_routing_test.go","pattern":"func TestProviderRustDirectCatalogSelection"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderRustDirectFilePreparation"}]}] diff --git a/docs/10-19-llm-gateway/10-routing-and-inference/10.01-llm-gateway-and-routing.org b/docs/10-19-llm-gateway/10-routing-and-inference/10.01-llm-gateway-and-routing.org index a31f4a78..5e78788f 100644 --- a/docs/10-19-llm-gateway/10-routing-and-inference/10.01-llm-gateway-and-routing.org +++ b/docs/10-19-llm-gateway/10-routing-and-inference/10.01-llm-gateway-and-routing.org @@ -499,7 +499,7 @@ and [[https://docs.litellm.ai/docs/proxy/architecture][LiteLLM request architect ** Import external provider configuration -Run =weaver-import-provider json|yaml LITELLM_FILE REVIEW_JSON= to emit +Run =weaver-server import-provider json|yaml LITELLM_FILE REVIEW_JSON= to emit the existing catalog proposal record on stdout. The review manifest is JSON with a =parent= digest and =bindings= keyed by the external model alias. Each binding has a concrete Weaver =plan=, an inert diff --git a/docs/50-59-research-program/59-provider-rpc/59.00-index.org b/docs/50-59-research-program/59-provider-rpc/59.00-index.org index 12485e2a..d59dc99b 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.00-index.org +++ b/docs/50-59-research-program/59-provider-rpc/59.00-index.org @@ -142,7 +142,7 @@ It does not introduce another permission or transport owner. |-----------+------------------------------| | Go routing | =go/internal/routing=: source-bound request and ordered route proposal | | Scheme semantics | =scheme/=: reusable functions and Agentic AI Lab Governance/Governor POO values; current delivery freezes a task/plan artifact through inert Rust Policy C FFI | -| Go control service | =go/cmd/weaver-control=: acknowledged source activation, frozen routing and authenticated streaming proxy | +| Source preparation | =weaver-server prepare=: authenticated source activation. =go/dev/controlref= preserves the old proxy for reference controls. | | Go RPC client | =go/internal/gatewayclient=: explicit mTLS, no application retry, sequence and receipt checks | | Shared wire contract | =proto/gateway/v1/gateway.proto=: typed proposals, roles, observations and encoding choice | | Rust contracts | =crates/contracts=: immutable provider commitments and closed native event/outcome types | diff --git a/docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2 b/docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2 index 1003e398..d78c87b8 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2 +++ b/docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2 @@ -53,24 +53,26 @@ vars: { d2-config: { data: { figure: |json "model": "dev/sysml/ResearchReaderViews.sysml", "model0": "Project.sysml", "model1": "dev/sysml/AdmissionReaderViews.sysml", - "model10": "dev/sysml/FloorReaderViews.sysml", - "model11": "dev/sysml/GatewayArchitecture.sysml", - "model12": "dev/sysml/PolicyEvidenceDesign.sysml", - "model13": "dev/sysml/ProviderRpc.sysml", - "model14": "dev/sysml/ReaderDesigns.sysml", - "model15": "dev/sysml/ResearchReaderViews.sysml", - "model16": "dev/sysml/StoragePersistence.sysml", - "model17": "dev/sysml/StreamingExecution.sysml", - "model18": "dev/sysml/WeaverExecution.sysml", - "model19": "dev/sysml/ZeroTrustRefinement.sysml", - "model2": "dev/sysml/ArchitectureReaderViews.sysml", - "model3": "dev/sysml/ArchitectureViews.sysml", - "model4": "dev/sysml/AssuranceReaderViews.sysml", - "model5": "dev/sysml/AttemptReaderViews.sysml", - "model6": "dev/sysml/AuthorityReaderViews.sysml", - "model7": "dev/sysml/ControlActivation.sysml", - "model8": "dev/sysml/CorrespondenceReaderView.sysml", - "model9": "dev/sysml/ExecutionReaderViews.sysml", + "model10": "dev/sysml/CorrespondenceReaderView.sysml", + "model11": "dev/sysml/ExecutionReaderViews.sysml", + "model12": "dev/sysml/FloorReaderViews.sysml", + "model13": "dev/sysml/GatewayArchitecture.sysml", + "model14": "dev/sysml/PolicyEvidenceDesign.sysml", + "model15": "dev/sysml/ProviderRpc.sysml", + "model16": "dev/sysml/ReaderDesigns.sysml", + "model17": "dev/sysml/ResearchReaderViews.sysml", + "model18": "dev/sysml/StoragePersistence.sysml", + "model19": "dev/sysml/StreamingExecution.sysml", + "model2": "dev/sysml/ArchitectureEvolution.sysml", + "model20": "dev/sysml/WeaverExecution.sysml", + "model21": "dev/sysml/ZeroTrustRefinement.sysml", + "model3": "dev/sysml/ArchitectureReaderViews.sysml", + "model4": "dev/sysml/ArchitectureViews.sysml", + "model5": "dev/sysml/AssuranceReaderViews.sysml", + "model6": "dev/sysml/AttemptReaderViews.sysml", + "model7": "dev/sysml/AuthorityReaderViews.sysml", + "model8": "dev/sysml/ControlActivation.sysml", + "model9": "dev/sysml/ControllerObjectLifecycle.sysml", "proof0": "dev/proofs/lean/StreamingExecution.lean", "sdkCapture": "dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json" }, @@ -80,12 +82,14 @@ vars: { d2-config: { data: { figure: |json "modelRefs": [ "Project.sysml", "dev/sysml/AdmissionReaderViews.sysml", + "dev/sysml/ArchitectureEvolution.sysml", "dev/sysml/ArchitectureReaderViews.sysml", "dev/sysml/ArchitectureViews.sysml", "dev/sysml/AssuranceReaderViews.sysml", "dev/sysml/AttemptReaderViews.sysml", "dev/sysml/AuthorityReaderViews.sysml", "dev/sysml/ControlActivation.sysml", + "dev/sysml/ControllerObjectLifecycle.sysml", "dev/sysml/CorrespondenceReaderView.sysml", "dev/sysml/ExecutionReaderViews.sysml", "dev/sysml/FloorReaderViews.sysml", @@ -201,11 +205,11 @@ vars: { d2-config: { data: { figure: |json "modelSource": { "ref": "sdkCapture", "view": "WeaverResearchReaderViews::rpcCore", - "modelHash": "1e5a9bb646c6e0f7676306f3a8bbf9b549a682c0d31fb9b9053fa2523b6be33d", + "modelHash": "116cd33cb1473e7f17e398a7fe55b25f4f2dab261c144fba9b09948e33684f62", "portProjection": "owner", "labels": { "n0": "Governed config\nTyped Scheme or data", - "n1": "Go control RPC\nCarry the bound proposal", + "n1": "Rust source RPC\nCarry the bound proposal", "n2": "Rust admission\nCheck Cedar and claim", "n3": "Provider I/O\nSend the exact request", "n4": "Guarded stream\nRelease under current Policy", diff --git a/docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.png b/docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.png index 004b4ebf05029a6edf006546b5507b74bda32c9a..ecb225fcba61f7aa992eeae5cba62c95a4945ce1 100644 GIT binary patch delta 61157 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 z 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

MZV`iu=mbJ(81k5ifo4i3zjD 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ƫt;@e-x0;$QD+l5c(2#gblg6EZ`dXxGOmXfY#BWt z0X& zuY*C{^FpIIHPGYe#%2Be3rv*5)<}NC36s^WNpsXx4WlK1WKvQhWJpE-1hd0S&7k>1 z`5w1OMxbi80oSF6_i^@VW2$Z=e9k9@J{m8QJf~l8G0quZX4)Avi1%=@6OiQa=l?TG zTQ~I~m4l$1o)|AE1x>Ay|7_m^>n^HBcrPhIoJ?Z}cS~x|YeOlX#jgpn_e<-qhIjobZ6Id<^6I(U-iIx0?mlJFl?C&5SH;&QF|9TNo6! zUy>lEKK#-|(EBGR`=&E^*c?$L$gj_%67U=eM*&remxvUl?{dE0Mjs(qsjmS)ZR{7- z;$rw~j8TyqZ3$h!m{5tb3Y@@1S$cv3A{rdjo=CFks;0^ecQwyUl+DSuO(;&9>0$Y^ zAu?XwD{L$3CX6^;DuJawu z?#VcY9e%Q&UKBHmKg?lMBl9Xfm5yEcSR${b1rqk^p=$&@{-j^*#O~(AwHaYU`7Lf` z-O%iXaRl^irj>eNL@~3FP$tF%W8MQ>*UX;rWhVRHI7+CtG-OgpPcMcW+GxElzdb8ymTxaHdmhU;Pug9xkMDh7hS6l7tPSTgQ3;>|LTUqu3 zb^eI)Z*{=vX1Kt#P|mkVx>IWmc$lf5t^_P|Wba45yRPITFZlpx;`32*bILSrWIEZW zdTmQU2s>Rn+|u%xFVf%&cgS!i?J$<_W{JtK1yb=9vAf02aA0ez>f zZd(%~OZUEhy)BViyT3X)!M2Tg3~Dz@F9jBQk0YG0F-)jO4UD+}i+>fVHwX?MmgT+o z_;CsKS{hU~M;YricKs{yz;PVYuMRqi+>S}JEDG)QM1V$O+!1rnJN6d%|Fp}qyb8F3 z;(8El!D|s`A!o{KpCUjb-M=bFs-EEB;2NF+nYITrC3xORa~IT3@R!1Q{s0TeKK^fq z5a55F|L>11@T=~Z8^MM!#Qg6c!2iDJ|Cf?B|F;$XpIV$k7#PmZF5V~tqunr^|FygN aoxy(UVcX7l(y#7i(ALmb$3A}k_P+ow{Pc_f delta 61140 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

=yjB-&G@G@FmuEv0|E|+^;meblwuxyr+<_lQmH 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 ay?|wt;N~Qpg@AW1yjIpyDt`I)-~R)r)e}en diff --git a/docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.svg b/docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.svg index 16a77726..61b2ba1f 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.svg +++ b/docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.svg @@ -30,14 +30,16 @@ SPDX-FileComment: Weaver-authored diagram; embedded third-party fonts and marks .scene-title{font-size:26px}.scene-detail{font-size:26px}.scene-group-title{font-size:26px} @font-face{font-family:"Kalam";font-style:normal;font-weight:400;src:url(data:font/woff2;base64,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) format('woff2')} -@font-face{font-family:"Kalam";font-style:normal;font-weight:700;src:url(data:font/woff2;base64,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) format('woff2')}{"renderer":{"package":"@deterministic-engineering/render","version":"1.0.0","icons":{"agent":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","agent-request":"4efdd12166f2dd11f0269537588bdf4c092a8207f6d3aed7f69b324b5457a390","authentication":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","authorization":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","bounded-write":"ec844639440fe3fd3a5c7258bce663d7c96c6ffce3d422680f649ec1f3e4cee5","budget":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","budget-ledger":"c21b8727507b7ca0e1300b34c4613a9295ce12d424f5aa1486bf2f955aa45867","capture":"a647d42aa11f4e5e85d0bbf66f483f57f3c4ba3a9536362ed0eaaaae10a89cee","catalog":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","claim":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","decision":"3535642a5b613372c3fd374151ec90aafa19b64b2d33d10b19162cad07a35c7a","document":"0bf9674a401262da8a646305cab00006954721c07765b9962e0dee1c31d560f7","evidence":"0a91b169aaa644829a054cbb94194efffaf4298f2b6f8fa8c6ec2b7b413a1766","go":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","history":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","kubernetes":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","ledger":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","library":"df474fa36a74016b79236fff58a980a8c18c682d1866211776e349a0eb4b2979","message":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","model":"0cfd1f9ed3873f556ace725a7b6a251ebe75d7d976567699276f34df36b2443b","model-catalog":"462cd80fcfda09b55dbd56ed86421393591ac22d54feb60dec9b72858e7380a2","model-provider":"f9bc33c731a1c6da16ba2e5cc95cb84e65a580b9f986b1b639fcdc4355a8b790","obligation":"e76f4d34a7190400446c89e4e7d187762b885808a64a00c99455599d902570c5","pending":"cca7589bc3b1dcdebacb867c6836c6fc166257f05823555a268354ff9bfac00c","permission-check":"3ae75b575dfbb7d84fe6b215f72b28c3489715c72d9314be84f1e4a766d3db28","policy":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","provider":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","publication":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","question":"dbf231e1568dc37189d5674d73c4bfc58a17eb8ada579b3f03bf2813d33c56f4","recovery":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","reference":"3814c570f79ab294252c36530de464c9364814b797afb862d9c62e728a8660fc","route-choice":"b6060f37795d5b078cfb8d09e9b3ec2053068935416a5c5c6f6c600d3b9dbf7b","routine":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","routing":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","rust":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","selection":"82b4ab6faf195fea0a891c35268e61c186e93e7c6a9d7967a4f6a73dbf25ae7f","stream":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","task-contract":"4da0bd2fd156b69dba5791f558d4524901401707972dbc2fea8f2aab29dd3263","telemetry":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","unknown":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","unknown-hold":"6e243f03d4cdb79637f60d268aa4402d4963218adc9e3c4f9f64ebdb99e3c437","writer":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e"}},"design":{"audience":"Gateway design and runtime reviewers","medium":"GitHub at 830 CSS pixels","message":"Rust owns final admission and response release.","questionRefs":["q1"],"requiredSubjects":["n0","n1","n2","n3","n4","n5"],"requiredRelations":[],"focalSubjects":["n2"]},"evidence":[],"layout":"model-view","presentation":{"illustrations":{"n1":"route-choice","n2":"permission-check","n3":"model-provider"},"objectRows":[["n0","n1","n2"],["n3","n4","n5"]],"notation":"objects","options":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.layered.spacing.nodeNodeBetweenLayers":"27","elk.spacing.nodeNode":"16"},"icons":{"n0":"routine","n1":"routing","n2":"authorization","n3":"provider","n4":"stream","n5":"telemetry"},"roles":{},"edgeLabels":true,"graph":{"id":"declared-reading-order","children":[{"id":"n0","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n1","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n2","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n3","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n4","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n5","layoutOptions":{"elk.partitioning.partition":"1"}}],"layoutOptions":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.layered.spacing.nodeNodeBetweenLayers":"27","elk.partitioning.activate":"true","elk.spacing.nodeNode":"16"}},"textColumns":22},"drawing":{"mode":"sketch","options":{"seed":29,"roughness":1.3,"strokeWidth":1.2,"fillStyle":"hachure","hachureGap":9,"fillWeight":0.6}},"fonts":[{"family":"Kalam","weight":400,"source":"@fontsource/kalam/files/kalam-latin-400-normal.woff2"},{"family":"Kalam","weight":700,"source":"@fontsource/kalam/files/kalam-latin-700-normal.woff2"}],"palette":{"background":"#F6FAF9","surface":"#FFFFFF","ink":"#163C43","muted":"#496A70","border":"#C9DDDA","accent":"#087E82","secondary":"#946044","tint":"#E1F1EC","secondaryTint":"#F4EADA","onAccent":"#FFFFFF","supported":"#237653","pending":"#986320","conflict":"#A13E54"},"inputSHA256":"1a42475f0e830361a8a02c704c2da9e0467d2c9461a4cf81024e3725965d1d7e","model":{"subjects":[{"id":"n0","type":"part","sourceName":"WeaverResearchReaderViews::rpcCoreBoundary::p_config","label":"Governed config\nTyped Scheme or data"},{"id":"n1","type":"part","sourceName":"WeaverResearchReaderViews::rpcCoreBoundary::p_control","label":"Go control RPC\nCarry the bound proposal"},{"id":"n2","type":"part","sourceName":"WeaverResearchReaderViews::rpcCoreBoundary::p_admit","label":"Rust admission\nCheck Cedar and claim"},{"id":"n3","type":"part","sourceName":"WeaverResearchReaderViews::rpcCoreBoundary::p_provider","label":"Provider I/O\nSend the exact request"},{"id":"n4","type":"part","sourceName":"WeaverResearchReaderViews::rpcCoreBoundary::p_release","label":"Guarded stream\nRelease under current Policy"},{"id":"n5","type":"part","sourceName":"WeaverResearchReaderViews::rpcCoreBoundary::p_metrics","label":"Telemetry\nObserve bounded events"}],"relations":[{"id":"edge:0","src":"n0","dst":"n1","label":"configure","kind":"connection","fromPort":"n0.1","toPort":"n1.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:1","src":"n1","dst":"n2","label":"propose","kind":"connection","fromPort":"n1.1","toPort":"n2.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:2","src":"n2","dst":"n3","label":"mediate","kind":"connection","fromPort":"n2.1","toPort":"n3.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:3","src":"n3","dst":"n4","label":"stream","kind":"connection","fromPort":"n3.1","toPort":"n4.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:4","src":"n2","dst":"n5","label":"observe","kind":"connection","fromPort":"n2.1","toPort":"n5.0","srcArrow":"none","dstArrow":"none"}]},"modelSource":{"ref":"sdkCapture","modelHash":"1e5a9bb646c6e0f7676306f3a8bbf9b549a682c0d31fb9b9053fa2523b6be33d","view":"WeaverResearchReaderViews::rpcCore","portProjection":"owner","labels":{"n0":"Governed config\nTyped Scheme or data","n1":"Go control RPC\nCarry the bound proposal","n2":"Rust admission\nCheck Cedar and claim","n3":"Provider I/O\nSend the exact request","n4":"Guarded stream\nRelease under current Policy","n5":"Telemetry\nObserve bounded events"}},"modelTrace":{"modelHash":"1e5a9bb646c6e0f7676306f3a8bbf9b549a682c0d31fb9b9053fa2523b6be33d","requestedView":"WeaverResearchReaderViews::rpcCore","resolvedView":"WeaverResearchReaderViews::rpcCore","renderingSHA256":"1ad9f77dcbf5a7a4f65813304a75bb7b3c961fb4aa6fa1bfb0a7ff06709dd4ba","capturedRenderingJSON":"{\"modelHash\":\"1e5a9bb646c6e0f7676306f3a8bbf9b549a682c0d31fb9b9053fa2523b6be33d\",\"requestedView\":\"WeaverResearchReaderViews::rpcCore\",\"rendering\":{\"view\":\"WeaverResearchReaderViews::rpcCore\",\"kind\":\"interconnection\",\"stated\":\"render asInterconnectionDiagram\",\"nodes\":[{\"id\":\"n0\",\"kind\":\"part\",\"name\":\"WeaverResearchReaderViews::rpcCoreBoundary::p_config\",\"nameSynthesized\":false,\"type\":\"rpcCore_config\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n0.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":283,\"startCol\":9,\"endLine\":283,\"endCol\":40}},{\"id\":\"n1\",\"kind\":\"part\",\"name\":\"WeaverResearchReaderViews::rpcCoreBoundary::p_control\",\"nameSynthesized\":false,\"type\":\"rpcCore_control\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n1.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"},{\"id\":\"n1.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":284,\"startCol\":9,\"endLine\":284,\"endCol\":42}},{\"id\":\"n2\",\"kind\":\"part\",\"name\":\"WeaverResearchReaderViews::rpcCoreBoundary::p_admit\",\"nameSynthesized\":false,\"type\":\"rpcCore_admit\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n2.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"},{\"id\":\"n2.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":285,\"startCol\":9,\"endLine\":285,\"endCol\":38}},{\"id\":\"n3\",\"kind\":\"part\",\"name\":\"WeaverResearchReaderViews::rpcCoreBoundary::p_provider\",\"nameSynthesized\":false,\"type\":\"rpcCore_provider\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n3.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"},{\"id\":\"n3.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":286,\"startCol\":9,\"endLine\":286,\"endCol\":44}},{\"id\":\"n4\",\"kind\":\"part\",\"name\":\"WeaverResearchReaderViews::rpcCoreBoundary::p_release\",\"nameSynthesized\":false,\"type\":\"rpcCore_release\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n4.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":287,\"startCol\":9,\"endLine\":287,\"endCol\":42}},{\"id\":\"n5\",\"kind\":\"part\",\"name\":\"WeaverResearchReaderViews::rpcCoreBoundary::p_metrics\",\"nameSynthesized\":false,\"type\":\"rpcCore_metrics\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n5.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":288,\"startCol\":9,\"endLine\":288,\"endCol\":42}}],\"edges\":[{\"from\":\"n0\",\"to\":\"n1\",\"fromPort\":\"n0.1\",\"toPort\":\"n1.0\",\"label\":\"configure\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":289,\"startCol\":9,\"endLine\":289,\"endCol\":78}},{\"from\":\"n1\",\"to\":\"n2\",\"fromPort\":\"n1.1\",\"toPort\":\"n2.0\",\"label\":\"propose\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":290,\"startCol\":9,\"endLine\":290,\"endCol\":75}},{\"from\":\"n2\",\"to\":\"n3\",\"fromPort\":\"n2.1\",\"toPort\":\"n3.0\",\"label\":\"mediate\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":291,\"startCol\":9,\"endLine\":291,\"endCol\":76}},{\"from\":\"n3\",\"to\":\"n4\",\"fromPort\":\"n3.1\",\"toPort\":\"n4.0\",\"label\":\"stream\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":292,\"startCol\":9,\"endLine\":292,\"endCol\":77}},{\"from\":\"n2\",\"to\":\"n5\",\"fromPort\":\"n2.1\",\"toPort\":\"n5.0\",\"label\":\"observe\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":293,\"startCol\":9,\"endLine\":293,\"endCol\":75}}],\"columns\":[],\"rows\":[],\"notes\":[],\"notices\":[],\"shown\":[]}}","portProjection":"owner","nodes":[{"id":"n0","parent":"","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":283,"startCol":9,"endLine":283,"endCol":40}},{"id":"n1","parent":"","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":284,"startCol":9,"endLine":284,"endCol":42}},{"id":"n2","parent":"","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":285,"startCol":9,"endLine":285,"endCol":38}},{"id":"n3","parent":"","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":286,"startCol":9,"endLine":286,"endCol":44}},{"id":"n4","parent":"","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":287,"startCol":9,"endLine":287,"endCol":42}},{"id":"n5","parent":"","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":288,"startCol":9,"endLine":288,"endCol":42}}],"edges":[{"id":"edge:0","index":0,"from":"n0","to":"n1","fromPort":"n0.1","toPort":"n1.0","kind":"connection","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":289,"startCol":9,"endLine":289,"endCol":78}},{"id":"edge:1","index":1,"from":"n1","to":"n2","fromPort":"n1.1","toPort":"n2.0","kind":"connection","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":290,"startCol":9,"endLine":290,"endCol":75}},{"id":"edge:2","index":2,"from":"n2","to":"n3","fromPort":"n2.1","toPort":"n3.0","kind":"connection","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":291,"startCol":9,"endLine":291,"endCol":76}},{"id":"edge:3","index":3,"from":"n3","to":"n4","fromPort":"n3.1","toPort":"n4.0","kind":"connection","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":292,"startCol":9,"endLine":292,"endCol":77}},{"id":"edge:4","index":4,"from":"n2","to":"n5","fromPort":"n2.1","toPort":"n5.0","kind":"connection","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":293,"startCol":9,"endLine":293,"endCol":75}}]},"view":{"source":"docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2","title":"Separate control RPC from provider I/O","purpose":"workflow","kind":"routing","question":{"subjectRefs":["n2"],"ref":"q1","text":"How does the gRPC proposal become a bounded provider effect?","focusRefs":["model"]},"basis":{"captureRef":"docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2#design-view","modelRefs":["Project.sysml","dev/sysml/AdmissionReaderViews.sysml","dev/sysml/ArchitectureReaderViews.sysml","dev/sysml/ArchitectureViews.sysml","dev/sysml/AssuranceReaderViews.sysml","dev/sysml/AttemptReaderViews.sysml","dev/sysml/AuthorityReaderViews.sysml","dev/sysml/ControlActivation.sysml","dev/sysml/CorrespondenceReaderView.sysml","dev/sysml/ExecutionReaderViews.sysml","dev/sysml/FloorReaderViews.sysml","dev/sysml/GatewayArchitecture.sysml","dev/sysml/PolicyEvidenceDesign.sysml","dev/sysml/ProviderRpc.sysml","dev/sysml/ReaderDesigns.sysml","dev/sysml/ResearchReaderViews.sysml","dev/sysml/StoragePersistence.sysml","dev/sysml/StreamingExecution.sysml","dev/sysml/WeaverExecution.sysml","dev/sysml/ZeroTrustRefinement.sysml"],"obligationRefs":["proof0"],"evidenceRefs":[]}},"questions":[{"subjectRefs":["n2"],"ref":"q1","text":"How does the gRPC proposal become a bounded provider effect?","focusRefs":["model"]}],"references":{"model":"dev/sysml/ResearchReaderViews.sysml","model0":"Project.sysml","model1":"dev/sysml/AdmissionReaderViews.sysml","model10":"dev/sysml/FloorReaderViews.sysml","model11":"dev/sysml/GatewayArchitecture.sysml","model12":"dev/sysml/PolicyEvidenceDesign.sysml","model13":"dev/sysml/ProviderRpc.sysml","model14":"dev/sysml/ReaderDesigns.sysml","model15":"dev/sysml/ResearchReaderViews.sysml","model16":"dev/sysml/StoragePersistence.sysml","model17":"dev/sysml/StreamingExecution.sysml","model18":"dev/sysml/WeaverExecution.sysml","model19":"dev/sysml/ZeroTrustRefinement.sysml","model2":"dev/sysml/ArchitectureReaderViews.sysml","model3":"dev/sysml/ArchitectureViews.sysml","model4":"dev/sysml/AssuranceReaderViews.sysml","model5":"dev/sysml/AttemptReaderViews.sysml","model6":"dev/sysml/AuthorityReaderViews.sysml","model7":"dev/sysml/ControlActivation.sysml","model8":"dev/sysml/CorrespondenceReaderView.sysml","model9":"dev/sysml/ExecutionReaderViews.sysml","proof0":"dev/proofs/lean/StreamingExecution.lean","sdkCapture":"dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json"},"sourceSHA256":{"dev/d2/themes/assurance.d2":"f7723f53e005a68c803a38ce5c04cd733f46f4a2688fa4b17c66f9d5b308fe24","dev/d2/themes/data.d2":"19fceb46186892da02b763217963cc3ca2a35021219c0d353fdeec84604ddaee","dev/d2/themes/flow.d2":"1f13588619d0c8087c08d8afd023c4c0efe12726711c311e623eea3872726c1f","dev/d2/themes/routing.d2":"f185df198e7435d12b17b7b57b62dfc5795597d95eb926159ee13b448727bcce","dev/d2/themes/sequence.d2":"6e39472720dccc717f984c95b79570494b6ce3828b86227629841649e6c956e6","dev/d2/themes/state.d2":"f1a35cbca0f9cbb055ea9f793ba3dfb86e5fee4e462038ef3e72b94baa61d781","dev/d2/themes/system.d2":"b2a32ec6959ca5df9103c16454c4e34b758e061f850f7de6b619bcbc5fcf17a6","dev/d2/themes/vocabulary.d2":"add21e9b87eab485e5daabf6316fea44eb56b1007b70123f24b0e32e3357f744","dev/proofs/cedar/DomainMigrationComposition.lean":"c81a284bdf2006a1689cdadcc2c78442b3033774c2f103dd50a32c577ad4be77","dev/proofs/cedar/QualifiedReview.lean":"1ae16e06ad03a2906fa8c21dbeea1e3eb7700aa1e9359e64848dec65ccfd079f","dev/proofs/cedar/WeaverPolicyBridge.lean":"a9628a8123d504a34f64bf986feb4471325aa2b0ddc603d76b62632481eab67b","dev/proofs/cedar/ZeroTrustEnrichment.lean":"0c4b138843cc176c27d42d4a31177a3c12486b2d8ff124a6453e3d0922170884","dev/proofs/lean/ProviderRpc.lean":"e79d7639ac11220585e59e85dc5bec12b6717f7b51fb28fdcd62dc96d8fae38e","dev/proofs/lean/RuntimeAdmission.lean":"6111d4b9e93ebaa9f7cc44a55ed504c88c20c8d9de81e947a2e13b3f4a13b13c","dev/proofs/lean/SharedDomains.lean":"c45cba453b4271a7f8f87ded67217b8af0517d22fa1b1d5d81618c64644cc636","dev/proofs/lean/StreamingExecution.lean":"3fba798a7887a0b2ae29a7e3f0aaa3d7e2fb191e5f1f28109a4a73d28e27b776","dev/sysml/AdmissionReaderViews.sysml":"27ebc6c98ec3a1f7f9081e77a130953c3b646a1fdf6f1d6fc1fa6ed6376e9623","dev/sysml/ArchitectureReaderViews.sysml":"52ffbccbb17bd257e8ad9f4aa9f727c8ce0c00149e7d6738b82042ba06fdd0e3","dev/sysml/ArchitectureViews.sysml":"adbeeab4171045dc5dead2caf060cb4dbcd9c8dd5f914be993ab98d3eca0df37","dev/sysml/AssuranceReaderViews.sysml":"cd99fb7e9b23e08beac265bc832a8debee0dc1e1d318b0f64d5263519270e390","dev/sysml/AttemptReaderViews.sysml":"0d87cf71e15c26566422a6ddb5945fdb8add8af0484d9d024c32b97597675e21","dev/sysml/AuthorityReaderViews.sysml":"6fa25bd3a64e7f89987caec8e4773928be2cbea0a3c943299e536ca81978316d","dev/sysml/captures/WeaverAdmissionReaderViews-beneficiaryRegistration.json":"c032918360bf483ae1f405814b1e92cd0c9391a778df883a2243fe1d50ae7e3e","dev/sysml/captures/WeaverAdmissionReaderViews-bootstrapInvitation.json":"17073ea8d9f3da40647d233b400059d8dd0d4abc86cabff4e542e72e2b0d3bbc","dev/sysml/captures/WeaverAdmissionReaderViews-callerCustody.json":"975ed2715ebbe10406afef31f5cbed41a778039b75afc9c32c653e8e0533e1d9","dev/sysml/captures/WeaverAdmissionReaderViews-custodyPublication.json":"eb089628fdddad2d5f045b2c0f4bd77ca62a9b674224cf4a22f6bdee5317d726","dev/sysml/captures/WeaverAdmissionReaderViews-enrollmentCredential.json":"e9fd37134a25ec9812be1f3318fbd8c578f8cc350424f0400b7fa495959f9f29","dev/sysml/captures/WeaverAdmissionReaderViews-incarnationIssuance.json":"8a2f9ee448ac9e48d7e6935075c7b332259fa6d3b3319f8bdd03b2fc1cfc004b","dev/sysml/captures/WeaverAdmissionReaderViews-routineRouting.json":"0e0b20893ed9635dd8e20e55954645496c7ac46013178413095d9625f47b19a3","dev/sysml/captures/WeaverAdmissionReaderViews-sourceCustody.json":"1860e7fd0266fa0c80e6163ecf4631e604e7ff0dd1ed6466c200fb320f2569a6","dev/sysml/captures/WeaverAdmissionReaderViews-sourceJoin.json":"c55166d939a7d9858041e02cb1de512473d5853d26df29d0fedc314eeb9f00fe","dev/sysml/captures/WeaverAdmissionReaderViews-subjectAuthority.json":"64b8b0ccc3c62b9b631142bd5ff5d28900151adf51db08a4c10dc84ddd76caa2","dev/sysml/captures/WeaverArchitectureReaderViews-adapterBroker.json":"b34141293f261d69bcbd32dce349f629f07ece0375c22e8b0f31bfa939d95622","dev/sysml/captures/WeaverArchitectureReaderViews-anchorBroker.json":"592daccba731ab56628ee09c733f3d7f03cca31dc690ce81d69a10c7e7cb0d39","dev/sysml/captures/WeaverArchitectureReaderViews-anchorEgress.json":"b5ff8ed02f65cba74afb004154e159ecfebbdd16832f0b196cfe87c8735eba28","dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json":"6b67168d1fdd39dd1ff24f78877e37173191f827379485873ef42b216b08e25e","dev/sysml/captures/WeaverArchitectureReaderViews-codePolicy.json":"0d62625775b5780da1ce2934fcf1b9197eecce256ca203adc032cf7070829b37","dev/sysml/captures/WeaverArchitectureReaderViews-configPrefix.json":"3de87ca6e9db7f38989fe394703253e1db5de40d205ee9e13d27370af9f1282e","dev/sysml/captures/WeaverArchitectureReaderViews-driverCompletion.json":"faf32a3b87741d27d4c3e10b7c040b323260cdc5cfbb363379fb80bfa0e5eaaa","dev/sysml/captures/WeaverArchitectureReaderViews-fencing.json":"ee08c435ee5466598a95feadeadce64d25ab710e0c7e273df954caa67410cb1f","dev/sysml/captures/WeaverArchitectureReaderViews-gatePersistence.json":"d0887fc4e101deaea7f3788c462573b14355d22f3d83be5e693b9c37d2ac5dcd","dev/sysml/captures/WeaverArchitectureReaderViews-journalLifecycle.json":"e4a050cc314d2347d4d3682fbf696455707fa8644d8ecef434c559534bcfb5bc","dev/sysml/captures/WeaverArchitectureReaderViews-logicalObservation.json":"d0eb59627785a3a1e1b7182a162290c569d68e9ab6ecbf8fef870e01ae1f9b27","dev/sysml/captures/WeaverArchitectureReaderViews-manifest.json":"922cab9c9784df60877b590a1815b34228c26c6452a7eb1cb9c3db31460133ad","dev/sysml/captures/WeaverArchitectureReaderViews-migration.json":"10ba40fc4e772b106292818e86d8023dcc81860cd2092e4508799279138a6f5f","dev/sysml/captures/WeaverArchitectureReaderViews-policyExecution.json":"04e6f2a6b95d955c2ef054faf6f4e869eff56a16c13eeb94c48ce03b5dca3b88","dev/sysml/captures/WeaverArchitectureReaderViews-quorumPromises.json":"614c887183ab021b713e40b18a3cb82f25e60af6fa00481aa9cdcd9c9cde31de","dev/sysml/captures/WeaverArchitectureReaderViews-relationships.json":"3eca8149e8f1f30ce7c6b853c0d579684b8db7eed93ccff8a1f1eb8d8168b349","dev/sysml/captures/WeaverArchitectureReaderViews-settlementAnchor.json":"742b5388072eb493c6f4793aa54231466623ac27f19529223d7f33b991c39d80","dev/sysml/captures/WeaverArchitectureReaderViews-sharedBudget.json":"c0fc22ee8c78877b4fe91487ac4f95c4e7d05a71e251dd3deaa2265eaa896569","dev/sysml/captures/WeaverArchitectureReaderViews-sharedExposure.json":"35fb239ce8bea0cd55c2f52de52eb035f4bab2b5485b8e7582287474bc43abd6","dev/sysml/captures/WeaverArchitectureReaderViews-spentState.json":"ad19ec8c239c9f82b7b073b485a960ab498fcbfbd5148c90fb8e290113d026f4","dev/sysml/captures/WeaverArchitectureReaderViews-writerSettlement.json":"0bfe561678512fda1a44bf77473a59ee04360f3021bb5d5f9aed8884e1f1aa4b","dev/sysml/captures/WeaverArchitectureReaderViews-zeroAssurance.json":"5ab290cb43564718f9c0e991fa3c1112fafa74838780deceafad10ad12a1ecc4","dev/sysml/captures/WeaverAssuranceReaderViews-brokerQueue.json":"1bffc321a7ab072e84cb4b22eaa0060190736ffee31a43c4b35fb75b745753c9","dev/sysml/captures/WeaverAssuranceReaderViews-continuation.json":"28c8edc68fbf860c63b6dd3918dedf76064004df2aba7c1bd8f65773afb4df7b","dev/sysml/captures/WeaverAssuranceReaderViews-deviceEvidence.json":"678b5d32006e2cb4288495d242ebc0e5e80f739dbfb204e91d1bcd332bbed371","dev/sysml/captures/WeaverAssuranceReaderViews-gatewayHead.json":"130f4eb2e632248e6bbba7c6f34c58cc72d56a3f679776b680f540de20f20f96","dev/sysml/captures/WeaverAssuranceReaderViews-keySession.json":"4be65df864587275e959d2364b12d028235d0ab6d488d8dbc847561e849dce5b","dev/sysml/captures/WeaverAssuranceReaderViews-rangeRecovery.json":"504c83b6a3651f011771f776201c7b1d76138afd09be54d477ca9d3a3e25bd07","dev/sysml/captures/WeaverAssuranceReaderViews-signer.json":"27db88549f7f743ea60c73b71e37e37ffe542c69c4a7685a00944f4a9a739f8e","dev/sysml/captures/WeaverAttemptReaderViews-admission.json":"c845667f622701d0ddbf38c0c1af61c0e77cad7a9dec3a2738a5bfb81b776e74","dev/sysml/captures/WeaverAttemptReaderViews-outcome.json":"8f215e9cc05107dff8b3da34060ff9a0561ac9710d921991f86a034d8c386b4b","dev/sysml/captures/WeaverAuthorityReaderViews-attemptLedger.json":"6c389d951433962202990f82ef167235acb0319c02e1eb2d2a497eba36732821","dev/sysml/captures/WeaverAuthorityReaderViews-canonical.json":"a8c6a868371a81bd41c7d92001080fa908cf242f1dc9cb4a3807d118bf16cbd2","dev/sysml/captures/WeaverAuthorityReaderViews-multiKey.json":"6ccc723d7c18bdbf5dcf6e4ff71fb0eec181f15797482b8c3160b092b69dd592","dev/sysml/captures/WeaverAuthorityReaderViews-publication.json":"730aa60655e4aa3d3ec5562b12c47d7ed836034b6078ba114ae923f03522531c","dev/sysml/captures/WeaverAuthorityReaderViews-recoveryCAS.json":"ee6430c3109cde3de4c325dc840cf62bb0caab5a6f5caa014d3f4f027640dd65","dev/sysml/captures/WeaverAuthorityReaderViews-scope.json":"9c16143b95a35058aa3b5bcaa5bb8cbaedd21cff3f3be9c4f3f4a0d88deddb0b","dev/sysml/captures/WeaverCorrespondenceReaderView-correspondence.json":"3d1ca08f803def4648537a8c0544365ce4d0f3111632969e45c665f28e053203","dev/sysml/captures/WeaverExecutionReaderViews-accountCommit.json":"57b5afc0babad1a4daece90ed68ab8293d5374aba1e409f421aa823575adc562","dev/sysml/captures/WeaverExecutionReaderViews-admissionFloor.json":"9a5033aa8871a21c66f41330d36c1b0f5f9d8390ff7fd885ec7ea404cbb46226","dev/sysml/captures/WeaverExecutionReaderViews-appendHandoff.json":"b3d5a0bcdf95e52a2bd6e5ddee68a4cbb7db135b4ddb658250063b3699f36594","dev/sysml/captures/WeaverExecutionReaderViews-checkpoint.json":"920fa59556237f15d5313ede43ad6a0a7268be59a627f8083a701f8a6e3a5533","dev/sysml/captures/WeaverExecutionReaderViews-executionEvidence.json":"e04b9f763a56cbbf13413371be4a83d773693f2036e32c9db4fa087848fe416d","dev/sysml/captures/WeaverExecutionReaderViews-executorOffer.json":"d11d28bc736807c8d0364dad6f9668ac12a77cb395c29c86473bc28256942514","dev/sysml/captures/WeaverExecutionReaderViews-joinEnqueue.json":"8cb4cd55c378d7a622b2456def81613b3b44ff3b16be0079d81a52e150c25aef","dev/sysml/captures/WeaverExecutionReaderViews-manifestSwitch.json":"cf0e351a80367319c04c1cbb7ce283567852e11ba8ab9b00ded5f059b663c41e","dev/sysml/captures/WeaverExecutionReaderViews-resultProjection.json":"81cf7ed0eec3af4429db89c17634a7d735a6be3d42876d594c837ff230db1258","dev/sysml/captures/WeaverExecutionReaderViews-walActivation.json":"705d1f09677dcf28ae1bca177ee5aae3e589b77221ad1ca889f2064fa31a7b73","dev/sysml/captures/WeaverFloorReaderViews-floorOrdering.json":"8aa43a594e10be22f62b423b0a20561e3e1db198c5773413c8ba8ce3041c817e","dev/sysml/captures/WeaverFloorReaderViews-floorRecovery.json":"46fd2b8fbaec21683a6773946f024211151ba6fc5dbde9c4504e2a0970d7f6ac","dev/sysml/captures/WeaverResearchReaderViews-embeddedTooling.json":"6e85c9972d66392bb4f2f69c9dab18edd9ad514ab81464b5bbc71bf335f3081f","dev/sysml/captures/WeaverResearchReaderViews-floorTransport.json":"4d37e38648832c0e5a138469ff2664e1054c579e9d1087c7a03b0f161e28c079","dev/sysml/captures/WeaverResearchReaderViews-gerbilLifecycle.json":"00b0deae0d6d5a9bb3a13c50519644d25aab7261e02524072b6bf35f3b533172","dev/sysml/captures/WeaverResearchReaderViews-gxiLifecycle.json":"fd39c0bb16f1e4150258156a8684411d3c6cbfeb16bd9d4c757d74c5f729146f","dev/sysml/captures/WeaverResearchReaderViews-parentReplay.json":"b35651124c0cd02d80f1b1728a2b8a758f12947a77bd2a4ccdefacb76ae2d0b4","dev/sysml/captures/WeaverResearchReaderViews-profileBinding.json":"576272fce35d1266dbb0cdf6a490f07e79df1448ce13777b14463a7380745cc2","dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json":"1ad9f77dcbf5a7a4f65813304a75bb7b3c961fb4aa6fa1bfb0a7ff06709dd4ba","dev/sysml/captures/WeaverResearchReaderViews-runtimeAssets.json":"090f43fad22d6d6203bb9c3993c01378fbfe26bb0d38c224ab29aee02b257d2d","dev/sysml/captures/WeaverResearchReaderViews-semanticSlice.json":"07e91bc664ff3dce725fdc81fb53d42d9dedf03137a56215a791d70a0681641e","dev/sysml/captures/WeaverViews-architecture.json":"0eb28dd65702a601e8804d27cd7dc1d279bd4719a8153dcbe4e3b567c0fd30a0","dev/sysml/captures/WeaverViews-assurance.json":"75f373024582998109faca55f2aa67855ff8a675b7a79702beef0c826e2eae38","dev/sysml/captures/WeaverViews-contractRefinement.json":"2b5ff7cb278fc3a00c9c64b9a9b768b56ad2bf34b2df18d82b219c1856a61244","dev/sysml/captures/WeaverViews-execution.json":"d61366c9fd4fdfdb9b784a0a5caf2a35e168efa236037a529ab7aa1a2debabb8","dev/sysml/captures/WeaverViews-gateway.json":"498eeefacdb219de8a4aa69e3fb5653267b99bcd95a3d61009a50402e6eb63ea","dev/sysml/captures/WeaverViews-rangeRecovery.json":"459ba4e2376d21d2487f47a7e886dbecd5df71e166a3876fe29cb837b3f6f061","dev/sysml/captures/WeaverViews-routeExecution.json":"bae92275847a95a0c82d865fd93e1f3695d0c12e1eb3ca7817c60050890f8321","dev/sysml/captures/WeaverViews-routeSelection.json":"7aa5e25ad092a9ba35ab3d6b1e115a679cfdb557fb3073faf84976767d3d4cee","dev/sysml/captures/WeaverViews-storage.json":"176ee88f33e38104eea551582e55cfa17b3dcd2b769628ea6aa83fcc1c16b880","dev/sysml/captures/WeaverViews-streamAdmission.json":"a7a5870185e1676918922fc88ed2fff2b1abe259e65f5fcea7125987dc20b8fc","dev/sysml/captures/WeaverViews-zeroTrust.json":"8e50d7c70d6b786b576c365cd9fac514b8ef92bf2a0bf5ff48f79df6b66e048b","dev/sysml/ControlActivation.sysml":"78bc6792c3a64ee54210720d3d88c1984b5c876d3a0647b6829bf904a811014f","dev/sysml/CorrespondenceReaderView.sysml":"24b811c00528feaab3547d5db3b7fada290ff89478ac2be0a1d252d8ea1e5828","dev/sysml/ExecutionReaderViews.sysml":"88f690ed1fed91f63f7571d14bf5d7c1c8d14ee3b8d1d17ae333dfd7a6176df3","dev/sysml/FloorReaderViews.sysml":"93401ba5b2009dd54614f7e5aff81d91a20085efbb77b3a143726ffdea16592c","dev/sysml/GatewayArchitecture.sysml":"dbec3964b7873ed0633964b05d1ba1ee828050aed35a3066858d0c38893f2642","dev/sysml/PolicyEvidenceDesign.sysml":"6a7d738b004be62e7412ea68080944f8cb6fb3aea785258efaefc2efc1c4e0e6","dev/sysml/ProviderRpc.sysml":"46000a122f91081bc756a408859ffb64c4638ba7fc84360a9d7562de46f5e0c1","dev/sysml/ReaderDesigns.sysml":"4df8352980f9727b85a26533dc5ebfd67730540359d553a17d562574f3ea2529","dev/sysml/ResearchReaderViews.sysml":"cb10ed4ab79e911197834a8102e8a84986c567a358098e36d234d15b9c5acaec","dev/sysml/StoragePersistence.sysml":"b6b58b8802a557a7f3af787c2e7875be64865169ca3fd7e9973b13f6c3dc792d","dev/sysml/StreamingExecution.sysml":"d0d4d92300fba2b908ace30d9065cb2bac1d86f3b7c98219c1853a30f3110e85","dev/sysml/WeaverExecution.sysml":"12d87cfe55b53ad54ccef0c5b965c9a4cd19cefe2856fb7262396b967b920ffc","dev/sysml/ZeroTrustRefinement.sysml":"7cbec57110f03ed68469a1f49cb2046769516b09a6eb1b9433d866161bba6a82","docs/10-19-llm-gateway/10-routing-and-inference/10.02-llm-routing.d2":"513cad143cde846a9393bb5020dc4843caa1bb844204d3d0c13d1b5ada5efc70","docs/10-19-llm-gateway/10-routing-and-inference/10.05-route-execution.d2":"ea6130b51598910a59384943fa5d7cb1c74566ce1091f6414a6309c2ce9618ed","docs/10-19-llm-gateway/11-attempts-and-failover/11.02-attempt-ledger.d2":"5438329d7af60e9596b5fe4519b04a27a7c36ce1d1dc1aa5442db6df7167cd8e","docs/10-19-llm-gateway/12-semantic-contracts/12.02-semantic-contract.d2":"8560ac03652d2dfb8aeb7797c0e3b61031e49f9a3276d3207c8758a32037c530","docs/10-19-llm-gateway/13-authoritative-scope/13.02-authoritative-scope.d2":"e5950b420b85e30891bdb2264c7fad7ccd9ec9934b6175906d592d683b3a844c","docs/10-19-llm-gateway/14-registry-publication/14.02-registry-publication.d2":"9153743fc734fb044f94a4d22175fbe963f0f15f02598143dfbd7a06cd880177","docs/10-19-llm-gateway/15-recovery-cas/15.02-recovery-cas.d2":"c5de2f6cb52b0450361b2ed0523f647bdcad1fc43d410231f91ae86aee450859","docs/10-19-llm-gateway/16-policy-publication/16.02-policy-publication.d2":"4be00575666b7ada7185a30e553b42b9c36fe9109ce89df3d0dbb4b30ac10cab","docs/10-19-llm-gateway/17-policy-continuation/17.02-policy-continuation.d2":"4108a821aba5a2de1ffebc59b9e0d9180130bb3f598ac2130d59a83e8eca571f","docs/10-19-llm-gateway/18-canonical-registry/18.02-canonical-registry.d2":"f3b44cf54b006df34b528075bbc54742963a53e2afd4cbee435f81095b59b800","docs/10-19-llm-gateway/19-multi-key-registry/19.02-multi-key-registry.d2":"c44a2569dec8ae1fab46acb1ddd58f8b468e7ea7b11136c120a6bf2b042cf8b7","docs/20-29-execution-authority/20-result-projection/20.02-result-projection.d2":"696df32a9d705c6915bcc43a33616126cdce61ce5af0ae198c0dca5bc898d645","docs/20-29-execution-authority/21-join-enqueue/21.02-join-enqueue.d2":"430f46389111827b9f0ad5c9c3193366729fffe917ef18a5bfa0ec8238f6ab02","docs/20-29-execution-authority/22-executor-offer/22.02-executor-offer.d2":"0d93c13abcc1bd79afb32e6ae8a965cc5ec3b0c30fc1958f2f212e12b5e4b65a","docs/20-29-execution-authority/23-execution-reconciliation/23.02-execution-reconciliation.d2":"14c698ad47a243d46d788ab3494b1ad22ae7f14a163140eb6b4f5e8e071c6269","docs/20-29-execution-authority/24-account-commit/24.02-account-commit.d2":"10d6a5116d2c8be77ce7f27312d9d49ad832645c6748bb7bd68bb6942055990e","docs/20-29-execution-authority/25-wal-activation/25.02-wal-activation.d2":"9ebcd14701116e583157282a1678a6f1e0fe70e1ee4b9b7e038b520d4392ce05","docs/20-29-execution-authority/26-checkpoint-truncation/26.02-checkpoint-truncation.d2":"c5c1a35a16fe9b33029169b16d4c0af113f49e665eed0074ce524fc7a15bdb77","docs/20-29-execution-authority/27-manifest-switch/27.02-manifest-switch.d2":"c4de2ef519af25b2c41194df561860ad0236b0309b3178b388204c29cebf9f41","docs/20-29-execution-authority/28-append-handoff/28.02-append-handoff.d2":"f7646793e8540ec5f1e587d5e13deaf16d166180f80107ac8f9c904ea5c9372c","docs/20-29-execution-authority/29-admission-floor/29.02-admission-floor.d2":"0b9794f3d5fdfc7dcdbb519426eecf7e6ec6cb707de5017387c9aa47208ea385","docs/30-39-assurance/31-protected-signer/31.02-protected-signer.d2":"bc787086ae26a1a6cd56e51a2b4182c86e476f13e28ed1f5d80363b1d827e013","docs/30-39-assurance/32-key-boundary/32.02-key-boundary.d2":"1b616363aa68166988cc1d09404d637da406f048b9647676ec5f42d15f1762ca","docs/30-39-assurance/33-device-isolation/33.02-device-isolation.d2":"f4b086efce29484b70d4d4b2c04dad3887976d69187c25234e734e90260a6c7c","docs/30-39-assurance/34-floor-decision/34.02-floor-decision.d2":"78e2de9f044edb41944a56c1c8c8251a9cacd3470cf73c16b87f5ba100139a04","docs/30-39-assurance/34-floor-decision/34.04-floor-recovery.d2":"296d821eae11d4b77a552ae21d91eadcddcf032a15989dd35490128397044203","docs/30-39-assurance/35-intent-continuation/35.02-intent-continuation.d2":"08475ba17d7c98911a7db912041b669d049c75315c861322f72a5b50a471df55","docs/30-39-assurance/36-gateway-head-cas/36.02-gateway-head-cas.d2":"51669df10ec208197e690f656b962b259959af5f225243b62e5ff6bbea5637a5","docs/30-39-assurance/37-broker-consumption-queue/37.02-broker-consumption-queue.d2":"1ad636df3ba980d5f25b1a330c00c8b21f152958fe7c86617736e1b1f85a1ed8","docs/30-39-assurance/38-logical-range-recovery/38.02-logical-range-recovery.d2":"8ed5e1adc741da6852d027828993a83816cadb0c7bc1732bfaf121b2a64878d3","docs/40-49-admission-coordination/40-source-join/40.02-source-join.d2":"b8815cf59a1be49a4657b6ec3857d39e6d7d39ab4bb3ed44521c71ffe0ec5cee","docs/40-49-admission-coordination/41-source-custody/41.02-source-custody.d2":"feef18f62d537d4eb0659c0f1d719218df1a3eda506c9468b59423b151550bd7","docs/40-49-admission-coordination/42-custody-publication/42.02-custody-publication.d2":"24f019e8633cc816f7488e3f65384d2dea96ac8a3685714665a47bc6144b1e5c","docs/40-49-admission-coordination/43-caller-custody/43.02-caller-custody.d2":"6352167e4d3427fd9a66befb74fb3eebf91a127c5e82ecff8312b24178d5117f","docs/40-49-admission-coordination/44-incarnation-issuance/44.02-incarnation-issuance.d2":"215f52c84c9f41c36352f8b6da8b4670f1b375672cfc9efdf6a8bd1df95c946e","docs/40-49-admission-coordination/45-bootstrap-invitation/45.02-bootstrap-invitation.d2":"9e019de8289428a97580fe66ccefc6b9d0a43c1bac07433d2f29596f4d407401","docs/40-49-admission-coordination/46-beneficiary-registration/46.02-beneficiary-registration.d2":"322b848fdd67ea88c99b509cb5d913d7a5023e327edea51f16f44816356d81ce","docs/40-49-admission-coordination/47-enrollment-credential/47.02-enrollment-credential.d2":"ea0aa0bed915bea42d3d65c8f6572f799eb63d0aee1018b75803e61ef034d303","docs/40-49-admission-coordination/48-subject-authority/48.02-subject-authority.d2":"9f707fbc6e5ba8933a0e4d9d057f013c5764afc503f819288f628d3f9709f88d","docs/40-49-admission-coordination/49-routine-routing-config/49.02-routine-routing-config.d2":"7fa18b652ba97e8fe66f402a9a85d65740db9d3ffadff7890db7d72826c498b6","docs/50-59-research-program/51-qualified-semantic-slice/51.06-semantic-gateway-slice.d2":"d63df655a635fccac3c92eded92c039a3f079c24fa2b7a2fd0dc1f3fabd3c0f5","docs/50-59-research-program/52-committed-profile-binding/52.04-committed-profile.d2":"3ea30976830c607bf8cec62cbabc4291c384bd5f368049a45777f6f981d87d6e","docs/50-59-research-program/53-gerbil-exit/53.04-gerbil-lifecycle.d2":"b7b623664edc6e86efe62eeee7f5977dc207f0cb12e40cb6f0e77e38160695de","docs/50-59-research-program/54-dynamic-gxi-exit/54.04-dynamic-lifecycle.d2":"d4d410dd8cb10de6d3526b54ac7f96731d2f2a94dd9763aad96a0926608e251c","docs/50-59-research-program/55-dynamic-gxi-paired/55.04-runtime-boundary.d2":"573b248a6b7ce2d7eee1e70a469c54e4f195c4894ec7b0f61c8406fae843eccc","docs/50-59-research-program/56-gambit-image-closure/56.04-locator-boundary.d2":"0c45ee11d269b0cab8998c7fc3432ec851b9390b7530486225134b261d8d7de8","docs/50-59-research-program/57-runtime-implementation/57.03-runtime-boundary.d2":"193d22a5bd9e4b23260334d085df8aa5ec19c349f13cd9f56eaa26fe54f7e3ac","docs/50-59-research-program/58-streaming-execution/58.03-streaming-runtime.d2":"76ea49c83b4b36af1e775f80475d40747640b80a330434bf86635e255e84ef14","docs/50-59-research-program/58-streaming-execution/58.05-range-progress-recovery.d2":"aef20c8ad7d7420a65422add6d9fb635bdbe32e42e49427d3179bf20499ae4cd","docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2":"6f4e8218ea262e35efaebaf8cc2f96345b2ef1e7e9c1a6b12b68290dd99c683d","docs/50-59-research-program/59-provider-rpc/59.21-verification-ownership.d2":"e035ae7e56ee5e6498f131ed62f4792547c1e716aa5ed29865b333f54665e8f1","docs/50-59-research-program/59-provider-rpc/59.26-semantic-execution-ecosystem.d2":"50c091b094125693e2debe73599a63405849f1f55ab3658030674692c9334e14","docs/50-59-research-program/59-provider-rpc/59.30-governance-adapter-acceptance.d2":"88cbbd45e63358bb45a58fb27f85e275b9cc9fb3d3aee6af19eabed0912545d2","docs/50-59-research-program/59-provider-rpc/59.43-floor-transport-owner.d2":"36c4d6b561332ab30deb464a92bb4c2f02ceed5c8a1ca66617f72b6086b2c555","docs/50-59-research-program/59-provider-rpc/59.44-cloud-rpc-arrow-boundaries.d2":"fe0ac2220e04f6ccea851247ecf8ae1cab4ec8c8ba8744010c478992c233ebed","docs/50-59-research-program/59-provider-rpc/59.45-slow-consumer-zero-trust.d2":"e36cf58a239a2d9f0c99789bb7484de4e26180a8f941970540f72b530a79d813","docs/50-59-research-program/59-provider-rpc/59.46-functional-security-frameworks.d2":"e541b969352e8149e71e5b539988f9955b525e5e5ba3e7e7270bd4a98fbe19f5","docs/50-59-research-program/59-provider-rpc/59.47-property-testing-framework.d2":"f66ed065dcf955a233968ca295517c642be30dad9b24e23a781fe34e4bed45d9","docs/50-59-research-program/59-provider-rpc/59.49-policy-proposal-barrier.d2":"3a8559bb22f812075d9d7de4a397978995d06c32ed22e9415f990413551aebb6","docs/50-59-research-program/59-provider-rpc/59.50-parent-contract-and-replay.d2":"2db3983f56e938c927b68077551573c8e86362da892f47890459ab7b3f929c64","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-architecture.d2":"10e92e79b69f4b0813551dd2ddadc5ad225b7b0fa8374ed7015b7f2fe66bb6e1","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-contract-refinement.d2":"204c9e20d9027b7a38bf2a964da9a7cadb92744561fa9f1eb3fa29d00f4fa386","docs/50-59-research-program/59-provider-rpc/59.52-reviewed-publication-cas.d2":"4e0998e61717d5441e242cde0dfc52198312b67b63f0ce8b0425a423d1b88a24","docs/50-59-research-program/59-provider-rpc/59.53-artifact-registry-recovery.d2":"f7083a48413d41ad99e7191281bd6e74a92b33c7cc1f4f2f9ae322bb1405088a","docs/50-59-research-program/59-provider-rpc/59.54-source-incarnation-authority.d2":"1e55c0487f01d70462e8df6b46eff9e799b0dc592c0e780c759fa602e3d84444","docs/50-59-research-program/59-provider-rpc/59.55-evidence-reviewed-publication.d2":"c66435372642f7a93ca7fc6f78c2abcbc364a4dde447d10dcc4b2b21ccc06456","docs/50-59-research-program/59-provider-rpc/59.56-runtime-assets-and-authority-floor.d2":"c675469701bb6994fed1976d1e90d01dc1cc4e416a6788f865494fa3243d32c1","docs/50-59-research-program/59-provider-rpc/59.57-schema-bound-candidate-replay.d2":"5ca15af556e0a4ba5bdf1742cf81182ad72e7f51b2eb63352b839e068a7ad7d2","docs/50-59-research-program/59-provider-rpc/59.58-independent-source-recovery.d2":"4b21999b3554be15374448f36ffbccf517b32784a65cadde0f4c1eb8308da377","docs/50-59-research-program/59-provider-rpc/59.59-retained-root-and-recovery-coverage.d2":"37fdf1d3dd01f087434a6108b43a5657d7aecf79a2b9e60638d70eb0b1a4984b","docs/50-59-research-program/59-provider-rpc/59.60-persistent-source-key-custody.d2":"d27df3a14df5d57ad725c1455c82a4ab5bad45b78acea8cd1a76e59958b710eb","docs/50-59-research-program/59-provider-rpc/59.61-authority-bound-replay-pair.d2":"bd4962775564848a90ec49439301cf0cdfbaa4018956344e809f5b318bea6ccd","docs/50-59-research-program/59-provider-rpc/59.62-burn-exposure-recovery.d2":"fab4ea6d0981d75dd4c704f302268f3c5af0898e299e8e0fb38b34d07200b22c","docs/50-59-research-program/59-provider-rpc/59.63-mrr-admission-contract.d2":"ed3c604e0d350049f00528c7117675a7db751b3d6683719b03be116bcf49d5c5","docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.d2":"7164874fdbeec99f2185e1091f759466a68a3b7d9b239db6a503f16383fce50e","docs/50-59-research-program/59-provider-rpc/59.65-turso-concurrent-admission.d2":"0ade3ea326e2066ce908129e383b7e0f371a429710ed0a0bad30ddcfd61f034e","docs/50-59-research-program/59-provider-rpc/59.66-bounded-writer-reuse.d2":"9390a3c12f06c2f33e3df99088dc39de92d3bccc971ddf5a632910515a67623e","docs/50-59-research-program/59-provider-rpc/59.67-writer-owner-lifecycle.d2":"c28559ccf38b2f3320d84bbc0ffc6133e2708081e95bff39d5ed75d064287bde","docs/50-59-research-program/59-provider-rpc/59.69-hot-path-cost-boundaries.d2":"e5789625590fab63bc3635627b7e20ac41f64b8f40cbeee84d51a85f27ab31f1","docs/50-59-research-program/59-provider-rpc/59.75-complete-entry-and-output-contract.d2":"d667501bc15d6c31d986994f641d8d38f63c1d910784e6852e596c24c4e4c7c7","docs/50-59-research-program/59-provider-rpc/59.75-package-linkage.d2":"bc655ae71cc46e0d5b7f42637b78530f262c3142394485e2a9ba31f6516a0a10","docs/50-59-research-program/59-provider-rpc/59.76-embedded-tooling-and-darwin-io.d2":"87655d7c6d81c1ab203f886930f1630003e006c0edb71f90ac3ca23a0cb91845","docs/50-59-research-program/59-provider-rpc/59.77-mrr-turso-storage.d2":"72a4dceeb20cca337276f64537d47dbbd2ac0ce359a7a63997090e6476a40c96","docs/50-59-research-program/59-provider-rpc/59.84-quint-preparation-and-completion.d2":"17f485d7c541506c42003ebba887705ea61972f00c9498aa3c0d153a33b02922","docs/architecture/08-diagram-catalog.org":"353a4296584381207513468ef291e7e1aefdcd6f9f2b854c92be90aab47577ea","docs/architecture/diagrams/00a-readme-overview.d2":"86e7b66d4d8959aaf500ea2717fdc054015655a79f3a095c490d39dfde38ed5f","docs/architecture/diagrams/00c-gateway-runtime.d2":"f6dced6718aa151adb0cdce6268f51b86bd95f6fdd7133a6164449293d98205d","docs/architecture/diagrams/00d-zero-trust-overview.d2":"316cbda9c86fe10cef3cb3268f00984b3a3cb50d5c4aa2df2e323937901a18ac","docs/architecture/diagrams/01-system-boundaries.d2":"69b4622c26b18a8518d46f79db8ce281c756a16f7f1a46977272086bf4dc38e0","docs/architecture/diagrams/01-system-relationships.d2":"dde40fac8667b79a070fda14ebd892f1f1e7c1217726595179b541c855f80c2c","docs/architecture/diagrams/02-admission-sequence.d2":"97077cb16cd4457fe14092caeb4bc8cf2912d434763a08fcf350cd6a4c2b2c74","docs/architecture/diagrams/03-attempt-state.d2":"e696fc0f1d63f58100405852e88e8a7dfb1a625e43be398f3bb54bbc1d90e13a","docs/architecture/diagrams/03a-attempt-observation.d2":"6b387ec7fbcff7d5e3e129bad7ea9590afe0324800a5a13bf7a89377ad86c387","docs/architecture/diagrams/04-consume-timeout.d2":"2ccfe8d033069e0d891531f3b5afef4febf21b2722209a612454d14321cac940","docs/architecture/diagrams/05-fencing-boundaries.d2":"1103ed75ac615b1a2f8239c0321d046a5a87acfa235d5042d8a529e23acd7483","docs/architecture/diagrams/06-source-admission.d2":"4d20817291c5de93b7f97366e6cb1b4af954f22de1ebcb3012c139a4b9dbd82c","docs/architecture/diagrams/07-post-claim-outcomes.d2":"63258620c15c2f52963dcdba33b4ac82cd12aadd1c2de005cd029655493493c1","docs/architecture/diagrams/08-code-as-policy.d2":"fc2263ff1ae000055e6054b89beee60f53b9621707510354c34ef45057889676","docs/architecture/diagrams/09-claim-wins-race.d2":"9eff775ddac29c47acd2c0b69fb1ff98ba9a20943da970c2804e270979555c41","docs/architecture/diagrams/10-commit-dispatch-sequence.d2":"fa5d56c49bc3f590c88cf7c3b63e180afd2d2a39fca878d1515917077ff1687a","docs/architecture/diagrams/11-zero-trust-assurance.d2":"ea93840da2ff4bdac59349f5ad7a56cee5506600283d0c364c53275dde0b5b48","docs/architecture/diagrams/12-execution-correspondence.d2":"1dd66ee8c517fd9c6f2f4b1700aeec3e620d699fbe9eeee20df8e05a7f1decb0","docs/architecture/diagrams/13-policy-to-execution.d2":"4bb05b74c3bc0ca997c5e5035ddc949fa374db3ff49bf2104a6c9753e12be3ef","docs/architecture/diagrams/14-adapter-broker-boundary.d2":"b855fa0482a5524226354b26bc8d7ecef0daf2ab1cab54c1783eba0ff29fab01","docs/architecture/diagrams/15-stream-message-authorization.d2":"cedf1c545a853ec2a9ae51bea928b04376d192f1a4c2af117fa54f475ad541e0","docs/architecture/diagrams/16-authoritative-spent-state.d2":"201bd9fe5eb6101543d939e3d83aca646e2b07c13ff1e3c56779571a0cd1172e","docs/architecture/diagrams/17-logical-message-observation.d2":"2333ad147295ead60ed6a92dc824cf6f5769f3828eff1e0cdf58e50aace7b1e1","docs/architecture/diagrams/18-shared-identity-budget.d2":"5ab4992fd8b6a6abf518fb0bbc8c2c8ad8b920d0be74a6e734d846319252ffa7","docs/architecture/diagrams/19-finite-domains-and-migration.d2":"b72b451d0bb97de46831e4b266d8fdd22d59e7d54db99446d53549f081a008e2","docs/architecture/diagrams/20-anchor-recovery-and-egress.d2":"9479271410f1bb57f92106a1d91ec73c73872568d9fcda55cac5aa64b89e5c9f","docs/architecture/diagrams/21-composed-journal-transport-lifecycle.d2":"0fffe555ee4c2c1222c97eebd24ca9b0df91a4d3ec118300ae3b88240004c3c8","docs/architecture/diagrams/22-finite-stream-manifest.d2":"60b33eb6d06aeaa1027546a1fc9d6c07069c3cd3c7d23df8ff8d63a341afe2ea","docs/architecture/diagrams/23-driver-completion-recovery.d2":"271963db2cd881bb82e164bb1544c7bcf311e1781f20170d858ccb65a596d8f5","docs/architecture/diagrams/24-writer-settlement-closure.d2":"ea1930326b0073e7fabd8b64ef3ffea781f1aef60db0d942f9ab14f1150296e9","docs/architecture/diagrams/25-settlement-anchor-recovery.d2":"8904bfcda525de21b48ea8f2db8d12aaa27e85818ccde43fb545851dc522ba3b","docs/architecture/diagrams/26-gate-consumption-persistence.d2":"42e676634ecb40cfb2dee06db1f5497d0e58c05f30097618c3852eb946992f0d","docs/architecture/diagrams/27-anchor-commit-broker-fencing.d2":"5c2ae36987b00655bbcdba36352e03b61765739ad2f3fc80a561ff0d325a9461","docs/architecture/diagrams/28-anchor-configuration-prefix.d2":"1ac0eeb3c76f5ae0ce3565d4469e50210786c3bc53c703a1a61d519dfa075512","docs/architecture/diagrams/29-quorum-durable-promises.d2":"2e4a24c3fae49e710d5afc31d4681a9efc8c2e8af3fa58a0957ede05fe7c0255","docs/architecture/diagrams/39-shared-execution-exposure.d2":"2c08f5b3d4531a7be2aadec8f1ff9d4476495418e94e84c1ff643583ac991ce4","docs/architecture/diagrams/assets/agent-request.svg":"4efdd12166f2dd11f0269537588bdf4c092a8207f6d3aed7f69b324b5457a390","docs/architecture/diagrams/assets/bounded-write.svg":"ec844639440fe3fd3a5c7258bce663d7c96c6ffce3d422680f649ec1f3e4cee5","docs/architecture/diagrams/assets/budget-ledger.svg":"c21b8727507b7ca0e1300b34c4613a9295ce12d424f5aa1486bf2f955aa45867","docs/architecture/diagrams/assets/components/activity.svg":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","docs/architecture/diagrams/assets/components/book-open.svg":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","docs/architecture/diagrams/assets/components/bot.svg":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","docs/architecture/diagrams/assets/components/brain.svg":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","docs/architecture/diagrams/assets/components/circle-question-mark.svg":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","docs/architecture/diagrams/assets/components/clipboard-check.svg":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","docs/architecture/diagrams/assets/components/coins.svg":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","docs/architecture/diagrams/assets/components/database.svg":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","docs/architecture/diagrams/assets/components/file-check.svg":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","docs/architecture/diagrams/assets/components/fingerprint-pattern.svg":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","docs/architecture/diagrams/assets/components/message-square.svg":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","docs/architecture/diagrams/assets/components/rotate-ccw-clock.svg":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","docs/architecture/diagrams/assets/components/rotate-ccw.svg":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","docs/architecture/diagrams/assets/components/route.svg":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","docs/architecture/diagrams/assets/components/send.svg":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e","docs/architecture/diagrams/assets/components/shield-check.svg":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","docs/architecture/diagrams/assets/components/ticket-check.svg":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","docs/architecture/diagrams/assets/components/waves-horizontal.svg":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","docs/architecture/diagrams/assets/components/workflow.svg":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","docs/architecture/diagrams/assets/go.svg":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","docs/architecture/diagrams/assets/kubernetes.svg":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","docs/architecture/diagrams/assets/model-catalog.svg":"462cd80fcfda09b55dbd56ed86421393591ac22d54feb60dec9b72858e7380a2","docs/architecture/diagrams/assets/model-provider.svg":"f9bc33c731a1c6da16ba2e5cc95cb84e65a580b9f986b1b639fcdc4355a8b790","docs/architecture/diagrams/assets/permission-check.svg":"3ae75b575dfbb7d84fe6b215f72b28c3489715c72d9314be84f1e4a766d3db28","docs/architecture/diagrams/assets/route-choice.svg":"b6060f37795d5b078cfb8d09e9b3ec2053068935416a5c5c6f6c600d3b9dbf7b","docs/architecture/diagrams/assets/rust.svg":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","docs/architecture/diagrams/assets/task-contract.svg":"4da0bd2fd156b69dba5791f558d4524901401707972dbc2fea8f2aab29dd3263","docs/architecture/diagrams/assets/unknown-hold.svg":"6e243f03d4cdb79637f60d268aa4402d4963218adc9e3c4f9f64ebdb99e3c437","Project.sysml":"563dfa1854f26de71d6d401f27bf990243c540dbc37156e592df717c6922d2d1"},"rendered":{"observation":{"canvas":{"x":0,"y":0,"width":980,"height":846.765625},"subjects":[{"id":"n0","role":"default","x":28,"y":251,"width":286.65625,"height":85.984375},{"id":"n1","role":"default","x":346.65625,"y":251,"width":286.671875,"height":238.890625},{"id":"n2","role":"default","x":665.328125,"y":251,"width":286.65625,"height":238.875},{"id":"n3","role":"default","x":28,"y":567.890625,"width":286.65625,"height":238.875},{"id":"n4","role":"default","x":346.65625,"y":567.890625,"width":286.671875,"height":86},{"id":"n5","role":"default","x":665.328125,"y":567.890625,"width":286.65625,"height":85.984375}],"relations":["edge:0","edge:1","edge:2","edge:3","edge:4"],"headings":[{"role":"title","x":20,"y":20,"width":940,"height":63},{"role":"question","x":20,"y":83,"width":940,"height":56},{"role":"note","x":20,"y":155,"width":940,"height":48}]},"readability":{"minimumTextSize":24.839930555555554,"samples":16},"bounds":{"objects":{"x":20,"y":231,"width":940,"height":595.765625}}}}Separate control RPC from provider I/O?How does the gRPC proposal become a bounded provider effect?Rust owns final admission and response release. +@font-face{font-family:"Kalam";font-style:normal;font-weight:700;src:url(data:font/woff2;base64,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) format('woff2')}{"renderer":{"package":"@deterministic-engineering/render","version":"1.0.0","icons":{"agent":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","agent-request":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","authentication":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","authorization":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","bounded-write":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","budget":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","budget-ledger":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","capture":"a647d42aa11f4e5e85d0bbf66f483f57f3c4ba3a9536362ed0eaaaae10a89cee","catalog":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","claim":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","decision":"3535642a5b613372c3fd374151ec90aafa19b64b2d33d10b19162cad07a35c7a","document":"0bf9674a401262da8a646305cab00006954721c07765b9962e0dee1c31d560f7","evidence":"0a91b169aaa644829a054cbb94194efffaf4298f2b6f8fa8c6ec2b7b413a1766","go":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","history":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","kubernetes":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","ledger":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","library":"df474fa36a74016b79236fff58a980a8c18c682d1866211776e349a0eb4b2979","message":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","model":"0cfd1f9ed3873f556ace725a7b6a251ebe75d7d976567699276f34df36b2443b","model-catalog":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","model-provider":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","obligation":"e76f4d34a7190400446c89e4e7d187762b885808a64a00c99455599d902570c5","pending":"cca7589bc3b1dcdebacb867c6836c6fc166257f05823555a268354ff9bfac00c","permission-check":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","policy":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","provider":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","publication":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","question":"dbf231e1568dc37189d5674d73c4bfc58a17eb8ada579b3f03bf2813d33c56f4","recovery":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","reference":"3814c570f79ab294252c36530de464c9364814b797afb862d9c62e728a8660fc","route-choice":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","routine":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","routing":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","rust":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","selection":"82b4ab6faf195fea0a891c35268e61c186e93e7c6a9d7967a4f6a73dbf25ae7f","stream":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","task-contract":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","telemetry":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","unknown":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","unknown-hold":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","writer":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e"}},"design":{"audience":"Gateway design and runtime reviewers","medium":"GitHub at 830 CSS pixels","message":"Rust owns final admission and response release.","questionRefs":["q1"],"requiredSubjects":["n0","n1","n2","n3","n4","n5"],"requiredRelations":[],"focalSubjects":["n2"]},"evidence":[],"layout":"model-view","presentation":{"illustrations":{"n1":"route-choice","n2":"permission-check","n3":"model-provider"},"objectRows":[["n0","n1","n2"],["n3","n4","n5"]],"notation":"objects","options":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.layered.spacing.nodeNodeBetweenLayers":"27","elk.spacing.nodeNode":"16"},"icons":{"n0":"routine","n1":"routing","n2":"authorization","n3":"provider","n4":"stream","n5":"telemetry"},"roles":{},"edgeLabels":true,"graph":{"id":"declared-reading-order","children":[{"id":"n0","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n1","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n2","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n3","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n4","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n5","layoutOptions":{"elk.partitioning.partition":"1"}}],"layoutOptions":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.layered.spacing.nodeNodeBetweenLayers":"27","elk.partitioning.activate":"true","elk.spacing.nodeNode":"16"}},"textColumns":22},"drawing":{"mode":"sketch","options":{"seed":29,"roughness":1.3,"strokeWidth":1.2,"fillStyle":"hachure","hachureGap":9,"fillWeight":0.6}},"fonts":[{"family":"Kalam","weight":400,"source":"@fontsource/kalam/files/kalam-latin-400-normal.woff2"},{"family":"Kalam","weight":700,"source":"@fontsource/kalam/files/kalam-latin-700-normal.woff2"}],"palette":{"background":"#F6FAF9","surface":"#FFFFFF","ink":"#163C43","muted":"#496A70","border":"#C9DDDA","accent":"#087E82","secondary":"#946044","tint":"#E1F1EC","secondaryTint":"#F4EADA","onAccent":"#FFFFFF","supported":"#237653","pending":"#986320","conflict":"#A13E54"},"inputSHA256":"fe0eb65d40d445a7c6b51e3d70b6361bb024b4a268cf91e1ad599e95a23f91fb","model":{"subjects":[{"id":"n0","type":"part","sourceName":"WeaverResearchReaderViews::rpcCoreBoundary::p_config","label":"Governed config\nTyped Scheme or data"},{"id":"n1","type":"part","sourceName":"WeaverResearchReaderViews::rpcCoreBoundary::p_control","label":"Rust source RPC\nCarry the bound proposal"},{"id":"n2","type":"part","sourceName":"WeaverResearchReaderViews::rpcCoreBoundary::p_admit","label":"Rust admission\nCheck Cedar and claim"},{"id":"n3","type":"part","sourceName":"WeaverResearchReaderViews::rpcCoreBoundary::p_provider","label":"Provider I/O\nSend the exact request"},{"id":"n4","type":"part","sourceName":"WeaverResearchReaderViews::rpcCoreBoundary::p_release","label":"Guarded stream\nRelease under current Policy"},{"id":"n5","type":"part","sourceName":"WeaverResearchReaderViews::rpcCoreBoundary::p_metrics","label":"Telemetry\nObserve bounded events"}],"relations":[{"id":"edge:0","src":"n0","dst":"n1","label":"configure","kind":"connection","fromPort":"n0.1","toPort":"n1.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:1","src":"n1","dst":"n2","label":"propose","kind":"connection","fromPort":"n1.1","toPort":"n2.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:2","src":"n2","dst":"n3","label":"mediate","kind":"connection","fromPort":"n2.1","toPort":"n3.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:3","src":"n3","dst":"n4","label":"stream","kind":"connection","fromPort":"n3.1","toPort":"n4.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:4","src":"n2","dst":"n5","label":"observe","kind":"connection","fromPort":"n2.1","toPort":"n5.0","srcArrow":"none","dstArrow":"none"}]},"modelSource":{"ref":"sdkCapture","modelHash":"116cd33cb1473e7f17e398a7fe55b25f4f2dab261c144fba9b09948e33684f62","view":"WeaverResearchReaderViews::rpcCore","portProjection":"owner","labels":{"n0":"Governed config\nTyped Scheme or data","n1":"Rust source RPC\nCarry the bound proposal","n2":"Rust admission\nCheck Cedar and claim","n3":"Provider I/O\nSend the exact request","n4":"Guarded stream\nRelease under current Policy","n5":"Telemetry\nObserve bounded events"}},"modelTrace":{"modelHash":"116cd33cb1473e7f17e398a7fe55b25f4f2dab261c144fba9b09948e33684f62","requestedView":"WeaverResearchReaderViews::rpcCore","resolvedView":"WeaverResearchReaderViews::rpcCore","renderingSHA256":"020ca25ef6aef2a4d7beb8ae451a2f5f752bb276a70e3590a8e553b13646a646","capturedRenderingJSON":"{\"modelHash\":\"116cd33cb1473e7f17e398a7fe55b25f4f2dab261c144fba9b09948e33684f62\",\"requestedView\":\"WeaverResearchReaderViews::rpcCore\",\"rendering\":{\"view\":\"WeaverResearchReaderViews::rpcCore\",\"kind\":\"interconnection\",\"stated\":\"render asInterconnectionDiagram\",\"nodes\":[{\"id\":\"n0\",\"kind\":\"part\",\"name\":\"WeaverResearchReaderViews::rpcCoreBoundary::p_config\",\"nameSynthesized\":false,\"type\":\"rpcCore_config\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n0.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":283,\"startCol\":9,\"endLine\":283,\"endCol\":40}},{\"id\":\"n1\",\"kind\":\"part\",\"name\":\"WeaverResearchReaderViews::rpcCoreBoundary::p_control\",\"nameSynthesized\":false,\"type\":\"rpcCore_control\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n1.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"},{\"id\":\"n1.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":284,\"startCol\":9,\"endLine\":284,\"endCol\":42}},{\"id\":\"n2\",\"kind\":\"part\",\"name\":\"WeaverResearchReaderViews::rpcCoreBoundary::p_admit\",\"nameSynthesized\":false,\"type\":\"rpcCore_admit\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n2.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"},{\"id\":\"n2.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":285,\"startCol\":9,\"endLine\":285,\"endCol\":38}},{\"id\":\"n3\",\"kind\":\"part\",\"name\":\"WeaverResearchReaderViews::rpcCoreBoundary::p_provider\",\"nameSynthesized\":false,\"type\":\"rpcCore_provider\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n3.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"},{\"id\":\"n3.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":286,\"startCol\":9,\"endLine\":286,\"endCol\":44}},{\"id\":\"n4\",\"kind\":\"part\",\"name\":\"WeaverResearchReaderViews::rpcCoreBoundary::p_release\",\"nameSynthesized\":false,\"type\":\"rpcCore_release\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n4.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":287,\"startCol\":9,\"endLine\":287,\"endCol\":42}},{\"id\":\"n5\",\"kind\":\"part\",\"name\":\"WeaverResearchReaderViews::rpcCoreBoundary::p_metrics\",\"nameSynthesized\":false,\"type\":\"rpcCore_metrics\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n5.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":288,\"startCol\":9,\"endLine\":288,\"endCol\":42}}],\"edges\":[{\"from\":\"n0\",\"to\":\"n1\",\"fromPort\":\"n0.1\",\"toPort\":\"n1.0\",\"label\":\"configure\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":289,\"startCol\":9,\"endLine\":289,\"endCol\":78}},{\"from\":\"n1\",\"to\":\"n2\",\"fromPort\":\"n1.1\",\"toPort\":\"n2.0\",\"label\":\"propose\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":290,\"startCol\":9,\"endLine\":290,\"endCol\":75}},{\"from\":\"n2\",\"to\":\"n3\",\"fromPort\":\"n2.1\",\"toPort\":\"n3.0\",\"label\":\"mediate\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":291,\"startCol\":9,\"endLine\":291,\"endCol\":76}},{\"from\":\"n3\",\"to\":\"n4\",\"fromPort\":\"n3.1\",\"toPort\":\"n4.0\",\"label\":\"stream\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":292,\"startCol\":9,\"endLine\":292,\"endCol\":77}},{\"from\":\"n2\",\"to\":\"n5\",\"fromPort\":\"n2.1\",\"toPort\":\"n5.0\",\"label\":\"observe\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ResearchReaderViews.sysml\",\"startLine\":293,\"startCol\":9,\"endLine\":293,\"endCol\":75}}],\"columns\":[],\"rows\":[],\"notes\":[],\"notices\":[],\"shown\":[]}}","portProjection":"owner","nodes":[{"id":"n0","parent":"","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":283,"startCol":9,"endLine":283,"endCol":40}},{"id":"n1","parent":"","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":284,"startCol":9,"endLine":284,"endCol":42}},{"id":"n2","parent":"","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":285,"startCol":9,"endLine":285,"endCol":38}},{"id":"n3","parent":"","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":286,"startCol":9,"endLine":286,"endCol":44}},{"id":"n4","parent":"","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":287,"startCol":9,"endLine":287,"endCol":42}},{"id":"n5","parent":"","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":288,"startCol":9,"endLine":288,"endCol":42}}],"edges":[{"id":"edge:0","index":0,"from":"n0","to":"n1","fromPort":"n0.1","toPort":"n1.0","kind":"connection","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":289,"startCol":9,"endLine":289,"endCol":78}},{"id":"edge:1","index":1,"from":"n1","to":"n2","fromPort":"n1.1","toPort":"n2.0","kind":"connection","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":290,"startCol":9,"endLine":290,"endCol":75}},{"id":"edge:2","index":2,"from":"n2","to":"n3","fromPort":"n2.1","toPort":"n3.0","kind":"connection","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":291,"startCol":9,"endLine":291,"endCol":76}},{"id":"edge:3","index":3,"from":"n3","to":"n4","fromPort":"n3.1","toPort":"n4.0","kind":"connection","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":292,"startCol":9,"endLine":292,"endCol":77}},{"id":"edge:4","index":4,"from":"n2","to":"n5","fromPort":"n2.1","toPort":"n5.0","kind":"connection","origin":{"file":"dev/sysml/ResearchReaderViews.sysml","startLine":293,"startCol":9,"endLine":293,"endCol":75}}]},"view":{"source":"docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2","title":"Separate control RPC from provider I/O","purpose":"workflow","kind":"routing","question":{"subjectRefs":["n2"],"ref":"q1","text":"How does the gRPC proposal become a bounded provider effect?","focusRefs":["model"]},"basis":{"captureRef":"docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2#design-view","modelRefs":["Project.sysml","dev/sysml/AdmissionReaderViews.sysml","dev/sysml/ArchitectureEvolution.sysml","dev/sysml/ArchitectureReaderViews.sysml","dev/sysml/ArchitectureViews.sysml","dev/sysml/AssuranceReaderViews.sysml","dev/sysml/AttemptReaderViews.sysml","dev/sysml/AuthorityReaderViews.sysml","dev/sysml/ControlActivation.sysml","dev/sysml/ControllerObjectLifecycle.sysml","dev/sysml/CorrespondenceReaderView.sysml","dev/sysml/ExecutionReaderViews.sysml","dev/sysml/FloorReaderViews.sysml","dev/sysml/GatewayArchitecture.sysml","dev/sysml/PolicyEvidenceDesign.sysml","dev/sysml/ProviderRpc.sysml","dev/sysml/ReaderDesigns.sysml","dev/sysml/ResearchReaderViews.sysml","dev/sysml/StoragePersistence.sysml","dev/sysml/StreamingExecution.sysml","dev/sysml/WeaverExecution.sysml","dev/sysml/ZeroTrustRefinement.sysml"],"obligationRefs":["proof0"],"evidenceRefs":[]}},"questions":[{"subjectRefs":["n2"],"ref":"q1","text":"How does the gRPC proposal become a bounded provider effect?","focusRefs":["model"]}],"references":{"model":"dev/sysml/ResearchReaderViews.sysml","model0":"Project.sysml","model1":"dev/sysml/AdmissionReaderViews.sysml","model10":"dev/sysml/CorrespondenceReaderView.sysml","model11":"dev/sysml/ExecutionReaderViews.sysml","model12":"dev/sysml/FloorReaderViews.sysml","model13":"dev/sysml/GatewayArchitecture.sysml","model14":"dev/sysml/PolicyEvidenceDesign.sysml","model15":"dev/sysml/ProviderRpc.sysml","model16":"dev/sysml/ReaderDesigns.sysml","model17":"dev/sysml/ResearchReaderViews.sysml","model18":"dev/sysml/StoragePersistence.sysml","model19":"dev/sysml/StreamingExecution.sysml","model2":"dev/sysml/ArchitectureEvolution.sysml","model20":"dev/sysml/WeaverExecution.sysml","model21":"dev/sysml/ZeroTrustRefinement.sysml","model3":"dev/sysml/ArchitectureReaderViews.sysml","model4":"dev/sysml/ArchitectureViews.sysml","model5":"dev/sysml/AssuranceReaderViews.sysml","model6":"dev/sysml/AttemptReaderViews.sysml","model7":"dev/sysml/AuthorityReaderViews.sysml","model8":"dev/sysml/ControlActivation.sysml","model9":"dev/sysml/ControllerObjectLifecycle.sysml","proof0":"dev/proofs/lean/StreamingExecution.lean","sdkCapture":"dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json"},"sourceSHA256":{"dev/d2/themes/assurance.d2":"f7723f53e005a68c803a38ce5c04cd733f46f4a2688fa4b17c66f9d5b308fe24","dev/d2/themes/data.d2":"19fceb46186892da02b763217963cc3ca2a35021219c0d353fdeec84604ddaee","dev/d2/themes/flow.d2":"1f13588619d0c8087c08d8afd023c4c0efe12726711c311e623eea3872726c1f","dev/d2/themes/routing.d2":"f185df198e7435d12b17b7b57b62dfc5795597d95eb926159ee13b448727bcce","dev/d2/themes/sequence.d2":"6e39472720dccc717f984c95b79570494b6ce3828b86227629841649e6c956e6","dev/d2/themes/state.d2":"f1a35cbca0f9cbb055ea9f793ba3dfb86e5fee4e462038ef3e72b94baa61d781","dev/d2/themes/system.d2":"b2a32ec6959ca5df9103c16454c4e34b758e061f850f7de6b619bcbc5fcf17a6","dev/d2/themes/vocabulary.d2":"add21e9b87eab485e5daabf6316fea44eb56b1007b70123f24b0e32e3357f744","dev/proofs/cedar/DomainMigrationComposition.lean":"97c2564f79b3ad81b538d763e70727d4505995019d8a96d401bb738486b190e9","dev/proofs/cedar/QualifiedReview.lean":"1ae16e06ad03a2906fa8c21dbeea1e3eb7700aa1e9359e64848dec65ccfd079f","dev/proofs/cedar/WeaverPolicyBridge.lean":"a9628a8123d504a34f64bf986feb4471325aa2b0ddc603d76b62632481eab67b","dev/proofs/cedar/ZeroTrustEnrichment.lean":"0c4b138843cc176c27d42d4a31177a3c12486b2d8ff124a6453e3d0922170884","dev/proofs/lean/ProviderAdmissionTurn.lean":"9b30418066f14197ad601d0f439a7326c7940a5f67785353c37f2ac044801bf4","dev/proofs/lean/ProviderEgressWindow.lean":"c4a15b4ccd3a6474290b71374499087dba7dac7a1fda53f3a870100ec2e768a9","dev/proofs/lean/ProviderLifecycleFootprint.lean":"4786544c8a8193c5221bda2f7cd5cf20531bd1856d88b10ae29b280f223e307c","dev/proofs/lean/ProviderReadCustody.lean":"67e83773a1a063852e2303512d4b75b73cd3b9a90117972aafda9ee7348e6b77","dev/proofs/lean/ProviderRpc.lean":"e79d7639ac11220585e59e85dc5bec12b6717f7b51fb28fdcd62dc96d8fae38e","dev/proofs/lean/ProviderSemanticProgress.lean":"d32e010145a7dfcd646daeeeb4b08c0e852b9006bca404681af7e7fe10d0eaa0","dev/proofs/lean/ProviderSnapshotPublication.lean":"312c0380e334fbc5380815d882c6b5b0007747100f818becbee9c6784eeb5716","dev/proofs/lean/RuntimeAdmission.lean":"6111d4b9e93ebaa9f7cc44a55ed504c88c20c8d9de81e947a2e13b3f4a13b13c","dev/proofs/lean/SharedDomains.lean":"10eef67918986264689b09f0a6c0d53b314d7bf43b42f4b9652b403570beb58d","dev/proofs/lean/StreamingExecution.lean":"3fba798a7887a0b2ae29a7e3f0aaa3d7e2fb191e5f1f28109a4a73d28e27b776","dev/sysml/AdmissionReaderViews.sysml":"27ebc6c98ec3a1f7f9081e77a130953c3b646a1fdf6f1d6fc1fa6ed6376e9623","dev/sysml/ArchitectureEvolution.sysml":"6d7f4514180fb4a7d93fd5b01e888c1d95e36570e9fefc6ca0c415c66334922b","dev/sysml/ArchitectureReaderViews.sysml":"1113b05e7103c157b2291f12a003fc78fee07dcc68d90e2bdcd1a1b1a53f7c35","dev/sysml/ArchitectureViews.sysml":"e5b5dbbd27acfba0bd5d5b52e45990b99471d88da0e814ec13fb7ab23d752d4b","dev/sysml/AssuranceReaderViews.sysml":"cd99fb7e9b23e08beac265bc832a8debee0dc1e1d318b0f64d5263519270e390","dev/sysml/AttemptReaderViews.sysml":"0d87cf71e15c26566422a6ddb5945fdb8add8af0484d9d024c32b97597675e21","dev/sysml/AuthorityReaderViews.sysml":"6fa25bd3a64e7f89987caec8e4773928be2cbea0a3c943299e536ca81978316d","dev/sysml/captures/ArchitectureEvolution-reinforcingCapabilities.json":"bdea3da2ce576a8d02d6a13e1a5a462341501d7bf38533cf327b8b817880f793","dev/sysml/captures/ControllerObjectLifecycle-lifecycle.json":"70f46345a1186aeb1d8cbf0e05cbca0746d9e3ba5bc1599a4feb5c4777b13806","dev/sysml/captures/WeaverAdmissionReaderViews-beneficiaryRegistration.json":"282371e766597824b2ef7800e9029eb69615a2b42b27a194d41e330b7bc08469","dev/sysml/captures/WeaverAdmissionReaderViews-bootstrapInvitation.json":"11b2c898d5107fbef1722872b8b0186f7933888fe80aa9e6ea134729f46dc18c","dev/sysml/captures/WeaverAdmissionReaderViews-callerCustody.json":"4063156bcac98c3a052a57c9e98ac885656ee9944065c839afa92dff20b8efa8","dev/sysml/captures/WeaverAdmissionReaderViews-custodyPublication.json":"1c7c3a3e76cada1c3aeb237470b88a82266b260b5ca0a8596b0bf5ee8e8e00b5","dev/sysml/captures/WeaverAdmissionReaderViews-enrollmentCredential.json":"6fdbc68c9a291b0a8ac6ad03829e721129425dedc625c5bae5aa319b8b6b31ad","dev/sysml/captures/WeaverAdmissionReaderViews-incarnationIssuance.json":"f03ef4515964101e9c5e040edc1dee425dac0dcaa3f09aad96bb80e7af885189","dev/sysml/captures/WeaverAdmissionReaderViews-routineRouting.json":"098a72a7f858dbe2bd4437f388bdbb52170a07225cad910e532a63f9b40bcb90","dev/sysml/captures/WeaverAdmissionReaderViews-sourceCustody.json":"0ffa1435dbf2865ddb1b359ebef0d77c5457780b0698a0d6745e3722bd29e648","dev/sysml/captures/WeaverAdmissionReaderViews-sourceJoin.json":"69f9666d5228226552762b0f8dd938515cfca0060a7b7b225a9cd6800b1e70a1","dev/sysml/captures/WeaverAdmissionReaderViews-subjectAuthority.json":"1a97b2c4325f5a1d2240e2443815b8114354cfeb363a2d3fe43b78f704219691","dev/sysml/captures/WeaverArchitectureReaderViews-adapterBroker.json":"ea5f360522738a643211b250d6dc7e376755d0491445be2320aa8ad37c9c2476","dev/sysml/captures/WeaverArchitectureReaderViews-anchorBroker.json":"bdf8f7d100130ac92eccf09121af3590398e38dbddb27dd9f561fb03ea95bbf2","dev/sysml/captures/WeaverArchitectureReaderViews-anchorEgress.json":"d19cddd8f2a4a0c40b47c9d444bfa7b3e025ee51d1dac2f676483817d36d7a34","dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json":"b9fdd680841c1a7b8bf7864004d397b2e00818250f0764dbcdbe3ac7a9092715","dev/sysml/captures/WeaverArchitectureReaderViews-codePolicy.json":"f52d9406ce39b41f8302e4ab56e7000bbb93e0e67491011f7fdd4f8335745b87","dev/sysml/captures/WeaverArchitectureReaderViews-configPrefix.json":"ee76055919b8888a801b2f1c3c44cd9a34e6f693859611f7dc7c3e62d80da1d0","dev/sysml/captures/WeaverArchitectureReaderViews-driverCompletion.json":"5dfbc07f3605b96c8d491c80f5396e510692b12d10d37ff53b457b7a3d189676","dev/sysml/captures/WeaverArchitectureReaderViews-fencing.json":"9bb9bfe87ddfff0c4245a7623b8c4b75ec773d8487a6738240bcdb8add3614b4","dev/sysml/captures/WeaverArchitectureReaderViews-gatePersistence.json":"149e75852c1d33bb1b0e10d1b47b2961d12892539831b72348f2d21329ed6644","dev/sysml/captures/WeaverArchitectureReaderViews-journalLifecycle.json":"0ea02d10c18da42bbd761cb608d6364e8879beafe3231797d9485a6b322e333b","dev/sysml/captures/WeaverArchitectureReaderViews-logicalObservation.json":"b2978cc1e46a32bfda1421f4102b4f679fa749a701ca500f5ff69fe460240cfc","dev/sysml/captures/WeaverArchitectureReaderViews-manifest.json":"38d2f88bc53a0a3b35ed995471af88da08c807bcced157804ebca3137e177b1d","dev/sysml/captures/WeaverArchitectureReaderViews-migration.json":"46d37e698acae75a8e934f14ce96463c6fb66487d3b9c94868e54396bc22881d","dev/sysml/captures/WeaverArchitectureReaderViews-policyExecution.json":"824a99762907c683cfa679502164cbc0ef153ae0fbdf97ae417303f23215dc02","dev/sysml/captures/WeaverArchitectureReaderViews-quorumPromises.json":"3cfd2ee775239e649e22d8a623b35a332a2de862af4d348446cae706403e46d6","dev/sysml/captures/WeaverArchitectureReaderViews-relationships.json":"f0aa6f762966bff244ae2e68342c52d6c8f592059848672b8b7d94725423d59a","dev/sysml/captures/WeaverArchitectureReaderViews-settlementAnchor.json":"2622e5958db1b8b5c8e249e94c7f916f31d03eb9ea0575ce6a950b2e780927ce","dev/sysml/captures/WeaverArchitectureReaderViews-sharedBudget.json":"9423f93a750b393b6a4941e198916a58acec751376d54057fec6a95b00bbbd07","dev/sysml/captures/WeaverArchitectureReaderViews-sharedExposure.json":"3589c03f85619e1fac42b597efcfdadc7a6dd127670d71ca24f91d24f72c0bab","dev/sysml/captures/WeaverArchitectureReaderViews-spentState.json":"c0c314d39891da99ec2d00b95857e0767e1768fd3af54214be25dddf6fb2d2d1","dev/sysml/captures/WeaverArchitectureReaderViews-writerSettlement.json":"5da30fafcc667f583ba1adc6664b6322150acf67551da31a61f4ef97a808bd67","dev/sysml/captures/WeaverArchitectureReaderViews-zeroAssurance.json":"63ad0b61d770dfbe7188f902f66036549a526120ff1bf93aa31972dfa01b8917","dev/sysml/captures/WeaverAssuranceReaderViews-brokerQueue.json":"5c8f294b9de9ef6006e4540785f8228556b9c4e0ee61dd097aba3c63ebf022df","dev/sysml/captures/WeaverAssuranceReaderViews-continuation.json":"b8e5965bbb13edd9f53b7fd91ea14cbc8839976f7dab5594568ac60d4c6c40ec","dev/sysml/captures/WeaverAssuranceReaderViews-deviceEvidence.json":"be8393a9eb150ee433d5120e790eba12bb76faa17dab371b74cfd431147a0bcd","dev/sysml/captures/WeaverAssuranceReaderViews-gatewayHead.json":"2d3cc0dd678c43d22b58061f8cad62f70043fa50149bbe2a5b2508d11dd3a47f","dev/sysml/captures/WeaverAssuranceReaderViews-keySession.json":"4159167f92723446572c6803705b4011b25722172ba8e94a5415a25dfe981004","dev/sysml/captures/WeaverAssuranceReaderViews-rangeRecovery.json":"c571ba4f5fe9aab6d4de13576b9d379f6b273200a03f9d4e7a06545af3ac8710","dev/sysml/captures/WeaverAssuranceReaderViews-signer.json":"eb1bf192465d20dc0016135ec1c1efde68295508a7e2ab8f62c6903b3b9e560b","dev/sysml/captures/WeaverAttemptReaderViews-admission.json":"30031d020abcc0d7fd46ca74a4e4c63fb39d75f10b918a832d3454a70a68e4dc","dev/sysml/captures/WeaverAttemptReaderViews-outcome.json":"a419013e32ab3e54ce95259a1519c733c4cacd2c28ea010e0975e4c9d883f447","dev/sysml/captures/WeaverAuthorityReaderViews-attemptLedger.json":"24701be8a5c32bbf48a8ab2110da1e0514eca7c5550e5639d4779f0dfd021a8e","dev/sysml/captures/WeaverAuthorityReaderViews-canonical.json":"58970dbd9b9bbdb608ba919f6e88b7fe4c0d38cd63fecc4a671e1760142e4394","dev/sysml/captures/WeaverAuthorityReaderViews-multiKey.json":"16e4e9b86e0cf78683b15cc1fe38ca93799eb94d482220f2ce022a1d456918c3","dev/sysml/captures/WeaverAuthorityReaderViews-publication.json":"1338546411c0957603c4bd89ef57418bb31c4bc22f97e1756da5672cf4c17211","dev/sysml/captures/WeaverAuthorityReaderViews-recoveryCAS.json":"29007a3d936a773b5d491dc43f63b711e3dc033059ace971498841fc665ae620","dev/sysml/captures/WeaverAuthorityReaderViews-scope.json":"b2fbaab4bd0fb8cce7a303ae7063798e19eefb5086ccdef680a9d621d23e9dd4","dev/sysml/captures/WeaverCorrespondenceReaderView-correspondence.json":"1c7a57ada0b6ebabd3db27ffa1bea0f73f7701847275b1bfe788e975890f3da2","dev/sysml/captures/WeaverExecutionReaderViews-accountCommit.json":"351fec0e5c5e31f2ffaeba55197f90b801c468c92159b65bf9e07c58a9548062","dev/sysml/captures/WeaverExecutionReaderViews-admissionFloor.json":"e179d9dedf7f45338628d06320db13b99b575f2f122d2322d18e904c987a68f6","dev/sysml/captures/WeaverExecutionReaderViews-appendHandoff.json":"2e9515041d71931cdd5b87e8dfd0c7a81130d7ba472db01857065272632231d7","dev/sysml/captures/WeaverExecutionReaderViews-checkpoint.json":"2b3ba6783fc5bf49efc5d8702068de3534a5ee1fa22d181ebbef5361f07f3dba","dev/sysml/captures/WeaverExecutionReaderViews-executionEvidence.json":"1a8c699e151560ba9dbc29601bd5de843fb55002213f9da7851cb9d353190b12","dev/sysml/captures/WeaverExecutionReaderViews-executorOffer.json":"351d47f86e27612a4237378de1c872499b61304552f5ae74fa04224ad35e7dc1","dev/sysml/captures/WeaverExecutionReaderViews-joinEnqueue.json":"0f91d7980296be0cdc1add3bc03cfab28e28e39b0b8f3d6400bf21b10f55f57b","dev/sysml/captures/WeaverExecutionReaderViews-manifestSwitch.json":"f4fd93c905cde27c3b8799fe26251a40780b59761119c88262df00209209c292","dev/sysml/captures/WeaverExecutionReaderViews-resultProjection.json":"d13ef5015978f9ab7e3dd1964ed38643c660d38336f6b37fdc9fc12be8e80417","dev/sysml/captures/WeaverExecutionReaderViews-walActivation.json":"53950d7718f811f0b0cd828ee7bbee2719f7915d603a87b2a713f5ccc1e81875","dev/sysml/captures/WeaverFloorReaderViews-floorOrdering.json":"c480d14ae5b18c146fb5d80e6ddd7f4036149508396322eb467ab5f022e16188","dev/sysml/captures/WeaverFloorReaderViews-floorRecovery.json":"16cfb4eb51bd76e0aa3e9c11e200303a0256a13365de74842bb2cdf6cbfa5b4e","dev/sysml/captures/WeaverResearchReaderViews-embeddedTooling.json":"86a41ad0c6e5b2c9c8f3acfd42facd72eb37c84584d6866b10e7377190b49bc8","dev/sysml/captures/WeaverResearchReaderViews-floorTransport.json":"cc3417722abc10e9445fca1eac1eb3a5043c62d0a94d9c90fd23e6ee689be471","dev/sysml/captures/WeaverResearchReaderViews-gerbilLifecycle.json":"62141c8a81dfb0d208f0dfc850f7a9dcc6628d30f689cc75298394b7a1ecd8cb","dev/sysml/captures/WeaverResearchReaderViews-gxiLifecycle.json":"ff1eb0c01f0a8a7a6108baa8fa9b4211be25b06754e8c6f00eb10355286f70ac","dev/sysml/captures/WeaverResearchReaderViews-parentReplay.json":"e05af04dcf85e861558f61a1225ae15b528d207f5852d0d651ce0ceda71d90a7","dev/sysml/captures/WeaverResearchReaderViews-profileBinding.json":"1206342019d76835e466cdd0912eac3595a4ffca434692947ffeb866001d7f4e","dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json":"020ca25ef6aef2a4d7beb8ae451a2f5f752bb276a70e3590a8e553b13646a646","dev/sysml/captures/WeaverResearchReaderViews-runtimeAssets.json":"b7a2cb1537e9bd68522f2bed7a3193a3915683bf43d14e65bbded76817487008","dev/sysml/captures/WeaverResearchReaderViews-semanticSlice.json":"16208111d04383bc319ce5440d8bd96434b13201cbc427b1668c260dc7fa6f1c","dev/sysml/captures/WeaverViews-architecture.json":"7b682ae26b90c95f9658f3070c25dc4c857a7a07c91bd14c88b040e4c4c14ea8","dev/sysml/captures/WeaverViews-assurance.json":"f730eccdd0eaba396b7d0c33fc42700fb203f349690fd6873334a9ecb9368704","dev/sysml/captures/WeaverViews-contractRefinement.json":"85d2838fbb52045f4e46be8e1dca60bdc46a2d200cd41a34ad0b6c517eb8cdd7","dev/sysml/captures/WeaverViews-execution.json":"6041eba84d0fbc2180a7a9d87511079672d9435aebce1d3d1c2b9c25217138d6","dev/sysml/captures/WeaverViews-gateway.json":"1d12f4f84cc6c5978f95d52bd173e7a7c0a29588d164451068a2c8819be73426","dev/sysml/captures/WeaverViews-providerDeliveryJoin.json":"3fb68d917a40849f519db0648bc53d429eaa87c2e81c238260b66b65388b559e","dev/sysml/captures/WeaverViews-providerEgressWindow.json":"f2671bdb541233fead17d7cf855e49633422ff16ef8230807c6a433013d1f484","dev/sysml/captures/WeaverViews-rangeRecovery.json":"4c13edca66ab6581dc8ae0f943c9ed9c299b80c32d1a3f2ad0a0dc9b2738831c","dev/sysml/captures/WeaverViews-routeExecution.json":"ae77699f114e1ed5a30f9aeb6d34c54be0aae3bf7ee3b42a61a4bfc417d09d22","dev/sysml/captures/WeaverViews-routeSelection.json":"70e152dd6f715bd7a7f96e029e87b8183f2069e98f1e151ad3b4b20fa6d6eca5","dev/sysml/captures/WeaverViews-storage.json":"7c3168a02518f111381f2699a3f60d5e7c2d4f9fe99c6e7a6571ff58211c79b1","dev/sysml/captures/WeaverViews-streamAdmission.json":"99abf0e6755db2727e2949acc4bb49492a8b2ddcc0f7e3875e581df9cdf138d6","dev/sysml/captures/WeaverViews-zeroTrust.json":"dcc2307f64695bbf9c557bdace5ca8a814fcf440857255db6e050d0911d7c2ac","dev/sysml/ControlActivation.sysml":"3fff66cb1f637af46ceaa276295f90b742d2c492fcb9282ce0ca3eae825d6f83","dev/sysml/ControllerObjectLifecycle.sysml":"b0b8302f1641748cfc3312f8dba8625f2a2961f2d4de3756990c40448eb2eaf2","dev/sysml/CorrespondenceReaderView.sysml":"24b811c00528feaab3547d5db3b7fada290ff89478ac2be0a1d252d8ea1e5828","dev/sysml/ExecutionReaderViews.sysml":"88f690ed1fed91f63f7571d14bf5d7c1c8d14ee3b8d1d17ae333dfd7a6176df3","dev/sysml/FloorReaderViews.sysml":"93401ba5b2009dd54614f7e5aff81d91a20085efbb77b3a143726ffdea16592c","dev/sysml/GatewayArchitecture.sysml":"dbec3964b7873ed0633964b05d1ba1ee828050aed35a3066858d0c38893f2642","dev/sysml/PolicyEvidenceDesign.sysml":"2476fbebe5f299283eca4e0e0f77b114893717c09d839b1f4a7ffad6ea4428ae","dev/sysml/ProviderRpc.sysml":"f1fbde1c104ba448b7af802275b8a903d6830afc52342d06873ce85fa5964e0d","dev/sysml/ReaderDesigns.sysml":"4df8352980f9727b85a26533dc5ebfd67730540359d553a17d562574f3ea2529","dev/sysml/ResearchReaderViews.sysml":"517b8d9359b03cdc1905e2ce61651d2995d23692899864985c0c81123592a4af","dev/sysml/StoragePersistence.sysml":"b6b58b8802a557a7f3af787c2e7875be64865169ca3fd7e9973b13f6c3dc792d","dev/sysml/StreamingExecution.sysml":"d0d4d92300fba2b908ace30d9065cb2bac1d86f3b7c98219c1853a30f3110e85","dev/sysml/WeaverExecution.sysml":"8d09c4ceb0a3dc677047cc1d69700574df8a1f1bddf2a156a3cf93fae89b2f25","dev/sysml/ZeroTrustRefinement.sysml":"7cbec57110f03ed68469a1f49cb2046769516b09a6eb1b9433d866161bba6a82","docs/10-19-llm-gateway/10-routing-and-inference/10.02-llm-routing.d2":"513cad143cde846a9393bb5020dc4843caa1bb844204d3d0c13d1b5ada5efc70","docs/10-19-llm-gateway/10-routing-and-inference/10.05-route-execution.d2":"7c3ff8609c24983d0b27511756d8c5c04d0dc2cf5c973fc7012eaa0acda421e2","docs/10-19-llm-gateway/10-routing-and-inference/10.07-provider-egress-window.d2":"3c9c7c67296700d3b08cea62dddd5bdd011e7bafd61c2b4ecf1e38c32a94d6e7","docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2":"80b85a1f845c440259a93a52b33fae42f5373f985b6dd24d1fcef2c798e5ccf4","docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.d2":"88b797085111294078072dce5983614195e50ac500bcfadad72145dbb295f0be","docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.d2":"d1d5ebe1aeacd18a1f295bf479edb64b2f6f231c4beaf1fe39611bf34c70252f","docs/10-19-llm-gateway/11-attempts-and-failover/11.02-attempt-ledger.d2":"5438329d7af60e9596b5fe4519b04a27a7c36ce1d1dc1aa5442db6df7167cd8e","docs/10-19-llm-gateway/12-semantic-contracts/12.02-semantic-contract.d2":"8560ac03652d2dfb8aeb7797c0e3b61031e49f9a3276d3207c8758a32037c530","docs/10-19-llm-gateway/13-authoritative-scope/13.02-authoritative-scope.d2":"e5950b420b85e30891bdb2264c7fad7ccd9ec9934b6175906d592d683b3a844c","docs/10-19-llm-gateway/14-registry-publication/14.02-registry-publication.d2":"9153743fc734fb044f94a4d22175fbe963f0f15f02598143dfbd7a06cd880177","docs/10-19-llm-gateway/15-recovery-cas/15.02-recovery-cas.d2":"c5de2f6cb52b0450361b2ed0523f647bdcad1fc43d410231f91ae86aee450859","docs/10-19-llm-gateway/16-policy-publication/16.02-policy-publication.d2":"4be00575666b7ada7185a30e553b42b9c36fe9109ce89df3d0dbb4b30ac10cab","docs/10-19-llm-gateway/17-policy-continuation/17.02-policy-continuation.d2":"4108a821aba5a2de1ffebc59b9e0d9180130bb3f598ac2130d59a83e8eca571f","docs/10-19-llm-gateway/18-canonical-registry/18.02-canonical-registry.d2":"f3b44cf54b006df34b528075bbc54742963a53e2afd4cbee435f81095b59b800","docs/10-19-llm-gateway/19-multi-key-registry/19.02-multi-key-registry.d2":"c44a2569dec8ae1fab46acb1ddd58f8b468e7ea7b11136c120a6bf2b042cf8b7","docs/20-29-execution-authority/20-result-projection/20.02-result-projection.d2":"696df32a9d705c6915bcc43a33616126cdce61ce5af0ae198c0dca5bc898d645","docs/20-29-execution-authority/21-join-enqueue/21.02-join-enqueue.d2":"430f46389111827b9f0ad5c9c3193366729fffe917ef18a5bfa0ec8238f6ab02","docs/20-29-execution-authority/22-executor-offer/22.02-executor-offer.d2":"0d93c13abcc1bd79afb32e6ae8a965cc5ec3b0c30fc1958f2f212e12b5e4b65a","docs/20-29-execution-authority/23-execution-reconciliation/23.02-execution-reconciliation.d2":"14c698ad47a243d46d788ab3494b1ad22ae7f14a163140eb6b4f5e8e071c6269","docs/20-29-execution-authority/24-account-commit/24.02-account-commit.d2":"10d6a5116d2c8be77ce7f27312d9d49ad832645c6748bb7bd68bb6942055990e","docs/20-29-execution-authority/25-wal-activation/25.02-wal-activation.d2":"9ebcd14701116e583157282a1678a6f1e0fe70e1ee4b9b7e038b520d4392ce05","docs/20-29-execution-authority/26-checkpoint-truncation/26.02-checkpoint-truncation.d2":"c5c1a35a16fe9b33029169b16d4c0af113f49e665eed0074ce524fc7a15bdb77","docs/20-29-execution-authority/27-manifest-switch/27.02-manifest-switch.d2":"c4de2ef519af25b2c41194df561860ad0236b0309b3178b388204c29cebf9f41","docs/20-29-execution-authority/28-append-handoff/28.02-append-handoff.d2":"f7646793e8540ec5f1e587d5e13deaf16d166180f80107ac8f9c904ea5c9372c","docs/20-29-execution-authority/29-admission-floor/29.02-admission-floor.d2":"0b9794f3d5fdfc7dcdbb519426eecf7e6ec6cb707de5017387c9aa47208ea385","docs/30-39-assurance/31-protected-signer/31.02-protected-signer.d2":"bc787086ae26a1a6cd56e51a2b4182c86e476f13e28ed1f5d80363b1d827e013","docs/30-39-assurance/32-key-boundary/32.02-key-boundary.d2":"1b616363aa68166988cc1d09404d637da406f048b9647676ec5f42d15f1762ca","docs/30-39-assurance/33-device-isolation/33.02-device-isolation.d2":"f4b086efce29484b70d4d4b2c04dad3887976d69187c25234e734e90260a6c7c","docs/30-39-assurance/34-floor-decision/34.02-floor-decision.d2":"78e2de9f044edb41944a56c1c8c8251a9cacd3470cf73c16b87f5ba100139a04","docs/30-39-assurance/34-floor-decision/34.04-floor-recovery.d2":"296d821eae11d4b77a552ae21d91eadcddcf032a15989dd35490128397044203","docs/30-39-assurance/35-intent-continuation/35.02-intent-continuation.d2":"08475ba17d7c98911a7db912041b669d049c75315c861322f72a5b50a471df55","docs/30-39-assurance/36-gateway-head-cas/36.02-gateway-head-cas.d2":"51669df10ec208197e690f656b962b259959af5f225243b62e5ff6bbea5637a5","docs/30-39-assurance/37-broker-consumption-queue/37.02-broker-consumption-queue.d2":"1ad636df3ba980d5f25b1a330c00c8b21f152958fe7c86617736e1b1f85a1ed8","docs/30-39-assurance/38-logical-range-recovery/38.02-logical-range-recovery.d2":"8ed5e1adc741da6852d027828993a83816cadb0c7bc1732bfaf121b2a64878d3","docs/40-49-admission-coordination/40-source-join/40.02-source-join.d2":"b8815cf59a1be49a4657b6ec3857d39e6d7d39ab4bb3ed44521c71ffe0ec5cee","docs/40-49-admission-coordination/41-source-custody/41.02-source-custody.d2":"feef18f62d537d4eb0659c0f1d719218df1a3eda506c9468b59423b151550bd7","docs/40-49-admission-coordination/42-custody-publication/42.02-custody-publication.d2":"24f019e8633cc816f7488e3f65384d2dea96ac8a3685714665a47bc6144b1e5c","docs/40-49-admission-coordination/43-caller-custody/43.02-caller-custody.d2":"6352167e4d3427fd9a66befb74fb3eebf91a127c5e82ecff8312b24178d5117f","docs/40-49-admission-coordination/44-incarnation-issuance/44.02-incarnation-issuance.d2":"215f52c84c9f41c36352f8b6da8b4670f1b375672cfc9efdf6a8bd1df95c946e","docs/40-49-admission-coordination/45-bootstrap-invitation/45.02-bootstrap-invitation.d2":"9e019de8289428a97580fe66ccefc6b9d0a43c1bac07433d2f29596f4d407401","docs/40-49-admission-coordination/46-beneficiary-registration/46.02-beneficiary-registration.d2":"322b848fdd67ea88c99b509cb5d913d7a5023e327edea51f16f44816356d81ce","docs/40-49-admission-coordination/47-enrollment-credential/47.02-enrollment-credential.d2":"ea0aa0bed915bea42d3d65c8f6572f799eb63d0aee1018b75803e61ef034d303","docs/40-49-admission-coordination/48-subject-authority/48.02-subject-authority.d2":"9f707fbc6e5ba8933a0e4d9d057f013c5764afc503f819288f628d3f9709f88d","docs/40-49-admission-coordination/49-routine-routing-config/49.02-routine-routing-config.d2":"7fa18b652ba97e8fe66f402a9a85d65740db9d3ffadff7890db7d72826c498b6","docs/50-59-research-program/51-qualified-semantic-slice/51.06-semantic-gateway-slice.d2":"d63df655a635fccac3c92eded92c039a3f079c24fa2b7a2fd0dc1f3fabd3c0f5","docs/50-59-research-program/52-committed-profile-binding/52.04-committed-profile.d2":"3ea30976830c607bf8cec62cbabc4291c384bd5f368049a45777f6f981d87d6e","docs/50-59-research-program/53-gerbil-exit/53.04-gerbil-lifecycle.d2":"b7b623664edc6e86efe62eeee7f5977dc207f0cb12e40cb6f0e77e38160695de","docs/50-59-research-program/54-dynamic-gxi-exit/54.04-dynamic-lifecycle.d2":"d4d410dd8cb10de6d3526b54ac7f96731d2f2a94dd9763aad96a0926608e251c","docs/50-59-research-program/55-dynamic-gxi-paired/55.04-runtime-boundary.d2":"573b248a6b7ce2d7eee1e70a469c54e4f195c4894ec7b0f61c8406fae843eccc","docs/50-59-research-program/56-gambit-image-closure/56.04-locator-boundary.d2":"0c45ee11d269b0cab8998c7fc3432ec851b9390b7530486225134b261d8d7de8","docs/50-59-research-program/57-runtime-implementation/57.03-runtime-boundary.d2":"193d22a5bd9e4b23260334d085df8aa5ec19c349f13cd9f56eaa26fe54f7e3ac","docs/50-59-research-program/58-streaming-execution/58.03-streaming-runtime.d2":"76ea49c83b4b36af1e775f80475d40747640b80a330434bf86635e255e84ef14","docs/50-59-research-program/58-streaming-execution/58.05-range-progress-recovery.d2":"aef20c8ad7d7420a65422add6d9fb635bdbe32e42e49427d3179bf20499ae4cd","docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2":"20208cf52e745a108af602d4e5c88b06fe8b93c0fc87230b0577faf6029f8dd9","docs/50-59-research-program/59-provider-rpc/59.21-verification-ownership.d2":"e035ae7e56ee5e6498f131ed62f4792547c1e716aa5ed29865b333f54665e8f1","docs/50-59-research-program/59-provider-rpc/59.26-semantic-execution-ecosystem.d2":"50c091b094125693e2debe73599a63405849f1f55ab3658030674692c9334e14","docs/50-59-research-program/59-provider-rpc/59.30-governance-adapter-acceptance.d2":"88cbbd45e63358bb45a58fb27f85e275b9cc9fb3d3aee6af19eabed0912545d2","docs/50-59-research-program/59-provider-rpc/59.43-floor-transport-owner.d2":"36c4d6b561332ab30deb464a92bb4c2f02ceed5c8a1ca66617f72b6086b2c555","docs/50-59-research-program/59-provider-rpc/59.44-cloud-rpc-arrow-boundaries.d2":"fe0ac2220e04f6ccea851247ecf8ae1cab4ec8c8ba8744010c478992c233ebed","docs/50-59-research-program/59-provider-rpc/59.45-slow-consumer-zero-trust.d2":"e36cf58a239a2d9f0c99789bb7484de4e26180a8f941970540f72b530a79d813","docs/50-59-research-program/59-provider-rpc/59.46-functional-security-frameworks.d2":"e541b969352e8149e71e5b539988f9955b525e5e5ba3e7e7270bd4a98fbe19f5","docs/50-59-research-program/59-provider-rpc/59.47-property-testing-framework.d2":"f66ed065dcf955a233968ca295517c642be30dad9b24e23a781fe34e4bed45d9","docs/50-59-research-program/59-provider-rpc/59.49-policy-proposal-barrier.d2":"3a8559bb22f812075d9d7de4a397978995d06c32ed22e9415f990413551aebb6","docs/50-59-research-program/59-provider-rpc/59.50-parent-contract-and-replay.d2":"2db3983f56e938c927b68077551573c8e86362da892f47890459ab7b3f929c64","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-architecture.d2":"10e92e79b69f4b0813551dd2ddadc5ad225b7b0fa8374ed7015b7f2fe66bb6e1","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-contract-refinement.d2":"204c9e20d9027b7a38bf2a964da9a7cadb92744561fa9f1eb3fa29d00f4fa386","docs/50-59-research-program/59-provider-rpc/59.52-reviewed-publication-cas.d2":"4e0998e61717d5441e242cde0dfc52198312b67b63f0ce8b0425a423d1b88a24","docs/50-59-research-program/59-provider-rpc/59.53-artifact-registry-recovery.d2":"f7083a48413d41ad99e7191281bd6e74a92b33c7cc1f4f2f9ae322bb1405088a","docs/50-59-research-program/59-provider-rpc/59.54-source-incarnation-authority.d2":"1e55c0487f01d70462e8df6b46eff9e799b0dc592c0e780c759fa602e3d84444","docs/50-59-research-program/59-provider-rpc/59.55-evidence-reviewed-publication.d2":"c66435372642f7a93ca7fc6f78c2abcbc364a4dde447d10dcc4b2b21ccc06456","docs/50-59-research-program/59-provider-rpc/59.56-runtime-assets-and-authority-floor.d2":"c675469701bb6994fed1976d1e90d01dc1cc4e416a6788f865494fa3243d32c1","docs/50-59-research-program/59-provider-rpc/59.57-schema-bound-candidate-replay.d2":"5ca15af556e0a4ba5bdf1742cf81182ad72e7f51b2eb63352b839e068a7ad7d2","docs/50-59-research-program/59-provider-rpc/59.58-independent-source-recovery.d2":"4b21999b3554be15374448f36ffbccf517b32784a65cadde0f4c1eb8308da377","docs/50-59-research-program/59-provider-rpc/59.59-retained-root-and-recovery-coverage.d2":"37fdf1d3dd01f087434a6108b43a5657d7aecf79a2b9e60638d70eb0b1a4984b","docs/50-59-research-program/59-provider-rpc/59.60-persistent-source-key-custody.d2":"d27df3a14df5d57ad725c1455c82a4ab5bad45b78acea8cd1a76e59958b710eb","docs/50-59-research-program/59-provider-rpc/59.61-authority-bound-replay-pair.d2":"bd4962775564848a90ec49439301cf0cdfbaa4018956344e809f5b318bea6ccd","docs/50-59-research-program/59-provider-rpc/59.62-burn-exposure-recovery.d2":"fab4ea6d0981d75dd4c704f302268f3c5af0898e299e8e0fb38b34d07200b22c","docs/50-59-research-program/59-provider-rpc/59.63-mrr-admission-contract.d2":"ed3c604e0d350049f00528c7117675a7db751b3d6683719b03be116bcf49d5c5","docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.d2":"7164874fdbeec99f2185e1091f759466a68a3b7d9b239db6a503f16383fce50e","docs/50-59-research-program/59-provider-rpc/59.65-turso-concurrent-admission.d2":"0ade3ea326e2066ce908129e383b7e0f371a429710ed0a0bad30ddcfd61f034e","docs/50-59-research-program/59-provider-rpc/59.66-bounded-writer-reuse.d2":"9390a3c12f06c2f33e3df99088dc39de92d3bccc971ddf5a632910515a67623e","docs/50-59-research-program/59-provider-rpc/59.67-writer-owner-lifecycle.d2":"c28559ccf38b2f3320d84bbc0ffc6133e2708081e95bff39d5ed75d064287bde","docs/50-59-research-program/59-provider-rpc/59.69-hot-path-cost-boundaries.d2":"e5789625590fab63bc3635627b7e20ac41f64b8f40cbeee84d51a85f27ab31f1","docs/50-59-research-program/59-provider-rpc/59.75-complete-entry-and-output-contract.d2":"d667501bc15d6c31d986994f641d8d38f63c1d910784e6852e596c24c4e4c7c7","docs/50-59-research-program/59-provider-rpc/59.75-package-linkage.d2":"bc655ae71cc46e0d5b7f42637b78530f262c3142394485e2a9ba31f6516a0a10","docs/50-59-research-program/59-provider-rpc/59.76-embedded-tooling-and-darwin-io.d2":"87655d7c6d81c1ab203f886930f1630003e006c0edb71f90ac3ca23a0cb91845","docs/50-59-research-program/59-provider-rpc/59.77-mrr-turso-storage.d2":"72a4dceeb20cca337276f64537d47dbbd2ac0ce359a7a63997090e6476a40c96","docs/50-59-research-program/59-provider-rpc/59.84-quint-preparation-and-completion.d2":"17f485d7c541506c42003ebba887705ea61972f00c9498aa3c0d153a33b02922","docs/architecture/08-diagram-catalog.org":"353a4296584381207513468ef291e7e1aefdcd6f9f2b854c92be90aab47577ea","docs/architecture/diagrams/00a-readme-overview.d2":"1e6119c9d5b2d8a40d3bec0c8add35e8c078dd739e46fcf45c589b8125c7c46f","docs/architecture/diagrams/00c-gateway-runtime.d2":"c1d93cc1f635803872e3349c89b5127145bdcdd2b85e9a48f83d63f0bda439da","docs/architecture/diagrams/00d-zero-trust-overview.d2":"0d3d1a5de0967db2331b9be81468cee1b7cb1d1d98966c5e541e4fc24023f2e6","docs/architecture/diagrams/01-system-boundaries.d2":"0d35addc4e27ab2d6220103872deab6abc1754a6bc36ba236ab3088b1c6d22b5","docs/architecture/diagrams/01-system-relationships.d2":"dde40fac8667b79a070fda14ebd892f1f1e7c1217726595179b541c855f80c2c","docs/architecture/diagrams/02-admission-sequence.d2":"97077cb16cd4457fe14092caeb4bc8cf2912d434763a08fcf350cd6a4c2b2c74","docs/architecture/diagrams/03-attempt-state.d2":"e696fc0f1d63f58100405852e88e8a7dfb1a625e43be398f3bb54bbc1d90e13a","docs/architecture/diagrams/03a-attempt-observation.d2":"6b387ec7fbcff7d5e3e129bad7ea9590afe0324800a5a13bf7a89377ad86c387","docs/architecture/diagrams/04-consume-timeout.d2":"2ccfe8d033069e0d891531f3b5afef4febf21b2722209a612454d14321cac940","docs/architecture/diagrams/05-fencing-boundaries.d2":"1103ed75ac615b1a2f8239c0321d046a5a87acfa235d5042d8a529e23acd7483","docs/architecture/diagrams/06-source-admission.d2":"4d20817291c5de93b7f97366e6cb1b4af954f22de1ebcb3012c139a4b9dbd82c","docs/architecture/diagrams/07-post-claim-outcomes.d2":"63258620c15c2f52963dcdba33b4ac82cd12aadd1c2de005cd029655493493c1","docs/architecture/diagrams/08-code-as-policy.d2":"fc2263ff1ae000055e6054b89beee60f53b9621707510354c34ef45057889676","docs/architecture/diagrams/09-claim-wins-race.d2":"9eff775ddac29c47acd2c0b69fb1ff98ba9a20943da970c2804e270979555c41","docs/architecture/diagrams/10-commit-dispatch-sequence.d2":"fa5d56c49bc3f590c88cf7c3b63e180afd2d2a39fca878d1515917077ff1687a","docs/architecture/diagrams/11-zero-trust-assurance.d2":"ea93840da2ff4bdac59349f5ad7a56cee5506600283d0c364c53275dde0b5b48","docs/architecture/diagrams/12-execution-correspondence.d2":"1dd66ee8c517fd9c6f2f4b1700aeec3e620d699fbe9eeee20df8e05a7f1decb0","docs/architecture/diagrams/13-policy-to-execution.d2":"4bb05b74c3bc0ca997c5e5035ddc949fa374db3ff49bf2104a6c9753e12be3ef","docs/architecture/diagrams/14-adapter-broker-boundary.d2":"b855fa0482a5524226354b26bc8d7ecef0daf2ab1cab54c1783eba0ff29fab01","docs/architecture/diagrams/15-stream-message-authorization.d2":"cedf1c545a853ec2a9ae51bea928b04376d192f1a4c2af117fa54f475ad541e0","docs/architecture/diagrams/16-authoritative-spent-state.d2":"201bd9fe5eb6101543d939e3d83aca646e2b07c13ff1e3c56779571a0cd1172e","docs/architecture/diagrams/17-logical-message-observation.d2":"2333ad147295ead60ed6a92dc824cf6f5769f3828eff1e0cdf58e50aace7b1e1","docs/architecture/diagrams/18-shared-identity-budget.d2":"5ab4992fd8b6a6abf518fb0bbc8c2c8ad8b920d0be74a6e734d846319252ffa7","docs/architecture/diagrams/19-finite-domains-and-migration.d2":"b72b451d0bb97de46831e4b266d8fdd22d59e7d54db99446d53549f081a008e2","docs/architecture/diagrams/20-anchor-recovery-and-egress.d2":"9479271410f1bb57f92106a1d91ec73c73872568d9fcda55cac5aa64b89e5c9f","docs/architecture/diagrams/21-composed-journal-transport-lifecycle.d2":"0fffe555ee4c2c1222c97eebd24ca9b0df91a4d3ec118300ae3b88240004c3c8","docs/architecture/diagrams/22-finite-stream-manifest.d2":"60b33eb6d06aeaa1027546a1fc9d6c07069c3cd3c7d23df8ff8d63a341afe2ea","docs/architecture/diagrams/23-driver-completion-recovery.d2":"271963db2cd881bb82e164bb1544c7bcf311e1781f20170d858ccb65a596d8f5","docs/architecture/diagrams/24-writer-settlement-closure.d2":"ea1930326b0073e7fabd8b64ef3ffea781f1aef60db0d942f9ab14f1150296e9","docs/architecture/diagrams/25-settlement-anchor-recovery.d2":"8904bfcda525de21b48ea8f2db8d12aaa27e85818ccde43fb545851dc522ba3b","docs/architecture/diagrams/26-gate-consumption-persistence.d2":"42e676634ecb40cfb2dee06db1f5497d0e58c05f30097618c3852eb946992f0d","docs/architecture/diagrams/27-anchor-commit-broker-fencing.d2":"5c2ae36987b00655bbcdba36352e03b61765739ad2f3fc80a561ff0d325a9461","docs/architecture/diagrams/28-anchor-configuration-prefix.d2":"1ac0eeb3c76f5ae0ce3565d4469e50210786c3bc53c703a1a61d519dfa075512","docs/architecture/diagrams/29-quorum-durable-promises.d2":"2e4a24c3fae49e710d5afc31d4681a9efc8c2e8af3fa58a0957ede05fe7c0255","docs/architecture/diagrams/39-shared-execution-exposure.d2":"2c08f5b3d4531a7be2aadec8f1ff9d4476495418e94e84c1ff643583ac991ce4","docs/architecture/diagrams/assets/agent-request.svg":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","docs/architecture/diagrams/assets/bounded-write.svg":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","docs/architecture/diagrams/assets/budget-ledger.svg":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","docs/architecture/diagrams/assets/components/activity.svg":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","docs/architecture/diagrams/assets/components/book-open.svg":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","docs/architecture/diagrams/assets/components/bot.svg":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","docs/architecture/diagrams/assets/components/brain.svg":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","docs/architecture/diagrams/assets/components/circle-question-mark.svg":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","docs/architecture/diagrams/assets/components/clipboard-check.svg":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","docs/architecture/diagrams/assets/components/coins.svg":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","docs/architecture/diagrams/assets/components/database.svg":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","docs/architecture/diagrams/assets/components/file-check.svg":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","docs/architecture/diagrams/assets/components/fingerprint-pattern.svg":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","docs/architecture/diagrams/assets/components/message-square.svg":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","docs/architecture/diagrams/assets/components/rotate-ccw-clock.svg":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","docs/architecture/diagrams/assets/components/rotate-ccw.svg":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","docs/architecture/diagrams/assets/components/route.svg":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","docs/architecture/diagrams/assets/components/send.svg":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e","docs/architecture/diagrams/assets/components/shield-check.svg":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","docs/architecture/diagrams/assets/components/ticket-check.svg":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","docs/architecture/diagrams/assets/components/waves-horizontal.svg":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","docs/architecture/diagrams/assets/components/workflow.svg":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","docs/architecture/diagrams/assets/go.svg":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","docs/architecture/diagrams/assets/kubernetes.svg":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","docs/architecture/diagrams/assets/model-catalog.svg":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","docs/architecture/diagrams/assets/model-provider.svg":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","docs/architecture/diagrams/assets/permission-check.svg":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","docs/architecture/diagrams/assets/route-choice.svg":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","docs/architecture/diagrams/assets/rust.svg":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","docs/architecture/diagrams/assets/task-contract.svg":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","docs/architecture/diagrams/assets/unknown-hold.svg":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","Project.sysml":"5691b1b59a24eb80b61b7e6e49cab49c2e9516640d872c273eaa3b05ee9975bb"},"rendered":{"observation":{"canvas":{"x":0,"y":0,"width":980,"height":846.765625},"subjects":[{"id":"n0","role":"default","x":28,"y":251,"width":286.65625,"height":85.984375},{"id":"n1","role":"default","x":346.65625,"y":251,"width":286.671875,"height":238.890625},{"id":"n2","role":"default","x":665.328125,"y":251,"width":286.65625,"height":238.875},{"id":"n3","role":"default","x":28,"y":567.890625,"width":286.65625,"height":238.875},{"id":"n4","role":"default","x":346.65625,"y":567.890625,"width":286.671875,"height":86},{"id":"n5","role":"default","x":665.328125,"y":567.890625,"width":286.65625,"height":85.984375}],"relations":["edge:0","edge:1","edge:2","edge:3","edge:4"],"headings":[{"role":"title","x":20,"y":20,"width":940,"height":63},{"role":"question","x":20,"y":83,"width":940,"height":56},{"role":"note","x":20,"y":155,"width":940,"height":48}]},"readability":{"minimumTextSize":24.839930555555554,"samples":16},"bounds":{"objects":{"x":20,"y":231,"width":940,"height":595.765625}}}}Separate control RPC from provider I/O?How does the gRPC proposal become a bounded provider effect?Rust owns final admission and response release. -Governed configTyped Scheme or data - +Governed configTyped Scheme or data + @@ -45,9 +47,11 @@ SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 --> -Go control RPCCarry the bound proposal - +Rust source RPCCarry the bound proposal + @@ -55,8 +59,10 @@ SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 --> Rust admissionCheck Cedar and claim - + diff --git a/docs/50-59-research-program/59-provider-rpc/59.19-governance-control.org b/docs/50-59-research-program/59-provider-rpc/59.19-governance-control.org index 81545726..67d8d788 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.19-governance-control.org +++ b/docs/50-59-research-program/59-provider-rpc/59.19-governance-control.org @@ -467,21 +467,23 @@ The retired Go linked-source checker is not evidence for this delegated path. #+begin_src text go -C go run ./cmd/weaver-dev check go -C go run ./cmd/weaver-dev check-scheme -go -C go build ./cmd/weaver-control +cargo build --release --locked -p weaver-server --features arrow,scheme-program +target/release/weaver-server prepare --config /path/to/weaver.toml #+end_src Use the SDK's =GERBIL_GXI= override only when compiler discovery needs an explicit selection. Weaver calls native package/staging APIs and exports typed FFI data. -The actual =weaver-control= executable selects exactly one of -=WEAVER_CONTROL_PRODUCER= (approved Rust producer name) and -=WEAVER_CONTROL_CONFIG= (JSON/YAML data file), and uses =WEAVER_CONTROL_LISTEN=. -It never starts a Scheme compiler or accepts a Scheme file as runtime code. -An absent producer/catalog or failed compile cannot fall back to a data file. -The Rust deployment must explicitly install the approved program/catalog; -the test qualification graph is not a production program. There is no operation -CLI or stdin protocol. - -| Environment group | Required settings | +Rust preparation reads the separate source connection settings from =[source]= +in =weaver.toml=. Choose exactly one =producer= or =file=. The producer path +requires the approved program and catalog to be installed. The file path +accepts JSON/YAML data, is relative to =weaver.toml=, and uses the existing +source-only composition RPC. YAML accepts one UTF-8 document with the existing +core data types. Duplicate keys, custom tags, anchors and aliases are rejected. +Operation clients connect to the Rust listener. +The Go reference executable under =go/dev/controlref= is used by the acceptance +suite to compare the previous file and relay paths. + +| Environment group for the Go reference | Required settings | |-------------------+-------------------| | Frontend TLS | =WEAVER_CONTROL_SERVER_CERT=, =WEAVER_CONTROL_SERVER_KEY=, =WEAVER_CONTROL_CLIENT_CA= | | Frontend caller | =WEAVER_CONTROL_PEER_SHA256=, =WEAVER_CONTROL_TOKEN_SHA256= | diff --git a/docs/50-59-research-program/59-provider-rpc/59.82-semantic-responsibility-allocation.org b/docs/50-59-research-program/59-provider-rpc/59.82-semantic-responsibility-allocation.org index 94a3a80c..faf50d2c 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.82-semantic-responsibility-allocation.org +++ b/docs/50-59-research-program/59-provider-rpc/59.82-semantic-responsibility-allocation.org @@ -13,7 +13,7 @@ actions, rather than introducing another issuer, coordinator or source ledger: | Existing owner | Allocated action | Contract and boundary | |----------------+------------------+-----------------------| | SchemeSemanticPublisher | DeriveSemanticCandidate | Independently admitted SemanticCommitment to inert SourceCommand | -| GoControlAdapter | OrchestrateSourcePublication | Preserve the original while submitting an authenticated SourceCommand | +| SourceControlAdapter | OrchestrateSourcePublication | Preserve the original while submitting an authenticated SourceCommand | | RustLedger | CommitOriginalAdmission | SourceCommand to PublishedObservation under current authority and durable CAS | | RustFinalBroker | GuardFinalEffect | ConsumedPermit to actual wire request under current final custody | diff --git a/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org b/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org index 3ef98c21..49bdb731 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org +++ b/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org @@ -271,6 +271,55 @@ R3 still owns further startup/configuration consolidation. R4 cloud adapters and R5 reference/packaging removal are separate work; neither is required to route a default R2 operation through Go. +** R3 startup and source handoff + +Publisher credential rotation changes the source mutation identity. A fixed task +already registered under its committed publication keeps the original activation +revision and fence. Cold lookup, a warmed projection and restart must make the +same original available to the broker. Withdrawal uses the existing publication +or hard-fact decision path. A catalog scope still needs its declaring epoch when +it registers a selected task. + +Qualify =weaver-server prepare= first with an approved Weaver Scheme producer +and the existing Snake Oil deployment. The command uses the separate source TLS +identity, checks the compiled source's authority, and verifies publication key, +revision and fence on the existing stage, register and commit path. Retry from +the exact publication receipt after ambiguous replies. Continue with +=weaver.toml= after the original native entry passes. Treat file configuration +and independent review as explicit input paths in the migration inventory. + +The scoped baseline commit =156c89a9bb460040e1cc43ad65113e6022466889= passed the +repository hook. Its isolated archive matched all 11,336 tracked files and +passed the project architecture, SysML trace and shared RPC schema controls. +The snapshot exceeded the existing 480-second build budget during native +Scheme object compilation. The candidate built through the working-tree entry and +passed the fixed-plan handoff controls and the first Rust preparation and +operation call. The first reply-loss diagnostic run +reached the three-second listener bound in the staging case and the ten-second +CompileSource bound before staging in the publication case. Preserve those +outcomes separately from the later same-image cohort. That cohort passed +both reply-loss controls, direct environment and TOML preparation, and all +three fixed-plan handoff modes. Its first process exceeded the three-second +listener readiness deadline before the main marker. The bounded single-case +follow-up on the same image passed hard-fact withdrawal, exact pending-barrier +recovery and A-to-B-to-A. The whole cohort remains open. + +** R4 Kubernetes source observation + +The Weaver-owned =ProviderAvailability= resource is bound by namespace, name and +UID. The Rust watcher reads the current resource after events, stages a new +intent before resolving older pending work, and writes status with an exact +resource-version precondition. The feed observation API authenticates the +existing source credential and returns the installed cut and pending barriers. + +The initial Kubernetes-feature build exceeded the 480-second budget. The +subsequent incremental build completed in 2m39s. On that release, the +hard-fact withdrawal/restart/A-to-B-to-A case passed in 10.97s and the Kubernetes +loopback case passed in 6.75s. The latter exercises adapter restart, duplicate +delivery, expired watch and relist, replacement-UID withdrawal and one real +provider execution. It uses a local API fixture and the real source lane, +Scheme impact, ledger and broker. Live Kubernetes deployment remains separate. + ** Current implementation and destination matrix | Existing owner | Actual responsibility | Target owner and reuse | Migration obligation | @@ -287,15 +336,42 @@ route a default R2 operation through Go. | metering/issuer.go and cmd/weaver-meter | Independent terminal-usage signing and settlement | Separate issuer role, optionally implemented in Rust | Preserve independent key custody, deterministic application ID and restart idempotence; do not fold signer into gateway authority | | specreview/producer.go | Deployment-qualified SPEC catalog binding and independent review signing | Separate review role using existing SPEC outputs and Rust contracts | Preserve pinned artifact, audience/epoch and independent keys; Scheme cannot self-approve a migration | | telemetry/metrics.go | Admission/completion/frame counters | Rust telemetry plus bounded protocol export | Equivalent meanings; no synchronous collector dependency in frame loop | -| cmd/weaver-import-provider | Operator import utility | Rust adapter + existing Scheme profile entry | Preserve explicit review; no hot-path interpreter or second build entry | +| Offline LiteLLM import | Operator import utility | Rust =weaver-server import-provider= and existing catalog contract | Preserve explicit review, original plan digest and no publication side effects | | internal/devrunner, go/dev, cmd/weaver-dev | OpenSysML analysis/rendering, finite orchestration, Go reference/negative controls | Retain now; use existing SDK and runners | No rewrite merely for language uniformity; Go-less production can coexist with Go development tools | | go/api | Generated RPC and Go-side contract/reference code | Keep generated bindings for live consumers; Rust contract is execution owner | Remove handwritten duplicates only after all callers and reference tests have a replacement | +The checked-in relay build consumer is =go/dev/provider_fixture_test.go=. +It builds =go/dev/controlref= under the development boundary. Deployment uses +=weaver-server prepare= for approved producers and JSON/YAML files. Both use +the existing source checks and durable publication path, and JSON/YAML files +can carry independently issued review evidence. The Rust offline LiteLLM import +emits the existing catalog proposal record. =weaver-meter= and the independent +review issuer have separate key custody and consumers. + +R5 acceptance uses the existing =go/dev= integration entry with +=TestProviderRustDirectFilePreparation=, +=TestProviderRustDirectCatalogSelection= and +=TestProviderRustDirectReviewedCatalogImport=. The cases cover signed JSON and +TOML-selected YAML sources, catalog replacement and guarded execution, and an +offline proposal equal to the existing reviewed Go import. The independent +review tests cover signature interoperability and rejection of changed signed +coordinates. Metering application and review recovery are separate integration +cases. The Go entry list and the production asset boundary verify which +packages remain reachable from =weaver-meter=. + +Verification source, fixtures and acceptance commands are versioned with the +implementation. Release executables and generated receipts remain local +outputs. The harness can compare a release SHA-256 to bind multiple cases +to the same Cargo executable. + +When the Cargo target is cleaned, regenerate the Policy FFI pkg-config +record with the existing =policy_pkg_config= example. Its selected library +must exist through Scheme staging and consumer verification. + Current go/go.mod contains OpenSysML, Arrow, gRPC, Protobuf and format handling; it does not contain Kubernetes client-go/controller-runtime, Helm or Istio. -Thus current production Go forwarding and semantic duplication have concrete -maintenance cost; present cloud-native SDK reuse is not their justification. -This is a source/dependency finding, not a claim that Go is generally slow. +The former Go gateway used the shared RPC protocol and carried no cloud-native +SDK integration. The retained Go command owns independent metering. ** Cloud-native integration beyond Kubernetes diff --git a/docs/architecture/00-system-design.org b/docs/architecture/00-system-design.org index d00f38be..b4da7f19 100644 --- a/docs/architecture/00-system-design.org +++ b/docs/architecture/00-system-design.org @@ -48,8 +48,8 @@ owned parts of the system to which those contracts apply. | Element | Core architectural role | Relationship to the execution chain | |---------+-------------------------+-------------------------------------| | Scheme / POO | Governance authoring, composition, source and lifecycle ownership | Selects the admitted policy closure and supplies owner-bound operation/currentness contracts | -| Go | Current typed transport; OpenSysML development tooling; optional justified SDK integration | Carries source proposals and observations; no deployed semantic selector, Workflow interpreter or execution right | -| Rust | Reference authority integration, durable coordinator and constrained broker | Enforces consumption, ledger transitions, unique claims and final transport guards | +| Go | OpenSysML development tooling, reference controls and independent signing | Reference clients exercise the same typed protocol. The signing service owns its separate keys | +| Rust | Source preparation, durable coordination and constrained broker | Enforces consumption, ledger transitions, unique claims and final transport guards | | Cedar | Shared authorization language and selected evaluation kernel | Evaluates the complete required permission questions on the bound operation; allow alone cannot send | | Quint | Concurrent/fault state model | Models consumption, commit, claim, send, recovery and cloud-update races across all implementation owners | | Lean / cedar-poo-spec | Semantic foundation and preservation obligations | Reuses owned definitions and proves meaningful projection/transition properties under stated physical premises | @@ -163,17 +163,17 @@ state transition or a field named =signature= or =durability= cannot establish cryptographic verification, serialized consumption, or durable storage. Preserve these host obligations when reusing the existing semantic APIs. -** Go: typed transport, development tools and selected SDK reuse +** Source transport, development tools and selected SDK reuse -The default Go command performs source preparation and exits; operation clients +The Rust =weaver-server prepare= command performs source preparation and exits. Operation clients connect directly to the existing Rust listener. JSON/YAML and compiled Scheme sources declare exact fixed plans or a bounded catalog selector through the existing authenticated source RPC. The existing ledger retains those source scopes. Rust resolves fixed plans directly; dynamic selection uses the existing Scheme/POO/ASCENT owner and rejoins current source/publication/catalog state in the task-registration transaction. Reused projections carry no permission. -Go's explicit =serve= path remains for reference controls and later R5 retirement. -R1's remaining Bundle/routing functions serve development/reference callers. +The Go relay and remaining Bundle/routing functions serve development reference +controls under the development boundary. OpenSysML development analysis/rendering remains Go because the project already reuses its SDK. Future production Go adapters need a concrete required library diff --git a/docs/architecture/06-go-control-plane-role.org b/docs/architecture/06-go-control-plane-role.org index 9acc8d1f..2f604a79 100644 --- a/docs/architecture/06-go-control-plane-role.org +++ b/docs/architecture/06-go-control-plane-role.org @@ -5,7 +5,7 @@ #+title: Rust, Scheme and Go: Runtime and Cloud Integration Boundaries #+language: en #+date: 2026-11-10 -#+property: STATUS R1-R2-locally-verified-later-stages-planned +#+property: STATUS local-delivery #+options: toc:2 * Architecture decision @@ -14,9 +14,10 @@ The production target is Rust + Scheme/POO/gerbil-ascent. Rust owns network I/O, bounded queues, durable state and final effects. Scheme owns higher-order configuration, object composition, rule inference and Workflow semantics. Go is optional for concrete integration/development reuse; it is not a required -planning hop in the target architecture. R2's default source-preparation command -exits before fixed or catalog-selected operations reach Rust directly. Only -explicit =serve= retains the Go relay for reference controls and R5 retirement. +planning hop in the target architecture. =weaver-server prepare= exits after +source activation. Fixed and catalog-selected operations enter Rust directly. +The former Go gateway command lives under =go/dev/controlref= for reference +controls. The model authority is [[file:../../dev/sysml/ArchitectureEvolution.sysml][ArchitectureEvolution::RustSchemeAllocation]], linked to [[file:../../dev/sysml/WeaverExecution.sysml][WeaverExecution]] and the existing source, ledger and object-lifecycle @@ -28,15 +29,15 @@ latency gate or establish exact-head GitHub CI. | Responsibility | Owner and existing mechanism | |----------------+------------------------------| -| Decode external JSON/YAML syntax and copy typed data | Existing Go file adapter; no semantic selection | +| Decode external JSON/YAML syntax and copy typed data | Rust source preparation decodes into the existing Scheme composition contract | | Candidate eligibility, exact rounded cost/latency/digest ranking | Scheme POO records and gerbil-ascent on the existing affine owner | | Session topology, nested choice/parallel/join and ready-node derivation | Existing Scheme Session/Funflow/Governor and ASCENT | | Canonical plan/body commitments and request/profile/endpoint guards | Rust contracts and shared HTTPS transport guard | -| Configuration/source proposal delivery | Existing authenticated source gRPC; Go currently transports the data | +| Configuration/source proposal delivery | Rust source preparation uses the existing authenticated source gRPC | | Catalog observation and typed fact projection | Existing Rust source owner and ledger; no second database | | Immutable projection reuse | Existing version/record cache and bounded coalescing; no cached permission | | Publication, exact source/currentness, claim, reservation, hard-fact barriers | Existing Rust deciding transactions | -| Credentialed request, streamed response release, fallback and uncertain outcomes | Existing Rust broker/runtime; R2 fixed/catalog callers connect directly, retained relay callers use serve | +| Credentialed request, streamed response release, fallback and uncertain outcomes | Existing Rust broker/runtime and direct authenticated ingress | | Independently issued SPEC review and terminal usage signatures | Existing separate issuer custody; language migration cannot merge keys | | OpenSysML analysis, model rendering and development drivers | Go, retained for direct existing SDK reuse | @@ -61,7 +62,7 @@ observed version and recheck it afterward. Full source assessment remains in CompileSource; pure composition does not delay listener readiness with module source evaluation. Rust keeps fresh deciding checks at actual use. -The Go adapter copies independent SPEC review data without regenerating it. +The Rust file adapter copies independent SPEC review data without regenerating it. A new candidate or source response cannot self-approve the publication it suggests. See [[file:09-code-as-policy.org][Code as Policy]], [[file:05-authorization-execution-protocol.org][authorization-to-execution coordination]] and [[file:13-go-adapter-broker-boundary.org][adapter-to-broker custody]]. @@ -103,7 +104,7 @@ Language choice follows the required integration and its existing evidence: | Agentgateway's Go controller dependencies include Kubernetes, Gateway API, Istio, Helm and xDS | Go can aggregate substantial integration machinery when those exact capabilities are required | | Helm pkg/action provides release lifecycle APIs | An embedded Helm lifecycle can justify a separate Go deployment adapter; ordinary chart installation need not be embedded | | containerd exposes a rich Go client and remote service APIs | Choose protocol access or a Go SDK by required lifecycle behavior; do not turn the gateway into a container orchestrator by default | -| OpenTelemetry Collector is independently deployed and Rust has an SDK | Reuse the Collector through its interface; its Go implementation does not require embedding Go | +| Praxis embeds request metrics, structured logging and optional OTLP tracing in its proxy. Agentgateway embeds metrics and configurable OTLP export in its Rust data plane. | Weaver's Rust runtime owns instrumentation and protocol export. A separately deployed Collector can receive, process and forward telemetry. | These decisions use upstream source/interfaces and maintenance evidence. Weaver need not implement both ecosystems or rerun generic ecosystem benchmarks to @@ -138,3 +139,56 @@ Finite R1 evidence and remaining gates live in the delivery plan. Compile, listener readiness, first source assessment, hot execution and drain are separate measurements. The same release and original acceptance thresholds apply; a language-placement change alone does not satisfy the outstanding 1 ms target. + +The first R4 integration uses the Weaver-owned +[[file:../../prod/kubernetes/provideravailability.crd.yaml][ProviderAvailability resource]] +in =weaver.hardenedlinux.org/v1alpha1=. Its namespace, name and UID identify +the bound resource. =spec.available= is the requested hard fact. The =status= +subresource records the observed generation and resolved ledger coordinates. +Build =weaver-server= with the =kubernetes= feature and run +=weaver-server reconcile-kubernetes --config weaver.toml= as a separate process. +The example [[file:../../prod/kubernetes/provideravailability.rbac.yaml][namespaced RBAC]] +binds its service account to one named resource. The gateway uses its existing +hard-fact feed and source TLS credentials. The adapter uses the Kubernetes +service account for the watch and =status= subresource. + +#+begin_src toml +[source] +address = "weaver-source.weaver-system.svc:7443" +server_name = "weaver-source.weaver-system.svc" +ca = "source-ca.pem" +certificate = "source-client.pem" +key = "source-client-key.pem" +token_env = "WEAVER_SOURCE_TOKEN" + +[kubernetes] +namespace = "weaver-system" +name = "provider-availability" +uid = "" +domain = "availability" +#+end_src + +The adapter reads the resource after watch events and relists. It uses the +Kubernetes resource version for watch recovery and as a status write precondition. +The ledger assigns its own source epoch, revision, snapshot and intent prefix. +The adapter stages the latest observed change before resolving older pending +intents. Deletion or a replacement UID requests withdrawal. A Kubernetes +connection error leaves the last committed ledger decision in effect and retries +the observation. The focused integration test uses a loopback Kubernetes API +fixture and real source, ASCENT, ledger and broker paths. From the prepared +Gerbil package environment, use the existing integration test entry: + +#+begin_src sh +export WEAVER_GOVERNANCE_APPLICATION=hardenedlinux/weaver/scheme/gateway/provider-program +export WEAVER_GOVERNANCE_APPLICATION_SOURCE="$PWD/scheme/gateway/provider-program.ss" +timeout 480s cargo build --release --locked --offline -j4 -p weaver-server \ + --bin weaver-server --features arrow,scheme-program,kubernetes +release="$PWD/target/release/weaver-server" +WEAVER_TEST_PREBUILT_PROVIDER_IMAGE="$release" \ +WEAVER_TEST_PROVIDER_IMAGE_SHA256="$(shasum -a 256 "$release" | cut -d ' ' -f1)" \ + go -C go test -mod=readonly -parallel=4 -cpu=4 -count=1 -timeout=55s \ + -tags=integration,schemeintegration,kubernetesintegration ./dev \ + -run '^TestProviderKubernetesAvailability$' +#+end_src + +See [[https://kubernetes.io/docs/reference/using-api/api-concepts/][Kubernetes API concepts]]. diff --git a/docs/architecture/diagrams/01-system-boundaries.d2 b/docs/architecture/diagrams/01-system-boundaries.d2 index d693eea2..f3cdf467 100644 --- a/docs/architecture/diagrams/01-system-boundaries.d2 +++ b/docs/architecture/diagrams/01-system-boundaries.d2 @@ -9,7 +9,7 @@ vars: { d2-config: { data: { figure: |json "design": { "audience": "Gateway design and runtime reviewers", "medium": "GitHub at 830 CSS pixels", - "message": "Scheme supplies semantics. Go coordinates. Rust owns actual effects.", + "message": "Scheme supplies semantics. Rust coordinates publication and owns effects.", "questionRefs": [ "q1" ], @@ -52,24 +52,26 @@ vars: { d2-config: { data: { figure: |json "model": "dev/sysml/ArchitectureReaderViews.sysml", "model0": "Project.sysml", "model1": "dev/sysml/AdmissionReaderViews.sysml", - "model10": "dev/sysml/FloorReaderViews.sysml", - "model11": "dev/sysml/GatewayArchitecture.sysml", - "model12": "dev/sysml/PolicyEvidenceDesign.sysml", - "model13": "dev/sysml/ProviderRpc.sysml", - "model14": "dev/sysml/ReaderDesigns.sysml", - "model15": "dev/sysml/ResearchReaderViews.sysml", - "model16": "dev/sysml/StoragePersistence.sysml", - "model17": "dev/sysml/StreamingExecution.sysml", - "model18": "dev/sysml/WeaverExecution.sysml", - "model19": "dev/sysml/ZeroTrustRefinement.sysml", - "model2": "dev/sysml/ArchitectureReaderViews.sysml", - "model3": "dev/sysml/ArchitectureViews.sysml", - "model4": "dev/sysml/AssuranceReaderViews.sysml", - "model5": "dev/sysml/AttemptReaderViews.sysml", - "model6": "dev/sysml/AuthorityReaderViews.sysml", - "model7": "dev/sysml/ControlActivation.sysml", - "model8": "dev/sysml/CorrespondenceReaderView.sysml", - "model9": "dev/sysml/ExecutionReaderViews.sysml", + "model10": "dev/sysml/CorrespondenceReaderView.sysml", + "model11": "dev/sysml/ExecutionReaderViews.sysml", + "model12": "dev/sysml/FloorReaderViews.sysml", + "model13": "dev/sysml/GatewayArchitecture.sysml", + "model14": "dev/sysml/PolicyEvidenceDesign.sysml", + "model15": "dev/sysml/ProviderRpc.sysml", + "model16": "dev/sysml/ReaderDesigns.sysml", + "model17": "dev/sysml/ResearchReaderViews.sysml", + "model18": "dev/sysml/StoragePersistence.sysml", + "model19": "dev/sysml/StreamingExecution.sysml", + "model2": "dev/sysml/ArchitectureEvolution.sysml", + "model20": "dev/sysml/WeaverExecution.sysml", + "model21": "dev/sysml/ZeroTrustRefinement.sysml", + "model3": "dev/sysml/ArchitectureReaderViews.sysml", + "model4": "dev/sysml/ArchitectureViews.sysml", + "model5": "dev/sysml/AssuranceReaderViews.sysml", + "model6": "dev/sysml/AttemptReaderViews.sysml", + "model7": "dev/sysml/AuthorityReaderViews.sysml", + "model8": "dev/sysml/ControlActivation.sysml", + "model9": "dev/sysml/ControllerObjectLifecycle.sysml", "proof0": "dev/proofs/lean/StreamingExecution.lean", "sdkCapture": "dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json" }, @@ -79,12 +81,14 @@ vars: { d2-config: { data: { figure: |json "modelRefs": [ "Project.sysml", "dev/sysml/AdmissionReaderViews.sysml", + "dev/sysml/ArchitectureEvolution.sysml", "dev/sysml/ArchitectureReaderViews.sysml", "dev/sysml/ArchitectureViews.sysml", "dev/sysml/AssuranceReaderViews.sysml", "dev/sysml/AttemptReaderViews.sysml", "dev/sysml/AuthorityReaderViews.sysml", "dev/sysml/ControlActivation.sysml", + "dev/sysml/ControllerObjectLifecycle.sysml", "dev/sysml/CorrespondenceReaderView.sysml", "dev/sysml/ExecutionReaderViews.sysml", "dev/sysml/FloorReaderViews.sysml", @@ -193,11 +197,11 @@ vars: { d2-config: { data: { figure: |json "modelSource": { "ref": "sdkCapture", "view": "WeaverArchitectureReaderViews::boundaries", - "modelHash": "1e5a9bb646c6e0f7676306f3a8bbf9b549a682c0d31fb9b9053fa2523b6be33d", + "modelHash": "116cd33cb1473e7f17e398a7fe55b25f4f2dab261c144fba9b09948e33684f62", "portProjection": "owner", "labels": { "n0": "Scheme governance\nTyped policy and contracts", - "n1": "Go control\nRoute and publish intent", + "n1": "Rust source lane\nPrepare and publish intent", "n2": "Rust broker\nCurrent claim and policy", "n3": "Final writer\nOnly bounded provider use", "n4": "Telemetry\nObserve without authority" diff --git a/docs/architecture/diagrams/01-system-boundaries.png b/docs/architecture/diagrams/01-system-boundaries.png index 179daa4c6b9c006e3be56811a857d329527ada1a..9b06602b6d372b542a860663b45f6577df99630b 100644 GIT binary patch literal 112842 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%0DCDkNY$1FXf%(bb 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 E0ab6o+W-In diff --git a/docs/architecture/diagrams/01-system-boundaries.svg b/docs/architecture/diagrams/01-system-boundaries.svg index 8e9df9a5..06e70e13 100644 --- a/docs/architecture/diagrams/01-system-boundaries.svg +++ b/docs/architecture/diagrams/01-system-boundaries.svg @@ -30,9 +30,11 @@ SPDX-FileComment: Weaver-authored diagram; embedded third-party fonts and marks .scene-title{font-size:26px}.scene-detail{font-size:26px}.scene-group-title{font-size:26px} @font-face{font-family:"Kalam";font-style:normal;font-weight:400;src:url(data:font/woff2;base64,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) format('woff2')} -@font-face{font-family:"Kalam";font-style:normal;font-weight:700;src:url(data:font/woff2;base64,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) format('woff2')}{"renderer":{"package":"@deterministic-engineering/render","version":"1.0.0","icons":{"agent":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","agent-request":"4efdd12166f2dd11f0269537588bdf4c092a8207f6d3aed7f69b324b5457a390","authentication":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","authorization":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","bounded-write":"ec844639440fe3fd3a5c7258bce663d7c96c6ffce3d422680f649ec1f3e4cee5","budget":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","budget-ledger":"c21b8727507b7ca0e1300b34c4613a9295ce12d424f5aa1486bf2f955aa45867","capture":"a647d42aa11f4e5e85d0bbf66f483f57f3c4ba3a9536362ed0eaaaae10a89cee","catalog":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","claim":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","decision":"3535642a5b613372c3fd374151ec90aafa19b64b2d33d10b19162cad07a35c7a","document":"0bf9674a401262da8a646305cab00006954721c07765b9962e0dee1c31d560f7","evidence":"0a91b169aaa644829a054cbb94194efffaf4298f2b6f8fa8c6ec2b7b413a1766","go":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","history":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","kubernetes":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","ledger":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","library":"df474fa36a74016b79236fff58a980a8c18c682d1866211776e349a0eb4b2979","message":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","model":"0cfd1f9ed3873f556ace725a7b6a251ebe75d7d976567699276f34df36b2443b","model-catalog":"462cd80fcfda09b55dbd56ed86421393591ac22d54feb60dec9b72858e7380a2","model-provider":"f9bc33c731a1c6da16ba2e5cc95cb84e65a580b9f986b1b639fcdc4355a8b790","obligation":"e76f4d34a7190400446c89e4e7d187762b885808a64a00c99455599d902570c5","pending":"cca7589bc3b1dcdebacb867c6836c6fc166257f05823555a268354ff9bfac00c","permission-check":"3ae75b575dfbb7d84fe6b215f72b28c3489715c72d9314be84f1e4a766d3db28","policy":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","provider":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","publication":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","question":"dbf231e1568dc37189d5674d73c4bfc58a17eb8ada579b3f03bf2813d33c56f4","recovery":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","reference":"3814c570f79ab294252c36530de464c9364814b797afb862d9c62e728a8660fc","route-choice":"b6060f37795d5b078cfb8d09e9b3ec2053068935416a5c5c6f6c600d3b9dbf7b","routine":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","routing":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","rust":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","selection":"82b4ab6faf195fea0a891c35268e61c186e93e7c6a9d7967a4f6a73dbf25ae7f","stream":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","task-contract":"4da0bd2fd156b69dba5791f558d4524901401707972dbc2fea8f2aab29dd3263","telemetry":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","unknown":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","unknown-hold":"6e243f03d4cdb79637f60d268aa4402d4963218adc9e3c4f9f64ebdb99e3c437","writer":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e"}},"design":{"audience":"Gateway design and runtime reviewers","medium":"GitHub at 830 CSS pixels","message":"Scheme supplies semantics. Go coordinates. Rust owns actual effects.","questionRefs":["q1"],"requiredSubjects":["n0","n1","n2","n3","n4"],"requiredRelations":[],"focalSubjects":["n3"]},"evidence":[],"layout":"model-view","presentation":{"illustrations":{"n0":"task-contract","n1":"route-choice","n2":"permission-check","n3":"bounded-write"},"objectRows":[["n0","n1"],["n2","n3","n4"]],"notation":"objects","options":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.layered.spacing.nodeNodeBetweenLayers":"27","elk.spacing.nodeNode":"16"},"icons":{"n0":"routine","n1":"routing","n2":"authorization","n3":"writer","n4":"telemetry"},"roles":{},"edgeLabels":true,"graph":{"id":"declared-reading-order","children":[{"id":"n0","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n1","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n2","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n3","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n4","layoutOptions":{"elk.partitioning.partition":"1"}}],"layoutOptions":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.layered.spacing.nodeNodeBetweenLayers":"27","elk.partitioning.activate":"true","elk.spacing.nodeNode":"16"}},"textColumns":22},"drawing":{"mode":"sketch","options":{"seed":29,"roughness":1.3,"strokeWidth":1.2,"fillStyle":"hachure","hachureGap":9,"fillWeight":0.6}},"fonts":[{"family":"Kalam","weight":400,"source":"@fontsource/kalam/files/kalam-latin-400-normal.woff2"},{"family":"Kalam","weight":700,"source":"@fontsource/kalam/files/kalam-latin-700-normal.woff2"}],"palette":{"background":"#F6FAF9","surface":"#FFFFFF","ink":"#163C43","muted":"#496A70","border":"#C9DDDA","accent":"#087E82","secondary":"#946044","tint":"#E1F1EC","secondaryTint":"#F4EADA","onAccent":"#FFFFFF","supported":"#237653","pending":"#986320","conflict":"#A13E54"},"inputSHA256":"367e45786f0d2a0c9979531a4ef955b4d7ae3fd8176fa7af1dfa2e710b1fb69d","model":{"subjects":[{"id":"n0","type":"part","sourceName":"WeaverArchitectureReaderViews::boundariesBoundary::p_meaning","label":"Scheme governance\nTyped policy and contracts"},{"id":"n1","type":"part","sourceName":"WeaverArchitectureReaderViews::boundariesBoundary::p_control","label":"Go control\nRoute and publish intent"},{"id":"n2","type":"part","sourceName":"WeaverArchitectureReaderViews::boundariesBoundary::p_guard","label":"Rust broker\nCurrent claim and policy"},{"id":"n3","type":"part","sourceName":"WeaverArchitectureReaderViews::boundariesBoundary::p_writer","label":"Final writer\nOnly bounded provider use"},{"id":"n4","type":"part","sourceName":"WeaverArchitectureReaderViews::boundariesBoundary::p_metrics","label":"Telemetry\nObserve without authority"}],"relations":[{"id":"edge:0","src":"n0","dst":"n1","label":"carrySemantics","kind":"connection","fromPort":"n0.1","toPort":"n1.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:1","src":"n1","dst":"n2","label":"propose","kind":"connection","fromPort":"n1.1","toPort":"n2.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:2","src":"n2","dst":"n3","label":"authorizeUse","kind":"connection","fromPort":"n2.1","toPort":"n3.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:3","src":"n3","dst":"n4","label":"observe","kind":"connection","fromPort":"n3.1","toPort":"n4.0","srcArrow":"none","dstArrow":"none"}]},"modelSource":{"ref":"sdkCapture","modelHash":"1e5a9bb646c6e0f7676306f3a8bbf9b549a682c0d31fb9b9053fa2523b6be33d","view":"WeaverArchitectureReaderViews::boundaries","portProjection":"owner","labels":{"n0":"Scheme governance\nTyped policy and contracts","n1":"Go control\nRoute and publish intent","n2":"Rust broker\nCurrent claim and policy","n3":"Final writer\nOnly bounded provider use","n4":"Telemetry\nObserve without authority"}},"modelTrace":{"modelHash":"1e5a9bb646c6e0f7676306f3a8bbf9b549a682c0d31fb9b9053fa2523b6be33d","requestedView":"WeaverArchitectureReaderViews::boundaries","resolvedView":"WeaverArchitectureReaderViews::boundaries","renderingSHA256":"6b67168d1fdd39dd1ff24f78877e37173191f827379485873ef42b216b08e25e","capturedRenderingJSON":"{\"modelHash\":\"1e5a9bb646c6e0f7676306f3a8bbf9b549a682c0d31fb9b9053fa2523b6be33d\",\"requestedView\":\"WeaverArchitectureReaderViews::boundaries\",\"rendering\":{\"view\":\"WeaverArchitectureReaderViews::boundaries\",\"kind\":\"interconnection\",\"stated\":\"render asInterconnectionDiagram\",\"nodes\":[{\"id\":\"n0\",\"kind\":\"part\",\"name\":\"WeaverArchitectureReaderViews::boundariesBoundary::p_meaning\",\"nameSynthesized\":false,\"type\":\"boundaries_meaning\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n0.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":47,\"startCol\":9,\"endLine\":47,\"endCol\":45}},{\"id\":\"n1\",\"kind\":\"part\",\"name\":\"WeaverArchitectureReaderViews::boundariesBoundary::p_control\",\"nameSynthesized\":false,\"type\":\"boundaries_control\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n1.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"},{\"id\":\"n1.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":48,\"startCol\":9,\"endLine\":48,\"endCol\":45}},{\"id\":\"n2\",\"kind\":\"part\",\"name\":\"WeaverArchitectureReaderViews::boundariesBoundary::p_guard\",\"nameSynthesized\":false,\"type\":\"boundaries_guard\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n2.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"},{\"id\":\"n2.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":49,\"startCol\":9,\"endLine\":49,\"endCol\":41}},{\"id\":\"n3\",\"kind\":\"part\",\"name\":\"WeaverArchitectureReaderViews::boundariesBoundary::p_writer\",\"nameSynthesized\":false,\"type\":\"boundaries_writer\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n3.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"},{\"id\":\"n3.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":50,\"startCol\":9,\"endLine\":50,\"endCol\":43}},{\"id\":\"n4\",\"kind\":\"part\",\"name\":\"WeaverArchitectureReaderViews::boundariesBoundary::p_metrics\",\"nameSynthesized\":false,\"type\":\"boundaries_metrics\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n4.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":51,\"startCol\":9,\"endLine\":51,\"endCol\":45}}],\"edges\":[{\"from\":\"n0\",\"to\":\"n1\",\"fromPort\":\"n0.1\",\"toPort\":\"n1.0\",\"label\":\"carrySemantics\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":52,\"startCol\":9,\"endLine\":52,\"endCol\":84}},{\"from\":\"n1\",\"to\":\"n2\",\"fromPort\":\"n1.1\",\"toPort\":\"n2.0\",\"label\":\"propose\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":53,\"startCol\":9,\"endLine\":53,\"endCol\":75}},{\"from\":\"n2\",\"to\":\"n3\",\"fromPort\":\"n2.1\",\"toPort\":\"n3.0\",\"label\":\"authorizeUse\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":54,\"startCol\":9,\"endLine\":54,\"endCol\":79}},{\"from\":\"n3\",\"to\":\"n4\",\"fromPort\":\"n3.1\",\"toPort\":\"n4.0\",\"label\":\"observe\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":55,\"startCol\":9,\"endLine\":55,\"endCol\":76}}],\"columns\":[],\"rows\":[],\"notes\":[],\"notices\":[],\"shown\":[]}}","portProjection":"owner","nodes":[{"id":"n0","parent":"","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":47,"startCol":9,"endLine":47,"endCol":45}},{"id":"n1","parent":"","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":48,"startCol":9,"endLine":48,"endCol":45}},{"id":"n2","parent":"","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":49,"startCol":9,"endLine":49,"endCol":41}},{"id":"n3","parent":"","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":50,"startCol":9,"endLine":50,"endCol":43}},{"id":"n4","parent":"","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":51,"startCol":9,"endLine":51,"endCol":45}}],"edges":[{"id":"edge:0","index":0,"from":"n0","to":"n1","fromPort":"n0.1","toPort":"n1.0","kind":"connection","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":52,"startCol":9,"endLine":52,"endCol":84}},{"id":"edge:1","index":1,"from":"n1","to":"n2","fromPort":"n1.1","toPort":"n2.0","kind":"connection","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":53,"startCol":9,"endLine":53,"endCol":75}},{"id":"edge:2","index":2,"from":"n2","to":"n3","fromPort":"n2.1","toPort":"n3.0","kind":"connection","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":54,"startCol":9,"endLine":54,"endCol":79}},{"id":"edge:3","index":3,"from":"n3","to":"n4","fromPort":"n3.1","toPort":"n4.0","kind":"connection","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":55,"startCol":9,"endLine":55,"endCol":76}}]},"view":{"source":"docs/architecture/diagrams/01-system-boundaries.d2","title":"Trace authority to the final writer","purpose":"architecture","kind":"system","question":{"subjectRefs":["n3"],"ref":"q1","text":"Who owns meaning, coordination and actual effects?","focusRefs":["model"]},"basis":{"captureRef":"docs/architecture/diagrams/01-system-boundaries.d2#design-view","modelRefs":["Project.sysml","dev/sysml/AdmissionReaderViews.sysml","dev/sysml/ArchitectureReaderViews.sysml","dev/sysml/ArchitectureViews.sysml","dev/sysml/AssuranceReaderViews.sysml","dev/sysml/AttemptReaderViews.sysml","dev/sysml/AuthorityReaderViews.sysml","dev/sysml/ControlActivation.sysml","dev/sysml/CorrespondenceReaderView.sysml","dev/sysml/ExecutionReaderViews.sysml","dev/sysml/FloorReaderViews.sysml","dev/sysml/GatewayArchitecture.sysml","dev/sysml/PolicyEvidenceDesign.sysml","dev/sysml/ProviderRpc.sysml","dev/sysml/ReaderDesigns.sysml","dev/sysml/ResearchReaderViews.sysml","dev/sysml/StoragePersistence.sysml","dev/sysml/StreamingExecution.sysml","dev/sysml/WeaverExecution.sysml","dev/sysml/ZeroTrustRefinement.sysml"],"obligationRefs":["proof0"],"evidenceRefs":[]}},"questions":[{"subjectRefs":["n3"],"ref":"q1","text":"Who owns meaning, coordination and actual effects?","focusRefs":["model"]}],"references":{"model":"dev/sysml/ArchitectureReaderViews.sysml","model0":"Project.sysml","model1":"dev/sysml/AdmissionReaderViews.sysml","model10":"dev/sysml/FloorReaderViews.sysml","model11":"dev/sysml/GatewayArchitecture.sysml","model12":"dev/sysml/PolicyEvidenceDesign.sysml","model13":"dev/sysml/ProviderRpc.sysml","model14":"dev/sysml/ReaderDesigns.sysml","model15":"dev/sysml/ResearchReaderViews.sysml","model16":"dev/sysml/StoragePersistence.sysml","model17":"dev/sysml/StreamingExecution.sysml","model18":"dev/sysml/WeaverExecution.sysml","model19":"dev/sysml/ZeroTrustRefinement.sysml","model2":"dev/sysml/ArchitectureReaderViews.sysml","model3":"dev/sysml/ArchitectureViews.sysml","model4":"dev/sysml/AssuranceReaderViews.sysml","model5":"dev/sysml/AttemptReaderViews.sysml","model6":"dev/sysml/AuthorityReaderViews.sysml","model7":"dev/sysml/ControlActivation.sysml","model8":"dev/sysml/CorrespondenceReaderView.sysml","model9":"dev/sysml/ExecutionReaderViews.sysml","proof0":"dev/proofs/lean/StreamingExecution.lean","sdkCapture":"dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json"},"sourceSHA256":{"dev/d2/themes/assurance.d2":"f7723f53e005a68c803a38ce5c04cd733f46f4a2688fa4b17c66f9d5b308fe24","dev/d2/themes/data.d2":"19fceb46186892da02b763217963cc3ca2a35021219c0d353fdeec84604ddaee","dev/d2/themes/flow.d2":"1f13588619d0c8087c08d8afd023c4c0efe12726711c311e623eea3872726c1f","dev/d2/themes/routing.d2":"f185df198e7435d12b17b7b57b62dfc5795597d95eb926159ee13b448727bcce","dev/d2/themes/sequence.d2":"6e39472720dccc717f984c95b79570494b6ce3828b86227629841649e6c956e6","dev/d2/themes/state.d2":"f1a35cbca0f9cbb055ea9f793ba3dfb86e5fee4e462038ef3e72b94baa61d781","dev/d2/themes/system.d2":"b2a32ec6959ca5df9103c16454c4e34b758e061f850f7de6b619bcbc5fcf17a6","dev/d2/themes/vocabulary.d2":"add21e9b87eab485e5daabf6316fea44eb56b1007b70123f24b0e32e3357f744","dev/proofs/cedar/DomainMigrationComposition.lean":"c81a284bdf2006a1689cdadcc2c78442b3033774c2f103dd50a32c577ad4be77","dev/proofs/cedar/QualifiedReview.lean":"1ae16e06ad03a2906fa8c21dbeea1e3eb7700aa1e9359e64848dec65ccfd079f","dev/proofs/cedar/WeaverPolicyBridge.lean":"a9628a8123d504a34f64bf986feb4471325aa2b0ddc603d76b62632481eab67b","dev/proofs/cedar/ZeroTrustEnrichment.lean":"0c4b138843cc176c27d42d4a31177a3c12486b2d8ff124a6453e3d0922170884","dev/proofs/lean/ProviderRpc.lean":"e79d7639ac11220585e59e85dc5bec12b6717f7b51fb28fdcd62dc96d8fae38e","dev/proofs/lean/RuntimeAdmission.lean":"6111d4b9e93ebaa9f7cc44a55ed504c88c20c8d9de81e947a2e13b3f4a13b13c","dev/proofs/lean/SharedDomains.lean":"c45cba453b4271a7f8f87ded67217b8af0517d22fa1b1d5d81618c64644cc636","dev/proofs/lean/StreamingExecution.lean":"3fba798a7887a0b2ae29a7e3f0aaa3d7e2fb191e5f1f28109a4a73d28e27b776","dev/sysml/AdmissionReaderViews.sysml":"27ebc6c98ec3a1f7f9081e77a130953c3b646a1fdf6f1d6fc1fa6ed6376e9623","dev/sysml/ArchitectureReaderViews.sysml":"52ffbccbb17bd257e8ad9f4aa9f727c8ce0c00149e7d6738b82042ba06fdd0e3","dev/sysml/ArchitectureViews.sysml":"adbeeab4171045dc5dead2caf060cb4dbcd9c8dd5f914be993ab98d3eca0df37","dev/sysml/AssuranceReaderViews.sysml":"cd99fb7e9b23e08beac265bc832a8debee0dc1e1d318b0f64d5263519270e390","dev/sysml/AttemptReaderViews.sysml":"0d87cf71e15c26566422a6ddb5945fdb8add8af0484d9d024c32b97597675e21","dev/sysml/AuthorityReaderViews.sysml":"6fa25bd3a64e7f89987caec8e4773928be2cbea0a3c943299e536ca81978316d","dev/sysml/captures/WeaverAdmissionReaderViews-beneficiaryRegistration.json":"c032918360bf483ae1f405814b1e92cd0c9391a778df883a2243fe1d50ae7e3e","dev/sysml/captures/WeaverAdmissionReaderViews-bootstrapInvitation.json":"17073ea8d9f3da40647d233b400059d8dd0d4abc86cabff4e542e72e2b0d3bbc","dev/sysml/captures/WeaverAdmissionReaderViews-callerCustody.json":"975ed2715ebbe10406afef31f5cbed41a778039b75afc9c32c653e8e0533e1d9","dev/sysml/captures/WeaverAdmissionReaderViews-custodyPublication.json":"eb089628fdddad2d5f045b2c0f4bd77ca62a9b674224cf4a22f6bdee5317d726","dev/sysml/captures/WeaverAdmissionReaderViews-enrollmentCredential.json":"e9fd37134a25ec9812be1f3318fbd8c578f8cc350424f0400b7fa495959f9f29","dev/sysml/captures/WeaverAdmissionReaderViews-incarnationIssuance.json":"8a2f9ee448ac9e48d7e6935075c7b332259fa6d3b3319f8bdd03b2fc1cfc004b","dev/sysml/captures/WeaverAdmissionReaderViews-routineRouting.json":"0e0b20893ed9635dd8e20e55954645496c7ac46013178413095d9625f47b19a3","dev/sysml/captures/WeaverAdmissionReaderViews-sourceCustody.json":"1860e7fd0266fa0c80e6163ecf4631e604e7ff0dd1ed6466c200fb320f2569a6","dev/sysml/captures/WeaverAdmissionReaderViews-sourceJoin.json":"c55166d939a7d9858041e02cb1de512473d5853d26df29d0fedc314eeb9f00fe","dev/sysml/captures/WeaverAdmissionReaderViews-subjectAuthority.json":"64b8b0ccc3c62b9b631142bd5ff5d28900151adf51db08a4c10dc84ddd76caa2","dev/sysml/captures/WeaverArchitectureReaderViews-adapterBroker.json":"b34141293f261d69bcbd32dce349f629f07ece0375c22e8b0f31bfa939d95622","dev/sysml/captures/WeaverArchitectureReaderViews-anchorBroker.json":"592daccba731ab56628ee09c733f3d7f03cca31dc690ce81d69a10c7e7cb0d39","dev/sysml/captures/WeaverArchitectureReaderViews-anchorEgress.json":"b5ff8ed02f65cba74afb004154e159ecfebbdd16832f0b196cfe87c8735eba28","dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json":"6b67168d1fdd39dd1ff24f78877e37173191f827379485873ef42b216b08e25e","dev/sysml/captures/WeaverArchitectureReaderViews-codePolicy.json":"0d62625775b5780da1ce2934fcf1b9197eecce256ca203adc032cf7070829b37","dev/sysml/captures/WeaverArchitectureReaderViews-configPrefix.json":"3de87ca6e9db7f38989fe394703253e1db5de40d205ee9e13d27370af9f1282e","dev/sysml/captures/WeaverArchitectureReaderViews-driverCompletion.json":"faf32a3b87741d27d4c3e10b7c040b323260cdc5cfbb363379fb80bfa0e5eaaa","dev/sysml/captures/WeaverArchitectureReaderViews-fencing.json":"ee08c435ee5466598a95feadeadce64d25ab710e0c7e273df954caa67410cb1f","dev/sysml/captures/WeaverArchitectureReaderViews-gatePersistence.json":"d0887fc4e101deaea7f3788c462573b14355d22f3d83be5e693b9c37d2ac5dcd","dev/sysml/captures/WeaverArchitectureReaderViews-journalLifecycle.json":"e4a050cc314d2347d4d3682fbf696455707fa8644d8ecef434c559534bcfb5bc","dev/sysml/captures/WeaverArchitectureReaderViews-logicalObservation.json":"d0eb59627785a3a1e1b7182a162290c569d68e9ab6ecbf8fef870e01ae1f9b27","dev/sysml/captures/WeaverArchitectureReaderViews-manifest.json":"922cab9c9784df60877b590a1815b34228c26c6452a7eb1cb9c3db31460133ad","dev/sysml/captures/WeaverArchitectureReaderViews-migration.json":"10ba40fc4e772b106292818e86d8023dcc81860cd2092e4508799279138a6f5f","dev/sysml/captures/WeaverArchitectureReaderViews-policyExecution.json":"04e6f2a6b95d955c2ef054faf6f4e869eff56a16c13eeb94c48ce03b5dca3b88","dev/sysml/captures/WeaverArchitectureReaderViews-quorumPromises.json":"614c887183ab021b713e40b18a3cb82f25e60af6fa00481aa9cdcd9c9cde31de","dev/sysml/captures/WeaverArchitectureReaderViews-relationships.json":"3eca8149e8f1f30ce7c6b853c0d579684b8db7eed93ccff8a1f1eb8d8168b349","dev/sysml/captures/WeaverArchitectureReaderViews-settlementAnchor.json":"742b5388072eb493c6f4793aa54231466623ac27f19529223d7f33b991c39d80","dev/sysml/captures/WeaverArchitectureReaderViews-sharedBudget.json":"c0fc22ee8c78877b4fe91487ac4f95c4e7d05a71e251dd3deaa2265eaa896569","dev/sysml/captures/WeaverArchitectureReaderViews-sharedExposure.json":"35fb239ce8bea0cd55c2f52de52eb035f4bab2b5485b8e7582287474bc43abd6","dev/sysml/captures/WeaverArchitectureReaderViews-spentState.json":"ad19ec8c239c9f82b7b073b485a960ab498fcbfbd5148c90fb8e290113d026f4","dev/sysml/captures/WeaverArchitectureReaderViews-writerSettlement.json":"0bfe561678512fda1a44bf77473a59ee04360f3021bb5d5f9aed8884e1f1aa4b","dev/sysml/captures/WeaverArchitectureReaderViews-zeroAssurance.json":"5ab290cb43564718f9c0e991fa3c1112fafa74838780deceafad10ad12a1ecc4","dev/sysml/captures/WeaverAssuranceReaderViews-brokerQueue.json":"1bffc321a7ab072e84cb4b22eaa0060190736ffee31a43c4b35fb75b745753c9","dev/sysml/captures/WeaverAssuranceReaderViews-continuation.json":"28c8edc68fbf860c63b6dd3918dedf76064004df2aba7c1bd8f65773afb4df7b","dev/sysml/captures/WeaverAssuranceReaderViews-deviceEvidence.json":"678b5d32006e2cb4288495d242ebc0e5e80f739dbfb204e91d1bcd332bbed371","dev/sysml/captures/WeaverAssuranceReaderViews-gatewayHead.json":"130f4eb2e632248e6bbba7c6f34c58cc72d56a3f679776b680f540de20f20f96","dev/sysml/captures/WeaverAssuranceReaderViews-keySession.json":"4be65df864587275e959d2364b12d028235d0ab6d488d8dbc847561e849dce5b","dev/sysml/captures/WeaverAssuranceReaderViews-rangeRecovery.json":"504c83b6a3651f011771f776201c7b1d76138afd09be54d477ca9d3a3e25bd07","dev/sysml/captures/WeaverAssuranceReaderViews-signer.json":"27db88549f7f743ea60c73b71e37e37ffe542c69c4a7685a00944f4a9a739f8e","dev/sysml/captures/WeaverAttemptReaderViews-admission.json":"c845667f622701d0ddbf38c0c1af61c0e77cad7a9dec3a2738a5bfb81b776e74","dev/sysml/captures/WeaverAttemptReaderViews-outcome.json":"8f215e9cc05107dff8b3da34060ff9a0561ac9710d921991f86a034d8c386b4b","dev/sysml/captures/WeaverAuthorityReaderViews-attemptLedger.json":"6c389d951433962202990f82ef167235acb0319c02e1eb2d2a497eba36732821","dev/sysml/captures/WeaverAuthorityReaderViews-canonical.json":"a8c6a868371a81bd41c7d92001080fa908cf242f1dc9cb4a3807d118bf16cbd2","dev/sysml/captures/WeaverAuthorityReaderViews-multiKey.json":"6ccc723d7c18bdbf5dcf6e4ff71fb0eec181f15797482b8c3160b092b69dd592","dev/sysml/captures/WeaverAuthorityReaderViews-publication.json":"730aa60655e4aa3d3ec5562b12c47d7ed836034b6078ba114ae923f03522531c","dev/sysml/captures/WeaverAuthorityReaderViews-recoveryCAS.json":"ee6430c3109cde3de4c325dc840cf62bb0caab5a6f5caa014d3f4f027640dd65","dev/sysml/captures/WeaverAuthorityReaderViews-scope.json":"9c16143b95a35058aa3b5bcaa5bb8cbaedd21cff3f3be9c4f3f4a0d88deddb0b","dev/sysml/captures/WeaverCorrespondenceReaderView-correspondence.json":"3d1ca08f803def4648537a8c0544365ce4d0f3111632969e45c665f28e053203","dev/sysml/captures/WeaverExecutionReaderViews-accountCommit.json":"57b5afc0babad1a4daece90ed68ab8293d5374aba1e409f421aa823575adc562","dev/sysml/captures/WeaverExecutionReaderViews-admissionFloor.json":"9a5033aa8871a21c66f41330d36c1b0f5f9d8390ff7fd885ec7ea404cbb46226","dev/sysml/captures/WeaverExecutionReaderViews-appendHandoff.json":"b3d5a0bcdf95e52a2bd6e5ddee68a4cbb7db135b4ddb658250063b3699f36594","dev/sysml/captures/WeaverExecutionReaderViews-checkpoint.json":"920fa59556237f15d5313ede43ad6a0a7268be59a627f8083a701f8a6e3a5533","dev/sysml/captures/WeaverExecutionReaderViews-executionEvidence.json":"e04b9f763a56cbbf13413371be4a83d773693f2036e32c9db4fa087848fe416d","dev/sysml/captures/WeaverExecutionReaderViews-executorOffer.json":"d11d28bc736807c8d0364dad6f9668ac12a77cb395c29c86473bc28256942514","dev/sysml/captures/WeaverExecutionReaderViews-joinEnqueue.json":"8cb4cd55c378d7a622b2456def81613b3b44ff3b16be0079d81a52e150c25aef","dev/sysml/captures/WeaverExecutionReaderViews-manifestSwitch.json":"cf0e351a80367319c04c1cbb7ce283567852e11ba8ab9b00ded5f059b663c41e","dev/sysml/captures/WeaverExecutionReaderViews-resultProjection.json":"81cf7ed0eec3af4429db89c17634a7d735a6be3d42876d594c837ff230db1258","dev/sysml/captures/WeaverExecutionReaderViews-walActivation.json":"705d1f09677dcf28ae1bca177ee5aae3e589b77221ad1ca889f2064fa31a7b73","dev/sysml/captures/WeaverFloorReaderViews-floorOrdering.json":"8aa43a594e10be22f62b423b0a20561e3e1db198c5773413c8ba8ce3041c817e","dev/sysml/captures/WeaverFloorReaderViews-floorRecovery.json":"46fd2b8fbaec21683a6773946f024211151ba6fc5dbde9c4504e2a0970d7f6ac","dev/sysml/captures/WeaverResearchReaderViews-embeddedTooling.json":"6e85c9972d66392bb4f2f69c9dab18edd9ad514ab81464b5bbc71bf335f3081f","dev/sysml/captures/WeaverResearchReaderViews-floorTransport.json":"4d37e38648832c0e5a138469ff2664e1054c579e9d1087c7a03b0f161e28c079","dev/sysml/captures/WeaverResearchReaderViews-gerbilLifecycle.json":"00b0deae0d6d5a9bb3a13c50519644d25aab7261e02524072b6bf35f3b533172","dev/sysml/captures/WeaverResearchReaderViews-gxiLifecycle.json":"fd39c0bb16f1e4150258156a8684411d3c6cbfeb16bd9d4c757d74c5f729146f","dev/sysml/captures/WeaverResearchReaderViews-parentReplay.json":"b35651124c0cd02d80f1b1728a2b8a758f12947a77bd2a4ccdefacb76ae2d0b4","dev/sysml/captures/WeaverResearchReaderViews-profileBinding.json":"576272fce35d1266dbb0cdf6a490f07e79df1448ce13777b14463a7380745cc2","dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json":"1ad9f77dcbf5a7a4f65813304a75bb7b3c961fb4aa6fa1bfb0a7ff06709dd4ba","dev/sysml/captures/WeaverResearchReaderViews-runtimeAssets.json":"090f43fad22d6d6203bb9c3993c01378fbfe26bb0d38c224ab29aee02b257d2d","dev/sysml/captures/WeaverResearchReaderViews-semanticSlice.json":"07e91bc664ff3dce725fdc81fb53d42d9dedf03137a56215a791d70a0681641e","dev/sysml/captures/WeaverViews-architecture.json":"0eb28dd65702a601e8804d27cd7dc1d279bd4719a8153dcbe4e3b567c0fd30a0","dev/sysml/captures/WeaverViews-assurance.json":"75f373024582998109faca55f2aa67855ff8a675b7a79702beef0c826e2eae38","dev/sysml/captures/WeaverViews-contractRefinement.json":"2b5ff7cb278fc3a00c9c64b9a9b768b56ad2bf34b2df18d82b219c1856a61244","dev/sysml/captures/WeaverViews-execution.json":"d61366c9fd4fdfdb9b784a0a5caf2a35e168efa236037a529ab7aa1a2debabb8","dev/sysml/captures/WeaverViews-gateway.json":"498eeefacdb219de8a4aa69e3fb5653267b99bcd95a3d61009a50402e6eb63ea","dev/sysml/captures/WeaverViews-rangeRecovery.json":"459ba4e2376d21d2487f47a7e886dbecd5df71e166a3876fe29cb837b3f6f061","dev/sysml/captures/WeaverViews-routeExecution.json":"bae92275847a95a0c82d865fd93e1f3695d0c12e1eb3ca7817c60050890f8321","dev/sysml/captures/WeaverViews-routeSelection.json":"7aa5e25ad092a9ba35ab3d6b1e115a679cfdb557fb3073faf84976767d3d4cee","dev/sysml/captures/WeaverViews-storage.json":"176ee88f33e38104eea551582e55cfa17b3dcd2b769628ea6aa83fcc1c16b880","dev/sysml/captures/WeaverViews-streamAdmission.json":"a7a5870185e1676918922fc88ed2fff2b1abe259e65f5fcea7125987dc20b8fc","dev/sysml/captures/WeaverViews-zeroTrust.json":"8e50d7c70d6b786b576c365cd9fac514b8ef92bf2a0bf5ff48f79df6b66e048b","dev/sysml/ControlActivation.sysml":"78bc6792c3a64ee54210720d3d88c1984b5c876d3a0647b6829bf904a811014f","dev/sysml/CorrespondenceReaderView.sysml":"24b811c00528feaab3547d5db3b7fada290ff89478ac2be0a1d252d8ea1e5828","dev/sysml/ExecutionReaderViews.sysml":"88f690ed1fed91f63f7571d14bf5d7c1c8d14ee3b8d1d17ae333dfd7a6176df3","dev/sysml/FloorReaderViews.sysml":"93401ba5b2009dd54614f7e5aff81d91a20085efbb77b3a143726ffdea16592c","dev/sysml/GatewayArchitecture.sysml":"dbec3964b7873ed0633964b05d1ba1ee828050aed35a3066858d0c38893f2642","dev/sysml/PolicyEvidenceDesign.sysml":"6a7d738b004be62e7412ea68080944f8cb6fb3aea785258efaefc2efc1c4e0e6","dev/sysml/ProviderRpc.sysml":"46000a122f91081bc756a408859ffb64c4638ba7fc84360a9d7562de46f5e0c1","dev/sysml/ReaderDesigns.sysml":"4df8352980f9727b85a26533dc5ebfd67730540359d553a17d562574f3ea2529","dev/sysml/ResearchReaderViews.sysml":"cb10ed4ab79e911197834a8102e8a84986c567a358098e36d234d15b9c5acaec","dev/sysml/StoragePersistence.sysml":"b6b58b8802a557a7f3af787c2e7875be64865169ca3fd7e9973b13f6c3dc792d","dev/sysml/StreamingExecution.sysml":"d0d4d92300fba2b908ace30d9065cb2bac1d86f3b7c98219c1853a30f3110e85","dev/sysml/WeaverExecution.sysml":"12d87cfe55b53ad54ccef0c5b965c9a4cd19cefe2856fb7262396b967b920ffc","dev/sysml/ZeroTrustRefinement.sysml":"7cbec57110f03ed68469a1f49cb2046769516b09a6eb1b9433d866161bba6a82","docs/10-19-llm-gateway/10-routing-and-inference/10.02-llm-routing.d2":"513cad143cde846a9393bb5020dc4843caa1bb844204d3d0c13d1b5ada5efc70","docs/10-19-llm-gateway/10-routing-and-inference/10.05-route-execution.d2":"ea6130b51598910a59384943fa5d7cb1c74566ce1091f6414a6309c2ce9618ed","docs/10-19-llm-gateway/11-attempts-and-failover/11.02-attempt-ledger.d2":"5438329d7af60e9596b5fe4519b04a27a7c36ce1d1dc1aa5442db6df7167cd8e","docs/10-19-llm-gateway/12-semantic-contracts/12.02-semantic-contract.d2":"8560ac03652d2dfb8aeb7797c0e3b61031e49f9a3276d3207c8758a32037c530","docs/10-19-llm-gateway/13-authoritative-scope/13.02-authoritative-scope.d2":"e5950b420b85e30891bdb2264c7fad7ccd9ec9934b6175906d592d683b3a844c","docs/10-19-llm-gateway/14-registry-publication/14.02-registry-publication.d2":"9153743fc734fb044f94a4d22175fbe963f0f15f02598143dfbd7a06cd880177","docs/10-19-llm-gateway/15-recovery-cas/15.02-recovery-cas.d2":"c5de2f6cb52b0450361b2ed0523f647bdcad1fc43d410231f91ae86aee450859","docs/10-19-llm-gateway/16-policy-publication/16.02-policy-publication.d2":"4be00575666b7ada7185a30e553b42b9c36fe9109ce89df3d0dbb4b30ac10cab","docs/10-19-llm-gateway/17-policy-continuation/17.02-policy-continuation.d2":"4108a821aba5a2de1ffebc59b9e0d9180130bb3f598ac2130d59a83e8eca571f","docs/10-19-llm-gateway/18-canonical-registry/18.02-canonical-registry.d2":"f3b44cf54b006df34b528075bbc54742963a53e2afd4cbee435f81095b59b800","docs/10-19-llm-gateway/19-multi-key-registry/19.02-multi-key-registry.d2":"c44a2569dec8ae1fab46acb1ddd58f8b468e7ea7b11136c120a6bf2b042cf8b7","docs/20-29-execution-authority/20-result-projection/20.02-result-projection.d2":"696df32a9d705c6915bcc43a33616126cdce61ce5af0ae198c0dca5bc898d645","docs/20-29-execution-authority/21-join-enqueue/21.02-join-enqueue.d2":"430f46389111827b9f0ad5c9c3193366729fffe917ef18a5bfa0ec8238f6ab02","docs/20-29-execution-authority/22-executor-offer/22.02-executor-offer.d2":"0d93c13abcc1bd79afb32e6ae8a965cc5ec3b0c30fc1958f2f212e12b5e4b65a","docs/20-29-execution-authority/23-execution-reconciliation/23.02-execution-reconciliation.d2":"14c698ad47a243d46d788ab3494b1ad22ae7f14a163140eb6b4f5e8e071c6269","docs/20-29-execution-authority/24-account-commit/24.02-account-commit.d2":"10d6a5116d2c8be77ce7f27312d9d49ad832645c6748bb7bd68bb6942055990e","docs/20-29-execution-authority/25-wal-activation/25.02-wal-activation.d2":"9ebcd14701116e583157282a1678a6f1e0fe70e1ee4b9b7e038b520d4392ce05","docs/20-29-execution-authority/26-checkpoint-truncation/26.02-checkpoint-truncation.d2":"c5c1a35a16fe9b33029169b16d4c0af113f49e665eed0074ce524fc7a15bdb77","docs/20-29-execution-authority/27-manifest-switch/27.02-manifest-switch.d2":"c4de2ef519af25b2c41194df561860ad0236b0309b3178b388204c29cebf9f41","docs/20-29-execution-authority/28-append-handoff/28.02-append-handoff.d2":"f7646793e8540ec5f1e587d5e13deaf16d166180f80107ac8f9c904ea5c9372c","docs/20-29-execution-authority/29-admission-floor/29.02-admission-floor.d2":"0b9794f3d5fdfc7dcdbb519426eecf7e6ec6cb707de5017387c9aa47208ea385","docs/30-39-assurance/31-protected-signer/31.02-protected-signer.d2":"bc787086ae26a1a6cd56e51a2b4182c86e476f13e28ed1f5d80363b1d827e013","docs/30-39-assurance/32-key-boundary/32.02-key-boundary.d2":"1b616363aa68166988cc1d09404d637da406f048b9647676ec5f42d15f1762ca","docs/30-39-assurance/33-device-isolation/33.02-device-isolation.d2":"f4b086efce29484b70d4d4b2c04dad3887976d69187c25234e734e90260a6c7c","docs/30-39-assurance/34-floor-decision/34.02-floor-decision.d2":"78e2de9f044edb41944a56c1c8c8251a9cacd3470cf73c16b87f5ba100139a04","docs/30-39-assurance/34-floor-decision/34.04-floor-recovery.d2":"296d821eae11d4b77a552ae21d91eadcddcf032a15989dd35490128397044203","docs/30-39-assurance/35-intent-continuation/35.02-intent-continuation.d2":"08475ba17d7c98911a7db912041b669d049c75315c861322f72a5b50a471df55","docs/30-39-assurance/36-gateway-head-cas/36.02-gateway-head-cas.d2":"51669df10ec208197e690f656b962b259959af5f225243b62e5ff6bbea5637a5","docs/30-39-assurance/37-broker-consumption-queue/37.02-broker-consumption-queue.d2":"1ad636df3ba980d5f25b1a330c00c8b21f152958fe7c86617736e1b1f85a1ed8","docs/30-39-assurance/38-logical-range-recovery/38.02-logical-range-recovery.d2":"8ed5e1adc741da6852d027828993a83816cadb0c7bc1732bfaf121b2a64878d3","docs/40-49-admission-coordination/40-source-join/40.02-source-join.d2":"b8815cf59a1be49a4657b6ec3857d39e6d7d39ab4bb3ed44521c71ffe0ec5cee","docs/40-49-admission-coordination/41-source-custody/41.02-source-custody.d2":"feef18f62d537d4eb0659c0f1d719218df1a3eda506c9468b59423b151550bd7","docs/40-49-admission-coordination/42-custody-publication/42.02-custody-publication.d2":"24f019e8633cc816f7488e3f65384d2dea96ac8a3685714665a47bc6144b1e5c","docs/40-49-admission-coordination/43-caller-custody/43.02-caller-custody.d2":"6352167e4d3427fd9a66befb74fb3eebf91a127c5e82ecff8312b24178d5117f","docs/40-49-admission-coordination/44-incarnation-issuance/44.02-incarnation-issuance.d2":"215f52c84c9f41c36352f8b6da8b4670f1b375672cfc9efdf6a8bd1df95c946e","docs/40-49-admission-coordination/45-bootstrap-invitation/45.02-bootstrap-invitation.d2":"9e019de8289428a97580fe66ccefc6b9d0a43c1bac07433d2f29596f4d407401","docs/40-49-admission-coordination/46-beneficiary-registration/46.02-beneficiary-registration.d2":"322b848fdd67ea88c99b509cb5d913d7a5023e327edea51f16f44816356d81ce","docs/40-49-admission-coordination/47-enrollment-credential/47.02-enrollment-credential.d2":"ea0aa0bed915bea42d3d65c8f6572f799eb63d0aee1018b75803e61ef034d303","docs/40-49-admission-coordination/48-subject-authority/48.02-subject-authority.d2":"9f707fbc6e5ba8933a0e4d9d057f013c5764afc503f819288f628d3f9709f88d","docs/40-49-admission-coordination/49-routine-routing-config/49.02-routine-routing-config.d2":"7fa18b652ba97e8fe66f402a9a85d65740db9d3ffadff7890db7d72826c498b6","docs/50-59-research-program/51-qualified-semantic-slice/51.06-semantic-gateway-slice.d2":"d63df655a635fccac3c92eded92c039a3f079c24fa2b7a2fd0dc1f3fabd3c0f5","docs/50-59-research-program/52-committed-profile-binding/52.04-committed-profile.d2":"3ea30976830c607bf8cec62cbabc4291c384bd5f368049a45777f6f981d87d6e","docs/50-59-research-program/53-gerbil-exit/53.04-gerbil-lifecycle.d2":"b7b623664edc6e86efe62eeee7f5977dc207f0cb12e40cb6f0e77e38160695de","docs/50-59-research-program/54-dynamic-gxi-exit/54.04-dynamic-lifecycle.d2":"d4d410dd8cb10de6d3526b54ac7f96731d2f2a94dd9763aad96a0926608e251c","docs/50-59-research-program/55-dynamic-gxi-paired/55.04-runtime-boundary.d2":"573b248a6b7ce2d7eee1e70a469c54e4f195c4894ec7b0f61c8406fae843eccc","docs/50-59-research-program/56-gambit-image-closure/56.04-locator-boundary.d2":"0c45ee11d269b0cab8998c7fc3432ec851b9390b7530486225134b261d8d7de8","docs/50-59-research-program/57-runtime-implementation/57.03-runtime-boundary.d2":"193d22a5bd9e4b23260334d085df8aa5ec19c349f13cd9f56eaa26fe54f7e3ac","docs/50-59-research-program/58-streaming-execution/58.03-streaming-runtime.d2":"76ea49c83b4b36af1e775f80475d40747640b80a330434bf86635e255e84ef14","docs/50-59-research-program/58-streaming-execution/58.05-range-progress-recovery.d2":"aef20c8ad7d7420a65422add6d9fb635bdbe32e42e49427d3179bf20499ae4cd","docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2":"6f4e8218ea262e35efaebaf8cc2f96345b2ef1e7e9c1a6b12b68290dd99c683d","docs/50-59-research-program/59-provider-rpc/59.21-verification-ownership.d2":"e035ae7e56ee5e6498f131ed62f4792547c1e716aa5ed29865b333f54665e8f1","docs/50-59-research-program/59-provider-rpc/59.26-semantic-execution-ecosystem.d2":"50c091b094125693e2debe73599a63405849f1f55ab3658030674692c9334e14","docs/50-59-research-program/59-provider-rpc/59.30-governance-adapter-acceptance.d2":"88cbbd45e63358bb45a58fb27f85e275b9cc9fb3d3aee6af19eabed0912545d2","docs/50-59-research-program/59-provider-rpc/59.43-floor-transport-owner.d2":"36c4d6b561332ab30deb464a92bb4c2f02ceed5c8a1ca66617f72b6086b2c555","docs/50-59-research-program/59-provider-rpc/59.44-cloud-rpc-arrow-boundaries.d2":"fe0ac2220e04f6ccea851247ecf8ae1cab4ec8c8ba8744010c478992c233ebed","docs/50-59-research-program/59-provider-rpc/59.45-slow-consumer-zero-trust.d2":"e36cf58a239a2d9f0c99789bb7484de4e26180a8f941970540f72b530a79d813","docs/50-59-research-program/59-provider-rpc/59.46-functional-security-frameworks.d2":"e541b969352e8149e71e5b539988f9955b525e5e5ba3e7e7270bd4a98fbe19f5","docs/50-59-research-program/59-provider-rpc/59.47-property-testing-framework.d2":"f66ed065dcf955a233968ca295517c642be30dad9b24e23a781fe34e4bed45d9","docs/50-59-research-program/59-provider-rpc/59.49-policy-proposal-barrier.d2":"3a8559bb22f812075d9d7de4a397978995d06c32ed22e9415f990413551aebb6","docs/50-59-research-program/59-provider-rpc/59.50-parent-contract-and-replay.d2":"2db3983f56e938c927b68077551573c8e86362da892f47890459ab7b3f929c64","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-architecture.d2":"10e92e79b69f4b0813551dd2ddadc5ad225b7b0fa8374ed7015b7f2fe66bb6e1","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-contract-refinement.d2":"204c9e20d9027b7a38bf2a964da9a7cadb92744561fa9f1eb3fa29d00f4fa386","docs/50-59-research-program/59-provider-rpc/59.52-reviewed-publication-cas.d2":"4e0998e61717d5441e242cde0dfc52198312b67b63f0ce8b0425a423d1b88a24","docs/50-59-research-program/59-provider-rpc/59.53-artifact-registry-recovery.d2":"f7083a48413d41ad99e7191281bd6e74a92b33c7cc1f4f2f9ae322bb1405088a","docs/50-59-research-program/59-provider-rpc/59.54-source-incarnation-authority.d2":"1e55c0487f01d70462e8df6b46eff9e799b0dc592c0e780c759fa602e3d84444","docs/50-59-research-program/59-provider-rpc/59.55-evidence-reviewed-publication.d2":"c66435372642f7a93ca7fc6f78c2abcbc364a4dde447d10dcc4b2b21ccc06456","docs/50-59-research-program/59-provider-rpc/59.56-runtime-assets-and-authority-floor.d2":"c675469701bb6994fed1976d1e90d01dc1cc4e416a6788f865494fa3243d32c1","docs/50-59-research-program/59-provider-rpc/59.57-schema-bound-candidate-replay.d2":"5ca15af556e0a4ba5bdf1742cf81182ad72e7f51b2eb63352b839e068a7ad7d2","docs/50-59-research-program/59-provider-rpc/59.58-independent-source-recovery.d2":"4b21999b3554be15374448f36ffbccf517b32784a65cadde0f4c1eb8308da377","docs/50-59-research-program/59-provider-rpc/59.59-retained-root-and-recovery-coverage.d2":"37fdf1d3dd01f087434a6108b43a5657d7aecf79a2b9e60638d70eb0b1a4984b","docs/50-59-research-program/59-provider-rpc/59.60-persistent-source-key-custody.d2":"d27df3a14df5d57ad725c1455c82a4ab5bad45b78acea8cd1a76e59958b710eb","docs/50-59-research-program/59-provider-rpc/59.61-authority-bound-replay-pair.d2":"bd4962775564848a90ec49439301cf0cdfbaa4018956344e809f5b318bea6ccd","docs/50-59-research-program/59-provider-rpc/59.62-burn-exposure-recovery.d2":"fab4ea6d0981d75dd4c704f302268f3c5af0898e299e8e0fb38b34d07200b22c","docs/50-59-research-program/59-provider-rpc/59.63-mrr-admission-contract.d2":"ed3c604e0d350049f00528c7117675a7db751b3d6683719b03be116bcf49d5c5","docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.d2":"7164874fdbeec99f2185e1091f759466a68a3b7d9b239db6a503f16383fce50e","docs/50-59-research-program/59-provider-rpc/59.65-turso-concurrent-admission.d2":"0ade3ea326e2066ce908129e383b7e0f371a429710ed0a0bad30ddcfd61f034e","docs/50-59-research-program/59-provider-rpc/59.66-bounded-writer-reuse.d2":"9390a3c12f06c2f33e3df99088dc39de92d3bccc971ddf5a632910515a67623e","docs/50-59-research-program/59-provider-rpc/59.67-writer-owner-lifecycle.d2":"c28559ccf38b2f3320d84bbc0ffc6133e2708081e95bff39d5ed75d064287bde","docs/50-59-research-program/59-provider-rpc/59.69-hot-path-cost-boundaries.d2":"e5789625590fab63bc3635627b7e20ac41f64b8f40cbeee84d51a85f27ab31f1","docs/50-59-research-program/59-provider-rpc/59.75-complete-entry-and-output-contract.d2":"d667501bc15d6c31d986994f641d8d38f63c1d910784e6852e596c24c4e4c7c7","docs/50-59-research-program/59-provider-rpc/59.75-package-linkage.d2":"bc655ae71cc46e0d5b7f42637b78530f262c3142394485e2a9ba31f6516a0a10","docs/50-59-research-program/59-provider-rpc/59.76-embedded-tooling-and-darwin-io.d2":"87655d7c6d81c1ab203f886930f1630003e006c0edb71f90ac3ca23a0cb91845","docs/50-59-research-program/59-provider-rpc/59.77-mrr-turso-storage.d2":"72a4dceeb20cca337276f64537d47dbbd2ac0ce359a7a63997090e6476a40c96","docs/50-59-research-program/59-provider-rpc/59.84-quint-preparation-and-completion.d2":"17f485d7c541506c42003ebba887705ea61972f00c9498aa3c0d153a33b02922","docs/architecture/08-diagram-catalog.org":"353a4296584381207513468ef291e7e1aefdcd6f9f2b854c92be90aab47577ea","docs/architecture/diagrams/00a-readme-overview.d2":"86e7b66d4d8959aaf500ea2717fdc054015655a79f3a095c490d39dfde38ed5f","docs/architecture/diagrams/00c-gateway-runtime.d2":"f6dced6718aa151adb0cdce6268f51b86bd95f6fdd7133a6164449293d98205d","docs/architecture/diagrams/00d-zero-trust-overview.d2":"316cbda9c86fe10cef3cb3268f00984b3a3cb50d5c4aa2df2e323937901a18ac","docs/architecture/diagrams/01-system-boundaries.d2":"69b4622c26b18a8518d46f79db8ce281c756a16f7f1a46977272086bf4dc38e0","docs/architecture/diagrams/01-system-relationships.d2":"dde40fac8667b79a070fda14ebd892f1f1e7c1217726595179b541c855f80c2c","docs/architecture/diagrams/02-admission-sequence.d2":"97077cb16cd4457fe14092caeb4bc8cf2912d434763a08fcf350cd6a4c2b2c74","docs/architecture/diagrams/03-attempt-state.d2":"e696fc0f1d63f58100405852e88e8a7dfb1a625e43be398f3bb54bbc1d90e13a","docs/architecture/diagrams/03a-attempt-observation.d2":"6b387ec7fbcff7d5e3e129bad7ea9590afe0324800a5a13bf7a89377ad86c387","docs/architecture/diagrams/04-consume-timeout.d2":"2ccfe8d033069e0d891531f3b5afef4febf21b2722209a612454d14321cac940","docs/architecture/diagrams/05-fencing-boundaries.d2":"1103ed75ac615b1a2f8239c0321d046a5a87acfa235d5042d8a529e23acd7483","docs/architecture/diagrams/06-source-admission.d2":"4d20817291c5de93b7f97366e6cb1b4af954f22de1ebcb3012c139a4b9dbd82c","docs/architecture/diagrams/07-post-claim-outcomes.d2":"63258620c15c2f52963dcdba33b4ac82cd12aadd1c2de005cd029655493493c1","docs/architecture/diagrams/08-code-as-policy.d2":"fc2263ff1ae000055e6054b89beee60f53b9621707510354c34ef45057889676","docs/architecture/diagrams/09-claim-wins-race.d2":"9eff775ddac29c47acd2c0b69fb1ff98ba9a20943da970c2804e270979555c41","docs/architecture/diagrams/10-commit-dispatch-sequence.d2":"fa5d56c49bc3f590c88cf7c3b63e180afd2d2a39fca878d1515917077ff1687a","docs/architecture/diagrams/11-zero-trust-assurance.d2":"ea93840da2ff4bdac59349f5ad7a56cee5506600283d0c364c53275dde0b5b48","docs/architecture/diagrams/12-execution-correspondence.d2":"1dd66ee8c517fd9c6f2f4b1700aeec3e620d699fbe9eeee20df8e05a7f1decb0","docs/architecture/diagrams/13-policy-to-execution.d2":"4bb05b74c3bc0ca997c5e5035ddc949fa374db3ff49bf2104a6c9753e12be3ef","docs/architecture/diagrams/14-adapter-broker-boundary.d2":"b855fa0482a5524226354b26bc8d7ecef0daf2ab1cab54c1783eba0ff29fab01","docs/architecture/diagrams/15-stream-message-authorization.d2":"cedf1c545a853ec2a9ae51bea928b04376d192f1a4c2af117fa54f475ad541e0","docs/architecture/diagrams/16-authoritative-spent-state.d2":"201bd9fe5eb6101543d939e3d83aca646e2b07c13ff1e3c56779571a0cd1172e","docs/architecture/diagrams/17-logical-message-observation.d2":"2333ad147295ead60ed6a92dc824cf6f5769f3828eff1e0cdf58e50aace7b1e1","docs/architecture/diagrams/18-shared-identity-budget.d2":"5ab4992fd8b6a6abf518fb0bbc8c2c8ad8b920d0be74a6e734d846319252ffa7","docs/architecture/diagrams/19-finite-domains-and-migration.d2":"b72b451d0bb97de46831e4b266d8fdd22d59e7d54db99446d53549f081a008e2","docs/architecture/diagrams/20-anchor-recovery-and-egress.d2":"9479271410f1bb57f92106a1d91ec73c73872568d9fcda55cac5aa64b89e5c9f","docs/architecture/diagrams/21-composed-journal-transport-lifecycle.d2":"0fffe555ee4c2c1222c97eebd24ca9b0df91a4d3ec118300ae3b88240004c3c8","docs/architecture/diagrams/22-finite-stream-manifest.d2":"60b33eb6d06aeaa1027546a1fc9d6c07069c3cd3c7d23df8ff8d63a341afe2ea","docs/architecture/diagrams/23-driver-completion-recovery.d2":"271963db2cd881bb82e164bb1544c7bcf311e1781f20170d858ccb65a596d8f5","docs/architecture/diagrams/24-writer-settlement-closure.d2":"ea1930326b0073e7fabd8b64ef3ffea781f1aef60db0d942f9ab14f1150296e9","docs/architecture/diagrams/25-settlement-anchor-recovery.d2":"8904bfcda525de21b48ea8f2db8d12aaa27e85818ccde43fb545851dc522ba3b","docs/architecture/diagrams/26-gate-consumption-persistence.d2":"42e676634ecb40cfb2dee06db1f5497d0e58c05f30097618c3852eb946992f0d","docs/architecture/diagrams/27-anchor-commit-broker-fencing.d2":"5c2ae36987b00655bbcdba36352e03b61765739ad2f3fc80a561ff0d325a9461","docs/architecture/diagrams/28-anchor-configuration-prefix.d2":"1ac0eeb3c76f5ae0ce3565d4469e50210786c3bc53c703a1a61d519dfa075512","docs/architecture/diagrams/29-quorum-durable-promises.d2":"2e4a24c3fae49e710d5afc31d4681a9efc8c2e8af3fa58a0957ede05fe7c0255","docs/architecture/diagrams/39-shared-execution-exposure.d2":"2c08f5b3d4531a7be2aadec8f1ff9d4476495418e94e84c1ff643583ac991ce4","docs/architecture/diagrams/assets/agent-request.svg":"4efdd12166f2dd11f0269537588bdf4c092a8207f6d3aed7f69b324b5457a390","docs/architecture/diagrams/assets/bounded-write.svg":"ec844639440fe3fd3a5c7258bce663d7c96c6ffce3d422680f649ec1f3e4cee5","docs/architecture/diagrams/assets/budget-ledger.svg":"c21b8727507b7ca0e1300b34c4613a9295ce12d424f5aa1486bf2f955aa45867","docs/architecture/diagrams/assets/components/activity.svg":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","docs/architecture/diagrams/assets/components/book-open.svg":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","docs/architecture/diagrams/assets/components/bot.svg":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","docs/architecture/diagrams/assets/components/brain.svg":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","docs/architecture/diagrams/assets/components/circle-question-mark.svg":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","docs/architecture/diagrams/assets/components/clipboard-check.svg":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","docs/architecture/diagrams/assets/components/coins.svg":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","docs/architecture/diagrams/assets/components/database.svg":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","docs/architecture/diagrams/assets/components/file-check.svg":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","docs/architecture/diagrams/assets/components/fingerprint-pattern.svg":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","docs/architecture/diagrams/assets/components/message-square.svg":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","docs/architecture/diagrams/assets/components/rotate-ccw-clock.svg":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","docs/architecture/diagrams/assets/components/rotate-ccw.svg":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","docs/architecture/diagrams/assets/components/route.svg":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","docs/architecture/diagrams/assets/components/send.svg":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e","docs/architecture/diagrams/assets/components/shield-check.svg":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","docs/architecture/diagrams/assets/components/ticket-check.svg":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","docs/architecture/diagrams/assets/components/waves-horizontal.svg":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","docs/architecture/diagrams/assets/components/workflow.svg":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","docs/architecture/diagrams/assets/go.svg":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","docs/architecture/diagrams/assets/kubernetes.svg":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","docs/architecture/diagrams/assets/model-catalog.svg":"462cd80fcfda09b55dbd56ed86421393591ac22d54feb60dec9b72858e7380a2","docs/architecture/diagrams/assets/model-provider.svg":"f9bc33c731a1c6da16ba2e5cc95cb84e65a580b9f986b1b639fcdc4355a8b790","docs/architecture/diagrams/assets/permission-check.svg":"3ae75b575dfbb7d84fe6b215f72b28c3489715c72d9314be84f1e4a766d3db28","docs/architecture/diagrams/assets/route-choice.svg":"b6060f37795d5b078cfb8d09e9b3ec2053068935416a5c5c6f6c600d3b9dbf7b","docs/architecture/diagrams/assets/rust.svg":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","docs/architecture/diagrams/assets/task-contract.svg":"4da0bd2fd156b69dba5791f558d4524901401707972dbc2fea8f2aab29dd3263","docs/architecture/diagrams/assets/unknown-hold.svg":"6e243f03d4cdb79637f60d268aa4402d4963218adc9e3c4f9f64ebdb99e3c437","Project.sysml":"563dfa1854f26de71d6d401f27bf990243c540dbc37156e592df717c6922d2d1"},"rendered":{"observation":{"canvas":{"x":0,"y":0,"width":980,"height":857.890625},"subjects":[{"id":"n0","role":"default","x":101,"y":251,"width":300,"height":250},{"id":"n1","role":"default","x":579,"y":251,"width":300,"height":250},{"id":"n2","role":"default","x":28,"y":579,"width":286.65625,"height":238.875},{"id":"n3","role":"default","x":346.65625,"y":579,"width":286.671875,"height":238.890625},{"id":"n4","role":"default","x":665.328125,"y":579,"width":286.65625,"height":85.984375}],"relations":["edge:1","edge:2","edge:3","edge:0"],"headings":[{"role":"title","x":20,"y":20,"width":940,"height":63},{"role":"question","x":20,"y":83,"width":940,"height":56},{"role":"note","x":20,"y":155,"width":940,"height":48}]},"readability":{"minimumTextSize":24.839930555555554,"samples":14},"bounds":{"objects":{"x":20,"y":231,"width":940,"height":606.890625}}}}Trace authority to the final writer?Who owns meaning, coordination and actual effects?Scheme supplies semantics. Go coordinates. Rust owns actual effects. - +@font-face{font-family:"Kalam";font-style:normal;font-weight:700;src:url(data:font/woff2;base64,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) format('woff2')}{"renderer":{"package":"@deterministic-engineering/render","version":"1.0.0","icons":{"agent":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","agent-request":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","authentication":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","authorization":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","bounded-write":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","budget":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","budget-ledger":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","capture":"a647d42aa11f4e5e85d0bbf66f483f57f3c4ba3a9536362ed0eaaaae10a89cee","catalog":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","claim":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","decision":"3535642a5b613372c3fd374151ec90aafa19b64b2d33d10b19162cad07a35c7a","document":"0bf9674a401262da8a646305cab00006954721c07765b9962e0dee1c31d560f7","evidence":"0a91b169aaa644829a054cbb94194efffaf4298f2b6f8fa8c6ec2b7b413a1766","go":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","history":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","kubernetes":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","ledger":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","library":"df474fa36a74016b79236fff58a980a8c18c682d1866211776e349a0eb4b2979","message":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","model":"0cfd1f9ed3873f556ace725a7b6a251ebe75d7d976567699276f34df36b2443b","model-catalog":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","model-provider":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","obligation":"e76f4d34a7190400446c89e4e7d187762b885808a64a00c99455599d902570c5","pending":"cca7589bc3b1dcdebacb867c6836c6fc166257f05823555a268354ff9bfac00c","permission-check":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","policy":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","provider":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","publication":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","question":"dbf231e1568dc37189d5674d73c4bfc58a17eb8ada579b3f03bf2813d33c56f4","recovery":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","reference":"3814c570f79ab294252c36530de464c9364814b797afb862d9c62e728a8660fc","route-choice":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","routine":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","routing":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","rust":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","selection":"82b4ab6faf195fea0a891c35268e61c186e93e7c6a9d7967a4f6a73dbf25ae7f","stream":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","task-contract":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","telemetry":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","unknown":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","unknown-hold":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","writer":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e"}},"design":{"audience":"Gateway design and runtime reviewers","medium":"GitHub at 830 CSS pixels","message":"Scheme supplies semantics. Rust coordinates publication and owns effects.","questionRefs":["q1"],"requiredSubjects":["n0","n1","n2","n3","n4"],"requiredRelations":[],"focalSubjects":["n3"]},"evidence":[],"layout":"model-view","presentation":{"illustrations":{"n0":"task-contract","n1":"route-choice","n2":"permission-check","n3":"bounded-write"},"objectRows":[["n0","n1"],["n2","n3","n4"]],"notation":"objects","options":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.layered.spacing.nodeNodeBetweenLayers":"27","elk.spacing.nodeNode":"16"},"icons":{"n0":"routine","n1":"routing","n2":"authorization","n3":"writer","n4":"telemetry"},"roles":{},"edgeLabels":true,"graph":{"id":"declared-reading-order","children":[{"id":"n0","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n1","layoutOptions":{"elk.partitioning.partition":"0"}},{"id":"n2","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n3","layoutOptions":{"elk.partitioning.partition":"1"}},{"id":"n4","layoutOptions":{"elk.partitioning.partition":"1"}}],"layoutOptions":{"elk.algorithm":"layered","elk.direction":"DOWN","elk.edgeRouting":"ORTHOGONAL","elk.layered.spacing.nodeNodeBetweenLayers":"27","elk.partitioning.activate":"true","elk.spacing.nodeNode":"16"}},"textColumns":22},"drawing":{"mode":"sketch","options":{"seed":29,"roughness":1.3,"strokeWidth":1.2,"fillStyle":"hachure","hachureGap":9,"fillWeight":0.6}},"fonts":[{"family":"Kalam","weight":400,"source":"@fontsource/kalam/files/kalam-latin-400-normal.woff2"},{"family":"Kalam","weight":700,"source":"@fontsource/kalam/files/kalam-latin-700-normal.woff2"}],"palette":{"background":"#F6FAF9","surface":"#FFFFFF","ink":"#163C43","muted":"#496A70","border":"#C9DDDA","accent":"#087E82","secondary":"#946044","tint":"#E1F1EC","secondaryTint":"#F4EADA","onAccent":"#FFFFFF","supported":"#237653","pending":"#986320","conflict":"#A13E54"},"inputSHA256":"28d12dd4bbcb77fd5f4c4e2e34ca3f29f753f8c37842323e114d6292d8a15bf5","model":{"subjects":[{"id":"n0","type":"part","sourceName":"WeaverArchitectureReaderViews::boundariesBoundary::p_meaning","label":"Scheme governance\nTyped policy and contracts"},{"id":"n1","type":"part","sourceName":"WeaverArchitectureReaderViews::boundariesBoundary::p_control","label":"Rust source lane\nPrepare and publish intent"},{"id":"n2","type":"part","sourceName":"WeaverArchitectureReaderViews::boundariesBoundary::p_guard","label":"Rust broker\nCurrent claim and policy"},{"id":"n3","type":"part","sourceName":"WeaverArchitectureReaderViews::boundariesBoundary::p_writer","label":"Final writer\nOnly bounded provider use"},{"id":"n4","type":"part","sourceName":"WeaverArchitectureReaderViews::boundariesBoundary::p_metrics","label":"Telemetry\nObserve without authority"}],"relations":[{"id":"edge:0","src":"n0","dst":"n1","label":"carrySemantics","kind":"connection","fromPort":"n0.1","toPort":"n1.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:1","src":"n1","dst":"n2","label":"propose","kind":"connection","fromPort":"n1.1","toPort":"n2.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:2","src":"n2","dst":"n3","label":"authorizeUse","kind":"connection","fromPort":"n2.1","toPort":"n3.0","srcArrow":"none","dstArrow":"none"},{"id":"edge:3","src":"n3","dst":"n4","label":"observe","kind":"connection","fromPort":"n3.1","toPort":"n4.0","srcArrow":"none","dstArrow":"none"}]},"modelSource":{"ref":"sdkCapture","modelHash":"116cd33cb1473e7f17e398a7fe55b25f4f2dab261c144fba9b09948e33684f62","view":"WeaverArchitectureReaderViews::boundaries","portProjection":"owner","labels":{"n0":"Scheme governance\nTyped policy and contracts","n1":"Rust source lane\nPrepare and publish intent","n2":"Rust broker\nCurrent claim and policy","n3":"Final writer\nOnly bounded provider use","n4":"Telemetry\nObserve without authority"}},"modelTrace":{"modelHash":"116cd33cb1473e7f17e398a7fe55b25f4f2dab261c144fba9b09948e33684f62","requestedView":"WeaverArchitectureReaderViews::boundaries","resolvedView":"WeaverArchitectureReaderViews::boundaries","renderingSHA256":"b9fdd680841c1a7b8bf7864004d397b2e00818250f0764dbcdbe3ac7a9092715","capturedRenderingJSON":"{\"modelHash\":\"116cd33cb1473e7f17e398a7fe55b25f4f2dab261c144fba9b09948e33684f62\",\"requestedView\":\"WeaverArchitectureReaderViews::boundaries\",\"rendering\":{\"view\":\"WeaverArchitectureReaderViews::boundaries\",\"kind\":\"interconnection\",\"stated\":\"render asInterconnectionDiagram\",\"nodes\":[{\"id\":\"n0\",\"kind\":\"part\",\"name\":\"WeaverArchitectureReaderViews::boundariesBoundary::p_meaning\",\"nameSynthesized\":false,\"type\":\"boundaries_meaning\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n0.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":47,\"startCol\":9,\"endLine\":47,\"endCol\":45}},{\"id\":\"n1\",\"kind\":\"part\",\"name\":\"WeaverArchitectureReaderViews::boundariesBoundary::p_control\",\"nameSynthesized\":false,\"type\":\"boundaries_control\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n1.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"},{\"id\":\"n1.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":48,\"startCol\":9,\"endLine\":48,\"endCol\":45}},{\"id\":\"n2\",\"kind\":\"part\",\"name\":\"WeaverArchitectureReaderViews::boundariesBoundary::p_guard\",\"nameSynthesized\":false,\"type\":\"boundaries_guard\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n2.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"},{\"id\":\"n2.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":49,\"startCol\":9,\"endLine\":49,\"endCol\":41}},{\"id\":\"n3\",\"kind\":\"part\",\"name\":\"WeaverArchitectureReaderViews::boundariesBoundary::p_writer\",\"nameSynthesized\":false,\"type\":\"boundaries_writer\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n3.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"},{\"id\":\"n3.1\",\"name\":\"outgoing\",\"type\":\"FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":50,\"startCol\":9,\"endLine\":50,\"endCol\":43}},{\"id\":\"n4\",\"kind\":\"part\",\"name\":\"WeaverArchitectureReaderViews::boundariesBoundary::p_metrics\",\"nameSynthesized\":false,\"type\":\"boundaries_metrics\",\"detail\":\"\",\"text\":\"\",\"standIn\":false,\"compartment\":\"\",\"parent\":\"\",\"ports\":[{\"id\":\"n4.0\",\"name\":\"incoming\",\"type\":\"~FactPort\",\"direction\":\"\"}],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":51,\"startCol\":9,\"endLine\":51,\"endCol\":45}}],\"edges\":[{\"from\":\"n0\",\"to\":\"n1\",\"fromPort\":\"n0.1\",\"toPort\":\"n1.0\",\"label\":\"carrySemantics\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":52,\"startCol\":9,\"endLine\":52,\"endCol\":84}},{\"from\":\"n1\",\"to\":\"n2\",\"fromPort\":\"n1.1\",\"toPort\":\"n2.0\",\"label\":\"propose\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":53,\"startCol\":9,\"endLine\":53,\"endCol\":75}},{\"from\":\"n2\",\"to\":\"n3\",\"fromPort\":\"n2.1\",\"toPort\":\"n3.0\",\"label\":\"authorizeUse\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":54,\"startCol\":9,\"endLine\":54,\"endCol\":79}},{\"from\":\"n3\",\"to\":\"n4\",\"fromPort\":\"n3.1\",\"toPort\":\"n4.0\",\"label\":\"observe\",\"name\":\"\",\"kind\":\"connection\",\"route\":[],\"origin\":{\"file\":\"dev/sysml/ArchitectureReaderViews.sysml\",\"startLine\":55,\"startCol\":9,\"endLine\":55,\"endCol\":76}}],\"columns\":[],\"rows\":[],\"notes\":[],\"notices\":[],\"shown\":[]}}","portProjection":"owner","nodes":[{"id":"n0","parent":"","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":47,"startCol":9,"endLine":47,"endCol":45}},{"id":"n1","parent":"","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":48,"startCol":9,"endLine":48,"endCol":45}},{"id":"n2","parent":"","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":49,"startCol":9,"endLine":49,"endCol":41}},{"id":"n3","parent":"","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":50,"startCol":9,"endLine":50,"endCol":43}},{"id":"n4","parent":"","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":51,"startCol":9,"endLine":51,"endCol":45}}],"edges":[{"id":"edge:0","index":0,"from":"n0","to":"n1","fromPort":"n0.1","toPort":"n1.0","kind":"connection","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":52,"startCol":9,"endLine":52,"endCol":84}},{"id":"edge:1","index":1,"from":"n1","to":"n2","fromPort":"n1.1","toPort":"n2.0","kind":"connection","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":53,"startCol":9,"endLine":53,"endCol":75}},{"id":"edge:2","index":2,"from":"n2","to":"n3","fromPort":"n2.1","toPort":"n3.0","kind":"connection","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":54,"startCol":9,"endLine":54,"endCol":79}},{"id":"edge:3","index":3,"from":"n3","to":"n4","fromPort":"n3.1","toPort":"n4.0","kind":"connection","origin":{"file":"dev/sysml/ArchitectureReaderViews.sysml","startLine":55,"startCol":9,"endLine":55,"endCol":76}}]},"view":{"source":"docs/architecture/diagrams/01-system-boundaries.d2","title":"Trace authority to the final writer","purpose":"architecture","kind":"system","question":{"subjectRefs":["n3"],"ref":"q1","text":"Who owns meaning, coordination and actual effects?","focusRefs":["model"]},"basis":{"captureRef":"docs/architecture/diagrams/01-system-boundaries.d2#design-view","modelRefs":["Project.sysml","dev/sysml/AdmissionReaderViews.sysml","dev/sysml/ArchitectureEvolution.sysml","dev/sysml/ArchitectureReaderViews.sysml","dev/sysml/ArchitectureViews.sysml","dev/sysml/AssuranceReaderViews.sysml","dev/sysml/AttemptReaderViews.sysml","dev/sysml/AuthorityReaderViews.sysml","dev/sysml/ControlActivation.sysml","dev/sysml/ControllerObjectLifecycle.sysml","dev/sysml/CorrespondenceReaderView.sysml","dev/sysml/ExecutionReaderViews.sysml","dev/sysml/FloorReaderViews.sysml","dev/sysml/GatewayArchitecture.sysml","dev/sysml/PolicyEvidenceDesign.sysml","dev/sysml/ProviderRpc.sysml","dev/sysml/ReaderDesigns.sysml","dev/sysml/ResearchReaderViews.sysml","dev/sysml/StoragePersistence.sysml","dev/sysml/StreamingExecution.sysml","dev/sysml/WeaverExecution.sysml","dev/sysml/ZeroTrustRefinement.sysml"],"obligationRefs":["proof0"],"evidenceRefs":[]}},"questions":[{"subjectRefs":["n3"],"ref":"q1","text":"Who owns meaning, coordination and actual effects?","focusRefs":["model"]}],"references":{"model":"dev/sysml/ArchitectureReaderViews.sysml","model0":"Project.sysml","model1":"dev/sysml/AdmissionReaderViews.sysml","model10":"dev/sysml/CorrespondenceReaderView.sysml","model11":"dev/sysml/ExecutionReaderViews.sysml","model12":"dev/sysml/FloorReaderViews.sysml","model13":"dev/sysml/GatewayArchitecture.sysml","model14":"dev/sysml/PolicyEvidenceDesign.sysml","model15":"dev/sysml/ProviderRpc.sysml","model16":"dev/sysml/ReaderDesigns.sysml","model17":"dev/sysml/ResearchReaderViews.sysml","model18":"dev/sysml/StoragePersistence.sysml","model19":"dev/sysml/StreamingExecution.sysml","model2":"dev/sysml/ArchitectureEvolution.sysml","model20":"dev/sysml/WeaverExecution.sysml","model21":"dev/sysml/ZeroTrustRefinement.sysml","model3":"dev/sysml/ArchitectureReaderViews.sysml","model4":"dev/sysml/ArchitectureViews.sysml","model5":"dev/sysml/AssuranceReaderViews.sysml","model6":"dev/sysml/AttemptReaderViews.sysml","model7":"dev/sysml/AuthorityReaderViews.sysml","model8":"dev/sysml/ControlActivation.sysml","model9":"dev/sysml/ControllerObjectLifecycle.sysml","proof0":"dev/proofs/lean/StreamingExecution.lean","sdkCapture":"dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json"},"sourceSHA256":{"dev/d2/themes/assurance.d2":"f7723f53e005a68c803a38ce5c04cd733f46f4a2688fa4b17c66f9d5b308fe24","dev/d2/themes/data.d2":"19fceb46186892da02b763217963cc3ca2a35021219c0d353fdeec84604ddaee","dev/d2/themes/flow.d2":"1f13588619d0c8087c08d8afd023c4c0efe12726711c311e623eea3872726c1f","dev/d2/themes/routing.d2":"f185df198e7435d12b17b7b57b62dfc5795597d95eb926159ee13b448727bcce","dev/d2/themes/sequence.d2":"6e39472720dccc717f984c95b79570494b6ce3828b86227629841649e6c956e6","dev/d2/themes/state.d2":"f1a35cbca0f9cbb055ea9f793ba3dfb86e5fee4e462038ef3e72b94baa61d781","dev/d2/themes/system.d2":"b2a32ec6959ca5df9103c16454c4e34b758e061f850f7de6b619bcbc5fcf17a6","dev/d2/themes/vocabulary.d2":"add21e9b87eab485e5daabf6316fea44eb56b1007b70123f24b0e32e3357f744","dev/proofs/cedar/DomainMigrationComposition.lean":"97c2564f79b3ad81b538d763e70727d4505995019d8a96d401bb738486b190e9","dev/proofs/cedar/QualifiedReview.lean":"1ae16e06ad03a2906fa8c21dbeea1e3eb7700aa1e9359e64848dec65ccfd079f","dev/proofs/cedar/WeaverPolicyBridge.lean":"a9628a8123d504a34f64bf986feb4471325aa2b0ddc603d76b62632481eab67b","dev/proofs/cedar/ZeroTrustEnrichment.lean":"0c4b138843cc176c27d42d4a31177a3c12486b2d8ff124a6453e3d0922170884","dev/proofs/lean/ProviderAdmissionTurn.lean":"9b30418066f14197ad601d0f439a7326c7940a5f67785353c37f2ac044801bf4","dev/proofs/lean/ProviderEgressWindow.lean":"c4a15b4ccd3a6474290b71374499087dba7dac7a1fda53f3a870100ec2e768a9","dev/proofs/lean/ProviderLifecycleFootprint.lean":"4786544c8a8193c5221bda2f7cd5cf20531bd1856d88b10ae29b280f223e307c","dev/proofs/lean/ProviderReadCustody.lean":"67e83773a1a063852e2303512d4b75b73cd3b9a90117972aafda9ee7348e6b77","dev/proofs/lean/ProviderRpc.lean":"e79d7639ac11220585e59e85dc5bec12b6717f7b51fb28fdcd62dc96d8fae38e","dev/proofs/lean/ProviderSemanticProgress.lean":"d32e010145a7dfcd646daeeeb4b08c0e852b9006bca404681af7e7fe10d0eaa0","dev/proofs/lean/ProviderSnapshotPublication.lean":"312c0380e334fbc5380815d882c6b5b0007747100f818becbee9c6784eeb5716","dev/proofs/lean/RuntimeAdmission.lean":"6111d4b9e93ebaa9f7cc44a55ed504c88c20c8d9de81e947a2e13b3f4a13b13c","dev/proofs/lean/SharedDomains.lean":"10eef67918986264689b09f0a6c0d53b314d7bf43b42f4b9652b403570beb58d","dev/proofs/lean/StreamingExecution.lean":"3fba798a7887a0b2ae29a7e3f0aaa3d7e2fb191e5f1f28109a4a73d28e27b776","dev/sysml/AdmissionReaderViews.sysml":"27ebc6c98ec3a1f7f9081e77a130953c3b646a1fdf6f1d6fc1fa6ed6376e9623","dev/sysml/ArchitectureEvolution.sysml":"6d7f4514180fb4a7d93fd5b01e888c1d95e36570e9fefc6ca0c415c66334922b","dev/sysml/ArchitectureReaderViews.sysml":"1113b05e7103c157b2291f12a003fc78fee07dcc68d90e2bdcd1a1b1a53f7c35","dev/sysml/ArchitectureViews.sysml":"e5b5dbbd27acfba0bd5d5b52e45990b99471d88da0e814ec13fb7ab23d752d4b","dev/sysml/AssuranceReaderViews.sysml":"cd99fb7e9b23e08beac265bc832a8debee0dc1e1d318b0f64d5263519270e390","dev/sysml/AttemptReaderViews.sysml":"0d87cf71e15c26566422a6ddb5945fdb8add8af0484d9d024c32b97597675e21","dev/sysml/AuthorityReaderViews.sysml":"6fa25bd3a64e7f89987caec8e4773928be2cbea0a3c943299e536ca81978316d","dev/sysml/captures/ArchitectureEvolution-reinforcingCapabilities.json":"bdea3da2ce576a8d02d6a13e1a5a462341501d7bf38533cf327b8b817880f793","dev/sysml/captures/ControllerObjectLifecycle-lifecycle.json":"70f46345a1186aeb1d8cbf0e05cbca0746d9e3ba5bc1599a4feb5c4777b13806","dev/sysml/captures/WeaverAdmissionReaderViews-beneficiaryRegistration.json":"282371e766597824b2ef7800e9029eb69615a2b42b27a194d41e330b7bc08469","dev/sysml/captures/WeaverAdmissionReaderViews-bootstrapInvitation.json":"11b2c898d5107fbef1722872b8b0186f7933888fe80aa9e6ea134729f46dc18c","dev/sysml/captures/WeaverAdmissionReaderViews-callerCustody.json":"4063156bcac98c3a052a57c9e98ac885656ee9944065c839afa92dff20b8efa8","dev/sysml/captures/WeaverAdmissionReaderViews-custodyPublication.json":"1c7c3a3e76cada1c3aeb237470b88a82266b260b5ca0a8596b0bf5ee8e8e00b5","dev/sysml/captures/WeaverAdmissionReaderViews-enrollmentCredential.json":"6fdbc68c9a291b0a8ac6ad03829e721129425dedc625c5bae5aa319b8b6b31ad","dev/sysml/captures/WeaverAdmissionReaderViews-incarnationIssuance.json":"f03ef4515964101e9c5e040edc1dee425dac0dcaa3f09aad96bb80e7af885189","dev/sysml/captures/WeaverAdmissionReaderViews-routineRouting.json":"098a72a7f858dbe2bd4437f388bdbb52170a07225cad910e532a63f9b40bcb90","dev/sysml/captures/WeaverAdmissionReaderViews-sourceCustody.json":"0ffa1435dbf2865ddb1b359ebef0d77c5457780b0698a0d6745e3722bd29e648","dev/sysml/captures/WeaverAdmissionReaderViews-sourceJoin.json":"69f9666d5228226552762b0f8dd938515cfca0060a7b7b225a9cd6800b1e70a1","dev/sysml/captures/WeaverAdmissionReaderViews-subjectAuthority.json":"1a97b2c4325f5a1d2240e2443815b8114354cfeb363a2d3fe43b78f704219691","dev/sysml/captures/WeaverArchitectureReaderViews-adapterBroker.json":"ea5f360522738a643211b250d6dc7e376755d0491445be2320aa8ad37c9c2476","dev/sysml/captures/WeaverArchitectureReaderViews-anchorBroker.json":"bdf8f7d100130ac92eccf09121af3590398e38dbddb27dd9f561fb03ea95bbf2","dev/sysml/captures/WeaverArchitectureReaderViews-anchorEgress.json":"d19cddd8f2a4a0c40b47c9d444bfa7b3e025ee51d1dac2f676483817d36d7a34","dev/sysml/captures/WeaverArchitectureReaderViews-boundaries.json":"b9fdd680841c1a7b8bf7864004d397b2e00818250f0764dbcdbe3ac7a9092715","dev/sysml/captures/WeaverArchitectureReaderViews-codePolicy.json":"f52d9406ce39b41f8302e4ab56e7000bbb93e0e67491011f7fdd4f8335745b87","dev/sysml/captures/WeaverArchitectureReaderViews-configPrefix.json":"ee76055919b8888a801b2f1c3c44cd9a34e6f693859611f7dc7c3e62d80da1d0","dev/sysml/captures/WeaverArchitectureReaderViews-driverCompletion.json":"5dfbc07f3605b96c8d491c80f5396e510692b12d10d37ff53b457b7a3d189676","dev/sysml/captures/WeaverArchitectureReaderViews-fencing.json":"9bb9bfe87ddfff0c4245a7623b8c4b75ec773d8487a6738240bcdb8add3614b4","dev/sysml/captures/WeaverArchitectureReaderViews-gatePersistence.json":"149e75852c1d33bb1b0e10d1b47b2961d12892539831b72348f2d21329ed6644","dev/sysml/captures/WeaverArchitectureReaderViews-journalLifecycle.json":"0ea02d10c18da42bbd761cb608d6364e8879beafe3231797d9485a6b322e333b","dev/sysml/captures/WeaverArchitectureReaderViews-logicalObservation.json":"b2978cc1e46a32bfda1421f4102b4f679fa749a701ca500f5ff69fe460240cfc","dev/sysml/captures/WeaverArchitectureReaderViews-manifest.json":"38d2f88bc53a0a3b35ed995471af88da08c807bcced157804ebca3137e177b1d","dev/sysml/captures/WeaverArchitectureReaderViews-migration.json":"46d37e698acae75a8e934f14ce96463c6fb66487d3b9c94868e54396bc22881d","dev/sysml/captures/WeaverArchitectureReaderViews-policyExecution.json":"824a99762907c683cfa679502164cbc0ef153ae0fbdf97ae417303f23215dc02","dev/sysml/captures/WeaverArchitectureReaderViews-quorumPromises.json":"3cfd2ee775239e649e22d8a623b35a332a2de862af4d348446cae706403e46d6","dev/sysml/captures/WeaverArchitectureReaderViews-relationships.json":"f0aa6f762966bff244ae2e68342c52d6c8f592059848672b8b7d94725423d59a","dev/sysml/captures/WeaverArchitectureReaderViews-settlementAnchor.json":"2622e5958db1b8b5c8e249e94c7f916f31d03eb9ea0575ce6a950b2e780927ce","dev/sysml/captures/WeaverArchitectureReaderViews-sharedBudget.json":"9423f93a750b393b6a4941e198916a58acec751376d54057fec6a95b00bbbd07","dev/sysml/captures/WeaverArchitectureReaderViews-sharedExposure.json":"3589c03f85619e1fac42b597efcfdadc7a6dd127670d71ca24f91d24f72c0bab","dev/sysml/captures/WeaverArchitectureReaderViews-spentState.json":"c0c314d39891da99ec2d00b95857e0767e1768fd3af54214be25dddf6fb2d2d1","dev/sysml/captures/WeaverArchitectureReaderViews-writerSettlement.json":"5da30fafcc667f583ba1adc6664b6322150acf67551da31a61f4ef97a808bd67","dev/sysml/captures/WeaverArchitectureReaderViews-zeroAssurance.json":"63ad0b61d770dfbe7188f902f66036549a526120ff1bf93aa31972dfa01b8917","dev/sysml/captures/WeaverAssuranceReaderViews-brokerQueue.json":"5c8f294b9de9ef6006e4540785f8228556b9c4e0ee61dd097aba3c63ebf022df","dev/sysml/captures/WeaverAssuranceReaderViews-continuation.json":"b8e5965bbb13edd9f53b7fd91ea14cbc8839976f7dab5594568ac60d4c6c40ec","dev/sysml/captures/WeaverAssuranceReaderViews-deviceEvidence.json":"be8393a9eb150ee433d5120e790eba12bb76faa17dab371b74cfd431147a0bcd","dev/sysml/captures/WeaverAssuranceReaderViews-gatewayHead.json":"2d3cc0dd678c43d22b58061f8cad62f70043fa50149bbe2a5b2508d11dd3a47f","dev/sysml/captures/WeaverAssuranceReaderViews-keySession.json":"4159167f92723446572c6803705b4011b25722172ba8e94a5415a25dfe981004","dev/sysml/captures/WeaverAssuranceReaderViews-rangeRecovery.json":"c571ba4f5fe9aab6d4de13576b9d379f6b273200a03f9d4e7a06545af3ac8710","dev/sysml/captures/WeaverAssuranceReaderViews-signer.json":"eb1bf192465d20dc0016135ec1c1efde68295508a7e2ab8f62c6903b3b9e560b","dev/sysml/captures/WeaverAttemptReaderViews-admission.json":"30031d020abcc0d7fd46ca74a4e4c63fb39d75f10b918a832d3454a70a68e4dc","dev/sysml/captures/WeaverAttemptReaderViews-outcome.json":"a419013e32ab3e54ce95259a1519c733c4cacd2c28ea010e0975e4c9d883f447","dev/sysml/captures/WeaverAuthorityReaderViews-attemptLedger.json":"24701be8a5c32bbf48a8ab2110da1e0514eca7c5550e5639d4779f0dfd021a8e","dev/sysml/captures/WeaverAuthorityReaderViews-canonical.json":"58970dbd9b9bbdb608ba919f6e88b7fe4c0d38cd63fecc4a671e1760142e4394","dev/sysml/captures/WeaverAuthorityReaderViews-multiKey.json":"16e4e9b86e0cf78683b15cc1fe38ca93799eb94d482220f2ce022a1d456918c3","dev/sysml/captures/WeaverAuthorityReaderViews-publication.json":"1338546411c0957603c4bd89ef57418bb31c4bc22f97e1756da5672cf4c17211","dev/sysml/captures/WeaverAuthorityReaderViews-recoveryCAS.json":"29007a3d936a773b5d491dc43f63b711e3dc033059ace971498841fc665ae620","dev/sysml/captures/WeaverAuthorityReaderViews-scope.json":"b2fbaab4bd0fb8cce7a303ae7063798e19eefb5086ccdef680a9d621d23e9dd4","dev/sysml/captures/WeaverCorrespondenceReaderView-correspondence.json":"1c7a57ada0b6ebabd3db27ffa1bea0f73f7701847275b1bfe788e975890f3da2","dev/sysml/captures/WeaverExecutionReaderViews-accountCommit.json":"351fec0e5c5e31f2ffaeba55197f90b801c468c92159b65bf9e07c58a9548062","dev/sysml/captures/WeaverExecutionReaderViews-admissionFloor.json":"e179d9dedf7f45338628d06320db13b99b575f2f122d2322d18e904c987a68f6","dev/sysml/captures/WeaverExecutionReaderViews-appendHandoff.json":"2e9515041d71931cdd5b87e8dfd0c7a81130d7ba472db01857065272632231d7","dev/sysml/captures/WeaverExecutionReaderViews-checkpoint.json":"2b3ba6783fc5bf49efc5d8702068de3534a5ee1fa22d181ebbef5361f07f3dba","dev/sysml/captures/WeaverExecutionReaderViews-executionEvidence.json":"1a8c699e151560ba9dbc29601bd5de843fb55002213f9da7851cb9d353190b12","dev/sysml/captures/WeaverExecutionReaderViews-executorOffer.json":"351d47f86e27612a4237378de1c872499b61304552f5ae74fa04224ad35e7dc1","dev/sysml/captures/WeaverExecutionReaderViews-joinEnqueue.json":"0f91d7980296be0cdc1add3bc03cfab28e28e39b0b8f3d6400bf21b10f55f57b","dev/sysml/captures/WeaverExecutionReaderViews-manifestSwitch.json":"f4fd93c905cde27c3b8799fe26251a40780b59761119c88262df00209209c292","dev/sysml/captures/WeaverExecutionReaderViews-resultProjection.json":"d13ef5015978f9ab7e3dd1964ed38643c660d38336f6b37fdc9fc12be8e80417","dev/sysml/captures/WeaverExecutionReaderViews-walActivation.json":"53950d7718f811f0b0cd828ee7bbee2719f7915d603a87b2a713f5ccc1e81875","dev/sysml/captures/WeaverFloorReaderViews-floorOrdering.json":"c480d14ae5b18c146fb5d80e6ddd7f4036149508396322eb467ab5f022e16188","dev/sysml/captures/WeaverFloorReaderViews-floorRecovery.json":"16cfb4eb51bd76e0aa3e9c11e200303a0256a13365de74842bb2cdf6cbfa5b4e","dev/sysml/captures/WeaverResearchReaderViews-embeddedTooling.json":"86a41ad0c6e5b2c9c8f3acfd42facd72eb37c84584d6866b10e7377190b49bc8","dev/sysml/captures/WeaverResearchReaderViews-floorTransport.json":"cc3417722abc10e9445fca1eac1eb3a5043c62d0a94d9c90fd23e6ee689be471","dev/sysml/captures/WeaverResearchReaderViews-gerbilLifecycle.json":"62141c8a81dfb0d208f0dfc850f7a9dcc6628d30f689cc75298394b7a1ecd8cb","dev/sysml/captures/WeaverResearchReaderViews-gxiLifecycle.json":"ff1eb0c01f0a8a7a6108baa8fa9b4211be25b06754e8c6f00eb10355286f70ac","dev/sysml/captures/WeaverResearchReaderViews-parentReplay.json":"e05af04dcf85e861558f61a1225ae15b528d207f5852d0d651ce0ceda71d90a7","dev/sysml/captures/WeaverResearchReaderViews-profileBinding.json":"1206342019d76835e466cdd0912eac3595a4ffca434692947ffeb866001d7f4e","dev/sysml/captures/WeaverResearchReaderViews-rpcCore.json":"020ca25ef6aef2a4d7beb8ae451a2f5f752bb276a70e3590a8e553b13646a646","dev/sysml/captures/WeaverResearchReaderViews-runtimeAssets.json":"b7a2cb1537e9bd68522f2bed7a3193a3915683bf43d14e65bbded76817487008","dev/sysml/captures/WeaverResearchReaderViews-semanticSlice.json":"16208111d04383bc319ce5440d8bd96434b13201cbc427b1668c260dc7fa6f1c","dev/sysml/captures/WeaverViews-architecture.json":"7b682ae26b90c95f9658f3070c25dc4c857a7a07c91bd14c88b040e4c4c14ea8","dev/sysml/captures/WeaverViews-assurance.json":"f730eccdd0eaba396b7d0c33fc42700fb203f349690fd6873334a9ecb9368704","dev/sysml/captures/WeaverViews-contractRefinement.json":"85d2838fbb52045f4e46be8e1dca60bdc46a2d200cd41a34ad0b6c517eb8cdd7","dev/sysml/captures/WeaverViews-execution.json":"6041eba84d0fbc2180a7a9d87511079672d9435aebce1d3d1c2b9c25217138d6","dev/sysml/captures/WeaverViews-gateway.json":"1d12f4f84cc6c5978f95d52bd173e7a7c0a29588d164451068a2c8819be73426","dev/sysml/captures/WeaverViews-providerDeliveryJoin.json":"3fb68d917a40849f519db0648bc53d429eaa87c2e81c238260b66b65388b559e","dev/sysml/captures/WeaverViews-providerEgressWindow.json":"f2671bdb541233fead17d7cf855e49633422ff16ef8230807c6a433013d1f484","dev/sysml/captures/WeaverViews-rangeRecovery.json":"4c13edca66ab6581dc8ae0f943c9ed9c299b80c32d1a3f2ad0a0dc9b2738831c","dev/sysml/captures/WeaverViews-routeExecution.json":"ae77699f114e1ed5a30f9aeb6d34c54be0aae3bf7ee3b42a61a4bfc417d09d22","dev/sysml/captures/WeaverViews-routeSelection.json":"70e152dd6f715bd7a7f96e029e87b8183f2069e98f1e151ad3b4b20fa6d6eca5","dev/sysml/captures/WeaverViews-storage.json":"7c3168a02518f111381f2699a3f60d5e7c2d4f9fe99c6e7a6571ff58211c79b1","dev/sysml/captures/WeaverViews-streamAdmission.json":"99abf0e6755db2727e2949acc4bb49492a8b2ddcc0f7e3875e581df9cdf138d6","dev/sysml/captures/WeaverViews-zeroTrust.json":"dcc2307f64695bbf9c557bdace5ca8a814fcf440857255db6e050d0911d7c2ac","dev/sysml/ControlActivation.sysml":"3fff66cb1f637af46ceaa276295f90b742d2c492fcb9282ce0ca3eae825d6f83","dev/sysml/ControllerObjectLifecycle.sysml":"b0b8302f1641748cfc3312f8dba8625f2a2961f2d4de3756990c40448eb2eaf2","dev/sysml/CorrespondenceReaderView.sysml":"24b811c00528feaab3547d5db3b7fada290ff89478ac2be0a1d252d8ea1e5828","dev/sysml/ExecutionReaderViews.sysml":"88f690ed1fed91f63f7571d14bf5d7c1c8d14ee3b8d1d17ae333dfd7a6176df3","dev/sysml/FloorReaderViews.sysml":"93401ba5b2009dd54614f7e5aff81d91a20085efbb77b3a143726ffdea16592c","dev/sysml/GatewayArchitecture.sysml":"dbec3964b7873ed0633964b05d1ba1ee828050aed35a3066858d0c38893f2642","dev/sysml/PolicyEvidenceDesign.sysml":"2476fbebe5f299283eca4e0e0f77b114893717c09d839b1f4a7ffad6ea4428ae","dev/sysml/ProviderRpc.sysml":"f1fbde1c104ba448b7af802275b8a903d6830afc52342d06873ce85fa5964e0d","dev/sysml/ReaderDesigns.sysml":"4df8352980f9727b85a26533dc5ebfd67730540359d553a17d562574f3ea2529","dev/sysml/ResearchReaderViews.sysml":"517b8d9359b03cdc1905e2ce61651d2995d23692899864985c0c81123592a4af","dev/sysml/StoragePersistence.sysml":"b6b58b8802a557a7f3af787c2e7875be64865169ca3fd7e9973b13f6c3dc792d","dev/sysml/StreamingExecution.sysml":"d0d4d92300fba2b908ace30d9065cb2bac1d86f3b7c98219c1853a30f3110e85","dev/sysml/WeaverExecution.sysml":"8d09c4ceb0a3dc677047cc1d69700574df8a1f1bddf2a156a3cf93fae89b2f25","dev/sysml/ZeroTrustRefinement.sysml":"7cbec57110f03ed68469a1f49cb2046769516b09a6eb1b9433d866161bba6a82","docs/10-19-llm-gateway/10-routing-and-inference/10.02-llm-routing.d2":"513cad143cde846a9393bb5020dc4843caa1bb844204d3d0c13d1b5ada5efc70","docs/10-19-llm-gateway/10-routing-and-inference/10.05-route-execution.d2":"7c3ff8609c24983d0b27511756d8c5c04d0dc2cf5c973fc7012eaa0acda421e2","docs/10-19-llm-gateway/10-routing-and-inference/10.07-provider-egress-window.d2":"3c9c7c67296700d3b08cea62dddd5bdd011e7bafd61c2b4ecf1e38c32a94d6e7","docs/10-19-llm-gateway/10-routing-and-inference/10.09-provider-delivery-join.d2":"80b85a1f845c440259a93a52b33fae42f5373f985b6dd24d1fcef2c798e5ccf4","docs/10-19-llm-gateway/10-routing-and-inference/10.14-object-lifecycle.d2":"88b797085111294078072dce5983614195e50ac500bcfadad72145dbb295f0be","docs/10-19-llm-gateway/10-routing-and-inference/10.15-architecture-evolution.d2":"d1d5ebe1aeacd18a1f295bf479edb64b2f6f231c4beaf1fe39611bf34c70252f","docs/10-19-llm-gateway/11-attempts-and-failover/11.02-attempt-ledger.d2":"5438329d7af60e9596b5fe4519b04a27a7c36ce1d1dc1aa5442db6df7167cd8e","docs/10-19-llm-gateway/12-semantic-contracts/12.02-semantic-contract.d2":"8560ac03652d2dfb8aeb7797c0e3b61031e49f9a3276d3207c8758a32037c530","docs/10-19-llm-gateway/13-authoritative-scope/13.02-authoritative-scope.d2":"e5950b420b85e30891bdb2264c7fad7ccd9ec9934b6175906d592d683b3a844c","docs/10-19-llm-gateway/14-registry-publication/14.02-registry-publication.d2":"9153743fc734fb044f94a4d22175fbe963f0f15f02598143dfbd7a06cd880177","docs/10-19-llm-gateway/15-recovery-cas/15.02-recovery-cas.d2":"c5de2f6cb52b0450361b2ed0523f647bdcad1fc43d410231f91ae86aee450859","docs/10-19-llm-gateway/16-policy-publication/16.02-policy-publication.d2":"4be00575666b7ada7185a30e553b42b9c36fe9109ce89df3d0dbb4b30ac10cab","docs/10-19-llm-gateway/17-policy-continuation/17.02-policy-continuation.d2":"4108a821aba5a2de1ffebc59b9e0d9180130bb3f598ac2130d59a83e8eca571f","docs/10-19-llm-gateway/18-canonical-registry/18.02-canonical-registry.d2":"f3b44cf54b006df34b528075bbc54742963a53e2afd4cbee435f81095b59b800","docs/10-19-llm-gateway/19-multi-key-registry/19.02-multi-key-registry.d2":"c44a2569dec8ae1fab46acb1ddd58f8b468e7ea7b11136c120a6bf2b042cf8b7","docs/20-29-execution-authority/20-result-projection/20.02-result-projection.d2":"696df32a9d705c6915bcc43a33616126cdce61ce5af0ae198c0dca5bc898d645","docs/20-29-execution-authority/21-join-enqueue/21.02-join-enqueue.d2":"430f46389111827b9f0ad5c9c3193366729fffe917ef18a5bfa0ec8238f6ab02","docs/20-29-execution-authority/22-executor-offer/22.02-executor-offer.d2":"0d93c13abcc1bd79afb32e6ae8a965cc5ec3b0c30fc1958f2f212e12b5e4b65a","docs/20-29-execution-authority/23-execution-reconciliation/23.02-execution-reconciliation.d2":"14c698ad47a243d46d788ab3494b1ad22ae7f14a163140eb6b4f5e8e071c6269","docs/20-29-execution-authority/24-account-commit/24.02-account-commit.d2":"10d6a5116d2c8be77ce7f27312d9d49ad832645c6748bb7bd68bb6942055990e","docs/20-29-execution-authority/25-wal-activation/25.02-wal-activation.d2":"9ebcd14701116e583157282a1678a6f1e0fe70e1ee4b9b7e038b520d4392ce05","docs/20-29-execution-authority/26-checkpoint-truncation/26.02-checkpoint-truncation.d2":"c5c1a35a16fe9b33029169b16d4c0af113f49e665eed0074ce524fc7a15bdb77","docs/20-29-execution-authority/27-manifest-switch/27.02-manifest-switch.d2":"c4de2ef519af25b2c41194df561860ad0236b0309b3178b388204c29cebf9f41","docs/20-29-execution-authority/28-append-handoff/28.02-append-handoff.d2":"f7646793e8540ec5f1e587d5e13deaf16d166180f80107ac8f9c904ea5c9372c","docs/20-29-execution-authority/29-admission-floor/29.02-admission-floor.d2":"0b9794f3d5fdfc7dcdbb519426eecf7e6ec6cb707de5017387c9aa47208ea385","docs/30-39-assurance/31-protected-signer/31.02-protected-signer.d2":"bc787086ae26a1a6cd56e51a2b4182c86e476f13e28ed1f5d80363b1d827e013","docs/30-39-assurance/32-key-boundary/32.02-key-boundary.d2":"1b616363aa68166988cc1d09404d637da406f048b9647676ec5f42d15f1762ca","docs/30-39-assurance/33-device-isolation/33.02-device-isolation.d2":"f4b086efce29484b70d4d4b2c04dad3887976d69187c25234e734e90260a6c7c","docs/30-39-assurance/34-floor-decision/34.02-floor-decision.d2":"78e2de9f044edb41944a56c1c8c8251a9cacd3470cf73c16b87f5ba100139a04","docs/30-39-assurance/34-floor-decision/34.04-floor-recovery.d2":"296d821eae11d4b77a552ae21d91eadcddcf032a15989dd35490128397044203","docs/30-39-assurance/35-intent-continuation/35.02-intent-continuation.d2":"08475ba17d7c98911a7db912041b669d049c75315c861322f72a5b50a471df55","docs/30-39-assurance/36-gateway-head-cas/36.02-gateway-head-cas.d2":"51669df10ec208197e690f656b962b259959af5f225243b62e5ff6bbea5637a5","docs/30-39-assurance/37-broker-consumption-queue/37.02-broker-consumption-queue.d2":"1ad636df3ba980d5f25b1a330c00c8b21f152958fe7c86617736e1b1f85a1ed8","docs/30-39-assurance/38-logical-range-recovery/38.02-logical-range-recovery.d2":"8ed5e1adc741da6852d027828993a83816cadb0c7bc1732bfaf121b2a64878d3","docs/40-49-admission-coordination/40-source-join/40.02-source-join.d2":"b8815cf59a1be49a4657b6ec3857d39e6d7d39ab4bb3ed44521c71ffe0ec5cee","docs/40-49-admission-coordination/41-source-custody/41.02-source-custody.d2":"feef18f62d537d4eb0659c0f1d719218df1a3eda506c9468b59423b151550bd7","docs/40-49-admission-coordination/42-custody-publication/42.02-custody-publication.d2":"24f019e8633cc816f7488e3f65384d2dea96ac8a3685714665a47bc6144b1e5c","docs/40-49-admission-coordination/43-caller-custody/43.02-caller-custody.d2":"6352167e4d3427fd9a66befb74fb3eebf91a127c5e82ecff8312b24178d5117f","docs/40-49-admission-coordination/44-incarnation-issuance/44.02-incarnation-issuance.d2":"215f52c84c9f41c36352f8b6da8b4670f1b375672cfc9efdf6a8bd1df95c946e","docs/40-49-admission-coordination/45-bootstrap-invitation/45.02-bootstrap-invitation.d2":"9e019de8289428a97580fe66ccefc6b9d0a43c1bac07433d2f29596f4d407401","docs/40-49-admission-coordination/46-beneficiary-registration/46.02-beneficiary-registration.d2":"322b848fdd67ea88c99b509cb5d913d7a5023e327edea51f16f44816356d81ce","docs/40-49-admission-coordination/47-enrollment-credential/47.02-enrollment-credential.d2":"ea0aa0bed915bea42d3d65c8f6572f799eb63d0aee1018b75803e61ef034d303","docs/40-49-admission-coordination/48-subject-authority/48.02-subject-authority.d2":"9f707fbc6e5ba8933a0e4d9d057f013c5764afc503f819288f628d3f9709f88d","docs/40-49-admission-coordination/49-routine-routing-config/49.02-routine-routing-config.d2":"7fa18b652ba97e8fe66f402a9a85d65740db9d3ffadff7890db7d72826c498b6","docs/50-59-research-program/51-qualified-semantic-slice/51.06-semantic-gateway-slice.d2":"d63df655a635fccac3c92eded92c039a3f079c24fa2b7a2fd0dc1f3fabd3c0f5","docs/50-59-research-program/52-committed-profile-binding/52.04-committed-profile.d2":"3ea30976830c607bf8cec62cbabc4291c384bd5f368049a45777f6f981d87d6e","docs/50-59-research-program/53-gerbil-exit/53.04-gerbil-lifecycle.d2":"b7b623664edc6e86efe62eeee7f5977dc207f0cb12e40cb6f0e77e38160695de","docs/50-59-research-program/54-dynamic-gxi-exit/54.04-dynamic-lifecycle.d2":"d4d410dd8cb10de6d3526b54ac7f96731d2f2a94dd9763aad96a0926608e251c","docs/50-59-research-program/55-dynamic-gxi-paired/55.04-runtime-boundary.d2":"573b248a6b7ce2d7eee1e70a469c54e4f195c4894ec7b0f61c8406fae843eccc","docs/50-59-research-program/56-gambit-image-closure/56.04-locator-boundary.d2":"0c45ee11d269b0cab8998c7fc3432ec851b9390b7530486225134b261d8d7de8","docs/50-59-research-program/57-runtime-implementation/57.03-runtime-boundary.d2":"193d22a5bd9e4b23260334d085df8aa5ec19c349f13cd9f56eaa26fe54f7e3ac","docs/50-59-research-program/58-streaming-execution/58.03-streaming-runtime.d2":"76ea49c83b4b36af1e775f80475d40747640b80a330434bf86635e255e84ef14","docs/50-59-research-program/58-streaming-execution/58.05-range-progress-recovery.d2":"aef20c8ad7d7420a65422add6d9fb635bdbe32e42e49427d3179bf20499ae4cd","docs/50-59-research-program/59-provider-rpc/59.03-provider-rpc-core.d2":"6f4e8218ea262e35efaebaf8cc2f96345b2ef1e7e9c1a6b12b68290dd99c683d","docs/50-59-research-program/59-provider-rpc/59.21-verification-ownership.d2":"e035ae7e56ee5e6498f131ed62f4792547c1e716aa5ed29865b333f54665e8f1","docs/50-59-research-program/59-provider-rpc/59.26-semantic-execution-ecosystem.d2":"50c091b094125693e2debe73599a63405849f1f55ab3658030674692c9334e14","docs/50-59-research-program/59-provider-rpc/59.30-governance-adapter-acceptance.d2":"88cbbd45e63358bb45a58fb27f85e275b9cc9fb3d3aee6af19eabed0912545d2","docs/50-59-research-program/59-provider-rpc/59.43-floor-transport-owner.d2":"36c4d6b561332ab30deb464a92bb4c2f02ceed5c8a1ca66617f72b6086b2c555","docs/50-59-research-program/59-provider-rpc/59.44-cloud-rpc-arrow-boundaries.d2":"fe0ac2220e04f6ccea851247ecf8ae1cab4ec8c8ba8744010c478992c233ebed","docs/50-59-research-program/59-provider-rpc/59.45-slow-consumer-zero-trust.d2":"e36cf58a239a2d9f0c99789bb7484de4e26180a8f941970540f72b530a79d813","docs/50-59-research-program/59-provider-rpc/59.46-functional-security-frameworks.d2":"e541b969352e8149e71e5b539988f9955b525e5e5ba3e7e7270bd4a98fbe19f5","docs/50-59-research-program/59-provider-rpc/59.47-property-testing-framework.d2":"f66ed065dcf955a233968ca295517c642be30dad9b24e23a781fe34e4bed45d9","docs/50-59-research-program/59-provider-rpc/59.49-policy-proposal-barrier.d2":"3a8559bb22f812075d9d7de4a397978995d06c32ed22e9415f990413551aebb6","docs/50-59-research-program/59-provider-rpc/59.50-parent-contract-and-replay.d2":"2db3983f56e938c927b68077551573c8e86362da892f47890459ab7b3f929c64","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-architecture.d2":"10e92e79b69f4b0813551dd2ddadc5ad225b7b0fa8374ed7015b7f2fe66bb6e1","docs/50-59-research-program/59-provider-rpc/59.51-zero-trust-contract-refinement.d2":"204c9e20d9027b7a38bf2a964da9a7cadb92744561fa9f1eb3fa29d00f4fa386","docs/50-59-research-program/59-provider-rpc/59.52-reviewed-publication-cas.d2":"4e0998e61717d5441e242cde0dfc52198312b67b63f0ce8b0425a423d1b88a24","docs/50-59-research-program/59-provider-rpc/59.53-artifact-registry-recovery.d2":"f7083a48413d41ad99e7191281bd6e74a92b33c7cc1f4f2f9ae322bb1405088a","docs/50-59-research-program/59-provider-rpc/59.54-source-incarnation-authority.d2":"1e55c0487f01d70462e8df6b46eff9e799b0dc592c0e780c759fa602e3d84444","docs/50-59-research-program/59-provider-rpc/59.55-evidence-reviewed-publication.d2":"c66435372642f7a93ca7fc6f78c2abcbc364a4dde447d10dcc4b2b21ccc06456","docs/50-59-research-program/59-provider-rpc/59.56-runtime-assets-and-authority-floor.d2":"c675469701bb6994fed1976d1e90d01dc1cc4e416a6788f865494fa3243d32c1","docs/50-59-research-program/59-provider-rpc/59.57-schema-bound-candidate-replay.d2":"5ca15af556e0a4ba5bdf1742cf81182ad72e7f51b2eb63352b839e068a7ad7d2","docs/50-59-research-program/59-provider-rpc/59.58-independent-source-recovery.d2":"4b21999b3554be15374448f36ffbccf517b32784a65cadde0f4c1eb8308da377","docs/50-59-research-program/59-provider-rpc/59.59-retained-root-and-recovery-coverage.d2":"37fdf1d3dd01f087434a6108b43a5657d7aecf79a2b9e60638d70eb0b1a4984b","docs/50-59-research-program/59-provider-rpc/59.60-persistent-source-key-custody.d2":"d27df3a14df5d57ad725c1455c82a4ab5bad45b78acea8cd1a76e59958b710eb","docs/50-59-research-program/59-provider-rpc/59.61-authority-bound-replay-pair.d2":"bd4962775564848a90ec49439301cf0cdfbaa4018956344e809f5b318bea6ccd","docs/50-59-research-program/59-provider-rpc/59.62-burn-exposure-recovery.d2":"fab4ea6d0981d75dd4c704f302268f3c5af0898e299e8e0fb38b34d07200b22c","docs/50-59-research-program/59-provider-rpc/59.63-mrr-admission-contract.d2":"ed3c604e0d350049f00528c7117675a7db751b3d6683719b03be116bcf49d5c5","docs/50-59-research-program/59-provider-rpc/59.64-governance-capture-ownership.d2":"7164874fdbeec99f2185e1091f759466a68a3b7d9b239db6a503f16383fce50e","docs/50-59-research-program/59-provider-rpc/59.65-turso-concurrent-admission.d2":"0ade3ea326e2066ce908129e383b7e0f371a429710ed0a0bad30ddcfd61f034e","docs/50-59-research-program/59-provider-rpc/59.66-bounded-writer-reuse.d2":"9390a3c12f06c2f33e3df99088dc39de92d3bccc971ddf5a632910515a67623e","docs/50-59-research-program/59-provider-rpc/59.67-writer-owner-lifecycle.d2":"c28559ccf38b2f3320d84bbc0ffc6133e2708081e95bff39d5ed75d064287bde","docs/50-59-research-program/59-provider-rpc/59.69-hot-path-cost-boundaries.d2":"e5789625590fab63bc3635627b7e20ac41f64b8f40cbeee84d51a85f27ab31f1","docs/50-59-research-program/59-provider-rpc/59.75-complete-entry-and-output-contract.d2":"d667501bc15d6c31d986994f641d8d38f63c1d910784e6852e596c24c4e4c7c7","docs/50-59-research-program/59-provider-rpc/59.75-package-linkage.d2":"bc655ae71cc46e0d5b7f42637b78530f262c3142394485e2a9ba31f6516a0a10","docs/50-59-research-program/59-provider-rpc/59.76-embedded-tooling-and-darwin-io.d2":"87655d7c6d81c1ab203f886930f1630003e006c0edb71f90ac3ca23a0cb91845","docs/50-59-research-program/59-provider-rpc/59.77-mrr-turso-storage.d2":"72a4dceeb20cca337276f64537d47dbbd2ac0ce359a7a63997090e6476a40c96","docs/50-59-research-program/59-provider-rpc/59.84-quint-preparation-and-completion.d2":"17f485d7c541506c42003ebba887705ea61972f00c9498aa3c0d153a33b02922","docs/architecture/08-diagram-catalog.org":"353a4296584381207513468ef291e7e1aefdcd6f9f2b854c92be90aab47577ea","docs/architecture/diagrams/00a-readme-overview.d2":"1e6119c9d5b2d8a40d3bec0c8add35e8c078dd739e46fcf45c589b8125c7c46f","docs/architecture/diagrams/00c-gateway-runtime.d2":"c1d93cc1f635803872e3349c89b5127145bdcdd2b85e9a48f83d63f0bda439da","docs/architecture/diagrams/00d-zero-trust-overview.d2":"0d3d1a5de0967db2331b9be81468cee1b7cb1d1d98966c5e541e4fc24023f2e6","docs/architecture/diagrams/01-system-boundaries.d2":"0d35addc4e27ab2d6220103872deab6abc1754a6bc36ba236ab3088b1c6d22b5","docs/architecture/diagrams/01-system-relationships.d2":"dde40fac8667b79a070fda14ebd892f1f1e7c1217726595179b541c855f80c2c","docs/architecture/diagrams/02-admission-sequence.d2":"97077cb16cd4457fe14092caeb4bc8cf2912d434763a08fcf350cd6a4c2b2c74","docs/architecture/diagrams/03-attempt-state.d2":"e696fc0f1d63f58100405852e88e8a7dfb1a625e43be398f3bb54bbc1d90e13a","docs/architecture/diagrams/03a-attempt-observation.d2":"6b387ec7fbcff7d5e3e129bad7ea9590afe0324800a5a13bf7a89377ad86c387","docs/architecture/diagrams/04-consume-timeout.d2":"2ccfe8d033069e0d891531f3b5afef4febf21b2722209a612454d14321cac940","docs/architecture/diagrams/05-fencing-boundaries.d2":"1103ed75ac615b1a2f8239c0321d046a5a87acfa235d5042d8a529e23acd7483","docs/architecture/diagrams/06-source-admission.d2":"4d20817291c5de93b7f97366e6cb1b4af954f22de1ebcb3012c139a4b9dbd82c","docs/architecture/diagrams/07-post-claim-outcomes.d2":"63258620c15c2f52963dcdba33b4ac82cd12aadd1c2de005cd029655493493c1","docs/architecture/diagrams/08-code-as-policy.d2":"fc2263ff1ae000055e6054b89beee60f53b9621707510354c34ef45057889676","docs/architecture/diagrams/09-claim-wins-race.d2":"9eff775ddac29c47acd2c0b69fb1ff98ba9a20943da970c2804e270979555c41","docs/architecture/diagrams/10-commit-dispatch-sequence.d2":"fa5d56c49bc3f590c88cf7c3b63e180afd2d2a39fca878d1515917077ff1687a","docs/architecture/diagrams/11-zero-trust-assurance.d2":"ea93840da2ff4bdac59349f5ad7a56cee5506600283d0c364c53275dde0b5b48","docs/architecture/diagrams/12-execution-correspondence.d2":"1dd66ee8c517fd9c6f2f4b1700aeec3e620d699fbe9eeee20df8e05a7f1decb0","docs/architecture/diagrams/13-policy-to-execution.d2":"4bb05b74c3bc0ca997c5e5035ddc949fa374db3ff49bf2104a6c9753e12be3ef","docs/architecture/diagrams/14-adapter-broker-boundary.d2":"b855fa0482a5524226354b26bc8d7ecef0daf2ab1cab54c1783eba0ff29fab01","docs/architecture/diagrams/15-stream-message-authorization.d2":"cedf1c545a853ec2a9ae51bea928b04376d192f1a4c2af117fa54f475ad541e0","docs/architecture/diagrams/16-authoritative-spent-state.d2":"201bd9fe5eb6101543d939e3d83aca646e2b07c13ff1e3c56779571a0cd1172e","docs/architecture/diagrams/17-logical-message-observation.d2":"2333ad147295ead60ed6a92dc824cf6f5769f3828eff1e0cdf58e50aace7b1e1","docs/architecture/diagrams/18-shared-identity-budget.d2":"5ab4992fd8b6a6abf518fb0bbc8c2c8ad8b920d0be74a6e734d846319252ffa7","docs/architecture/diagrams/19-finite-domains-and-migration.d2":"b72b451d0bb97de46831e4b266d8fdd22d59e7d54db99446d53549f081a008e2","docs/architecture/diagrams/20-anchor-recovery-and-egress.d2":"9479271410f1bb57f92106a1d91ec73c73872568d9fcda55cac5aa64b89e5c9f","docs/architecture/diagrams/21-composed-journal-transport-lifecycle.d2":"0fffe555ee4c2c1222c97eebd24ca9b0df91a4d3ec118300ae3b88240004c3c8","docs/architecture/diagrams/22-finite-stream-manifest.d2":"60b33eb6d06aeaa1027546a1fc9d6c07069c3cd3c7d23df8ff8d63a341afe2ea","docs/architecture/diagrams/23-driver-completion-recovery.d2":"271963db2cd881bb82e164bb1544c7bcf311e1781f20170d858ccb65a596d8f5","docs/architecture/diagrams/24-writer-settlement-closure.d2":"ea1930326b0073e7fabd8b64ef3ffea781f1aef60db0d942f9ab14f1150296e9","docs/architecture/diagrams/25-settlement-anchor-recovery.d2":"8904bfcda525de21b48ea8f2db8d12aaa27e85818ccde43fb545851dc522ba3b","docs/architecture/diagrams/26-gate-consumption-persistence.d2":"42e676634ecb40cfb2dee06db1f5497d0e58c05f30097618c3852eb946992f0d","docs/architecture/diagrams/27-anchor-commit-broker-fencing.d2":"5c2ae36987b00655bbcdba36352e03b61765739ad2f3fc80a561ff0d325a9461","docs/architecture/diagrams/28-anchor-configuration-prefix.d2":"1ac0eeb3c76f5ae0ce3565d4469e50210786c3bc53c703a1a61d519dfa075512","docs/architecture/diagrams/29-quorum-durable-promises.d2":"2e4a24c3fae49e710d5afc31d4681a9efc8c2e8af3fa58a0957ede05fe7c0255","docs/architecture/diagrams/39-shared-execution-exposure.d2":"2c08f5b3d4531a7be2aadec8f1ff9d4476495418e94e84c1ff643583ac991ce4","docs/architecture/diagrams/assets/agent-request.svg":"3889ce199c814dfd5d9748d20cdce78d8c3ec3635d9fe90f58d5558f8ae1b281","docs/architecture/diagrams/assets/bounded-write.svg":"a0bc55e74f437d47af786c77e6704d411c5434e314276b7e47efe7290df1d03e","docs/architecture/diagrams/assets/budget-ledger.svg":"94adeac8656b4e24a5a9b99ee1d7a090884e6e853a9dbf4b2220d8b5d986e347","docs/architecture/diagrams/assets/components/activity.svg":"050fbcda05e13c2051cf857683645e19c6b180861ef4d0cc28a6f09ba1ea1666","docs/architecture/diagrams/assets/components/book-open.svg":"9b9bed0ff057283d5c5c5a1c71f8d3e927db26a56639603a92fdf7b25961510e","docs/architecture/diagrams/assets/components/bot.svg":"e46fe72fc5b33d7a17b0112df85da9ded851860312e8353f4fe23d87a4ce77f5","docs/architecture/diagrams/assets/components/brain.svg":"91830115f859daa12e7f2f63fc072311329e363bb8b0b4707f510bcb60c2ab18","docs/architecture/diagrams/assets/components/circle-question-mark.svg":"975db087da041530dbf59ba1e61a7b99c3519fad43dae6375e42ccc74ba63924","docs/architecture/diagrams/assets/components/clipboard-check.svg":"e2bac86a6b24caa0d7d0dcc2719ec6b7870ec5eef2d21afae498d8cb5eefda96","docs/architecture/diagrams/assets/components/coins.svg":"bcfec9236fd10d0aadbf90951f61dd31ec7cedc72dd38d2639f95c2b8437b9f1","docs/architecture/diagrams/assets/components/database.svg":"471eb14bc8d144896a82dfc4aa9daf350f769f0896f4bef33e50aabdbb51130d","docs/architecture/diagrams/assets/components/file-check.svg":"c64133f05e44d87830e37c7a9c45a439c5146017f86e91e563f806ff8a2ad4c1","docs/architecture/diagrams/assets/components/fingerprint-pattern.svg":"26a4e5756ca8fb809c7cf488a1b6b44f6921d4a34a37ca9be8facf53d362ad9b","docs/architecture/diagrams/assets/components/message-square.svg":"5812a3be783fdcd73efd2b6026e03131e4b8c6649e7d52aa2dc7bf2e2023a59d","docs/architecture/diagrams/assets/components/rotate-ccw-clock.svg":"a98ff758157910b9fc9d42d5d5dc80c2f4e037afa5f8ea4dee5f5649f03d438d","docs/architecture/diagrams/assets/components/rotate-ccw.svg":"622685386ab4017eabfde01cd74550a20b1924df233b353f73b6b155371f2afd","docs/architecture/diagrams/assets/components/route.svg":"fc169fd38a9963b016ad6d60fd72baa2b0ea8e0cec085bbc53287297c3d8121a","docs/architecture/diagrams/assets/components/send.svg":"a489257f447b808ab6b258ae888fa49686885bbc30a7a2774d97a01f11f9cd5e","docs/architecture/diagrams/assets/components/shield-check.svg":"8d4fcdbde5bba4abb1a2f6fe53e37ceb6343a1d5449a9d88f6f97c1971d26c4e","docs/architecture/diagrams/assets/components/ticket-check.svg":"04ba144ed3395846a46cc71ae3eaf927c4d0a52001d241cee971219144d55750","docs/architecture/diagrams/assets/components/waves-horizontal.svg":"b31f6534ef601e7c138922e99b0557ae61db7e5704c1a05806ecb78b2eaad443","docs/architecture/diagrams/assets/components/workflow.svg":"ae99ea8f56a2835a2cca35b2fbb57643ab73443610970dba23e24bd9df75cfec","docs/architecture/diagrams/assets/go.svg":"c89d8c4a31dd4f6487e69bc3bdb6585a52466a393f6e8d863bfc1a0189bc213c","docs/architecture/diagrams/assets/kubernetes.svg":"183e54760670315a937c9b515057dcdb033a53f5741c9c6ea4f0b02fe08e78d9","docs/architecture/diagrams/assets/model-catalog.svg":"97057bcacef0ff72f70ce827f997c635ef7843ead97de30acde37eac19185b12","docs/architecture/diagrams/assets/model-provider.svg":"1fdd1782e43f1359e8af8490719041ee1d33255b487ee21003a76a2820791d2c","docs/architecture/diagrams/assets/permission-check.svg":"4acf25f524193eacd457ea47d806fe59965cff5cc440ef5004da742dc200c409","docs/architecture/diagrams/assets/route-choice.svg":"8f1abed227e39a10241f0739d00f965abc0293b3583902ee9c26e1b78402669f","docs/architecture/diagrams/assets/rust.svg":"6fc2ce4862533b5c07c89c2c507172dd4bd1b3ea1efb6ad5553de4538a7e3787","docs/architecture/diagrams/assets/task-contract.svg":"6bdb3934faa820a53dd9b77f5b10cfa38096a61a998949e35f866f3958115047","docs/architecture/diagrams/assets/unknown-hold.svg":"f1522ea23b80f91624279a4595f419fba9a44f4ef0b959649e0da1b42f000314","Project.sysml":"5691b1b59a24eb80b61b7e6e49cab49c2e9516640d872c273eaa3b05ee9975bb"},"rendered":{"observation":{"canvas":{"x":0,"y":0,"width":980,"height":857.890625},"subjects":[{"id":"n0","role":"default","x":101,"y":251,"width":300,"height":250},{"id":"n1","role":"default","x":579,"y":251,"width":300,"height":250},{"id":"n2","role":"default","x":28,"y":579,"width":286.65625,"height":238.875},{"id":"n3","role":"default","x":346.65625,"y":579,"width":286.671875,"height":238.890625},{"id":"n4","role":"default","x":665.328125,"y":579,"width":286.65625,"height":85.984375}],"relations":["edge:1","edge:2","edge:3","edge:0"],"headings":[{"role":"title","x":20,"y":20,"width":940,"height":63},{"role":"question","x":20,"y":83,"width":940,"height":56},{"role":"note","x":20,"y":155,"width":940,"height":48}]},"readability":{"minimumTextSize":24.839930555555554,"samples":14},"bounds":{"objects":{"x":20,"y":231,"width":940,"height":606.890625}}}}Trace authority to the final writer?Who owns meaning, coordination and actual effects?Scheme supplies semantics. Rust coordinates publication and owns effects. + @@ -40,9 +42,11 @@ SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 --> -Scheme governanceTyped policy and contracts - +Scheme governanceTyped policy and contracts + @@ -50,9 +54,11 @@ SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 --> -Go controlRoute and publish intent - +Rust source lanePrepare and publish intent + @@ -60,8 +66,10 @@ SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 --> Rust brokerCurrent claim and policy - + diff --git a/go/api/gateway/v1/gateway.pb.go b/go/api/gateway/v1/gateway.pb.go index f3540b94..b2474416 100644 --- a/go/api/gateway/v1/gateway.pb.go +++ b/go/api/gateway/v1/gateway.pb.go @@ -585,6 +585,151 @@ func (x *HardFactBarrier) GetPendingPrefix() string { return "" } +type PendingHardFact struct { + state protoimpl.MessageState `protogen:"open.v1"` + Barrier *HardFactBarrier `protobuf:"bytes,1,opt,name=barrier,proto3" json:"barrier,omitempty"` + Available bool `protobuf:"varint,2,opt,name=available,proto3" json:"available,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PendingHardFact) Reset() { + *x = PendingHardFact{} + mi := &file_gateway_v1_gateway_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PendingHardFact) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PendingHardFact) ProtoMessage() {} + +func (x *PendingHardFact) ProtoReflect() protoreflect.Message { + mi := &file_gateway_v1_gateway_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PendingHardFact.ProtoReflect.Descriptor instead. +func (*PendingHardFact) Descriptor() ([]byte, []int) { + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{5} +} + +func (x *PendingHardFact) GetBarrier() *HardFactBarrier { + if x != nil { + return x.Barrier + } + return nil +} + +func (x *PendingHardFact) GetAvailable() bool { + if x != nil { + return x.Available + } + return false +} + +type HardFactFeedState struct { + state protoimpl.MessageState `protogen:"open.v1"` + Domain string `protobuf:"bytes,1,opt,name=domain,proto3" json:"domain,omitempty"` + SourceEpoch uint64 `protobuf:"varint,2,opt,name=source_epoch,json=sourceEpoch,proto3" json:"source_epoch,omitempty"` + Floor uint64 `protobuf:"varint,3,opt,name=floor,proto3" json:"floor,omitempty"` + Revision uint64 `protobuf:"varint,4,opt,name=revision,proto3" json:"revision,omitempty"` + Snapshot string `protobuf:"bytes,5,opt,name=snapshot,proto3" json:"snapshot,omitempty"` + Available *bool `protobuf:"varint,6,opt,name=available,proto3,oneof" json:"available,omitempty"` + // Exact durable barriers in resolution order. + Pending []*PendingHardFact `protobuf:"bytes,7,rep,name=pending,proto3" json:"pending,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HardFactFeedState) Reset() { + *x = HardFactFeedState{} + mi := &file_gateway_v1_gateway_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HardFactFeedState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HardFactFeedState) ProtoMessage() {} + +func (x *HardFactFeedState) ProtoReflect() protoreflect.Message { + mi := &file_gateway_v1_gateway_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HardFactFeedState.ProtoReflect.Descriptor instead. +func (*HardFactFeedState) Descriptor() ([]byte, []int) { + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{6} +} + +func (x *HardFactFeedState) GetDomain() string { + if x != nil { + return x.Domain + } + return "" +} + +func (x *HardFactFeedState) GetSourceEpoch() uint64 { + if x != nil { + return x.SourceEpoch + } + return 0 +} + +func (x *HardFactFeedState) GetFloor() uint64 { + if x != nil { + return x.Floor + } + return 0 +} + +func (x *HardFactFeedState) GetRevision() uint64 { + if x != nil { + return x.Revision + } + return 0 +} + +func (x *HardFactFeedState) GetSnapshot() string { + if x != nil { + return x.Snapshot + } + return "" +} + +func (x *HardFactFeedState) GetAvailable() bool { + if x != nil && x.Available != nil { + return *x.Available + } + return false +} + +func (x *HardFactFeedState) GetPending() []*PendingHardFact { + if x != nil { + return x.Pending + } + return nil +} + type FactBarrierResolution struct { state protoimpl.MessageState `protogen:"open.v1"` Barrier *HardFactBarrier `protobuf:"bytes,1,opt,name=barrier,proto3" json:"barrier,omitempty"` @@ -598,7 +743,7 @@ type FactBarrierResolution struct { func (x *FactBarrierResolution) Reset() { *x = FactBarrierResolution{} - mi := &file_gateway_v1_gateway_proto_msgTypes[5] + mi := &file_gateway_v1_gateway_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -610,7 +755,7 @@ func (x *FactBarrierResolution) String() string { func (*FactBarrierResolution) ProtoMessage() {} func (x *FactBarrierResolution) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[5] + mi := &file_gateway_v1_gateway_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -623,7 +768,7 @@ func (x *FactBarrierResolution) ProtoReflect() protoreflect.Message { // Deprecated: Use FactBarrierResolution.ProtoReflect.Descriptor instead. func (*FactBarrierResolution) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{5} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{7} } func (x *FactBarrierResolution) GetBarrier() *HardFactBarrier { @@ -671,7 +816,7 @@ type WorkflowEdge struct { func (x *WorkflowEdge) Reset() { *x = WorkflowEdge{} - mi := &file_gateway_v1_gateway_proto_msgTypes[6] + mi := &file_gateway_v1_gateway_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -683,7 +828,7 @@ func (x *WorkflowEdge) String() string { func (*WorkflowEdge) ProtoMessage() {} func (x *WorkflowEdge) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[6] + mi := &file_gateway_v1_gateway_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -696,7 +841,7 @@ func (x *WorkflowEdge) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkflowEdge.ProtoReflect.Descriptor instead. func (*WorkflowEdge) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{6} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{8} } func (x *WorkflowEdge) GetDependent() string { @@ -724,7 +869,7 @@ type WorkflowSelector struct { func (x *WorkflowSelector) Reset() { *x = WorkflowSelector{} - mi := &file_gateway_v1_gateway_proto_msgTypes[7] + mi := &file_gateway_v1_gateway_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -736,7 +881,7 @@ func (x *WorkflowSelector) String() string { func (*WorkflowSelector) ProtoMessage() {} func (x *WorkflowSelector) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[7] + mi := &file_gateway_v1_gateway_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -749,7 +894,7 @@ func (x *WorkflowSelector) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkflowSelector.ProtoReflect.Descriptor instead. func (*WorkflowSelector) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{7} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{9} } func (x *WorkflowSelector) GetSelector() string { @@ -786,7 +931,7 @@ type GovernanceSelection struct { func (x *GovernanceSelection) Reset() { *x = GovernanceSelection{} - mi := &file_gateway_v1_gateway_proto_msgTypes[8] + mi := &file_gateway_v1_gateway_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -798,7 +943,7 @@ func (x *GovernanceSelection) String() string { func (*GovernanceSelection) ProtoMessage() {} func (x *GovernanceSelection) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[8] + mi := &file_gateway_v1_gateway_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -811,7 +956,7 @@ func (x *GovernanceSelection) ProtoReflect() protoreflect.Message { // Deprecated: Use GovernanceSelection.ProtoReflect.Descriptor instead. func (*GovernanceSelection) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{8} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{10} } func (x *GovernanceSelection) GetSchema() string { @@ -861,7 +1006,7 @@ type SourceArtifact struct { func (x *SourceArtifact) Reset() { *x = SourceArtifact{} - mi := &file_gateway_v1_gateway_proto_msgTypes[9] + mi := &file_gateway_v1_gateway_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -873,7 +1018,7 @@ func (x *SourceArtifact) String() string { func (*SourceArtifact) ProtoMessage() {} func (x *SourceArtifact) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[9] + mi := &file_gateway_v1_gateway_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -886,7 +1031,7 @@ func (x *SourceArtifact) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceArtifact.ProtoReflect.Descriptor instead. func (*SourceArtifact) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{9} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{11} } func (x *SourceArtifact) GetGovernance() *GovernanceSelection { @@ -931,7 +1076,7 @@ type RoutingCandidate struct { func (x *RoutingCandidate) Reset() { *x = RoutingCandidate{} - mi := &file_gateway_v1_gateway_proto_msgTypes[10] + mi := &file_gateway_v1_gateway_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -943,7 +1088,7 @@ func (x *RoutingCandidate) String() string { func (*RoutingCandidate) ProtoMessage() {} func (x *RoutingCandidate) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[10] + mi := &file_gateway_v1_gateway_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -956,7 +1101,7 @@ func (x *RoutingCandidate) ProtoReflect() protoreflect.Message { // Deprecated: Use RoutingCandidate.ProtoReflect.Descriptor instead. func (*RoutingCandidate) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{10} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{12} } func (x *RoutingCandidate) GetModule() string { @@ -1016,7 +1161,7 @@ type RoutingSelection struct { func (x *RoutingSelection) Reset() { *x = RoutingSelection{} - mi := &file_gateway_v1_gateway_proto_msgTypes[11] + mi := &file_gateway_v1_gateway_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1028,7 +1173,7 @@ func (x *RoutingSelection) String() string { func (*RoutingSelection) ProtoMessage() {} func (x *RoutingSelection) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[11] + mi := &file_gateway_v1_gateway_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1041,7 +1186,7 @@ func (x *RoutingSelection) ProtoReflect() protoreflect.Message { // Deprecated: Use RoutingSelection.ProtoReflect.Descriptor instead. func (*RoutingSelection) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{11} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{13} } func (x *RoutingSelection) GetNode() string { @@ -1105,7 +1250,7 @@ type SourceCompositionRequest struct { func (x *SourceCompositionRequest) Reset() { *x = SourceCompositionRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[12] + mi := &file_gateway_v1_gateway_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1117,7 +1262,7 @@ func (x *SourceCompositionRequest) String() string { func (*SourceCompositionRequest) ProtoMessage() {} func (x *SourceCompositionRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[12] + mi := &file_gateway_v1_gateway_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1130,7 +1275,7 @@ func (x *SourceCompositionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceCompositionRequest.ProtoReflect.Descriptor instead. func (*SourceCompositionRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{12} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{14} } func (x *SourceCompositionRequest) GetSource() *SourceArtifact { @@ -1171,7 +1316,7 @@ type SourceCompositionReply struct { func (x *SourceCompositionReply) Reset() { *x = SourceCompositionReply{} - mi := &file_gateway_v1_gateway_proto_msgTypes[13] + mi := &file_gateway_v1_gateway_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1183,7 +1328,7 @@ func (x *SourceCompositionReply) String() string { func (*SourceCompositionReply) ProtoMessage() {} func (x *SourceCompositionReply) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[13] + mi := &file_gateway_v1_gateway_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1196,7 +1341,7 @@ func (x *SourceCompositionReply) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceCompositionReply.ProtoReflect.Descriptor instead. func (*SourceCompositionReply) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{13} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{15} } func (x *SourceCompositionReply) GetArtifact() *SourceArtifact { @@ -1225,7 +1370,7 @@ type CompiledSource struct { func (x *CompiledSource) Reset() { *x = CompiledSource{} - mi := &file_gateway_v1_gateway_proto_msgTypes[14] + mi := &file_gateway_v1_gateway_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1237,7 +1382,7 @@ func (x *CompiledSource) String() string { func (*CompiledSource) ProtoMessage() {} func (x *CompiledSource) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[14] + mi := &file_gateway_v1_gateway_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1250,7 +1395,7 @@ func (x *CompiledSource) ProtoReflect() protoreflect.Message { // Deprecated: Use CompiledSource.ProtoReflect.Descriptor instead. func (*CompiledSource) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{14} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{16} } func (x *CompiledSource) GetProducer() string { @@ -1284,7 +1429,7 @@ type OperationKey struct { func (x *OperationKey) Reset() { *x = OperationKey{} - mi := &file_gateway_v1_gateway_proto_msgTypes[15] + mi := &file_gateway_v1_gateway_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1296,7 +1441,7 @@ func (x *OperationKey) String() string { func (*OperationKey) ProtoMessage() {} func (x *OperationKey) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[15] + mi := &file_gateway_v1_gateway_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1309,7 +1454,7 @@ func (x *OperationKey) ProtoReflect() protoreflect.Message { // Deprecated: Use OperationKey.ProtoReflect.Descriptor instead. func (*OperationKey) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{15} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{17} } func (x *OperationKey) GetFamily() string { @@ -1336,7 +1481,7 @@ type Route struct { func (x *Route) Reset() { *x = Route{} - mi := &file_gateway_v1_gateway_proto_msgTypes[16] + mi := &file_gateway_v1_gateway_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1348,7 +1493,7 @@ func (x *Route) String() string { func (*Route) ProtoMessage() {} func (x *Route) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[16] + mi := &file_gateway_v1_gateway_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1361,7 +1506,7 @@ func (x *Route) ProtoReflect() protoreflect.Message { // Deprecated: Use Route.ProtoReflect.Descriptor instead. func (*Route) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{16} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{18} } func (x *Route) GetTarget() string { @@ -1396,7 +1541,7 @@ type ProviderPlan struct { func (x *ProviderPlan) Reset() { *x = ProviderPlan{} - mi := &file_gateway_v1_gateway_proto_msgTypes[17] + mi := &file_gateway_v1_gateway_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1408,7 +1553,7 @@ func (x *ProviderPlan) String() string { func (*ProviderPlan) ProtoMessage() {} func (x *ProviderPlan) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[17] + mi := &file_gateway_v1_gateway_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1421,7 +1566,7 @@ func (x *ProviderPlan) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderPlan.ProtoReflect.Descriptor instead. func (*ProviderPlan) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{17} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{19} } func (x *ProviderPlan) GetFamily() string { @@ -1506,7 +1651,7 @@ type ProviderRequest struct { func (x *ProviderRequest) Reset() { *x = ProviderRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[18] + mi := &file_gateway_v1_gateway_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1518,7 +1663,7 @@ func (x *ProviderRequest) String() string { func (*ProviderRequest) ProtoMessage() {} func (x *ProviderRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[18] + mi := &file_gateway_v1_gateway_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1531,7 +1676,7 @@ func (x *ProviderRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderRequest.ProtoReflect.Descriptor instead. func (*ProviderRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{18} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{20} } func (x *ProviderRequest) GetPlan() *ProviderPlan { @@ -1572,7 +1717,7 @@ type ProviderCatalogSnapshot struct { func (x *ProviderCatalogSnapshot) Reset() { *x = ProviderCatalogSnapshot{} - mi := &file_gateway_v1_gateway_proto_msgTypes[19] + mi := &file_gateway_v1_gateway_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1584,7 +1729,7 @@ func (x *ProviderCatalogSnapshot) String() string { func (*ProviderCatalogSnapshot) ProtoMessage() {} func (x *ProviderCatalogSnapshot) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[19] + mi := &file_gateway_v1_gateway_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1597,7 +1742,7 @@ func (x *ProviderCatalogSnapshot) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderCatalogSnapshot.ProtoReflect.Descriptor instead. func (*ProviderCatalogSnapshot) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{19} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{21} } func (x *ProviderCatalogSnapshot) GetVersion() string { @@ -1623,7 +1768,7 @@ type ProviderCatalogChange struct { func (x *ProviderCatalogChange) Reset() { *x = ProviderCatalogChange{} - mi := &file_gateway_v1_gateway_proto_msgTypes[20] + mi := &file_gateway_v1_gateway_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1635,7 +1780,7 @@ func (x *ProviderCatalogChange) String() string { func (*ProviderCatalogChange) ProtoMessage() {} func (x *ProviderCatalogChange) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[20] + mi := &file_gateway_v1_gateway_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1648,7 +1793,7 @@ func (x *ProviderCatalogChange) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderCatalogChange.ProtoReflect.Descriptor instead. func (*ProviderCatalogChange) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{20} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{22} } func (x *ProviderCatalogChange) GetRecord() []byte { @@ -1670,7 +1815,7 @@ type Event struct { func (x *Event) Reset() { *x = Event{} - mi := &file_gateway_v1_gateway_proto_msgTypes[21] + mi := &file_gateway_v1_gateway_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1682,7 +1827,7 @@ func (x *Event) String() string { func (*Event) ProtoMessage() {} func (x *Event) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[21] + mi := &file_gateway_v1_gateway_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1695,7 +1840,7 @@ func (x *Event) ProtoReflect() protoreflect.Message { // Deprecated: Use Event.ProtoReflect.Descriptor instead. func (*Event) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{21} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{23} } func (x *Event) GetSequence() uint64 { @@ -1737,7 +1882,7 @@ type ArrowBatch struct { func (x *ArrowBatch) Reset() { *x = ArrowBatch{} - mi := &file_gateway_v1_gateway_proto_msgTypes[22] + mi := &file_gateway_v1_gateway_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1749,7 +1894,7 @@ func (x *ArrowBatch) String() string { func (*ArrowBatch) ProtoMessage() {} func (x *ArrowBatch) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[22] + mi := &file_gateway_v1_gateway_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1762,7 +1907,7 @@ func (x *ArrowBatch) ProtoReflect() protoreflect.Message { // Deprecated: Use ArrowBatch.ProtoReflect.Descriptor instead. func (*ArrowBatch) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{22} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{24} } func (x *ArrowBatch) GetIpc() []byte { @@ -1801,7 +1946,7 @@ type ProviderFrame struct { func (x *ProviderFrame) Reset() { *x = ProviderFrame{} - mi := &file_gateway_v1_gateway_proto_msgTypes[23] + mi := &file_gateway_v1_gateway_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1813,7 +1958,7 @@ func (x *ProviderFrame) String() string { func (*ProviderFrame) ProtoMessage() {} func (x *ProviderFrame) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[23] + mi := &file_gateway_v1_gateway_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1826,7 +1971,7 @@ func (x *ProviderFrame) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderFrame.ProtoReflect.Descriptor instead. func (*ProviderFrame) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{23} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{25} } func (x *ProviderFrame) GetTarget() string { @@ -1900,7 +2045,7 @@ type ProviderReceipt struct { func (x *ProviderReceipt) Reset() { *x = ProviderReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[24] + mi := &file_gateway_v1_gateway_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1912,7 +2057,7 @@ func (x *ProviderReceipt) String() string { func (*ProviderReceipt) ProtoMessage() {} func (x *ProviderReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[24] + mi := &file_gateway_v1_gateway_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1925,7 +2070,7 @@ func (x *ProviderReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderReceipt.ProtoReflect.Descriptor instead. func (*ProviderReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{24} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{26} } func (x *ProviderReceipt) GetFamily() string { @@ -2004,7 +2149,7 @@ type Task struct { func (x *Task) Reset() { *x = Task{} - mi := &file_gateway_v1_gateway_proto_msgTypes[25] + mi := &file_gateway_v1_gateway_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2016,7 +2161,7 @@ func (x *Task) String() string { func (*Task) ProtoMessage() {} func (x *Task) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[25] + mi := &file_gateway_v1_gateway_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2029,7 +2174,7 @@ func (x *Task) ProtoReflect() protoreflect.Message { // Deprecated: Use Task.ProtoReflect.Descriptor instead. func (*Task) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{25} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{27} } func (x *Task) GetFamily() string { @@ -2129,7 +2274,7 @@ type ProviderProfile struct { func (x *ProviderProfile) Reset() { *x = ProviderProfile{} - mi := &file_gateway_v1_gateway_proto_msgTypes[26] + mi := &file_gateway_v1_gateway_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2141,7 +2286,7 @@ func (x *ProviderProfile) String() string { func (*ProviderProfile) ProtoMessage() {} func (x *ProviderProfile) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[26] + mi := &file_gateway_v1_gateway_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2154,7 +2299,7 @@ func (x *ProviderProfile) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderProfile.ProtoReflect.Descriptor instead. func (*ProviderProfile) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{26} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{28} } func (x *ProviderProfile) GetId() string { @@ -2201,7 +2346,7 @@ type RegisterTaskRequest struct { func (x *RegisterTaskRequest) Reset() { *x = RegisterTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[27] + mi := &file_gateway_v1_gateway_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2213,7 +2358,7 @@ func (x *RegisterTaskRequest) String() string { func (*RegisterTaskRequest) ProtoMessage() {} func (x *RegisterTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[27] + mi := &file_gateway_v1_gateway_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2226,7 +2371,7 @@ func (x *RegisterTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{27} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{29} } func (x *RegisterTaskRequest) GetTask() *Task { @@ -2248,7 +2393,7 @@ type DomainBinding struct { func (x *DomainBinding) Reset() { *x = DomainBinding{} - mi := &file_gateway_v1_gateway_proto_msgTypes[28] + mi := &file_gateway_v1_gateway_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2260,7 +2405,7 @@ func (x *DomainBinding) String() string { func (*DomainBinding) ProtoMessage() {} func (x *DomainBinding) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[28] + mi := &file_gateway_v1_gateway_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2273,7 +2418,7 @@ func (x *DomainBinding) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainBinding.ProtoReflect.Descriptor instead. func (*DomainBinding) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{28} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{30} } func (x *DomainBinding) GetOrigin() string { @@ -2318,7 +2463,7 @@ type DomainStamp struct { func (x *DomainStamp) Reset() { *x = DomainStamp{} - mi := &file_gateway_v1_gateway_proto_msgTypes[29] + mi := &file_gateway_v1_gateway_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2330,7 +2475,7 @@ func (x *DomainStamp) String() string { func (*DomainStamp) ProtoMessage() {} func (x *DomainStamp) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[29] + mi := &file_gateway_v1_gateway_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2343,7 +2488,7 @@ func (x *DomainStamp) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainStamp.ProtoReflect.Descriptor instead. func (*DomainStamp) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{29} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{31} } func (x *DomainStamp) GetOrigin() string { @@ -2402,7 +2547,7 @@ type DomainView struct { func (x *DomainView) Reset() { *x = DomainView{} - mi := &file_gateway_v1_gateway_proto_msgTypes[30] + mi := &file_gateway_v1_gateway_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2414,7 +2559,7 @@ func (x *DomainView) String() string { func (*DomainView) ProtoMessage() {} func (x *DomainView) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[30] + mi := &file_gateway_v1_gateway_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2427,7 +2572,7 @@ func (x *DomainView) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainView.ProtoReflect.Descriptor instead. func (*DomainView) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{30} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{32} } func (x *DomainView) GetFamily() string { @@ -2483,7 +2628,7 @@ type RegisterDomainTaskRequest struct { func (x *RegisterDomainTaskRequest) Reset() { *x = RegisterDomainTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[31] + mi := &file_gateway_v1_gateway_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2495,7 +2640,7 @@ func (x *RegisterDomainTaskRequest) String() string { func (*RegisterDomainTaskRequest) ProtoMessage() {} func (x *RegisterDomainTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[31] + mi := &file_gateway_v1_gateway_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2508,7 +2653,7 @@ func (x *RegisterDomainTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterDomainTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterDomainTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{31} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{33} } func (x *RegisterDomainTaskRequest) GetTask() *Task { @@ -2543,7 +2688,7 @@ type TaskAdmission struct { func (x *TaskAdmission) Reset() { *x = TaskAdmission{} - mi := &file_gateway_v1_gateway_proto_msgTypes[32] + mi := &file_gateway_v1_gateway_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2555,7 +2700,7 @@ func (x *TaskAdmission) String() string { func (*TaskAdmission) ProtoMessage() {} func (x *TaskAdmission) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[32] + mi := &file_gateway_v1_gateway_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2568,7 +2713,7 @@ func (x *TaskAdmission) ProtoReflect() protoreflect.Message { // Deprecated: Use TaskAdmission.ProtoReflect.Descriptor instead. func (*TaskAdmission) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{32} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{34} } func (x *TaskAdmission) GetTaskKey() string { @@ -2604,7 +2749,7 @@ type RegisterOriginalTaskRequest struct { func (x *RegisterOriginalTaskRequest) Reset() { *x = RegisterOriginalTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[33] + mi := &file_gateway_v1_gateway_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2616,7 +2761,7 @@ func (x *RegisterOriginalTaskRequest) String() string { func (*RegisterOriginalTaskRequest) ProtoMessage() {} func (x *RegisterOriginalTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[33] + mi := &file_gateway_v1_gateway_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2629,7 +2774,7 @@ func (x *RegisterOriginalTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterOriginalTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterOriginalTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{33} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{35} } func (x *RegisterOriginalTaskRequest) GetTask() *Task { @@ -2674,7 +2819,7 @@ type TaskAdmissionReceipt struct { func (x *TaskAdmissionReceipt) Reset() { *x = TaskAdmissionReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[34] + mi := &file_gateway_v1_gateway_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2686,7 +2831,7 @@ func (x *TaskAdmissionReceipt) String() string { func (*TaskAdmissionReceipt) ProtoMessage() {} func (x *TaskAdmissionReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[34] + mi := &file_gateway_v1_gateway_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2699,7 +2844,7 @@ func (x *TaskAdmissionReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use TaskAdmissionReceipt.ProtoReflect.Descriptor instead. func (*TaskAdmissionReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{34} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{36} } func (x *TaskAdmissionReceipt) GetOperationId() string { @@ -2754,7 +2899,7 @@ type FamilyAliasRequest struct { func (x *FamilyAliasRequest) Reset() { *x = FamilyAliasRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[35] + mi := &file_gateway_v1_gateway_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2766,7 +2911,7 @@ func (x *FamilyAliasRequest) String() string { func (*FamilyAliasRequest) ProtoMessage() {} func (x *FamilyAliasRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[35] + mi := &file_gateway_v1_gateway_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2779,7 +2924,7 @@ func (x *FamilyAliasRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FamilyAliasRequest.ProtoReflect.Descriptor instead. func (*FamilyAliasRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{35} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{37} } func (x *FamilyAliasRequest) GetFamily() string { @@ -2813,7 +2958,7 @@ type DomainMigration struct { func (x *DomainMigration) Reset() { *x = DomainMigration{} - mi := &file_gateway_v1_gateway_proto_msgTypes[36] + mi := &file_gateway_v1_gateway_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2825,7 +2970,7 @@ func (x *DomainMigration) String() string { func (*DomainMigration) ProtoMessage() {} func (x *DomainMigration) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[36] + mi := &file_gateway_v1_gateway_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2838,7 +2983,7 @@ func (x *DomainMigration) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainMigration.ProtoReflect.Descriptor instead. func (*DomainMigration) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{36} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{38} } func (x *DomainMigration) GetOperationId() string { @@ -2919,7 +3064,7 @@ type DomainMigrationReceipt struct { func (x *DomainMigrationReceipt) Reset() { *x = DomainMigrationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[37] + mi := &file_gateway_v1_gateway_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2931,7 +3076,7 @@ func (x *DomainMigrationReceipt) String() string { func (*DomainMigrationReceipt) ProtoMessage() {} func (x *DomainMigrationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[37] + mi := &file_gateway_v1_gateway_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2944,7 +3089,7 @@ func (x *DomainMigrationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use DomainMigrationReceipt.ProtoReflect.Descriptor instead. func (*DomainMigrationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{37} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{39} } func (x *DomainMigrationReceipt) GetOperationId() string { @@ -3010,7 +3155,7 @@ type RegisterPublishedTaskRequest struct { func (x *RegisterPublishedTaskRequest) Reset() { *x = RegisterPublishedTaskRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[38] + mi := &file_gateway_v1_gateway_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3022,7 +3167,7 @@ func (x *RegisterPublishedTaskRequest) String() string { func (*RegisterPublishedTaskRequest) ProtoMessage() {} func (x *RegisterPublishedTaskRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[38] + mi := &file_gateway_v1_gateway_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3035,7 +3180,7 @@ func (x *RegisterPublishedTaskRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterPublishedTaskRequest.ProtoReflect.Descriptor instead. func (*RegisterPublishedTaskRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{38} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{40} } func (x *RegisterPublishedTaskRequest) GetTask() *Task { @@ -3072,7 +3217,7 @@ type PublishRequest struct { func (x *PublishRequest) Reset() { *x = PublishRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[39] + mi := &file_gateway_v1_gateway_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3084,7 +3229,7 @@ func (x *PublishRequest) String() string { func (*PublishRequest) ProtoMessage() {} func (x *PublishRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[39] + mi := &file_gateway_v1_gateway_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3097,7 +3242,7 @@ func (x *PublishRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PublishRequest.ProtoReflect.Descriptor instead. func (*PublishRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{39} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{41} } func (x *PublishRequest) GetExpectedRevision() uint64 { @@ -3148,7 +3293,7 @@ type PublicationReceipt struct { func (x *PublicationReceipt) Reset() { *x = PublicationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[40] + mi := &file_gateway_v1_gateway_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3160,7 +3305,7 @@ func (x *PublicationReceipt) String() string { func (*PublicationReceipt) ProtoMessage() {} func (x *PublicationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[40] + mi := &file_gateway_v1_gateway_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3173,7 +3318,7 @@ func (x *PublicationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationReceipt.ProtoReflect.Descriptor instead. func (*PublicationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{40} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{42} } func (x *PublicationReceipt) GetOperationId() string { @@ -3221,7 +3366,7 @@ type PublicationKey struct { func (x *PublicationKey) Reset() { *x = PublicationKey{} - mi := &file_gateway_v1_gateway_proto_msgTypes[41] + mi := &file_gateway_v1_gateway_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3233,7 +3378,7 @@ func (x *PublicationKey) String() string { func (*PublicationKey) ProtoMessage() {} func (x *PublicationKey) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[41] + mi := &file_gateway_v1_gateway_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3246,7 +3391,7 @@ func (x *PublicationKey) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationKey.ProtoReflect.Descriptor instead. func (*PublicationKey) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{41} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{43} } func (x *PublicationKey) GetOperationId() string { @@ -3273,7 +3418,7 @@ type SourceAuthorityView struct { func (x *SourceAuthorityView) Reset() { *x = SourceAuthorityView{} - mi := &file_gateway_v1_gateway_proto_msgTypes[42] + mi := &file_gateway_v1_gateway_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3285,7 +3430,7 @@ func (x *SourceAuthorityView) String() string { func (*SourceAuthorityView) ProtoMessage() {} func (x *SourceAuthorityView) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[42] + mi := &file_gateway_v1_gateway_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3298,7 +3443,7 @@ func (x *SourceAuthorityView) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceAuthorityView.ProtoReflect.Descriptor instead. func (*SourceAuthorityView) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{42} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{44} } func (x *SourceAuthorityView) GetEpoch() uint64 { @@ -3328,7 +3473,7 @@ type SourceRotationRequest struct { func (x *SourceRotationRequest) Reset() { *x = SourceRotationRequest{} - mi := &file_gateway_v1_gateway_proto_msgTypes[43] + mi := &file_gateway_v1_gateway_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3340,7 +3485,7 @@ func (x *SourceRotationRequest) String() string { func (*SourceRotationRequest) ProtoMessage() {} func (x *SourceRotationRequest) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[43] + mi := &file_gateway_v1_gateway_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3353,7 +3498,7 @@ func (x *SourceRotationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceRotationRequest.ProtoReflect.Descriptor instead. func (*SourceRotationRequest) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{43} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{45} } func (x *SourceRotationRequest) GetOperationId() string { @@ -3396,7 +3541,7 @@ type SourceRotationReceipt struct { func (x *SourceRotationReceipt) Reset() { *x = SourceRotationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[44] + mi := &file_gateway_v1_gateway_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3408,7 +3553,7 @@ func (x *SourceRotationReceipt) String() string { func (*SourceRotationReceipt) ProtoMessage() {} func (x *SourceRotationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[44] + mi := &file_gateway_v1_gateway_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3421,7 +3566,7 @@ func (x *SourceRotationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use SourceRotationReceipt.ProtoReflect.Descriptor instead. func (*SourceRotationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{44} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{46} } func (x *SourceRotationReceipt) GetOperationId() string { @@ -3465,7 +3610,7 @@ type AuthorityParent struct { func (x *AuthorityParent) Reset() { *x = AuthorityParent{} - mi := &file_gateway_v1_gateway_proto_msgTypes[45] + mi := &file_gateway_v1_gateway_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3477,7 +3622,7 @@ func (x *AuthorityParent) String() string { func (*AuthorityParent) ProtoMessage() {} func (x *AuthorityParent) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[45] + mi := &file_gateway_v1_gateway_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3490,7 +3635,7 @@ func (x *AuthorityParent) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthorityParent.ProtoReflect.Descriptor instead. func (*AuthorityParent) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{45} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{47} } func (x *AuthorityParent) GetRevision() uint64 { @@ -3534,7 +3679,7 @@ type ReviewAuthority struct { func (x *ReviewAuthority) Reset() { *x = ReviewAuthority{} - mi := &file_gateway_v1_gateway_proto_msgTypes[46] + mi := &file_gateway_v1_gateway_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3546,7 +3691,7 @@ func (x *ReviewAuthority) String() string { func (*ReviewAuthority) ProtoMessage() {} func (x *ReviewAuthority) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[46] + mi := &file_gateway_v1_gateway_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3559,7 +3704,7 @@ func (x *ReviewAuthority) ProtoReflect() protoreflect.Message { // Deprecated: Use ReviewAuthority.ProtoReflect.Descriptor instead. func (*ReviewAuthority) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{46} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{48} } func (x *ReviewAuthority) GetAudience() string { @@ -3608,7 +3753,7 @@ type PublicationReview struct { func (x *PublicationReview) Reset() { *x = PublicationReview{} - mi := &file_gateway_v1_gateway_proto_msgTypes[47] + mi := &file_gateway_v1_gateway_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3620,7 +3765,7 @@ func (x *PublicationReview) String() string { func (*PublicationReview) ProtoMessage() {} func (x *PublicationReview) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[47] + mi := &file_gateway_v1_gateway_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3633,7 +3778,7 @@ func (x *PublicationReview) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationReview.ProtoReflect.Descriptor instead. func (*PublicationReview) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{47} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{49} } func (x *PublicationReview) GetPublication() *PublicationKey { @@ -3673,7 +3818,7 @@ type DeltaReview struct { func (x *DeltaReview) Reset() { *x = DeltaReview{} - mi := &file_gateway_v1_gateway_proto_msgTypes[48] + mi := &file_gateway_v1_gateway_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3685,7 +3830,7 @@ func (x *DeltaReview) String() string { func (*DeltaReview) ProtoMessage() {} func (x *DeltaReview) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[48] + mi := &file_gateway_v1_gateway_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3698,7 +3843,7 @@ func (x *DeltaReview) ProtoReflect() protoreflect.Message { // Deprecated: Use DeltaReview.ProtoReflect.Descriptor instead. func (*DeltaReview) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{48} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{50} } func (x *DeltaReview) GetReview() *PublicationReview { @@ -3769,7 +3914,7 @@ type PublicationReviewContext struct { func (x *PublicationReviewContext) Reset() { *x = PublicationReviewContext{} - mi := &file_gateway_v1_gateway_proto_msgTypes[49] + mi := &file_gateway_v1_gateway_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3781,7 +3926,7 @@ func (x *PublicationReviewContext) String() string { func (*PublicationReviewContext) ProtoMessage() {} func (x *PublicationReviewContext) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[49] + mi := &file_gateway_v1_gateway_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3794,7 +3939,7 @@ func (x *PublicationReviewContext) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicationReviewContext.ProtoReflect.Descriptor instead. func (*PublicationReviewContext) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{49} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{51} } func (x *PublicationReviewContext) GetPublication() *PublicationKey { @@ -3835,7 +3980,7 @@ type ReviewRegistrationReceipt struct { func (x *ReviewRegistrationReceipt) Reset() { *x = ReviewRegistrationReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[50] + mi := &file_gateway_v1_gateway_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3847,7 +3992,7 @@ func (x *ReviewRegistrationReceipt) String() string { func (*ReviewRegistrationReceipt) ProtoMessage() {} func (x *ReviewRegistrationReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[50] + mi := &file_gateway_v1_gateway_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3860,7 +4005,7 @@ func (x *ReviewRegistrationReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use ReviewRegistrationReceipt.ProtoReflect.Descriptor instead. func (*ReviewRegistrationReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{50} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{52} } func (x *ReviewRegistrationReceipt) GetPublication() *PublicationKey { @@ -3890,7 +4035,7 @@ type MeterCredentialRotation struct { func (x *MeterCredentialRotation) Reset() { *x = MeterCredentialRotation{} - mi := &file_gateway_v1_gateway_proto_msgTypes[51] + mi := &file_gateway_v1_gateway_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3902,7 +4047,7 @@ func (x *MeterCredentialRotation) String() string { func (*MeterCredentialRotation) ProtoMessage() {} func (x *MeterCredentialRotation) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[51] + mi := &file_gateway_v1_gateway_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3915,7 +4060,7 @@ func (x *MeterCredentialRotation) ProtoReflect() protoreflect.Message { // Deprecated: Use MeterCredentialRotation.ProtoReflect.Descriptor instead. func (*MeterCredentialRotation) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{51} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{53} } func (x *MeterCredentialRotation) GetTenant() string { @@ -3962,7 +4107,7 @@ type MeterCredentialEpoch struct { func (x *MeterCredentialEpoch) Reset() { *x = MeterCredentialEpoch{} - mi := &file_gateway_v1_gateway_proto_msgTypes[52] + mi := &file_gateway_v1_gateway_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3974,7 +4119,7 @@ func (x *MeterCredentialEpoch) String() string { func (*MeterCredentialEpoch) ProtoMessage() {} func (x *MeterCredentialEpoch) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[52] + mi := &file_gateway_v1_gateway_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3987,7 +4132,7 @@ func (x *MeterCredentialEpoch) ProtoReflect() protoreflect.Message { // Deprecated: Use MeterCredentialEpoch.ProtoReflect.Descriptor instead. func (*MeterCredentialEpoch) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{52} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{54} } func (x *MeterCredentialEpoch) GetEpoch() uint64 { @@ -4018,7 +4163,7 @@ type MeteringReceipt struct { func (x *MeteringReceipt) Reset() { *x = MeteringReceipt{} - mi := &file_gateway_v1_gateway_proto_msgTypes[53] + mi := &file_gateway_v1_gateway_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4030,7 +4175,7 @@ func (x *MeteringReceipt) String() string { func (*MeteringReceipt) ProtoMessage() {} func (x *MeteringReceipt) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[53] + mi := &file_gateway_v1_gateway_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4043,7 +4188,7 @@ func (x *MeteringReceipt) ProtoReflect() protoreflect.Message { // Deprecated: Use MeteringReceipt.ProtoReflect.Descriptor instead. func (*MeteringReceipt) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{53} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{55} } func (x *MeteringReceipt) GetAudience() string { @@ -4148,7 +4293,7 @@ type MeteringApplication struct { func (x *MeteringApplication) Reset() { *x = MeteringApplication{} - mi := &file_gateway_v1_gateway_proto_msgTypes[54] + mi := &file_gateway_v1_gateway_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4160,7 +4305,7 @@ func (x *MeteringApplication) String() string { func (*MeteringApplication) ProtoMessage() {} func (x *MeteringApplication) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[54] + mi := &file_gateway_v1_gateway_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4173,7 +4318,7 @@ func (x *MeteringApplication) ProtoReflect() protoreflect.Message { // Deprecated: Use MeteringApplication.ProtoReflect.Descriptor instead. func (*MeteringApplication) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{54} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{56} } func (x *MeteringApplication) GetApplication() string { @@ -4211,7 +4356,7 @@ type ProviderOAuthChange struct { func (x *ProviderOAuthChange) Reset() { *x = ProviderOAuthChange{} - mi := &file_gateway_v1_gateway_proto_msgTypes[55] + mi := &file_gateway_v1_gateway_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4223,7 +4368,7 @@ func (x *ProviderOAuthChange) String() string { func (*ProviderOAuthChange) ProtoMessage() {} func (x *ProviderOAuthChange) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[55] + mi := &file_gateway_v1_gateway_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4236,7 +4381,7 @@ func (x *ProviderOAuthChange) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderOAuthChange.ProtoReflect.Descriptor instead. func (*ProviderOAuthChange) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{55} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{57} } func (x *ProviderOAuthChange) GetAction() isProviderOAuthChange_Action { @@ -4315,7 +4460,7 @@ type ProviderOAuthGrant struct { func (x *ProviderOAuthGrant) Reset() { *x = ProviderOAuthGrant{} - mi := &file_gateway_v1_gateway_proto_msgTypes[56] + mi := &file_gateway_v1_gateway_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4327,7 +4472,7 @@ func (x *ProviderOAuthGrant) String() string { func (*ProviderOAuthGrant) ProtoMessage() {} func (x *ProviderOAuthGrant) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[56] + mi := &file_gateway_v1_gateway_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4340,7 +4485,7 @@ func (x *ProviderOAuthGrant) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderOAuthGrant.ProtoReflect.Descriptor instead. func (*ProviderOAuthGrant) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{56} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{58} } func (x *ProviderOAuthGrant) GetIssuer() string { @@ -4438,7 +4583,7 @@ type ProviderOAuthIssuerRotation struct { func (x *ProviderOAuthIssuerRotation) Reset() { *x = ProviderOAuthIssuerRotation{} - mi := &file_gateway_v1_gateway_proto_msgTypes[57] + mi := &file_gateway_v1_gateway_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4450,7 +4595,7 @@ func (x *ProviderOAuthIssuerRotation) String() string { func (*ProviderOAuthIssuerRotation) ProtoMessage() {} func (x *ProviderOAuthIssuerRotation) ProtoReflect() protoreflect.Message { - mi := &file_gateway_v1_gateway_proto_msgTypes[57] + mi := &file_gateway_v1_gateway_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4463,7 +4608,7 @@ func (x *ProviderOAuthIssuerRotation) ProtoReflect() protoreflect.Message { // Deprecated: Use ProviderOAuthIssuerRotation.ProtoReflect.Descriptor instead. func (*ProviderOAuthIssuerRotation) Descriptor() ([]byte, []int) { - return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{57} + return file_gateway_v1_gateway_proto_rawDescGZIP(), []int{59} } func (x *ProviderOAuthIssuerRotation) GetExpectedEpoch() uint64 { @@ -4521,7 +4666,20 @@ const file_gateway_v1_gateway_proto_rawDesc = "" + "\brevision\x18\x03 \x01(\x04R\brevision\x12\x1a\n" + "\bsnapshot\x18\x04 \x01(\tR\bsnapshot\x12\x14\n" + "\x05floor\x18\x05 \x01(\x04R\x05floor\x12%\n" + - "\x0epending_prefix\x18\x06 \x01(\tR\rpendingPrefix\"\x9b\x02\n" + + "\x0epending_prefix\x18\x06 \x01(\tR\rpendingPrefix\"m\n" + + "\x0fPendingHardFact\x12<\n" + + "\abarrier\x18\x01 \x01(\v2\".weaver.gateway.v1.HardFactBarrierR\abarrier\x12\x1c\n" + + "\tavailable\x18\x02 \x01(\bR\tavailable\"\x8b\x02\n" + + "\x11HardFactFeedState\x12\x16\n" + + "\x06domain\x18\x01 \x01(\tR\x06domain\x12!\n" + + "\fsource_epoch\x18\x02 \x01(\x04R\vsourceEpoch\x12\x14\n" + + "\x05floor\x18\x03 \x01(\x04R\x05floor\x12\x1a\n" + + "\brevision\x18\x04 \x01(\x04R\brevision\x12\x1a\n" + + "\bsnapshot\x18\x05 \x01(\tR\bsnapshot\x12!\n" + + "\tavailable\x18\x06 \x01(\bH\x00R\tavailable\x88\x01\x01\x12<\n" + + "\apending\x18\a \x03(\v2\".weaver.gateway.v1.PendingHardFactR\apendingB\f\n" + + "\n" + + "_available\"\x9b\x02\n" + "\x15FactBarrierResolution\x12<\n" + "\abarrier\x18\x01 \x01(\v2\".weaver.gateway.v1.HardFactBarrierR\abarrier\x12\x1a\n" + "\baffected\x18\x02 \x03(\tR\baffected\x12\x14\n" + @@ -4876,7 +5034,7 @@ const file_gateway_v1_gateway_proto_rawDesc = "" + "\x1dDELTA_DISPOSITION_UNSPECIFIED\x10\x00\x12\r\n" + "\tBOOTSTRAP\x10\x01\x12\x15\n" + "\x11NO_EXECUTION_GAIN\x10\x02\x12\x15\n" + - "\x11EXPLICIT_APPROVAL\x10\x032\x90\x15\n" + + "\x11EXPLICIT_APPROVAL\x10\x032\xe3\x15\n" + "\aGateway\x12Y\n" + "\x0fExecuteProvider\x12\".weaver.gateway.v1.ProviderRequest\x1a .weaver.gateway.v1.ProviderFrame0\x01\x12N\n" + "\aInspect\x12\x1f.weaver.gateway.v1.OperationKey\x1a\".weaver.gateway.v1.ProviderReceipt\x12l\n" + @@ -4897,7 +5055,8 @@ const file_gateway_v1_gateway_proto_rawDesc = "" + "\x18InspectPublicationReview\x12!.weaver.gateway.v1.PublicationKey\x1a+.weaver.gateway.v1.PublicationReviewContext\x12i\n" + "\x19RegisterPublicationReview\x12\x1e.weaver.gateway.v1.DeltaReview\x1a,.weaver.gateway.v1.ReviewRegistrationReceipt\x12Z\n" + "\x16InspectSourceAuthority\x12\x18.weaver.gateway.v1.Empty\x1a&.weaver.gateway.v1.SourceAuthorityView\x12k\n" + - "\x15RotateSourceAuthority\x12(.weaver.gateway.v1.SourceRotationRequest\x1a(.weaver.gateway.v1.SourceRotationReceipt\x12V\n" + + "\x15RotateSourceAuthority\x12(.weaver.gateway.v1.SourceRotationRequest\x1a(.weaver.gateway.v1.SourceRotationReceipt\x12Q\n" + + "\x0fInspectHardFact\x12\x18.weaver.gateway.v1.Empty\x1a$.weaver.gateway.v1.HardFactFeedState\x12V\n" + "\rStageHardFact\x12!.weaver.gateway.v1.HardFactIntent\x1a\".weaver.gateway.v1.HardFactBarrier\x12_\n" + "\x0fResolveHardFact\x12\".weaver.gateway.v1.HardFactBarrier\x1a(.weaver.gateway.v1.FactBarrierResolution\x12V\n" + "\rCompileSource\x12\".weaver.gateway.v1.ProducerRequest\x1a!.weaver.gateway.v1.CompiledSource\x12g\n" + @@ -4920,7 +5079,7 @@ func file_gateway_v1_gateway_proto_rawDescGZIP() []byte { } var file_gateway_v1_gateway_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_gateway_v1_gateway_proto_msgTypes = make([]protoimpl.MessageInfo, 62) +var file_gateway_v1_gateway_proto_msgTypes = make([]protoimpl.MessageInfo, 64) var file_gateway_v1_gateway_proto_goTypes = []any{ (Encoding)(0), // 0: weaver.gateway.v1.Encoding (PublicationOutcome)(0), // 1: weaver.gateway.v1.PublicationOutcome @@ -4931,176 +5090,182 @@ var file_gateway_v1_gateway_proto_goTypes = []any{ (*ProducerRequest)(nil), // 6: weaver.gateway.v1.ProducerRequest (*HardFactIntent)(nil), // 7: weaver.gateway.v1.HardFactIntent (*HardFactBarrier)(nil), // 8: weaver.gateway.v1.HardFactBarrier - (*FactBarrierResolution)(nil), // 9: weaver.gateway.v1.FactBarrierResolution - (*WorkflowEdge)(nil), // 10: weaver.gateway.v1.WorkflowEdge - (*WorkflowSelector)(nil), // 11: weaver.gateway.v1.WorkflowSelector - (*GovernanceSelection)(nil), // 12: weaver.gateway.v1.GovernanceSelection - (*SourceArtifact)(nil), // 13: weaver.gateway.v1.SourceArtifact - (*RoutingCandidate)(nil), // 14: weaver.gateway.v1.RoutingCandidate - (*RoutingSelection)(nil), // 15: weaver.gateway.v1.RoutingSelection - (*SourceCompositionRequest)(nil), // 16: weaver.gateway.v1.SourceCompositionRequest - (*SourceCompositionReply)(nil), // 17: weaver.gateway.v1.SourceCompositionReply - (*CompiledSource)(nil), // 18: weaver.gateway.v1.CompiledSource - (*OperationKey)(nil), // 19: weaver.gateway.v1.OperationKey - (*Route)(nil), // 20: weaver.gateway.v1.Route - (*ProviderPlan)(nil), // 21: weaver.gateway.v1.ProviderPlan - (*ProviderRequest)(nil), // 22: weaver.gateway.v1.ProviderRequest - (*ProviderCatalogSnapshot)(nil), // 23: weaver.gateway.v1.ProviderCatalogSnapshot - (*ProviderCatalogChange)(nil), // 24: weaver.gateway.v1.ProviderCatalogChange - (*Event)(nil), // 25: weaver.gateway.v1.Event - (*ArrowBatch)(nil), // 26: weaver.gateway.v1.ArrowBatch - (*ProviderFrame)(nil), // 27: weaver.gateway.v1.ProviderFrame - (*ProviderReceipt)(nil), // 28: weaver.gateway.v1.ProviderReceipt - (*Task)(nil), // 29: weaver.gateway.v1.Task - (*ProviderProfile)(nil), // 30: weaver.gateway.v1.ProviderProfile - (*RegisterTaskRequest)(nil), // 31: weaver.gateway.v1.RegisterTaskRequest - (*DomainBinding)(nil), // 32: weaver.gateway.v1.DomainBinding - (*DomainStamp)(nil), // 33: weaver.gateway.v1.DomainStamp - (*DomainView)(nil), // 34: weaver.gateway.v1.DomainView - (*RegisterDomainTaskRequest)(nil), // 35: weaver.gateway.v1.RegisterDomainTaskRequest - (*TaskAdmission)(nil), // 36: weaver.gateway.v1.TaskAdmission - (*RegisterOriginalTaskRequest)(nil), // 37: weaver.gateway.v1.RegisterOriginalTaskRequest - (*TaskAdmissionReceipt)(nil), // 38: weaver.gateway.v1.TaskAdmissionReceipt - (*FamilyAliasRequest)(nil), // 39: weaver.gateway.v1.FamilyAliasRequest - (*DomainMigration)(nil), // 40: weaver.gateway.v1.DomainMigration - (*DomainMigrationReceipt)(nil), // 41: weaver.gateway.v1.DomainMigrationReceipt - (*RegisterPublishedTaskRequest)(nil), // 42: weaver.gateway.v1.RegisterPublishedTaskRequest - (*PublishRequest)(nil), // 43: weaver.gateway.v1.PublishRequest - (*PublicationReceipt)(nil), // 44: weaver.gateway.v1.PublicationReceipt - (*PublicationKey)(nil), // 45: weaver.gateway.v1.PublicationKey - (*SourceAuthorityView)(nil), // 46: weaver.gateway.v1.SourceAuthorityView - (*SourceRotationRequest)(nil), // 47: weaver.gateway.v1.SourceRotationRequest - (*SourceRotationReceipt)(nil), // 48: weaver.gateway.v1.SourceRotationReceipt - (*AuthorityParent)(nil), // 49: weaver.gateway.v1.AuthorityParent - (*ReviewAuthority)(nil), // 50: weaver.gateway.v1.ReviewAuthority - (*PublicationReview)(nil), // 51: weaver.gateway.v1.PublicationReview - (*DeltaReview)(nil), // 52: weaver.gateway.v1.DeltaReview - (*PublicationReviewContext)(nil), // 53: weaver.gateway.v1.PublicationReviewContext - (*ReviewRegistrationReceipt)(nil), // 54: weaver.gateway.v1.ReviewRegistrationReceipt - (*MeterCredentialRotation)(nil), // 55: weaver.gateway.v1.MeterCredentialRotation - (*MeterCredentialEpoch)(nil), // 56: weaver.gateway.v1.MeterCredentialEpoch - (*MeteringReceipt)(nil), // 57: weaver.gateway.v1.MeteringReceipt - (*MeteringApplication)(nil), // 58: weaver.gateway.v1.MeteringApplication - (*ProviderOAuthChange)(nil), // 59: weaver.gateway.v1.ProviderOAuthChange - (*ProviderOAuthGrant)(nil), // 60: weaver.gateway.v1.ProviderOAuthGrant - (*ProviderOAuthIssuerRotation)(nil), // 61: weaver.gateway.v1.ProviderOAuthIssuerRotation - nil, // 62: weaver.gateway.v1.Task.EndpointsEntry - nil, // 63: weaver.gateway.v1.Task.BodyDigestsEntry - nil, // 64: weaver.gateway.v1.Task.NodeCostBoundsEntry - nil, // 65: weaver.gateway.v1.Task.StreamContractsEntry + (*PendingHardFact)(nil), // 9: weaver.gateway.v1.PendingHardFact + (*HardFactFeedState)(nil), // 10: weaver.gateway.v1.HardFactFeedState + (*FactBarrierResolution)(nil), // 11: weaver.gateway.v1.FactBarrierResolution + (*WorkflowEdge)(nil), // 12: weaver.gateway.v1.WorkflowEdge + (*WorkflowSelector)(nil), // 13: weaver.gateway.v1.WorkflowSelector + (*GovernanceSelection)(nil), // 14: weaver.gateway.v1.GovernanceSelection + (*SourceArtifact)(nil), // 15: weaver.gateway.v1.SourceArtifact + (*RoutingCandidate)(nil), // 16: weaver.gateway.v1.RoutingCandidate + (*RoutingSelection)(nil), // 17: weaver.gateway.v1.RoutingSelection + (*SourceCompositionRequest)(nil), // 18: weaver.gateway.v1.SourceCompositionRequest + (*SourceCompositionReply)(nil), // 19: weaver.gateway.v1.SourceCompositionReply + (*CompiledSource)(nil), // 20: weaver.gateway.v1.CompiledSource + (*OperationKey)(nil), // 21: weaver.gateway.v1.OperationKey + (*Route)(nil), // 22: weaver.gateway.v1.Route + (*ProviderPlan)(nil), // 23: weaver.gateway.v1.ProviderPlan + (*ProviderRequest)(nil), // 24: weaver.gateway.v1.ProviderRequest + (*ProviderCatalogSnapshot)(nil), // 25: weaver.gateway.v1.ProviderCatalogSnapshot + (*ProviderCatalogChange)(nil), // 26: weaver.gateway.v1.ProviderCatalogChange + (*Event)(nil), // 27: weaver.gateway.v1.Event + (*ArrowBatch)(nil), // 28: weaver.gateway.v1.ArrowBatch + (*ProviderFrame)(nil), // 29: weaver.gateway.v1.ProviderFrame + (*ProviderReceipt)(nil), // 30: weaver.gateway.v1.ProviderReceipt + (*Task)(nil), // 31: weaver.gateway.v1.Task + (*ProviderProfile)(nil), // 32: weaver.gateway.v1.ProviderProfile + (*RegisterTaskRequest)(nil), // 33: weaver.gateway.v1.RegisterTaskRequest + (*DomainBinding)(nil), // 34: weaver.gateway.v1.DomainBinding + (*DomainStamp)(nil), // 35: weaver.gateway.v1.DomainStamp + (*DomainView)(nil), // 36: weaver.gateway.v1.DomainView + (*RegisterDomainTaskRequest)(nil), // 37: weaver.gateway.v1.RegisterDomainTaskRequest + (*TaskAdmission)(nil), // 38: weaver.gateway.v1.TaskAdmission + (*RegisterOriginalTaskRequest)(nil), // 39: weaver.gateway.v1.RegisterOriginalTaskRequest + (*TaskAdmissionReceipt)(nil), // 40: weaver.gateway.v1.TaskAdmissionReceipt + (*FamilyAliasRequest)(nil), // 41: weaver.gateway.v1.FamilyAliasRequest + (*DomainMigration)(nil), // 42: weaver.gateway.v1.DomainMigration + (*DomainMigrationReceipt)(nil), // 43: weaver.gateway.v1.DomainMigrationReceipt + (*RegisterPublishedTaskRequest)(nil), // 44: weaver.gateway.v1.RegisterPublishedTaskRequest + (*PublishRequest)(nil), // 45: weaver.gateway.v1.PublishRequest + (*PublicationReceipt)(nil), // 46: weaver.gateway.v1.PublicationReceipt + (*PublicationKey)(nil), // 47: weaver.gateway.v1.PublicationKey + (*SourceAuthorityView)(nil), // 48: weaver.gateway.v1.SourceAuthorityView + (*SourceRotationRequest)(nil), // 49: weaver.gateway.v1.SourceRotationRequest + (*SourceRotationReceipt)(nil), // 50: weaver.gateway.v1.SourceRotationReceipt + (*AuthorityParent)(nil), // 51: weaver.gateway.v1.AuthorityParent + (*ReviewAuthority)(nil), // 52: weaver.gateway.v1.ReviewAuthority + (*PublicationReview)(nil), // 53: weaver.gateway.v1.PublicationReview + (*DeltaReview)(nil), // 54: weaver.gateway.v1.DeltaReview + (*PublicationReviewContext)(nil), // 55: weaver.gateway.v1.PublicationReviewContext + (*ReviewRegistrationReceipt)(nil), // 56: weaver.gateway.v1.ReviewRegistrationReceipt + (*MeterCredentialRotation)(nil), // 57: weaver.gateway.v1.MeterCredentialRotation + (*MeterCredentialEpoch)(nil), // 58: weaver.gateway.v1.MeterCredentialEpoch + (*MeteringReceipt)(nil), // 59: weaver.gateway.v1.MeteringReceipt + (*MeteringApplication)(nil), // 60: weaver.gateway.v1.MeteringApplication + (*ProviderOAuthChange)(nil), // 61: weaver.gateway.v1.ProviderOAuthChange + (*ProviderOAuthGrant)(nil), // 62: weaver.gateway.v1.ProviderOAuthGrant + (*ProviderOAuthIssuerRotation)(nil), // 63: weaver.gateway.v1.ProviderOAuthIssuerRotation + nil, // 64: weaver.gateway.v1.Task.EndpointsEntry + nil, // 65: weaver.gateway.v1.Task.BodyDigestsEntry + nil, // 66: weaver.gateway.v1.Task.NodeCostBoundsEntry + nil, // 67: weaver.gateway.v1.Task.StreamContractsEntry } var file_gateway_v1_gateway_proto_depIdxs = []int32{ - 8, // 0: weaver.gateway.v1.FactBarrierResolution.barrier:type_name -> weaver.gateway.v1.HardFactBarrier - 10, // 1: weaver.gateway.v1.GovernanceSelection.workflow_edges:type_name -> weaver.gateway.v1.WorkflowEdge - 11, // 2: weaver.gateway.v1.GovernanceSelection.workflow_selectors:type_name -> weaver.gateway.v1.WorkflowSelector - 12, // 3: weaver.gateway.v1.SourceArtifact.governance:type_name -> weaver.gateway.v1.GovernanceSelection - 29, // 4: weaver.gateway.v1.SourceArtifact.tasks:type_name -> weaver.gateway.v1.Task - 21, // 5: weaver.gateway.v1.SourceArtifact.plans:type_name -> weaver.gateway.v1.ProviderPlan - 43, // 6: weaver.gateway.v1.SourceArtifact.publication:type_name -> weaver.gateway.v1.PublishRequest - 21, // 7: weaver.gateway.v1.RoutingCandidate.plan:type_name -> weaver.gateway.v1.ProviderPlan - 14, // 8: weaver.gateway.v1.RoutingSelection.candidates:type_name -> weaver.gateway.v1.RoutingCandidate - 13, // 9: weaver.gateway.v1.SourceCompositionRequest.source:type_name -> weaver.gateway.v1.SourceArtifact - 15, // 10: weaver.gateway.v1.SourceCompositionRequest.routing:type_name -> weaver.gateway.v1.RoutingSelection - 13, // 11: weaver.gateway.v1.SourceCompositionReply.artifact:type_name -> weaver.gateway.v1.SourceArtifact - 46, // 12: weaver.gateway.v1.CompiledSource.authority:type_name -> weaver.gateway.v1.SourceAuthorityView - 13, // 13: weaver.gateway.v1.CompiledSource.artifact:type_name -> weaver.gateway.v1.SourceArtifact - 20, // 14: weaver.gateway.v1.ProviderPlan.routes:type_name -> weaver.gateway.v1.Route - 21, // 15: weaver.gateway.v1.ProviderRequest.plan:type_name -> weaver.gateway.v1.ProviderPlan - 0, // 16: weaver.gateway.v1.ProviderRequest.encoding:type_name -> weaver.gateway.v1.Encoding - 25, // 17: weaver.gateway.v1.ProviderFrame.event:type_name -> weaver.gateway.v1.Event - 26, // 18: weaver.gateway.v1.ProviderFrame.arrow:type_name -> weaver.gateway.v1.ArrowBatch - 62, // 19: weaver.gateway.v1.Task.endpoints:type_name -> weaver.gateway.v1.Task.EndpointsEntry - 63, // 20: weaver.gateway.v1.Task.body_digests:type_name -> weaver.gateway.v1.Task.BodyDigestsEntry - 64, // 21: weaver.gateway.v1.Task.node_cost_bounds:type_name -> weaver.gateway.v1.Task.NodeCostBoundsEntry - 65, // 22: weaver.gateway.v1.Task.stream_contracts:type_name -> weaver.gateway.v1.Task.StreamContractsEntry - 30, // 23: weaver.gateway.v1.Task.provider_profile:type_name -> weaver.gateway.v1.ProviderProfile - 29, // 24: weaver.gateway.v1.RegisterTaskRequest.task:type_name -> weaver.gateway.v1.Task - 33, // 25: weaver.gateway.v1.DomainView.stamp:type_name -> weaver.gateway.v1.DomainStamp - 29, // 26: weaver.gateway.v1.RegisterDomainTaskRequest.task:type_name -> weaver.gateway.v1.Task - 32, // 27: weaver.gateway.v1.RegisterDomainTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding - 45, // 28: weaver.gateway.v1.RegisterDomainTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey - 29, // 29: weaver.gateway.v1.RegisterOriginalTaskRequest.task:type_name -> weaver.gateway.v1.Task - 32, // 30: weaver.gateway.v1.RegisterOriginalTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding - 36, // 31: weaver.gateway.v1.RegisterOriginalTaskRequest.admission:type_name -> weaver.gateway.v1.TaskAdmission - 45, // 32: weaver.gateway.v1.RegisterOriginalTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey - 29, // 33: weaver.gateway.v1.RegisterPublishedTaskRequest.task:type_name -> weaver.gateway.v1.Task - 45, // 34: weaver.gateway.v1.RegisterPublishedTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey - 16, // 35: weaver.gateway.v1.RegisterPublishedTaskRequest.source_scope:type_name -> weaver.gateway.v1.SourceCompositionRequest - 1, // 36: weaver.gateway.v1.PublicationReceipt.outcome:type_name -> weaver.gateway.v1.PublicationOutcome - 2, // 37: weaver.gateway.v1.SourceRotationReceipt.outcome:type_name -> weaver.gateway.v1.SourceRotationOutcome - 46, // 38: weaver.gateway.v1.SourceRotationReceipt.authority:type_name -> weaver.gateway.v1.SourceAuthorityView - 45, // 39: weaver.gateway.v1.PublicationReview.publication:type_name -> weaver.gateway.v1.PublicationKey - 49, // 40: weaver.gateway.v1.PublicationReview.parent:type_name -> weaver.gateway.v1.AuthorityParent - 51, // 41: weaver.gateway.v1.DeltaReview.review:type_name -> weaver.gateway.v1.PublicationReview - 3, // 42: weaver.gateway.v1.DeltaReview.disposition:type_name -> weaver.gateway.v1.DeltaDisposition - 45, // 43: weaver.gateway.v1.PublicationReviewContext.publication:type_name -> weaver.gateway.v1.PublicationKey - 49, // 44: weaver.gateway.v1.PublicationReviewContext.parent:type_name -> weaver.gateway.v1.AuthorityParent - 50, // 45: weaver.gateway.v1.PublicationReviewContext.reviewer:type_name -> weaver.gateway.v1.ReviewAuthority - 46, // 46: weaver.gateway.v1.PublicationReviewContext.source:type_name -> weaver.gateway.v1.SourceAuthorityView - 45, // 47: weaver.gateway.v1.ReviewRegistrationReceipt.publication:type_name -> weaver.gateway.v1.PublicationKey - 60, // 48: weaver.gateway.v1.ProviderOAuthChange.grant:type_name -> weaver.gateway.v1.ProviderOAuthGrant - 61, // 49: weaver.gateway.v1.ProviderOAuthChange.rotate_issuer:type_name -> weaver.gateway.v1.ProviderOAuthIssuerRotation - 22, // 50: weaver.gateway.v1.Gateway.ExecuteProvider:input_type -> weaver.gateway.v1.ProviderRequest - 19, // 51: weaver.gateway.v1.Gateway.Inspect:input_type -> weaver.gateway.v1.OperationKey - 55, // 52: weaver.gateway.v1.Gateway.RotateMeterCredential:input_type -> weaver.gateway.v1.MeterCredentialRotation - 19, // 53: weaver.gateway.v1.Gateway.InspectTerminalUsage:input_type -> weaver.gateway.v1.OperationKey - 57, // 54: weaver.gateway.v1.Gateway.ApplyMetering:input_type -> weaver.gateway.v1.MeteringReceipt - 31, // 55: weaver.gateway.v1.Gateway.RegisterTask:input_type -> weaver.gateway.v1.RegisterTaskRequest - 42, // 56: weaver.gateway.v1.Gateway.RegisterPublishedTask:input_type -> weaver.gateway.v1.RegisterPublishedTaskRequest - 35, // 57: weaver.gateway.v1.Gateway.RegisterDomainTask:input_type -> weaver.gateway.v1.RegisterDomainTaskRequest - 37, // 58: weaver.gateway.v1.Gateway.RegisterOriginalTask:input_type -> weaver.gateway.v1.RegisterOriginalTaskRequest - 39, // 59: weaver.gateway.v1.Gateway.RegisterFamilyAlias:input_type -> weaver.gateway.v1.FamilyAliasRequest - 40, // 60: weaver.gateway.v1.Gateway.MigrateExecutionDomains:input_type -> weaver.gateway.v1.DomainMigration - 19, // 61: weaver.gateway.v1.Gateway.InspectExecutionDomains:input_type -> weaver.gateway.v1.OperationKey - 43, // 62: weaver.gateway.v1.Gateway.PublishAuthority:input_type -> weaver.gateway.v1.PublishRequest - 43, // 63: weaver.gateway.v1.Gateway.StageAuthority:input_type -> weaver.gateway.v1.PublishRequest - 45, // 64: weaver.gateway.v1.Gateway.InspectPublication:input_type -> weaver.gateway.v1.PublicationKey - 43, // 65: weaver.gateway.v1.Gateway.StageReviewedAuthority:input_type -> weaver.gateway.v1.PublishRequest - 45, // 66: weaver.gateway.v1.Gateway.InspectPublicationReview:input_type -> weaver.gateway.v1.PublicationKey - 52, // 67: weaver.gateway.v1.Gateway.RegisterPublicationReview:input_type -> weaver.gateway.v1.DeltaReview - 5, // 68: weaver.gateway.v1.Gateway.InspectSourceAuthority:input_type -> weaver.gateway.v1.Empty - 47, // 69: weaver.gateway.v1.Gateway.RotateSourceAuthority:input_type -> weaver.gateway.v1.SourceRotationRequest - 7, // 70: weaver.gateway.v1.Gateway.StageHardFact:input_type -> weaver.gateway.v1.HardFactIntent - 8, // 71: weaver.gateway.v1.Gateway.ResolveHardFact:input_type -> weaver.gateway.v1.HardFactBarrier - 6, // 72: weaver.gateway.v1.Gateway.CompileSource:input_type -> weaver.gateway.v1.ProducerRequest - 16, // 73: weaver.gateway.v1.Gateway.ComposeSource:input_type -> weaver.gateway.v1.SourceCompositionRequest - 5, // 74: weaver.gateway.v1.Gateway.InspectProviderCatalog:input_type -> weaver.gateway.v1.Empty - 24, // 75: weaver.gateway.v1.Gateway.PublishProviderCatalog:input_type -> weaver.gateway.v1.ProviderCatalogChange - 5, // 76: weaver.gateway.v1.Gateway.InspectTelemetry:input_type -> weaver.gateway.v1.Empty - 59, // 77: weaver.gateway.v1.Gateway.ChangeProviderOAuth:input_type -> weaver.gateway.v1.ProviderOAuthChange - 27, // 78: weaver.gateway.v1.Gateway.ExecuteProvider:output_type -> weaver.gateway.v1.ProviderFrame - 28, // 79: weaver.gateway.v1.Gateway.Inspect:output_type -> weaver.gateway.v1.ProviderReceipt - 56, // 80: weaver.gateway.v1.Gateway.RotateMeterCredential:output_type -> weaver.gateway.v1.MeterCredentialEpoch - 57, // 81: weaver.gateway.v1.Gateway.InspectTerminalUsage:output_type -> weaver.gateway.v1.MeteringReceipt - 58, // 82: weaver.gateway.v1.Gateway.ApplyMetering:output_type -> weaver.gateway.v1.MeteringApplication - 5, // 83: weaver.gateway.v1.Gateway.RegisterTask:output_type -> weaver.gateway.v1.Empty - 5, // 84: weaver.gateway.v1.Gateway.RegisterPublishedTask:output_type -> weaver.gateway.v1.Empty - 5, // 85: weaver.gateway.v1.Gateway.RegisterDomainTask:output_type -> weaver.gateway.v1.Empty - 38, // 86: weaver.gateway.v1.Gateway.RegisterOriginalTask:output_type -> weaver.gateway.v1.TaskAdmissionReceipt - 34, // 87: weaver.gateway.v1.Gateway.RegisterFamilyAlias:output_type -> weaver.gateway.v1.DomainView - 41, // 88: weaver.gateway.v1.Gateway.MigrateExecutionDomains:output_type -> weaver.gateway.v1.DomainMigrationReceipt - 34, // 89: weaver.gateway.v1.Gateway.InspectExecutionDomains:output_type -> weaver.gateway.v1.DomainView - 44, // 90: weaver.gateway.v1.Gateway.PublishAuthority:output_type -> weaver.gateway.v1.PublicationReceipt - 45, // 91: weaver.gateway.v1.Gateway.StageAuthority:output_type -> weaver.gateway.v1.PublicationKey - 44, // 92: weaver.gateway.v1.Gateway.InspectPublication:output_type -> weaver.gateway.v1.PublicationReceipt - 45, // 93: weaver.gateway.v1.Gateway.StageReviewedAuthority:output_type -> weaver.gateway.v1.PublicationKey - 53, // 94: weaver.gateway.v1.Gateway.InspectPublicationReview:output_type -> weaver.gateway.v1.PublicationReviewContext - 54, // 95: weaver.gateway.v1.Gateway.RegisterPublicationReview:output_type -> weaver.gateway.v1.ReviewRegistrationReceipt - 46, // 96: weaver.gateway.v1.Gateway.InspectSourceAuthority:output_type -> weaver.gateway.v1.SourceAuthorityView - 48, // 97: weaver.gateway.v1.Gateway.RotateSourceAuthority:output_type -> weaver.gateway.v1.SourceRotationReceipt - 8, // 98: weaver.gateway.v1.Gateway.StageHardFact:output_type -> weaver.gateway.v1.HardFactBarrier - 9, // 99: weaver.gateway.v1.Gateway.ResolveHardFact:output_type -> weaver.gateway.v1.FactBarrierResolution - 18, // 100: weaver.gateway.v1.Gateway.CompileSource:output_type -> weaver.gateway.v1.CompiledSource - 17, // 101: weaver.gateway.v1.Gateway.ComposeSource:output_type -> weaver.gateway.v1.SourceCompositionReply - 23, // 102: weaver.gateway.v1.Gateway.InspectProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot - 23, // 103: weaver.gateway.v1.Gateway.PublishProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot - 4, // 104: weaver.gateway.v1.Gateway.InspectTelemetry:output_type -> weaver.gateway.v1.TelemetrySnapshot - 5, // 105: weaver.gateway.v1.Gateway.ChangeProviderOAuth:output_type -> weaver.gateway.v1.Empty - 78, // [78:106] is the sub-list for method output_type - 50, // [50:78] is the sub-list for method input_type - 50, // [50:50] is the sub-list for extension type_name - 50, // [50:50] is the sub-list for extension extendee - 0, // [0:50] is the sub-list for field type_name + 8, // 0: weaver.gateway.v1.PendingHardFact.barrier:type_name -> weaver.gateway.v1.HardFactBarrier + 9, // 1: weaver.gateway.v1.HardFactFeedState.pending:type_name -> weaver.gateway.v1.PendingHardFact + 8, // 2: weaver.gateway.v1.FactBarrierResolution.barrier:type_name -> weaver.gateway.v1.HardFactBarrier + 12, // 3: weaver.gateway.v1.GovernanceSelection.workflow_edges:type_name -> weaver.gateway.v1.WorkflowEdge + 13, // 4: weaver.gateway.v1.GovernanceSelection.workflow_selectors:type_name -> weaver.gateway.v1.WorkflowSelector + 14, // 5: weaver.gateway.v1.SourceArtifact.governance:type_name -> weaver.gateway.v1.GovernanceSelection + 31, // 6: weaver.gateway.v1.SourceArtifact.tasks:type_name -> weaver.gateway.v1.Task + 23, // 7: weaver.gateway.v1.SourceArtifact.plans:type_name -> weaver.gateway.v1.ProviderPlan + 45, // 8: weaver.gateway.v1.SourceArtifact.publication:type_name -> weaver.gateway.v1.PublishRequest + 23, // 9: weaver.gateway.v1.RoutingCandidate.plan:type_name -> weaver.gateway.v1.ProviderPlan + 16, // 10: weaver.gateway.v1.RoutingSelection.candidates:type_name -> weaver.gateway.v1.RoutingCandidate + 15, // 11: weaver.gateway.v1.SourceCompositionRequest.source:type_name -> weaver.gateway.v1.SourceArtifact + 17, // 12: weaver.gateway.v1.SourceCompositionRequest.routing:type_name -> weaver.gateway.v1.RoutingSelection + 15, // 13: weaver.gateway.v1.SourceCompositionReply.artifact:type_name -> weaver.gateway.v1.SourceArtifact + 48, // 14: weaver.gateway.v1.CompiledSource.authority:type_name -> weaver.gateway.v1.SourceAuthorityView + 15, // 15: weaver.gateway.v1.CompiledSource.artifact:type_name -> weaver.gateway.v1.SourceArtifact + 22, // 16: weaver.gateway.v1.ProviderPlan.routes:type_name -> weaver.gateway.v1.Route + 23, // 17: weaver.gateway.v1.ProviderRequest.plan:type_name -> weaver.gateway.v1.ProviderPlan + 0, // 18: weaver.gateway.v1.ProviderRequest.encoding:type_name -> weaver.gateway.v1.Encoding + 27, // 19: weaver.gateway.v1.ProviderFrame.event:type_name -> weaver.gateway.v1.Event + 28, // 20: weaver.gateway.v1.ProviderFrame.arrow:type_name -> weaver.gateway.v1.ArrowBatch + 64, // 21: weaver.gateway.v1.Task.endpoints:type_name -> weaver.gateway.v1.Task.EndpointsEntry + 65, // 22: weaver.gateway.v1.Task.body_digests:type_name -> weaver.gateway.v1.Task.BodyDigestsEntry + 66, // 23: weaver.gateway.v1.Task.node_cost_bounds:type_name -> weaver.gateway.v1.Task.NodeCostBoundsEntry + 67, // 24: weaver.gateway.v1.Task.stream_contracts:type_name -> weaver.gateway.v1.Task.StreamContractsEntry + 32, // 25: weaver.gateway.v1.Task.provider_profile:type_name -> weaver.gateway.v1.ProviderProfile + 31, // 26: weaver.gateway.v1.RegisterTaskRequest.task:type_name -> weaver.gateway.v1.Task + 35, // 27: weaver.gateway.v1.DomainView.stamp:type_name -> weaver.gateway.v1.DomainStamp + 31, // 28: weaver.gateway.v1.RegisterDomainTaskRequest.task:type_name -> weaver.gateway.v1.Task + 34, // 29: weaver.gateway.v1.RegisterDomainTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding + 47, // 30: weaver.gateway.v1.RegisterDomainTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey + 31, // 31: weaver.gateway.v1.RegisterOriginalTaskRequest.task:type_name -> weaver.gateway.v1.Task + 34, // 32: weaver.gateway.v1.RegisterOriginalTaskRequest.domains:type_name -> weaver.gateway.v1.DomainBinding + 38, // 33: weaver.gateway.v1.RegisterOriginalTaskRequest.admission:type_name -> weaver.gateway.v1.TaskAdmission + 47, // 34: weaver.gateway.v1.RegisterOriginalTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey + 31, // 35: weaver.gateway.v1.RegisterPublishedTaskRequest.task:type_name -> weaver.gateway.v1.Task + 47, // 36: weaver.gateway.v1.RegisterPublishedTaskRequest.publication:type_name -> weaver.gateway.v1.PublicationKey + 18, // 37: weaver.gateway.v1.RegisterPublishedTaskRequest.source_scope:type_name -> weaver.gateway.v1.SourceCompositionRequest + 1, // 38: weaver.gateway.v1.PublicationReceipt.outcome:type_name -> weaver.gateway.v1.PublicationOutcome + 2, // 39: weaver.gateway.v1.SourceRotationReceipt.outcome:type_name -> weaver.gateway.v1.SourceRotationOutcome + 48, // 40: weaver.gateway.v1.SourceRotationReceipt.authority:type_name -> weaver.gateway.v1.SourceAuthorityView + 47, // 41: weaver.gateway.v1.PublicationReview.publication:type_name -> weaver.gateway.v1.PublicationKey + 51, // 42: weaver.gateway.v1.PublicationReview.parent:type_name -> weaver.gateway.v1.AuthorityParent + 53, // 43: weaver.gateway.v1.DeltaReview.review:type_name -> weaver.gateway.v1.PublicationReview + 3, // 44: weaver.gateway.v1.DeltaReview.disposition:type_name -> weaver.gateway.v1.DeltaDisposition + 47, // 45: weaver.gateway.v1.PublicationReviewContext.publication:type_name -> weaver.gateway.v1.PublicationKey + 51, // 46: weaver.gateway.v1.PublicationReviewContext.parent:type_name -> weaver.gateway.v1.AuthorityParent + 52, // 47: weaver.gateway.v1.PublicationReviewContext.reviewer:type_name -> weaver.gateway.v1.ReviewAuthority + 48, // 48: weaver.gateway.v1.PublicationReviewContext.source:type_name -> weaver.gateway.v1.SourceAuthorityView + 47, // 49: weaver.gateway.v1.ReviewRegistrationReceipt.publication:type_name -> weaver.gateway.v1.PublicationKey + 62, // 50: weaver.gateway.v1.ProviderOAuthChange.grant:type_name -> weaver.gateway.v1.ProviderOAuthGrant + 63, // 51: weaver.gateway.v1.ProviderOAuthChange.rotate_issuer:type_name -> weaver.gateway.v1.ProviderOAuthIssuerRotation + 24, // 52: weaver.gateway.v1.Gateway.ExecuteProvider:input_type -> weaver.gateway.v1.ProviderRequest + 21, // 53: weaver.gateway.v1.Gateway.Inspect:input_type -> weaver.gateway.v1.OperationKey + 57, // 54: weaver.gateway.v1.Gateway.RotateMeterCredential:input_type -> weaver.gateway.v1.MeterCredentialRotation + 21, // 55: weaver.gateway.v1.Gateway.InspectTerminalUsage:input_type -> weaver.gateway.v1.OperationKey + 59, // 56: weaver.gateway.v1.Gateway.ApplyMetering:input_type -> weaver.gateway.v1.MeteringReceipt + 33, // 57: weaver.gateway.v1.Gateway.RegisterTask:input_type -> weaver.gateway.v1.RegisterTaskRequest + 44, // 58: weaver.gateway.v1.Gateway.RegisterPublishedTask:input_type -> weaver.gateway.v1.RegisterPublishedTaskRequest + 37, // 59: weaver.gateway.v1.Gateway.RegisterDomainTask:input_type -> weaver.gateway.v1.RegisterDomainTaskRequest + 39, // 60: weaver.gateway.v1.Gateway.RegisterOriginalTask:input_type -> weaver.gateway.v1.RegisterOriginalTaskRequest + 41, // 61: weaver.gateway.v1.Gateway.RegisterFamilyAlias:input_type -> weaver.gateway.v1.FamilyAliasRequest + 42, // 62: weaver.gateway.v1.Gateway.MigrateExecutionDomains:input_type -> weaver.gateway.v1.DomainMigration + 21, // 63: weaver.gateway.v1.Gateway.InspectExecutionDomains:input_type -> weaver.gateway.v1.OperationKey + 45, // 64: weaver.gateway.v1.Gateway.PublishAuthority:input_type -> weaver.gateway.v1.PublishRequest + 45, // 65: weaver.gateway.v1.Gateway.StageAuthority:input_type -> weaver.gateway.v1.PublishRequest + 47, // 66: weaver.gateway.v1.Gateway.InspectPublication:input_type -> weaver.gateway.v1.PublicationKey + 45, // 67: weaver.gateway.v1.Gateway.StageReviewedAuthority:input_type -> weaver.gateway.v1.PublishRequest + 47, // 68: weaver.gateway.v1.Gateway.InspectPublicationReview:input_type -> weaver.gateway.v1.PublicationKey + 54, // 69: weaver.gateway.v1.Gateway.RegisterPublicationReview:input_type -> weaver.gateway.v1.DeltaReview + 5, // 70: weaver.gateway.v1.Gateway.InspectSourceAuthority:input_type -> weaver.gateway.v1.Empty + 49, // 71: weaver.gateway.v1.Gateway.RotateSourceAuthority:input_type -> weaver.gateway.v1.SourceRotationRequest + 5, // 72: weaver.gateway.v1.Gateway.InspectHardFact:input_type -> weaver.gateway.v1.Empty + 7, // 73: weaver.gateway.v1.Gateway.StageHardFact:input_type -> weaver.gateway.v1.HardFactIntent + 8, // 74: weaver.gateway.v1.Gateway.ResolveHardFact:input_type -> weaver.gateway.v1.HardFactBarrier + 6, // 75: weaver.gateway.v1.Gateway.CompileSource:input_type -> weaver.gateway.v1.ProducerRequest + 18, // 76: weaver.gateway.v1.Gateway.ComposeSource:input_type -> weaver.gateway.v1.SourceCompositionRequest + 5, // 77: weaver.gateway.v1.Gateway.InspectProviderCatalog:input_type -> weaver.gateway.v1.Empty + 26, // 78: weaver.gateway.v1.Gateway.PublishProviderCatalog:input_type -> weaver.gateway.v1.ProviderCatalogChange + 5, // 79: weaver.gateway.v1.Gateway.InspectTelemetry:input_type -> weaver.gateway.v1.Empty + 61, // 80: weaver.gateway.v1.Gateway.ChangeProviderOAuth:input_type -> weaver.gateway.v1.ProviderOAuthChange + 29, // 81: weaver.gateway.v1.Gateway.ExecuteProvider:output_type -> weaver.gateway.v1.ProviderFrame + 30, // 82: weaver.gateway.v1.Gateway.Inspect:output_type -> weaver.gateway.v1.ProviderReceipt + 58, // 83: weaver.gateway.v1.Gateway.RotateMeterCredential:output_type -> weaver.gateway.v1.MeterCredentialEpoch + 59, // 84: weaver.gateway.v1.Gateway.InspectTerminalUsage:output_type -> weaver.gateway.v1.MeteringReceipt + 60, // 85: weaver.gateway.v1.Gateway.ApplyMetering:output_type -> weaver.gateway.v1.MeteringApplication + 5, // 86: weaver.gateway.v1.Gateway.RegisterTask:output_type -> weaver.gateway.v1.Empty + 5, // 87: weaver.gateway.v1.Gateway.RegisterPublishedTask:output_type -> weaver.gateway.v1.Empty + 5, // 88: weaver.gateway.v1.Gateway.RegisterDomainTask:output_type -> weaver.gateway.v1.Empty + 40, // 89: weaver.gateway.v1.Gateway.RegisterOriginalTask:output_type -> weaver.gateway.v1.TaskAdmissionReceipt + 36, // 90: weaver.gateway.v1.Gateway.RegisterFamilyAlias:output_type -> weaver.gateway.v1.DomainView + 43, // 91: weaver.gateway.v1.Gateway.MigrateExecutionDomains:output_type -> weaver.gateway.v1.DomainMigrationReceipt + 36, // 92: weaver.gateway.v1.Gateway.InspectExecutionDomains:output_type -> weaver.gateway.v1.DomainView + 46, // 93: weaver.gateway.v1.Gateway.PublishAuthority:output_type -> weaver.gateway.v1.PublicationReceipt + 47, // 94: weaver.gateway.v1.Gateway.StageAuthority:output_type -> weaver.gateway.v1.PublicationKey + 46, // 95: weaver.gateway.v1.Gateway.InspectPublication:output_type -> weaver.gateway.v1.PublicationReceipt + 47, // 96: weaver.gateway.v1.Gateway.StageReviewedAuthority:output_type -> weaver.gateway.v1.PublicationKey + 55, // 97: weaver.gateway.v1.Gateway.InspectPublicationReview:output_type -> weaver.gateway.v1.PublicationReviewContext + 56, // 98: weaver.gateway.v1.Gateway.RegisterPublicationReview:output_type -> weaver.gateway.v1.ReviewRegistrationReceipt + 48, // 99: weaver.gateway.v1.Gateway.InspectSourceAuthority:output_type -> weaver.gateway.v1.SourceAuthorityView + 50, // 100: weaver.gateway.v1.Gateway.RotateSourceAuthority:output_type -> weaver.gateway.v1.SourceRotationReceipt + 10, // 101: weaver.gateway.v1.Gateway.InspectHardFact:output_type -> weaver.gateway.v1.HardFactFeedState + 8, // 102: weaver.gateway.v1.Gateway.StageHardFact:output_type -> weaver.gateway.v1.HardFactBarrier + 11, // 103: weaver.gateway.v1.Gateway.ResolveHardFact:output_type -> weaver.gateway.v1.FactBarrierResolution + 20, // 104: weaver.gateway.v1.Gateway.CompileSource:output_type -> weaver.gateway.v1.CompiledSource + 19, // 105: weaver.gateway.v1.Gateway.ComposeSource:output_type -> weaver.gateway.v1.SourceCompositionReply + 25, // 106: weaver.gateway.v1.Gateway.InspectProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot + 25, // 107: weaver.gateway.v1.Gateway.PublishProviderCatalog:output_type -> weaver.gateway.v1.ProviderCatalogSnapshot + 4, // 108: weaver.gateway.v1.Gateway.InspectTelemetry:output_type -> weaver.gateway.v1.TelemetrySnapshot + 5, // 109: weaver.gateway.v1.Gateway.ChangeProviderOAuth:output_type -> weaver.gateway.v1.Empty + 81, // [81:110] is the sub-list for method output_type + 52, // [52:81] is the sub-list for method input_type + 52, // [52:52] is the sub-list for extension type_name + 52, // [52:52] is the sub-list for extension extendee + 0, // [0:52] is the sub-list for field type_name } func init() { file_gateway_v1_gateway_proto_init() } @@ -5109,16 +5274,17 @@ func file_gateway_v1_gateway_proto_init() { return } file_gateway_v1_gateway_proto_msgTypes[3].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[5].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[23].OneofWrappers = []any{ + file_gateway_v1_gateway_proto_msgTypes[6].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[7].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[25].OneofWrappers = []any{ (*ProviderFrame_Event)(nil), (*ProviderFrame_Arrow)(nil), } - file_gateway_v1_gateway_proto_msgTypes[39].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[40].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[45].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[46].OneofWrappers = []any{} - file_gateway_v1_gateway_proto_msgTypes[55].OneofWrappers = []any{ + file_gateway_v1_gateway_proto_msgTypes[41].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[42].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[47].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[48].OneofWrappers = []any{} + file_gateway_v1_gateway_proto_msgTypes[57].OneofWrappers = []any{ (*ProviderOAuthChange_Grant)(nil), (*ProviderOAuthChange_RevokeTokenHash)(nil), (*ProviderOAuthChange_RotateIssuer)(nil), @@ -5129,7 +5295,7 @@ func file_gateway_v1_gateway_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_gateway_v1_gateway_proto_rawDesc), len(file_gateway_v1_gateway_proto_rawDesc)), NumEnums: 4, - NumMessages: 62, + NumMessages: 64, NumExtensions: 0, NumServices: 1, }, diff --git a/go/api/gateway/v1/gateway_grpc.pb.go b/go/api/gateway/v1/gateway_grpc.pb.go index 75de8746..1f7d713b 100644 --- a/go/api/gateway/v1/gateway_grpc.pb.go +++ b/go/api/gateway/v1/gateway_grpc.pb.go @@ -43,6 +43,7 @@ const ( Gateway_RegisterPublicationReview_FullMethodName = "/weaver.gateway.v1.Gateway/RegisterPublicationReview" Gateway_InspectSourceAuthority_FullMethodName = "/weaver.gateway.v1.Gateway/InspectSourceAuthority" Gateway_RotateSourceAuthority_FullMethodName = "/weaver.gateway.v1.Gateway/RotateSourceAuthority" + Gateway_InspectHardFact_FullMethodName = "/weaver.gateway.v1.Gateway/InspectHardFact" Gateway_StageHardFact_FullMethodName = "/weaver.gateway.v1.Gateway/StageHardFact" Gateway_ResolveHardFact_FullMethodName = "/weaver.gateway.v1.Gateway/ResolveHardFact" Gateway_CompileSource_FullMethodName = "/weaver.gateway.v1.Gateway/CompileSource" @@ -81,6 +82,7 @@ type GatewayClient interface { InspectSourceAuthority(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*SourceAuthorityView, error) RotateSourceAuthority(ctx context.Context, in *SourceRotationRequest, opts ...grpc.CallOption) (*SourceRotationReceipt, error) // Dedicated deployment-admitted feed. Resolve accepts only the exact durable barrier. + InspectHardFact(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*HardFactFeedState, error) StageHardFact(ctx context.Context, in *HardFactIntent, opts ...grpc.CallOption) (*HardFactBarrier, error) ResolveHardFact(ctx context.Context, in *HardFactBarrier, opts ...grpc.CallOption) (*FactBarrierResolution, error) // Preparation only. Actual ingress/source state selects an installed original; @@ -327,6 +329,16 @@ func (c *gatewayClient) RotateSourceAuthority(ctx context.Context, in *SourceRot return out, nil } +func (c *gatewayClient) InspectHardFact(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*HardFactFeedState, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(HardFactFeedState) + err := c.cc.Invoke(ctx, Gateway_InspectHardFact_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *gatewayClient) StageHardFact(ctx context.Context, in *HardFactIntent, opts ...grpc.CallOption) (*HardFactBarrier, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(HardFactBarrier) @@ -435,6 +447,7 @@ type GatewayServer interface { InspectSourceAuthority(context.Context, *Empty) (*SourceAuthorityView, error) RotateSourceAuthority(context.Context, *SourceRotationRequest) (*SourceRotationReceipt, error) // Dedicated deployment-admitted feed. Resolve accepts only the exact durable barrier. + InspectHardFact(context.Context, *Empty) (*HardFactFeedState, error) StageHardFact(context.Context, *HardFactIntent) (*HardFactBarrier, error) ResolveHardFact(context.Context, *HardFactBarrier) (*FactBarrierResolution, error) // Preparation only. Actual ingress/source state selects an installed original; @@ -515,6 +528,9 @@ func (UnimplementedGatewayServer) InspectSourceAuthority(context.Context, *Empty func (UnimplementedGatewayServer) RotateSourceAuthority(context.Context, *SourceRotationRequest) (*SourceRotationReceipt, error) { return nil, status.Errorf(codes.Unimplemented, "method RotateSourceAuthority not implemented") } +func (UnimplementedGatewayServer) InspectHardFact(context.Context, *Empty) (*HardFactFeedState, error) { + return nil, status.Errorf(codes.Unimplemented, "method InspectHardFact not implemented") +} func (UnimplementedGatewayServer) StageHardFact(context.Context, *HardFactIntent) (*HardFactBarrier, error) { return nil, status.Errorf(codes.Unimplemented, "method StageHardFact not implemented") } @@ -915,6 +931,24 @@ func _Gateway_RotateSourceAuthority_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } +func _Gateway_InspectHardFact_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GatewayServer).InspectHardFact(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Gateway_InspectHardFact_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GatewayServer).InspectHardFact(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + func _Gateway_StageHardFact_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(HardFactIntent) if err := dec(in); err != nil { @@ -1142,6 +1176,10 @@ var Gateway_ServiceDesc = grpc.ServiceDesc{ MethodName: "RotateSourceAuthority", Handler: _Gateway_RotateSourceAuthority_Handler, }, + { + MethodName: "InspectHardFact", + Handler: _Gateway_InspectHardFact_Handler, + }, { MethodName: "StageHardFact", Handler: _Gateway_StageHardFact_Handler, diff --git a/go/cmd/weaver-import-provider/main.go b/go/cmd/weaver-import-provider/main.go deleted file mode 100644 index f8125435..00000000 --- a/go/cmd/weaver-import-provider/main.go +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors -// -// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 - -package main - -import ( - "errors" - "fmt" - "io" - "os" - - v1 "github.com/HardenedLinux/weaver/go/api/v1" - "github.com/HardenedLinux/weaver/go/internal/config" -) - -func main() { - if err := run(); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} - -func run() error { - if len(os.Args) != 4 || (os.Args[1] != "json" && os.Args[1] != "yaml") { - return errors.New("usage: weaver-import-provider json|yaml LITELLM_FILE REVIEW_JSON") - } - read := func(path string, limit int) ([]byte, error) { - f, err := os.Open(path) - if err != nil { - return nil, err - } - defer f.Close() - return io.ReadAll(io.LimitReader(f, int64(limit)+1)) - } - source, err := read(os.Args[2], 262144) - if err != nil { - return err - } - raw, err := read(os.Args[3], v1.MaxInput) - if err != nil { - return err - } - review, err := v1.Decode[config.ProviderImportReview](raw) - if err != nil { - return errors.New("invalid provider review manifest") - } - proposal, err := config.ImportProviderCatalog(source, config.ProfileFormat(os.Args[1]), review) - if err != nil { - return err - } - _, err = fmt.Fprintln(os.Stdout, string(proposal)) - return err -} diff --git a/go/cmd/weaver-control/main.go b/go/dev/controlref/main.go similarity index 82% rename from go/cmd/weaver-control/main.go rename to go/dev/controlref/main.go index f0d38194..fbaa7aa2 100644 --- a/go/cmd/weaver-control/main.go +++ b/go/dev/controlref/main.go @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 -// Command weaver-control prepares source state; serve retains the reference relay. +// Command controlref exercises the old Go source client and relay in acceptance. package main import ( @@ -19,7 +19,7 @@ func main() { defer cancel() action := controlplane.PrepareFromEnv if len(os.Args) > 2 || (len(os.Args) == 2 && os.Args[1] != "prepare" && os.Args[1] != "serve") { - fmt.Fprintln(os.Stderr, "usage: weaver-control [prepare|serve]") + fmt.Fprintln(os.Stderr, "usage: controlref [prepare|serve]") os.Exit(2) } if len(os.Args) == 2 && os.Args[1] == "serve" { diff --git a/go/dev/provider_control_test.go b/go/dev/provider_control_test.go index 1feb4f25..89feeaef 100644 --- a/go/dev/provider_control_test.go +++ b/go/dev/provider_control_test.go @@ -111,10 +111,21 @@ func newControlProcess(t testing.TB, f *fixture, path string) *controlProcess { // Source preparation needs no operation credential or Go ingress socket. func (c *controlProcess) prepare(t testing.TB) { + c.prepareUsing(t, c.image) +} + +func (c *controlProcess) prepareUsing(t testing.TB, image string, args ...string) { t.Helper() ctx, cancel := context.WithTimeout(t.Context(), 15*time.Second) defer cancel() - command := exec.CommandContext(ctx, c.image) + command := c.prepareCommand(ctx, image, args...) + if output, err := command.CombinedOutput(); err != nil { + t.Fatalf("source-only preparation: %v: %s", err, output) + } +} + +func (c *controlProcess) prepareCommand(ctx context.Context, image string, args ...string) *exec.Cmd { + command := exec.CommandContext(ctx, image, args...) for _, value := range os.Environ() { if !strings.HasPrefix(value, "WEAVER_CONTROL_") { command.Env = append(command.Env, value) @@ -126,9 +137,7 @@ func (c *controlProcess) prepare(t testing.TB) { command.Env = append(command.Env, value) } } - if output, err := command.CombinedOutput(); err != nil { - t.Fatalf("source-only preparation: %v: %s", err, output) - } + return command } func (c *controlProcess) start(t testing.TB) { t.Helper() @@ -486,7 +495,12 @@ func (p *publicationReplyLoss) RegisterTask(ctx context.Context, in *pb.Register } func (p *publicationReplyLoss) CompileSource(ctx context.Context, in *pb.ProducerRequest) (*pb.CompiledSource, error) { source := p.sourceClient() - return source.RPC.CompileSource(source.Context(ctx), in) + started := time.Now() + reply, err := source.RPC.CompileSource(source.Context(ctx), in) + if p.observeCompile != nil { + p.observeCompile(time.Since(started), err) + } + return reply, err } func (p *publicationReplyLoss) RegisterPublishedTask(ctx context.Context, in *pb.RegisterPublishedTaskRequest) (*pb.Empty, error) { source := p.sourceClient() @@ -529,6 +543,10 @@ func TestProviderControlStagingReplyLossCannotActivateOrLosePending(t *testing.T } func exerciseControlSourceReplyLoss(t *testing.T, source func(*testing.T, *fixture, config.Bundle) string, loseStage bool, policies controlPolicySources) { + exerciseSourceReplyLoss(t, source, loseStage, policies, "") +} + +func exerciseSourceReplyLoss(t *testing.T, source func(*testing.T, *fixture, config.Bundle) string, loseStage bool, policies controlPolicySources, preparationImage string) { t.Helper() f := newFixture(t, completeSSE, false) bundle := controlBundle(t, f) @@ -551,6 +569,19 @@ func exerciseControlSourceReplyLoss(t *testing.T, source func(*testing.T, *fixtu } server := grpc.NewServer(grpc.Creds(credentials.NewTLS(&tls.Config{Certificates: []tls.Certificate{certificate}, ClientCAs: f.pki.root, ClientAuth: tls.RequireAndVerifyClientCert, MinVersion: tls.VersionTLS13}))) proxy := &publicationReplyLoss{source: f.admin, loseStage: loseStage} + if preparationImage != "" { + proxy.observeCompile = func(elapsed time.Duration, err error) { + t.Logf("source compile RPC elapsed=%s status=%v", elapsed, err) + if err != nil { + data, _ := os.ReadFile(filepath.Join(f.directory, "server.log")) + for _, line := range strings.Split(string(data), "\n") { + if strings.HasPrefix(line, "weaver scheme phase=") { + t.Log(line) + } + } + } + } + } pb.RegisterGatewayServer(server, proxy) exited := make(chan error, 1) go func() { exited <- server.Serve(listener) }() @@ -558,6 +589,17 @@ func exerciseControlSourceReplyLoss(t *testing.T, source func(*testing.T, *fixtu c.env = append(c.env, "WEAVER_CONTROL_AUTHORITY_SOURCE_ADDRESS="+listener.Addr().String()) child := exec.Command(controlBinary, "serve") child.Env = append(os.Environ(), c.env...) + if preparationImage != "" { + child = c.prepareCommand(t.Context(), preparationImage, "prepare") + } + recoverSource := func() { + if preparationImage == "" { + c.start(t) + return + } + c.prepareUsing(t, preparationImage, "prepare") + c.client = f.client + } log, err := os.Create(filepath.Join(c.directory, "lost-publication.log")) if err != nil { t.Fatal(err) @@ -614,7 +656,7 @@ func exerciseControlSourceReplyLoss(t *testing.T, source func(*testing.T, *fixtu f.stop(t) f.start(t) proxy.replaceSource(f.admin) - c.start(t) + recoverSource() ctx, cancel = context.WithTimeout(context.Background(), 12*time.Second) defer cancel() if _, err = c.client.Execute(ctx, bundle.Plans[0], pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }); err != nil { @@ -635,7 +677,7 @@ func exerciseControlSourceReplyLoss(t *testing.T, source func(*testing.T, *fixtu f.stop(t) f.start(t) proxy.replaceSource(f.admin) - c.start(t) + recoverSource() cancel() ctx, cancel = context.WithTimeout(context.Background(), 12*time.Second) defer cancel() @@ -659,7 +701,7 @@ func exerciseControlSourceReplyLoss(t *testing.T, source func(*testing.T, *fixtu f.stop(t) f.start(t) proxy.replaceSource(f.admin) - c.start(t) + recoverSource() cancel() ctx, cancel = context.WithTimeout(context.Background(), 12*time.Second) defer cancel() diff --git a/go/dev/provider_fixture_test.go b/go/dev/provider_fixture_test.go index 2a4ccb88..e3c0c165 100644 --- a/go/dev/provider_fixture_test.go +++ b/go/dev/provider_fixture_test.go @@ -122,7 +122,7 @@ func TestMain(m *testing.M) { if benchmark == "" { controlArgs = append(controlArgs, "-race") } - controlArgs = append(controlArgs, "-o", controlBinary, "./cmd/weaver-control") + controlArgs = append(controlArgs, "-o", controlBinary, "./dev/controlref") controlBuild := exec.Command(filepath.Join(runtime.GOROOT(), "bin/go"), controlArgs...) controlBuild.Dir, controlBuild.Stdout, controlBuild.Stderr = repo, os.Stderr, os.Stderr if err := controlBuild.Run(); err != nil { diff --git a/go/dev/provider_hard_fact_test.go b/go/dev/provider_hard_fact_test.go index a60022e2..4193f129 100644 --- a/go/dev/provider_hard_fact_test.go +++ b/go/dev/provider_hard_fact_test.go @@ -73,7 +73,7 @@ func TestProviderControlHardFactWithdrawalRestartAndABA(t *testing.T) { // before testing facts, rather than leaving an unrelated Policy barrier open. c := newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")) c.useProducer(sources.producer) - c.start(t) + c.prepareUsing(t, serverBinary, "prepare") ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second) defer cancel() @@ -104,8 +104,22 @@ func TestProviderControlHardFactWithdrawalRestartAndABA(t *testing.T) { } return result } + inspect := func() *pb.HardFactFeedState { + t.Helper() + state, err := f.admin.RPC.InspectHardFact(f.admin.Context(ctx), &pb.Empty{}) + if err != nil || state.GetDomain() != "availability" || state.GetSourceEpoch() != 0 { + t.Fatalf("inspect hard fact: %v %v", state, err) + } + return state + } blocked("before first admitted fact") + if state := inspect(); state.Available != nil || state.GetRevision() != 0 || len(state.Pending) != 0 { + t.Fatalf("genesis reported an installed fact: %v", state) + } + if _, err := f.client.RPC.InspectHardFact(f.client.Context(ctx), &pb.Empty{}); err == nil { + t.Fatal("operation credential inspected the hard-fact feed") + } intent := &pb.HardFactIntent{OperationId: "fact-a", Domain: "availability", Revision: 1, PreviousSnapshot: strings.Repeat("0", 64), Available: proto.Bool(true)} if _, err := f.client.RPC.StageHardFact(f.client.Context(ctx), intent); err == nil { @@ -129,11 +143,21 @@ func TestProviderControlHardFactWithdrawalRestartAndABA(t *testing.T) { blocked("withdrawal pending") f.stop(t) f.start(t) + state := inspect() + if state.Available == nil || !state.GetAvailable() || state.GetRevision() != a.Revision || + state.GetSnapshot() != a.Snapshot || state.GetFloor() != b.Floor || len(state.Pending) != 1 || + !proto.Equal(state.Pending[0].GetBarrier(), b) || state.Pending[0].GetAvailable() { + t.Fatalf("restart did not recover the original withdrawal and installed cut: %v", state) + } if retry := stage(withdrawal); !proto.Equal(retry, b) { t.Fatal("restart or lost stage reply changed the durable barrier") } blocked("withdrawal pending after restart") resolve(b) + if state := inspect(); state.Available == nil || state.GetAvailable() || + state.GetRevision() != b.Revision || len(state.Pending) != 0 { + t.Fatalf("withdrawal not installed: %v", state) + } blocked("withdrawal resolved") restoration := &pb.HardFactIntent{OperationId: "fact-a-again", Domain: intent.Domain, Revision: 3, diff --git a/go/dev/provider_import_test.go b/go/dev/provider_import_test.go new file mode 100644 index 00000000..ab4226e4 --- /dev/null +++ b/go/dev/provider_import_test.go @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build integration && schemeintegration && !windows + +package dev + +import ( + "bytes" + "encoding/json" + "os" + "os/exec" + "path/filepath" + "reflect" + "strings" + "testing" + + v1 "github.com/HardenedLinux/weaver/go/api/v1" + "github.com/HardenedLinux/weaver/go/internal/config" +) + +func TestProviderRustDirectReviewedCatalogImport(t *testing.T) { + const source = `{"model_list":[{"model_name":"alias","litellm_params":{"model":"openai/model","api_base":"https://provider.example/v1/","api_key":"os.environ/KEY"}}]}` + const yaml = `model_list: + - model_name: alias + litellm_params: + model: openai/model + api_base: https://provider.example/v1/ + api_key: os.environ/KEY +` + profile, err := providerProfile().Digest() + if err != nil { + t.Fatal(err) + } + plan := v1.ProviderPlan{Family: "original", Node: "run", Profile: "p", ProfileCommitment: profile, Model: "model", + Body: `{"model":"model","stream":true,"max_tokens":16,"messages":[{"role":"user","content":"hi"}]}`, + Ceiling: 4, Routes: []v1.ProviderRoute{{Target: "bound", Endpoint: "https://provider.example/v1/chat/completions"}}} + review := config.ProviderImportReview{Bindings: map[string]config.ProviderImportBinding{"alias": { + Plan: plan, Credential: "os.environ/KEY", + Entry: json.RawMessage(`{"module":"owned","capabilities":["text"],"latency_millis":1,"user_rates":[0,0,0,0],"quote":{"version":"v1","tenant":"tenant","formula_digest":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","procurement_rates":[0,0,0,0],"token_bounds":[0,0,0,16]}}`), + }}} + expected, err := config.ImportProviderCatalog([]byte(source), config.ProfileJSON, review) + if err != nil { + t.Fatal(err) + } + dir := t.TempDir() + write := func(name string, body []byte) string { + t.Helper() + path := filepath.Join(dir, name) + if err := os.WriteFile(path, body, 0600); err != nil { + t.Fatal(err) + } + return path + } + record, err := json.Marshal(review) + if err != nil { + t.Fatal(err) + } + manifest := write("review.json", record) + var original any + if err := json.Unmarshal(expected, &original); err != nil { + t.Fatal(err) + } + for format, input := range map[string]string{"json": source, "yaml": yaml} { + result, err := exec.CommandContext(t.Context(), serverBinary, "import-provider", format, + write("source."+format, []byte(input)), manifest).Output() + var candidate any + if err != nil || json.Unmarshal(result, &candidate) != nil || !reflect.DeepEqual(original, candidate) || bytes.Contains(result, []byte("os.environ/KEY")) { + t.Fatalf("%s reviewed import differs from the original proposal: %v %s", format, err, result) + } + } + for _, invalid := range []struct{ name, input string }{ + {"duplicate", yaml + " api_key: os.environ/KEY\n"}, + {"tagged", strings.Replace(yaml, "api_key: os.environ/KEY", "api_key: !custom os.environ/KEY", 1)}, + {"second-document", yaml + "---\nmodel_list: []\n"}, + } { + result, err := exec.CommandContext(t.Context(), serverBinary, "import-provider", "yaml", + write(invalid.name+".yaml", []byte(invalid.input)), manifest).Output() + if err == nil || len(result) != 0 { + t.Fatalf("%s YAML emitted a catalog proposal", invalid.name) + } + } +} diff --git a/go/dev/provider_kubernetes_test.go b/go/dev/provider_kubernetes_test.go new file mode 100644 index 00000000..387e5339 --- /dev/null +++ b/go/dev/provider_kubernetes_test.go @@ -0,0 +1,235 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build integration && schemeintegration && kubernetesintegration && !windows + +package dev + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "strconv" + "strings" + "sync" + "syscall" + "testing" + "time" + + pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +func TestProviderKubernetesAvailability(t *testing.T) { + f := newFixture(t, completeSSE, false) + bundle := controlBundle(t, f) + plan := bundle.Plans[0] + f.env = append(f.env, hardFactFeedSetting(t, f, plan.Family, plan.Node, [][2]string{{"next", plan.Node}}, nil, "", nil)) + sources := compiledControlSources(false) + sources.configure(t, f, bundle) + control := newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")) + control.useProducer(sources.producer) + control.prepareUsing(t, serverBinary, "prepare") + + // Simulate a crash after an older available intent was durably staged. + intent := &pb.HardFactIntent{OperationId: "kubernetes-interrupted", Domain: "availability", + Revision: 1, PreviousSnapshot: strings.Repeat("0", 64), Available: proto.Bool(true)} + ctx, cancel := context.WithTimeout(t.Context(), 12*time.Second) + defer cancel() + if _, err := f.admin.RPC.StageHardFact(f.admin.Context(ctx), intent); err != nil { + t.Fatal(err) + } + + const group = "weaver.hardenedlinux.org/v1alpha1" + const collection = "/apis/" + group + "/namespaces/weaver-system/provideravailabilities" + const name = "provider-availability" + var mu sync.Mutex + var installed map[string]any + uid, generation, resourceVersion, available := "original-uid", 1, 1, false + events := make(chan string, 8) + statusRevisions := make(chan uint64, 8) + cluster := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + if r.Header.Get("Authorization") != "Bearer cluster-fixture" { + t.Error("Kubernetes client did not use the cluster credential") + w.WriteHeader(http.StatusUnauthorized) + return + } + mu.Lock() + version := strconv.Itoa(resourceVersion) + object := map[string]any{"apiVersion": group, "kind": "ProviderAvailability", + "metadata": map[string]any{"name": name, "namespace": "weaver-system", "uid": uid, + "generation": generation, "resourceVersion": version}, + "spec": map[string]bool{"available": available}, "status": installed} + switch { + case r.Method == http.MethodPatch && r.URL.Path == collection+"/"+name+"/status": + var patch struct { + Metadata map[string]string + Status map[string]any + } + if json.NewDecoder(r.Body).Decode(&patch) != nil || patch.Metadata["resourceVersion"] != version || uid != "original-uid" { + mu.Unlock() + t.Error("stale or malformed status patch") + w.WriteHeader(http.StatusConflict) + return + } + installed = patch.Status + resourceVersion++ + object["status"] = installed + object["metadata"].(map[string]any)["resourceVersion"] = strconv.Itoa(resourceVersion) + revision := uint64(installed["revision"].(float64)) + mu.Unlock() + _ = json.NewEncoder(w).Encode(object) + statusRevisions <- revision + case r.Method == http.MethodGet && r.URL.Path == collection+"/"+name: + mu.Unlock() + _ = json.NewEncoder(w).Encode(object) + case r.Method == http.MethodGet && r.URL.Path == collection: + mu.Unlock() + if r.URL.Query().Get("fieldSelector") != "metadata.name="+name { + t.Error("watch/list escaped its configured resource name") + } + if r.URL.Query().Get("watch") == "true" { + w.WriteHeader(http.StatusOK) + flusher := w.(http.Flusher) + flusher.Flush() + for { + select { + case <-r.Context().Done(): + return + case event := <-events: + _, _ = fmt.Fprintln(w, event) + flusher.Flush() + if strings.Contains(event, `"code":410`) { + return + } + } + } + } + _ = json.NewEncoder(w).Encode(map[string]any{"apiVersion": group, "kind": "ProviderAvailabilityList", + "metadata": map[string]string{"resourceVersion": version}, "items": []any{object}}) + default: + mu.Unlock() + t.Errorf("unexpected Kubernetes request: %s %s", r.Method, r.URL.Path) + w.WriteHeader(http.StatusNotFound) + } + })) + t.Cleanup(cluster.Close) + config := filepath.Join(t.TempDir(), "kubeconfig") + if err := os.WriteFile(config, []byte(fmt.Sprintf(`apiVersion: v1 +kind: Config +clusters: +- name: fixture + cluster: {server: %s} +contexts: +- name: fixture + context: {cluster: fixture, user: fixture} +users: +- name: fixture + user: {token: cluster-fixture} +current-context: fixture +`, cluster.URL)), 0600); err != nil { + t.Fatal(err) + } + const binding = ` +[kubernetes] +namespace = "weaver-system" +name = "provider-availability" +uid = "original-uid" +domain = "availability" +` + logPath := filepath.Join(control.directory, "kubernetes.log") + log, err := os.Create(logPath) + if err != nil { + t.Fatal(err) + } + defer log.Close() + startAdapter := func() func() { + t.Helper() + command := sourceTOMLCommand(t, control, control.prepareCommand(t.Context(), serverBinary, "reconcile-kubernetes"), binding) + command.Env = append(command.Env, "KUBECONFIG="+config) + command.Stdout, command.Stderr = log, log + if err := command.Start(); err != nil { + t.Fatal(err) + } + done := make(chan error, 1) + go func() { done <- command.Wait() }() + return func() { + _ = command.Process.Signal(syscall.SIGTERM) + select { + case err := <-done: + if err != nil { + t.Error("Kubernetes owner did not exit normally", err) + } + case <-time.After(15 * time.Second): + _ = command.Process.Kill() + <-done + t.Error("Kubernetes owner exceeded drain deadline") + } + } + } + stopAdapter := startAdapter() + defer func() { + if stopAdapter != nil { + stopAdapter() + } + }() + waitStatus := func(want uint64) { + t.Helper() + select { + case got := <-statusRevisions: + if got != want { + t.Fatalf("status revision %d, expected %d", got, want) + } + case <-ctx.Done(): + data, _ := os.ReadFile(logPath) + t.Fatalf("status revision %d: %v: %s", want, ctx.Err(), data) + } + } + waitStatus(2) + if _, err := f.client.Execute(ctx, plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }); status.Code(err) != codes.FailedPrecondition || f.primary.Load() != 0 { + t.Fatal("pending available intent reopened a withdrawn provider", err) + } + stopAdapter() + stopAdapter = nil + mu.Lock() + available, generation, resourceVersion = true, 2, resourceVersion+1 + version := strconv.Itoa(resourceVersion) + mu.Unlock() + stopAdapter = startAdapter() + waitStatus(3) + update := fmt.Sprintf(`{"type":"MODIFIED","object":{"apiVersion":"%s","kind":"ProviderAvailability","metadata":{"namespace":"weaver-system","name":"%s","uid":"original-uid","resourceVersion":"%s"},"spec":{"available":true}}}`, group, name, version) + events <- update + events <- update + if _, err := f.client.Execute(ctx, plan, pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }); err != nil || f.primary.Load() != 1 { + t.Fatal("restored Kubernetes fact failed real provider execution", err) + } + mu.Lock() + uid, generation, resourceVersion, installed = "replacement-uid", 1, resourceVersion+1, nil + mu.Unlock() + events <- `{"type":"ERROR","object":{"apiVersion":"v1","kind":"Status","status":"Failure","reason":"Expired","code":410}}` + for { + cut, err := f.admin.RPC.InspectHardFact(f.admin.Context(ctx), &pb.Empty{}) + if err != nil { + t.Fatal(err) + } + if cut.GetRevision() == 4 && cut.Available != nil && !cut.GetAvailable() && len(cut.Pending) == 0 { + break + } + select { + case <-ctx.Done(): + t.Fatalf("replacement UID did not withdraw the original after relist: %v", cut) + case <-time.After(20 * time.Millisecond): + } + } + if _, err := f.client.Execute(ctx, bundle.Plans[1], pb.Encoding_PROTOBUF, 1, func(*pb.Event) error { return nil }); status.Code(err) != codes.FailedPrecondition || f.primary.Load() != 1 { + t.Fatal("replacement UID acquired authority or duplicate delivery advanced the cut", err) + } +} diff --git a/go/dev/provider_module_routing_test.go b/go/dev/provider_module_routing_test.go index b453c135..1d99560c 100644 --- a/go/dev/provider_module_routing_test.go +++ b/go/dev/provider_module_routing_test.go @@ -136,7 +136,7 @@ forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { c }} control := newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")) if direct { - control.prepare(t) + control.prepareUsing(t, serverBinary, "prepare") control.client = f.client } else { control.start(t) diff --git a/go/dev/provider_program_deployment_test.go b/go/dev/provider_program_deployment_test.go index e8ab67ee..d7c19d85 100644 --- a/go/dev/provider_program_deployment_test.go +++ b/go/dev/provider_program_deployment_test.go @@ -724,6 +724,15 @@ func TestProviderControlCompiledAssetsStagingReplyLossAndRestart(t *testing.T) { exerciseControlSourceReplyLoss(t, nil, true, compiledControlSources(true)) } +func TestProviderRustDirectPreparationLostReplies(t *testing.T) { + t.Run("staging", func(t *testing.T) { + exerciseSourceReplyLoss(t, nil, true, compiledControlSources(true), serverBinary) + }) + t.Run("publication", func(t *testing.T) { + exerciseSourceReplyLoss(t, nil, false, compiledControlSources(true), serverBinary) + }) +} + func TestProviderControlCompiledAssetsPartialRequestAndRestart(t *testing.T) { f := newFixture(t, partialRequestDisconnect, true) bundle := controlBundle(t, f) @@ -857,6 +866,19 @@ func TestProviderControlCompiledCatalogRequiresExactSourceEpoch(t *testing.T) { // The preparation command has source credentials only and exits before any // operation request. All frames then travel directly from the Rust listener. func TestProviderRustDirectPreparedOperationWithoutGoRelay(t *testing.T) { + checkDirectPreparedOperation(t, "", false) +} + +func TestProviderRustDirectPreparationCommand(t *testing.T) { + checkDirectPreparedOperation(t, serverBinary, false) +} + +func TestProviderRustDirectPreparationFromTOML(t *testing.T) { + checkDirectPreparedOperation(t, serverBinary, true) +} + +func checkDirectPreparedOperation(t *testing.T, preparationImage string, useTOML bool) { + t.Helper() f := newFixture(t, completeSSE, false) bundle := controlBundle(t, f) f.env = append(f.env, "WEAVER_GOVERNANCE_RETIRE_ON_ACTIVATION=1") @@ -866,18 +888,12 @@ func TestProviderRustDirectPreparedOperationWithoutGoRelay(t *testing.T) { control.useProducer(policy.producer) ctx, cancel := context.WithTimeout(t.Context(), 15*time.Second) defer cancel() - command := exec.CommandContext(ctx, control.image, "prepare") - for _, value := range os.Environ() { - if !strings.HasPrefix(value, "WEAVER_CONTROL_") { - command.Env = append(command.Env, value) - } + if preparationImage == "" { + preparationImage = control.image } - for _, value := range control.env { - name, _, _ := strings.Cut(value, "=") - if strings.HasPrefix(name, "WEAVER_CONTROL_AUTHORITY_SOURCE_") || name == "WEAVER_CONTROL_AUTHORITY_CA" || - name == "WEAVER_CONTROL_AUTHORITY_SERVER_NAME" || name == "WEAVER_CONTROL_CONFIG" || name == "WEAVER_CONTROL_PRODUCER" { - command.Env = append(command.Env, value) - } + command := control.prepareCommand(ctx, preparationImage, "prepare") + if useTOML { + command = sourceTOMLCommand(t, control, command) } if output, err := command.CombinedOutput(); err != nil { t.Fatalf("source-only preparation: %v: %s", err, output) @@ -927,16 +943,83 @@ func TestProviderRustDirectPreparedOperationWithoutGoRelay(t *testing.T) { } } -// JSON source preparation also retains exact plans for direct operation keys; +func sourceTOMLCommand(t *testing.T, control *controlProcess, command *exec.Cmd, kubernetes ...string) *exec.Cmd { + t.Helper() + settings := make(map[string]string) + environment := command.Env[:0] + for _, value := range command.Env { + name, text, _ := strings.Cut(value, "=") + if strings.HasPrefix(name, "WEAVER_CONTROL_") { + settings[name] = text + continue + } + environment = append(environment, value) + } + const tokenEnv = "WEAVER_TEST_PREPARATION_TOKEN" + var config strings.Builder + config.WriteString("[source]\n") + for _, field := range []struct{ key, env string }{ + {"producer", "WEAVER_CONTROL_PRODUCER"}, + {"file", "WEAVER_CONTROL_CONFIG"}, + {"address", "WEAVER_CONTROL_AUTHORITY_SOURCE_ADDRESS"}, + {"server_name", "WEAVER_CONTROL_AUTHORITY_SERVER_NAME"}, + {"ca", "WEAVER_CONTROL_AUTHORITY_CA"}, + {"certificate", "WEAVER_CONTROL_AUTHORITY_SOURCE_CERT"}, + {"key", "WEAVER_CONTROL_AUTHORITY_SOURCE_KEY"}, + } { + value := settings[field.env] + if (field.key == "producer" || field.key == "file") && (len(kubernetes) != 0 || value == "") { + continue + } + if field.key == "ca" || field.key == "certificate" || field.key == "key" || field.key == "file" { + var err error + value, err = filepath.Rel(control.directory, value) + if err != nil { + t.Fatal(err) + } + } + config.WriteString(field.key + " = " + strconv.Quote(value) + "\n") + } + config.WriteString("token_env = " + strconv.Quote(tokenEnv) + "\n") + for _, section := range kubernetes { + config.WriteString(section) + } + path := filepath.Join(control.directory, "weaver.toml") + if err := os.WriteFile(path, []byte(config.String()), 0600); err != nil { + t.Fatal(err) + } + command.Args = append(command.Args, "--config", path) + command.Env = append(environment, tokenEnv+"="+settings["WEAVER_CONTROL_AUTHORITY_SOURCE_TOKEN"]) + return command +} + +// File source preparation also retains exact plans for direct operation keys; // it does not rely on the optional compiled single-provider retirement profile. func TestProviderRustDirectFilePreparation(t *testing.T) { + for _, format := range []string{"json", "yaml"} { + t.Run(format, func(t *testing.T) { checkDirectFilePreparation(t, format) }) + } +} + +func checkDirectFilePreparation(t *testing.T, format string) { + t.Helper() f := newFixture(t, completeSSE, false) bundle := controlBundle(t, f) originalPolicy := bundle.Publication.Policy bundle.Publication.Policy += ` forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { context.family == "control" && context.node == "next" };` - control := newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")) - control.prepare(t) + control := newControlProcess(t, f, writeControlBundle(t, f, bundle, format)) + if format == "yaml" { + ctx, cancel := context.WithTimeout(t.Context(), 15*time.Second) + command := sourceTOMLCommand(t, control, control.prepareCommand(ctx, serverBinary, "prepare")) + output, err := command.CombinedOutput() + cancel() + if err != nil { + t.Fatalf("source-only preparation from TOML file: %v: %s", err, output) + } + } else { + control.prepareUsing(t, serverBinary, "prepare") + } ctx, cancel := context.WithTimeout(t.Context(), 12*time.Second) defer cancel() run := func() error { @@ -995,3 +1078,56 @@ forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { c t.Fatal("restart replayed file original", err) } } + +func TestProviderRustDirectFixedPlanSurvivesSourceHandoff(t *testing.T) { + for _, mode := range []string{"warm", "cold", "restart"} { + t.Run(mode, func(t *testing.T) { + f := newFixture(t, completeSSE, false) + bundle := controlBundle(t, f) + newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")).prepare(t) + ctx, cancel := context.WithTimeout(t.Context(), 12*time.Second) + defer cancel() + call := func(catalog string) error { + stream, err := f.client.RPC.ExecuteProvider(f.client.Context(ctx), &pb.ProviderRequest{ + Plan: &pb.ProviderPlan{Family: "control", Node: "next"}, BatchRows: 1, CatalogVersion: catalog, + }) + if err != nil { + return err + } + for { + frame, err := stream.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + if frame.GetEvent() == nil { + t.Fatal("expected protobuf event") + } + } + } + if mode == "warm" { + // Resolve the original while rejecting the caller's catalog precondition. + if err := call(strings.Repeat("a", 64)); status.Code(err) != codes.FailedPrecondition || f.primary.Load() != 0 { + t.Fatalf("catalog precondition consumed fixed plan: %v", err) + } + } + next := secondaryClient(t, f.pki) + token := sha256.Sum256([]byte(f.admin.Token)) + rotation := v1.SourceRotation{OperationID: "fixed-source-handoff", ExpectedEpoch: 0, NextCertificate: next.Certificate[0], NextCredentialSHA256: hex.EncodeToString(token[:])} + if receipt, err := f.admin.RotateSource(ctx, rotation); err != nil || receipt.GetAuthority().GetEpoch() != 1 { + t.Fatalf("source handoff: %v %v", receipt, err) + } + if _, err := f.admin.SourceAuthority(ctx); status.Code(err) != codes.PermissionDenied { + t.Fatalf("retired source retained mutation identity: %v", err) + } + if mode == "restart" { + restartWithSourceCertificate(t, f, next) + } + if err := call(""); err != nil || f.primary.Load() != 1 || f.backup.Load() != 0 { + t.Fatalf("fixed publication changed after source handoff: sends=%d error=%v", f.primary.Load(), err) + } + }) + } +} diff --git a/go/dev/publication_recovery_test.go b/go/dev/publication_recovery_test.go index deb72672..bc182a65 100644 --- a/go/dev/publication_recovery_test.go +++ b/go/dev/publication_recovery_test.go @@ -29,13 +29,14 @@ import ( // Test-only mTLS relay loses the successful source reply after forwarding one RPC. type publicationReplyLoss struct { pb.UnimplementedGatewayServer - source *gatewayclient.Client - sourceMu sync.RWMutex - calls atomic.Int64 - inspections atomic.Int64 - stages atomic.Int64 - sourceViews atomic.Int64 - loseStage bool + source *gatewayclient.Client + sourceMu sync.RWMutex + calls atomic.Int64 + inspections atomic.Int64 + stages atomic.Int64 + sourceViews atomic.Int64 + loseStage bool + observeCompile func(time.Duration, error) } func (s *publicationReplyLoss) sourceClient() *gatewayclient.Client { diff --git a/go/dev/runtime_boundary_test.go b/go/dev/runtime_boundary_test.go index a95023c8..0b3f5418 100644 --- a/go/dev/runtime_boundary_test.go +++ b/go/dev/runtime_boundary_test.go @@ -26,15 +26,29 @@ import ( type runtimeBoundary struct { forbiddenRoots, forbiddenReferences []string + resolvedPaths map[string]string } -func insidePath(path, parent string) bool { - if canonical, err := filepath.EvalSymlinks(parent); err == nil { - parent = canonical +func (boundary runtimeBoundary) resolve(path string) string { + if resolved, ok := boundary.resolvedPaths[path]; ok { + return resolved + } + resolved, err := filepath.EvalSymlinks(path) + if err != nil { + resolved = path } - if canonical, err := filepath.EvalSymlinks(path); err == nil { - path = canonical + if boundary.resolvedPaths != nil { + boundary.resolvedPaths[path] = resolved } + return resolved +} + +func insidePath(path, parent string) bool { + boundary := runtimeBoundary{} + return withinPath(boundary.resolve(path), boundary.resolve(parent)) +} + +func withinPath(path, parent string) bool { relative, err := filepath.Rel(parent, path) return err == nil && relative != ".." && !strings.HasPrefix(relative, ".."+string(filepath.Separator)) } @@ -51,24 +65,28 @@ func (boundary runtimeBoundary) reference(repository, source, reference string) for len(components) > 0 && (components[0] == "." || components[0] == "..") { components = components[1:] } + local := strings.Join(components, "/") for _, forbidden := range boundary.forbiddenRoots { - local := strings.Join(components, "/") if strings.EqualFold(local, forbidden) || strings.HasPrefix(strings.ToLower(local), strings.ToLower(forbidden)+"/") { return fmt.Errorf("development asset in runtime input %s: %s", source, reference) } - bases := []string{repository, filepath.Dir(source), filepath.Dir(filepath.Dir(source))} - for _, base := range bases { - candidate := reference - if !filepath.IsAbs(candidate) { - candidate = filepath.Join(base, filepath.FromSlash(reference)) - } - if resolved, err := filepath.EvalSymlinks(candidate); err == nil { - candidate = resolved - } - if insidePath(filepath.Clean(candidate), filepath.Join(repository, forbidden)) { + } + bases := []string{repository, filepath.Dir(source), filepath.Dir(filepath.Dir(source))} + for _, base := range bases { + candidate := reference + if !filepath.IsAbs(candidate) { + candidate = filepath.Join(base, filepath.FromSlash(reference)) + } + resolved := boundary.resolve(candidate) + candidate = boundary.resolve(filepath.Clean(resolved)) + for _, forbidden := range boundary.forbiddenRoots { + if withinPath(candidate, boundary.resolve(filepath.Join(repository, forbidden))) { return fmt.Errorf("runtime dependency resolves into %s: %s: %s", forbidden, source, reference) } } + if filepath.IsAbs(reference) { + break + } } return nil } @@ -152,7 +170,7 @@ func (boundary runtimeBoundary) source(repository, path string) error { func TestProjectArchitectureRuntimeAssetBoundary(t *testing.T) { repository := root(t) parts := projectParts(t) - boundary := runtimeBoundary{} + boundary := runtimeBoundary{resolvedPaths: make(map[string]string)} var entries, developmentEntries, roots, inputs []string assetRoots := 0 for _, part := range parts { @@ -268,7 +286,10 @@ func TestProjectArchitectureRejectsRuntimeDevReferences(t *testing.T) { t.Fatal(err) } } - boundary := runtimeBoundary{[]string{"dev", "go/internal/devrunner"}, []string{"example/go/dev", ":example/dev", "weaver-dev"}} + boundary := runtimeBoundary{ + forbiddenRoots: []string{"dev", "go/internal/devrunner"}, + forbiddenReferences: []string{"example/go/dev", ":example/dev", "weaver-dev"}, + } for _, path := range []string{"dev/proofs/review.cedar", "prod/policies/review.cedar"} { if err := os.WriteFile(filepath.Join(repository, path), []byte("permit(principal,action,resource);"), 0o600); err != nil { t.Fatal(err) diff --git a/prod/kubernetes/provideravailability.crd.yaml b/prod/kubernetes/provideravailability.crd.yaml new file mode 100644 index 00000000..863f106a --- /dev/null +++ b/prod/kubernetes/provideravailability.crd.yaml @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +# SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: provideravailabilities.weaver.hardenedlinux.org +spec: + group: weaver.hardenedlinux.org + scope: Namespaced + names: + plural: provideravailabilities + singular: provideravailability + kind: ProviderAvailability + versions: + - name: v1alpha1 + served: true + storage: true + subresources: + status: {} + schema: + openAPIV3Schema: + type: object + required: [spec] + properties: + spec: + type: object + required: [available] + properties: + available: + type: boolean + description: Desired availability of the deployment-bound provider fact. + status: + type: object + required: [observedGeneration, sourceEpoch, revision, snapshot] + properties: + observedGeneration: + type: integer + format: int64 + minimum: 1 + sourceEpoch: + type: integer + format: int64 + minimum: 0 + revision: + type: integer + format: int64 + minimum: 1 + snapshot: + type: string + pattern: '^[0-9a-f]{64}$' diff --git a/prod/kubernetes/provideravailability.rbac.yaml b/prod/kubernetes/provideravailability.rbac.yaml new file mode 100644 index 00000000..d8090264 --- /dev/null +++ b/prod/kubernetes/provideravailability.rbac.yaml @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +# SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 +apiVersion: v1 +kind: ServiceAccount +metadata: + name: weaver-provider-availability + namespace: weaver-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: weaver-provider-availability + namespace: weaver-system +rules: + - apiGroups: [weaver.hardenedlinux.org] + resources: [provideravailabilities] + resourceNames: [provider-availability] + verbs: [get, list, watch] + - apiGroups: [weaver.hardenedlinux.org] + resources: [provideravailabilities/status] + resourceNames: [provider-availability] + verbs: [patch] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: weaver-provider-availability + namespace: weaver-system +subjects: + - kind: ServiceAccount + name: weaver-provider-availability + namespace: weaver-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: weaver-provider-availability diff --git a/proto/gateway/v1/gateway.proto b/proto/gateway/v1/gateway.proto index b173d5d8..8d83def1 100644 --- a/proto/gateway/v1/gateway.proto +++ b/proto/gateway/v1/gateway.proto @@ -30,6 +30,7 @@ service Gateway { rpc InspectSourceAuthority(Empty) returns (SourceAuthorityView); rpc RotateSourceAuthority(SourceRotationRequest) returns (SourceRotationReceipt); // Dedicated deployment-admitted feed. Resolve accepts only the exact durable barrier. + rpc InspectHardFact(Empty) returns (HardFactFeedState); rpc StageHardFact(HardFactIntent) returns (HardFactBarrier); rpc ResolveHardFact(HardFactBarrier) returns (FactBarrierResolution); // Preparation only. Actual ingress/source state selects an installed original; @@ -74,6 +75,20 @@ message HardFactBarrier { uint64 floor = 5; string pending_prefix = 6; } +message PendingHardFact { + HardFactBarrier barrier = 1; + bool available = 2; +} +message HardFactFeedState { + string domain = 1; + uint64 source_epoch = 2; + uint64 floor = 3; + uint64 revision = 4; + string snapshot = 5; + optional bool available = 6; + // Exact durable barriers in resolution order. + repeated PendingHardFact pending = 7; +} message FactBarrierResolution { HardFactBarrier barrier = 1; repeated string affected = 2; From 952660804b3052f80a8861d296c02dd2d470d669 Mon Sep 17 00:00:00 2001 From: guangtao Date: Tue, 10 Nov 2026 18:30:50 +0800 Subject: [PATCH 103/105] Run offline provider import in the standard integration suite --- .../59.87-spec-upgrade-and-delivery-plan.org | 11 +++++++++-- go/dev/provider_import_test.go | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org b/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org index 49bdb731..7856d4d6 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org +++ b/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org @@ -353,12 +353,19 @@ R5 acceptance uses the existing =go/dev= integration entry with =TestProviderRustDirectCatalogSelection= and =TestProviderRustDirectReviewedCatalogImport=. The cases cover signed JSON and TOML-selected YAML sources, catalog replacement and guarded execution, and an -offline proposal equal to the existing reviewed Go import. The independent -review tests cover signature interoperability and rejection of changed signed +offline proposal equal to the existing reviewed Go import. The offline import +also runs in the standard Go/Rust integration suite without a Scheme owner. +Independent review tests cover signature interoperability and rejection of changed signed coordinates. Metering application and review recovery are separate integration cases. The Go entry list and the production asset boundary verify which packages remain reachable from =weaver-meter=. +The offline import case passed against a Rust release built with =arrow,kubernetes= +and no Scheme program. The positive JSON/YAML controls matched the Go proposal. +Duplicate keys, custom YAML tags and trailing documents failed without emitting a +proposal. Scheme-backed file preparation and catalog execution are separate +release controls. + Verification source, fixtures and acceptance commands are versioned with the implementation. Release executables and generated receipts remain local outputs. The harness can compare a release SHA-256 to bind multiple cases diff --git a/go/dev/provider_import_test.go b/go/dev/provider_import_test.go index ab4226e4..eef79f37 100644 --- a/go/dev/provider_import_test.go +++ b/go/dev/provider_import_test.go @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 -//go:build integration && schemeintegration && !windows +//go:build integration && !windows package dev From 0fe24eb0a8223eeb1e6209d2a739e466220d5829 Mon Sep 17 00:00:00 2001 From: guangtao Date: Tue, 10 Nov 2026 18:46:04 +0800 Subject: [PATCH 104/105] Keep routing verification and Scheme feature gates explicit The four-thread ledger library suite and cargo fmt pass. The full feature Clippy hook still requires the prepared Scheme SDK. --- crates/broker/src/provider/runtime.rs | 3 +- crates/governance/src/scheme_input/records.rs | 2 + crates/governance/src/scheme_input/values.rs | 1 + crates/ledger/src/hard_fact.rs | 1 + crates/ledger/src/lib.rs | 2 +- crates/ledger/src/provider_routing.rs | 104 ++++++++++-------- crates/ledger/tests/unit/provider.rs | 11 +- crates/ledger/tests/unit/provider_routing.rs | 6 +- .../59.87-spec-upgrade-and-delivery-plan.org | 6 + 9 files changed, 86 insertions(+), 50 deletions(-) diff --git a/crates/broker/src/provider/runtime.rs b/crates/broker/src/provider/runtime.rs index ddcaa421..1f2a5abb 100644 --- a/crates/broker/src/provider/runtime.rs +++ b/crates/broker/src/provider/runtime.rs @@ -222,7 +222,8 @@ pub trait ProviderOutput { _enqueue_nanos: u128, _consume_nanos: u128, _ledger: [weaver_ledger::TransactionTimings; 2], - ) {} + ) { + } #[cfg(feature = "test-loopback")] fn observe_dispatch(&self, _prepare_nanos: u128, _dispatch_nanos: u128) {} type Slot; diff --git a/crates/governance/src/scheme_input/records.rs b/crates/governance/src/scheme_input/records.rs index e6d73c77..b36f5aa1 100644 --- a/crates/governance/src/scheme_input/records.rs +++ b/crates/governance/src/scheme_input/records.rs @@ -180,6 +180,7 @@ fn root_plan<'r>(input: &Input<'r>, plan: &ProviderPlan) -> Result> { } /// Prepare bounded facts and canonical commitments without choosing a candidate. +#[cfg(feature = "scheme-program")] pub(crate) fn root_composition<'r>( vm: &'r GerbilRuntime, value: &crate::SourceComposition, @@ -264,6 +265,7 @@ pub(crate) fn root_composition<'r>( ("routing", input.vector(selections)?), ]) } +#[cfg(feature = "scheme-program")] fn numbers<'r>(input: &Input<'r>, values: &[u64]) -> Result> { input.vector( values diff --git a/crates/governance/src/scheme_input/values.rs b/crates/governance/src/scheme_input/values.rs index a17083c3..c684d793 100644 --- a/crates/governance/src/scheme_input/values.rs +++ b/crates/governance/src/scheme_input/values.rs @@ -45,6 +45,7 @@ impl<'r> Input<'r> { self.bytes(value.len())?; Ok(scheme_result(self.vm.string_from_utf8(value))?.into_object()) } + #[cfg(feature = "scheme-program")] pub(crate) fn bytes_vector(&self, value: &[u8]) -> Result> { self.node()?; self.bytes(value.len())?; diff --git a/crates/ledger/src/hard_fact.rs b/crates/ledger/src/hard_fact.rs index 58f79dc5..89c5d8a9 100644 --- a/crates/ledger/src/hard_fact.rs +++ b/crates/ledger/src/hard_fact.rs @@ -24,6 +24,7 @@ pub enum FactPreparation { Resolved(FactResolution), } +/// The current hard-fact cut and ordered pending barriers for its authenticated source. pub struct FactFeedState { pub domain: String, pub source_epoch: u64, diff --git a/crates/ledger/src/lib.rs b/crates/ledger/src/lib.rs index b76c13b5..a044c58b 100644 --- a/crates/ledger/src/lib.rs +++ b/crates/ledger/src/lib.rs @@ -79,9 +79,9 @@ mod stream_progress; mod stream_ranges; mod stream_state; mod task_publication; -pub use store::{Dispatch, Ledger}; #[cfg(feature = "commit-observer")] pub use store::ParkedProviderConnection; +pub use store::{Dispatch, Ledger}; pub(crate) use store::{db, integer}; pub use stream_custody::{StreamClaim, StreamOwner}; pub use stream_ranges::RangePermit; diff --git a/crates/ledger/src/provider_routing.rs b/crates/ledger/src/provider_routing.rs index 84202778..b2eb1c04 100644 --- a/crates/ledger/src/provider_routing.rs +++ b/crates/ledger/src/provider_routing.rs @@ -10,7 +10,7 @@ use crate::{ }; use weaver_contracts::{ Error, ProviderCatalog, ProviderOperationBinding, ProviderOperationScope, ProviderPlan, - ProviderRoutingScope, PublicationOutcome, Result, Task, + ProviderRoutingScope, Publication, PublicationOutcome, Result, Task, }; /// A coherent read for bounded Scheme work, never a later registration permit. @@ -92,6 +92,64 @@ fn cut(connection: &Connection, bound: ProviderOperationBinding) -> Result Result<()> { + if let Some(receipt) = + crate::publication::lookup(connection, &publication.operation_id, digest)? + { + return if receipt.outcome == PublicationOutcome::Rejected { + Err(Error::Denied) + } else { + Ok(()) + }; + } + let pending: Option<(String, String)> = persistence::maybe( + connection, + "SELECT digest,proposal FROM authority_pending WHERE operation_id=?1", + [publication.operation_id.as_str()], + |row| Ok((row.get(0)?, row.get(1)?)), + ) + .map_err(db)?; + let (staged, record) = pending.ok_or(Error::Conflict("routing publication not staged"))?; + let original: Publication = weaver_contracts::decode(record.as_bytes())?; + if staged != digest || original != *publication { + return Err(Error::Denied); + } + Ok(()) +} + +fn require_routed_cut( + connection: &Connection, + observed: &ProviderOperationCut, + family: &str, + node: &str, + digest: &str, +) -> Result<()> { + let original = binding(connection, family, node)?.ok_or(Error::Denied)?; + if original != observed.binding { + return Err(Error::Denied); + } + let current = cut(connection, original)?; + if current.catalog != observed.catalog + || current + .catalog + .as_ref() + .is_none_or(|catalog| !catalog.entries.contains_key(digest)) + { + return Err(Error::Denied); + } + if current.catalog_version != observed.catalog_version + || current.revision != observed.revision + || current.fence != observed.fence + { + return Err(Error::Conflict("provider routing cut changed")); + } + Ok(()) +} + impl Ledger { /// Explicit authenticated-source declaration. An operation credential cannot /// create or replace this scope. Replays preserve its exact source epoch. @@ -112,29 +170,7 @@ impl Ledger { if self.source.as_ref() != Some(&authority.identity) { return Err(Error::Denied); } - let committed = crate::publication::lookup(&tx, &publication.operation_id, &digest)?; - if committed - .as_ref() - .is_some_and(|r| r.outcome == PublicationOutcome::Rejected) - { - return Err(Error::Denied); - } - if committed.is_none() { - let pending: Option<(String, String)> = persistence::maybe( - &tx, - "SELECT digest,proposal FROM authority_pending WHERE operation_id=?1", - [publication.operation_id.as_str()], - |r| Ok((r.get(0)?, r.get(1)?)), - ) - .map_err(db)?; - let (staged, record) = - pending.ok_or(Error::Conflict("routing publication not staged"))?; - let original: weaver_contracts::Publication = - weaver_contracts::decode(record.as_bytes())?; - if staged != digest || original != *publication { - return Err(Error::Denied); - } - } + require_declared_publication(&tx, publication, &digest)?; let declared = ProviderOperationBinding { authority, scope: scope.clone(), @@ -194,25 +230,7 @@ impl Ledger { observed.binding.scope.admits(task, plan)?; let digest = plan.digest()?; let tx = persistence::begin(&mut self.connection).map_err(db)?; - let original = binding(&tx, &task.family, &plan.node)?.ok_or(Error::Denied)?; - if original != observed.binding { - return Err(Error::Denied); - } - let current = cut(&tx, original)?; - if current.catalog != observed.catalog - || current - .catalog - .as_ref() - .is_none_or(|catalog| !catalog.entries.contains_key(&digest)) - { - return Err(Error::Denied); - } - if current.catalog_version != observed.catalog_version - || current.revision != observed.revision - || current.fence != observed.fence - { - return Err(Error::Conflict("provider routing cut changed")); - } + require_routed_cut(&tx, observed, &task.family, &plan.node, &digest)?; let publication = observed.binding.scope.publication(); let key = weaver_contracts::PublicationKey { operation_id: publication.operation_id.clone(), diff --git a/crates/ledger/tests/unit/provider.rs b/crates/ledger/tests/unit/provider.rs index 813096e2..16e8cb58 100644 --- a/crates/ledger/tests/unit/provider.rs +++ b/crates/ledger/tests/unit/provider.rs @@ -96,10 +96,13 @@ fn reusing_physical_connection_rejects_old_provider_dispatch() { .checkout() .expect("fresh logical session"); let mut calls = 0; - assert!(next.dispatch_provider(&permit, || { - calls += 1; - Ok(()) - }).is_err()); + assert!( + next.dispatch_provider(&permit, || { + calls += 1; + Ok(()) + }) + .is_err() + ); assert_eq!(calls, 0); assert_eq!(next.held("f").expect("original hold"), 4); } diff --git a/crates/ledger/tests/unit/provider_routing.rs b/crates/ledger/tests/unit/provider_routing.rs index e17850f3..02e5cff5 100644 --- a/crates/ledger/tests/unit/provider_routing.rs +++ b/crates/ledger/tests/unit/provider_routing.rs @@ -3,7 +3,11 @@ // SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 use crate::persistence::{Session, exec, one}; -use weaver_contracts::*; +use weaver_contracts::{ + CatalogEntry, ProviderCatalog, ProviderOperationScope, ProviderPlan, ProviderProfile, + ProviderQuote, ProviderRoute, ProviderRoutingScope, Publication, RoutingCandidate, + RoutingSelection, SourceIdentity, SourceRotation, Task, body_digest, decode, +}; use weaver_ledger::Ledger; fn identity(id: u8) -> SourceIdentity { diff --git a/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org b/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org index 7856d4d6..222d7c96 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org +++ b/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org @@ -304,6 +304,12 @@ listener readiness deadline before the main marker. The bounded single-case follow-up on the same image passed hard-fact withdrawal, exact pending-barrier recovery and A-to-B-to-A. The whole cohort remains open. +The Ubuntu Scheme job at =fd782458= stopped during dependency preparation. +Agentic AI Lab's declared Parser pin =21fdb58642b135c48ad0006aab40e58e99e58c24= +could be queried directly on GitHub, but the standard dependency clone did not +contain its tree. The job produced no Weaver native result for that revision. +See [[https://github.com/hardenedlinux/weaver/actions/runs/42799007497/job/129771406740][Ubuntu Scheme job]]. + ** R4 Kubernetes source observation The Weaver-owned =ProviderAvailability= resource is bound by namespace, name and From b73813fe6049a0abbdf357e9fde52e7b36720950 Mon Sep 17 00:00:00 2001 From: guangtao Date: Tue, 10 Nov 2026 18:51:49 +0800 Subject: [PATCH 105/105] Qualify fixed source preparation through the standard integration suite --- dev/sysml/runtime-trace.json | 2 +- .../59.87-spec-upgrade-and-delivery-plan.org | 14 +- go/dev/provider_file_preparation_test.go | 224 ++++++++++++++++++ go/dev/provider_program_deployment_test.go | 189 --------------- go/dev/publication_recovery_test.go | 5 + 5 files changed, 239 insertions(+), 195 deletions(-) create mode 100644 go/dev/provider_file_preparation_test.go diff --git a/dev/sysml/runtime-trace.json b/dev/sysml/runtime-trace.json index 26ae3a7d..272aa505 100644 --- a/dev/sysml/runtime-trace.json +++ b/dev/sysml/runtime-trace.json @@ -1 +1 @@ -[{"id":"ProviderAdmissionTurn","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let selected_admission"},{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn begin_driver_counters_follow_their_admission_grant"},{"file":"crates/ledger/src/persistence/driver_observer.rs","pattern":"fn observe_read"},{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct AdmissionRequest"},{"file":"crates/ledger/tests/unit/provider_admission_turn.rs","pattern":"fn queued_unaccepted_admission_preserves_old_frame_and_original_hold"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionTurnProperty"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionCommitRecovery"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderAdmissionTurn"},{"file":"crates/broker/src/provider/request.rs","pattern":"Stage::Tls"},{"file":"go/dev/provider_transport_phases_test.go","pattern":"func reportProviderTransport"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run eagerQueueBlocksOldFrameCounterexampleTest"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem queue_preserves_arbitrary_requirement","declaration":"Weaver.ProviderAdmissionTurn.queue_preserves_arbitrary_requirement"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem finite_queue_preserves_final_offer","declaration":"Weaver.ProviderAdmissionTurn.finite_queue_preserves_final_offer"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem open_writer_cannot_mutate","declaration":"Weaver.ProviderAdmissionTurn.open_writer_cannot_mutate"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem accepted_hard_intent_blocks","declaration":"Weaver.ProviderAdmissionTurn.accepted_hard_intent_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_outcome_blocks","declaration":"Weaver.ProviderAdmissionTurn.unknown_outcome_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem changed_image_blocks","declaration":"Weaver.ProviderAdmissionTurn.changed_image_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem queued_admission_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.queued_admission_preserves_spec_final_use"},{"file":"go/internal/controlplane/deployment.go","pattern":"if gateway.source == nil"},{"file":"go/dev/provider_control_bench_test.go","pattern":"func TestProviderGoControlMeasuredChain"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem runtime_catalog_requires_source","declaration":"Weaver.ProviderAdmissionTurn.runtime_catalog_requires_source"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_activation_blocks_source_handoff","declaration":"Weaver.ProviderAdmissionTurn.unknown_activation_blocks_source_handoff"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem bootstrap_source_close_preserves_actual","declaration":"Weaver.ProviderAdmissionTurn.bootstrap_source_close_preserves_actual"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run failedBootstrapCleanupDoesNotActivateIngressTest"},{"file":"go/dev/provider_admission_overlap_bench_test.go","pattern":"func BenchmarkProviderAdmissionOverlap"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn collect_buffered"},{"file":"go/dev/provider_control_bench_test.go","pattern":"image := serverBinary"},{"file":"go/dev/provider_fixture_test.go","pattern":"test-owned Go control image sha256"},{"file":"crates/ledger/src/persistence/scope_trace.rs","pattern":"pub\\(super\\) fn observe_release"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"observed_release_covers_lease_removal_without_retaining_a_grant"},{"file":"crates/ledger/src/persistence/driver_observer.rs","pattern":"pub\\(super\\) fn observe_commit"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"commit_io_observes_native_spans_after_unobserved_setup"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"maybe_prepared\\(c, PREPARE"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn review_program_reuse_reads_replacement_and_rejects_projection_loss"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn review_program_reuse_preserves_native_receipts_and_currentness"},{"file":"go/dev/provider_control_bench_test.go","pattern":"both arms use Go forwarding"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"valid_review!\\(\"CROSS JOIN\"\\)"},{"file":"crates/ledger/src/domains/view.rs","pattern":"require_view\\(persistence::maybe_prepared"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn manifest_programs_rebind_current_members_and_reject_divergence"}]},{"id":"ProviderReadCustody","witnesses":[{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn conflicts"},{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn acquire_origin"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let shared_reads"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn compatible_origins_share_reads_but_an_older_writer_blocks_younger_readers"},{"file":"crates/ledger/tests/unit/provider_read_custody.rs","pattern":"fn shared_reads_keep_distinct_origin_native_writes_concurrent"},{"file":"go/dev/provider_read_custody_test.go","pattern":"func TestProviderReadCustodyProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderReadCustody"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem arbitrary_policy_preserved","declaration":"Weaver.ProviderReadCustody.arbitrary_policy_preserved"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem finite_interleaving_preserves_policy","declaration":"Weaver.ProviderReadCustody.finite_interleaving_preserves_policy"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem overlapping_writes_conflict","declaration":"Weaver.ProviderReadCustody.overlapping_writes_conflict"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessRetainsWriterAndSameOriginBarriers"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_binding_blocks","declaration":"Weaver.ProviderReadCustody.changed_binding_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_shared_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_shared_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_origin_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_origin_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_owner_blocks","declaration":"Weaver.ProviderReadCustody.changed_owner_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem shared_writer_conflicts","declaration":"Weaver.ProviderReadCustody.shared_writer_conflicts"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem older_conflicting_writer_blocks","declaration":"Weaver.ProviderReadCustody.older_conflicting_writer_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem read_custody_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.read_custody_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderReadCustody.qnt","pattern":"run unsafeSharedMutationCounterexampleTest"}]},{"id":"ProviderLifecycleFootprint","witnesses":[{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct OriginLifecycle"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"enum Impact"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_lifecycle"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_provider_lifecycle"},{"file":"crates/ledger/tests/unit/provider_lifecycle.rs","pattern":"fn peer_lifecycle_preserves_complete_view_but_shared_admission_does_not"},{"file":"go/dev/provider_lifecycle_test.go","pattern":"func TestProviderLifecycleCommitRecovery"},{"file":"crates/ledger/tests/unit/authority_footprint.rs","pattern":"fn local_commit_retires_whole_and_own_but_preserves_peer"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem origin_commit_retires_whole_reader","declaration":"Weaver.ProviderLifecycleFootprint.origin_commit_retires_whole_reader"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem arbitrary_cedar_predicate_preserved","declaration":"Weaver.ProviderLifecycleFootprint.arbitrary_cedar_predicate_preserved"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem shared_admission_requires_shared_invalidation","declaration":"Weaver.ProviderLifecycleFootprint.shared_admission_requires_shared_invalidation"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem peer_lifecycle_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.peer_lifecycle_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderLifecycleFootprint.qnt","pattern":"run unsafeNarrowAdmissionCounterexampleTest"}]},{"id":"ProviderSnapshotPublication","witnesses":[{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn release_provider_group_for_delivery"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"struct Snapshot"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn share_qualification"},{"file":"crates/ledger/src/provider.rs","pattern":"fn begin_snapshot_validation"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn take_refresh"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem pending_close_defers_renewal","declaration":"Weaver.ProviderSnapshotPublication.pending_close_defers_renewal"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn a_request_arriving_during_qualification_cannot_trigger_a_second_native_read"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn one_snapshot_requalification_covers_every_exact_frame"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn post_staging_native_failure_cannot_publish_a_partial_snapshot"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn queue_snapshot"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func awaitDeliveryCuts"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem final_use_joins_snapshot","declaration":"Weaver.ProviderSnapshotPublication.final_use_joins_snapshot"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem published_snapshot_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.published_snapshot_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSnapshotPublication.qnt","pattern":"run ungatedArcLoadIsCounterexampleTest"}]},{"id":"ProviderSemanticProgress","witnesses":[{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct RangeProgress"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_progress"},{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn stage_group"},{"file":"crates/ledger/tests/unit/provider_delivery.rs","pattern":"fn exact_range_progress_preserves_queued_authorization"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderSemanticProgressProperty"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_released_binding","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_released_binding"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_image","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_image"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem range_progress_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.range_progress_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSemanticProgress.qnt","pattern":"run hiddenSemanticEditIsCounterexampleTest"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"}]},{"id":"ProviderDeliveryJoin","witnesses":[{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn bounded_trace_retains_every_requalification"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeTraceChunksPreserveAllRecords"},{"file":"crates/ledger/tests/unit/persistence_owner.rs","pattern":"fn descriptor_copy_is_not_a_retained_execution_owner"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem retained_role_blocks_custody_retirement","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.retained_role_blocks_custody_retirement"},{"file":"dev/proofs/quint/ProviderDeliveryPipeline.qnt","pattern":"run threeInertFramesNeedNoStopAndWaitTest"},{"file":"crates/server/src/grpc_delivery_producer.rs","pattern":"fn reserve_guarded"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"pub fn poll"},{"file":"crates/server/src/grpc_delivery.rs","pattern":"impl Stream for ResponseStream"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryCommitAndReceiverRecovery"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryReceiverProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem orphaned_witness_cannot_activate","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.orphaned_witness_cannot_activate"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem acknowledged_delivery_preserves_same_actual_view","declaration":"Weaver.DomainMigrationComposition.acknowledged_delivery_preserves_same_actual_view"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run committedWithoutAcknowledgmentCannotAcceptTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run rollbackCannotEraseIndependentWitnessTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run oldOwnerCannotRequalifyAfterRestartTest"}]},{"id":"ProviderEgressPromotion","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_close_receipt_cannot_resolve_new_intent","declaration":"Weaver.ProviderEgressWindow.Promotion.old_close_receipt_cannot_resolve_new_intent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem expired_clock_blocks_receiver","declaration":"Weaver.ProviderEgressWindow.Promotion.expired_clock_blocks_receiver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem every_effect_writer_needs_mediation","declaration":"Weaver.ProviderEgressWindow.Promotion.every_effect_writer_needs_mediation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem other_writer_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.other_writer_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem uncertain_effect_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.uncertain_effect_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem unchanged_database_does_not_revalidate_old_read","declaration":"Weaver.ProviderEgressWindow.Promotion.unchanged_database_does_not_revalidate_old_read"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem witness_ahead_blocks_old_image","declaration":"Weaver.ProviderEgressWindow.Promotion.witness_ahead_blocks_old_image"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem only_current_owner_can_deliver","declaration":"Weaver.ProviderEgressWindow.Promotion.only_current_owner_can_deliver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_queued_frame_cannot_follow_replacement","declaration":"Weaver.ProviderEgressWindow.Promotion.old_queued_frame_cannot_follow_replacement"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem delivered_frame_cannot_be_delivered_twice","declaration":"Weaver.ProviderEgressWindow.Promotion.delivered_frame_cannot_be_delivered_twice"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem receiver_promotion_refines_interval_admission","declaration":"Weaver.ProviderEgressWindow.Promotion.receiver_promotion_refines_interval_admission"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run firstCommitCannotDeliverAnotherPendingWriterTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run independentWitnessBeforeDatabaseBlocksDeliveryTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run oldWorkerDeliveryCounterexampleTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run allWriterClassesUseTheSameCutTest"}]},{"id":"BoundedProviderEgressWindow","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem any_accepted_trace_keeps_disjoint_prefix","declaration":"Weaver.ProviderEgressWindow.any_accepted_trace_keeps_disjoint_prefix"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem loss_and_restart_close_old_window","declaration":"Weaver.ProviderEgressWindow.loss_and_restart_close_old_window"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem matching_image_does_not_reopen_old_cut","declaration":"Weaver.ProviderEgressWindow.matching_image_does_not_reopen_old_cut"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem connected_roots_cannot_use_distinct_lanes","declaration":"Weaver.ProviderEgressWindow.connected_roots_cannot_use_distinct_lanes"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem admitted_four_turn_envelope","declaration":"Weaver.ProviderEgressWindow.admitted_four_turn_envelope"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem settlement_is_idempotent","declaration":"Weaver.ProviderEgressWindow.settlement_is_idempotent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem holder_stage_overlap_cannot_exceed_ticket_wait","declaration":"Weaver.ProviderEgressWindow.holder_stage_overlap_cannot_exceed_ticket_wait"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run coherentStoreRollbackActuallyDuplicatesOfferTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run pendingRevocationStopsActualOfferTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run lostBurnAckSealsOriginalTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run rehydratingOldWindowActuallyDuplicatesOfferTest"}]},{"id":"OriginalFloorDecision","witnesses":[{"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run lostCommitResponseResolvesSameOperationTest"},{"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run unknownCommitCannotActivateTest"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"}]},{"id":"ProviderCurrentnessPerformance","witnesses":[{"file":"go/dev/provider_domain_program_test.go","pattern":"func BenchmarkProviderDomainProgram"},{"file":"go/dev/provider_domain_tail_test.go","pattern":"func BenchmarkProviderSharedLongTail"},{"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem prepared_domain_program_preserves_live_decision"}]},{"id":"ProviderSchedulerOwnership","witnesses":[{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn waiting_multi_root_range_precedes_younger_conflicts"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessCountsArrivalGrantInversions"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"}]},{"id":"SenderBoundProviderOAuth","witnesses":[{"file":"go/dev/provider_oauth_relay_test.go","pattern":"func TestProviderOAuthTwoHopRevocationAndRecovery"},{"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem retained_root_revocation_blocks_child"}]},{"id":"TransportAndExecutionLatencySeparation","witnesses":[{"file":"go/dev/provider_scheduler_bench_test.go","pattern":"func BenchmarkProviderScheduledEncoding"},{"file":"go/dev/provider_range_group_test.go","pattern":"func BenchmarkProviderRangePreparationGroup"}]},{"id":"TelemetryNoninterference","witnesses":[{"file":"crates/telemetry/tests/unit/metrics.rs","pattern":"fn observations_are_monotone_and_restart_local"},{"file":"go/internal/telemetry/metrics_test.go","pattern":"func TestPropertyCountersAreBoundedMonotoneAndRestartLocal"},{"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderTelemetryCannotRefundOrRedispatchUnknownSend"},{"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderControlTelemetryObservesBothServices"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryReadsAndRestartCannotRefundTest"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryAsRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem arbitrary_observations_keep_execution","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.arbitrary_observations_keep_execution"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem telemetry_reset_keeps_unknown_hold","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.telemetry_reset_keeps_unknown_hold"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem observations_preserve_effect_safety","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.observations_preserve_effect_safety"}]},{"id":"SharedDomainAuthority","witnesses":[{"file":"crates/ledger/src/domains/binding.rs","pattern":"fn bind"},{"file":"crates/ledger/src/domains/migration.rs","pattern":"fn migrate_execution_domains"},{"file":"crates/ledger/src/domains/view.rs","pattern":"fn require_stamp"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_cross_family_shared_history_serializes_final_use"},{"file":"crates/ledger/tests/unit/shared_domains.rs","pattern":"fn finite_families_never_split_a_shared_cap"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsProperty"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsCedarReadsCurrentAuthority"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run overCapacityUnionKeepsOriginalDecisionTest"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run domainSplitCounterexampleTest"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_cannot_split_any_shared_pair","declaration":"Weaver.SharedDomains.union_cannot_split_any_shared_pair"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem admitted_union_conserves_capacity","declaration":"Weaver.SharedDomains.admitted_union_conserves_capacity"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_retains_history","declaration":"Weaver.SharedDomains.union_retains_history"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_fences_both_old_permits","declaration":"Weaver.SharedDomains.union_fences_both_old_permits"}]},{"id":"TursoMvccCustody","witnesses":[{"file":"crates/ledger/src/persistence/owner.rs","pattern":"fn open"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_family"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_final_domains_overlap_including_new_executor_connection"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_same_budget_and_history_family_keeps_final_order"},{"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn mvcc_effect_before_failed_observation_never_releases_or_replays"},{"file":"go/dev/provider_final_domains_test.go","pattern":"func TestProviderMVCCIndependentFinalSendsAndRevocation"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run postSendCommitConflictKeepsPhysicalEffectTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem shared_final_readers_keep_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.shared_final_readers_keep_current_fence"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem failed_observation_after_send_keeps_spent_hold","declaration":"Weaver.RuntimeAdmission.MVCC.failed_observation_after_send_keeps_spent_hold"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_disjoint_admissions_have_overlapping_turso_writes"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_process_custody_refuses_a_second_process"},{"file":"crates/ledger/tests/unit/mvcc.rs","pattern":"fn mvcc_concurrent_family_budget_has_one_original_reservation"},{"file":"go/dev/provider_mvcc_test.go","pattern":"func TestProviderMVCCExecutionBoundary"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run snapshotWriteSkewCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem disjoint_domain_commits_commute","declaration":"Weaver.RuntimeAdmission.MVCC.disjoint_domain_commits_commute"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem family_step_preserves_all_budgets","declaration":"Weaver.RuntimeAdmission.MVCC.family_step_preserves_all_budgets"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exclusive_final_use_keeps_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.exclusive_final_use_keeps_current_fence"}]},{"id":"ArchitectureViewGrammar","witnesses":[{"file":"dev/sysml/ArchitectureViews.sysml","pattern":"view zeroTrust"},{"file":"go/internal/devrunner/model_views.go","pattern":"func CaptureModelViews"},{"file":"go/internal/devrunner/model_views_test.go","pattern":"func TestModelViewsUseActualSDK"},{"file":"go/internal/devrunner/model_views_test.go","pattern":"func FuzzModelViewCaptureTracksSource"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestArchitectureDiagramsUseDifferentViewProfiles"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramProfilesAreExplicitAndLocal"},{"file":"go/internal/devrunner/diagrams.go","pattern":"func RenderDiagrams"},{"file":"dev/d2/src/render.ts","pattern":"composeFigure[(]input,composer[)]"},{"file":"dev/d2/test/model-view.test.ts","pattern":"public Library binds SDK SysML identity"},{"file":"dev/d2/src/objects.ts","pattern":"export const composeObjects"},{"file":"dev/d2/test/model-view.test.ts","pattern":"missing captured views and unsupported source ports refuse"},{"file":"dev/d2/test/vector-readability.test.ts","pattern":"Preserve the original ordered-sequence line-overlap check"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramEvidenceRejectsLostNodesAndRelationships"}]},{"id":"ProductionAssetBoundary","witnesses":[{"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRuntimeAssetBoundary"},{"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRejectsRuntimeDevReferences"}]},{"id":"OriginalTaskBinding","witnesses":[{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem first_birth_seal_cannot_broaden","declaration":"Weaver.TaskOrigin.first_birth_seal_cannot_broaden"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem sealed_birth_cannot_be_replaced","declaration":"Weaver.TaskOrigin.sealed_birth_cannot_be_replaced"},{"file":"crates/ledger/tests/unit/task_publication.rs","pattern":"fn lost_birth_projection_cannot_authorize_or_be_silently_repaired"},{"file":"crates/ledger/src/task_origins.rs","pattern":"fn register_original_task"},{"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn source_rotation_cannot_reallocate_task_and_lost_reply_recovers_original_commit"},{"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn trusted_issuer_relabeling_every_identity_is_outside_local_deduplication"},{"file":"go/dev/provider_task_origin_test.go","pattern":"func TestProviderOriginalTaskOriginLostReplySourceSwitchAndRestart"},{"file":"dev/proofs/quint/TaskOrigin.qnt","pattern":"run issuerTrustCounterexampleTest"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem assigned_task_cannot_rebind","declaration":"Weaver.TaskOrigin.assigned_task_cannot_rebind"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem source_epoch_does_not_change_task_scope","declaration":"Weaver.TaskOrigin.source_epoch_does_not_change_task_scope"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem stale_source_command_cannot_commit","declaration":"Weaver.TaskOrigin.stale_source_command_cannot_commit"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn original_task_body_and_profile_cannot_be_replaced"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalBindingTest"}]},{"id":"SharedBudget","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn finite_manifest_siblings_cannot_mask_a_missing_original_member"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn maximum_manifest_cannot_replace_a_lost_sibling_after_restart"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityRecoveryGuardTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityFinalUseGuardTest"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn selected_message_binding_must_match_its_committed_digest_at_final_write"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn concurrent_message_admission_preserves_both_manifest_members"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exhausted_budget_cannot_publish_a_manifest_member_without_its_row"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem manifest_bound_runtime_step"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn surviving_stream_message_cannot_hide_a_lost_unknown_reservation"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exact_message_manifest_guards_recovery_and_existing_write_handles"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialMessageLossCounterexampleTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run digestSubstitutionFinalUseGuardTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exact_manifest_admission_covers_original_exposure"},{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn balanced_provider_projection_never_funds_a_different_original_plan"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_stream_projection_never_funds_the_next_logical_message"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem admission_covers_original_exposure"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run balancedProjectionCounterexampleTest"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_shrink_never_admits_a_different_node"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn require_family"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn mixed_request_and_stream_exposure_cannot_be_checked_in_separate_domains"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem orphaned_hold_blocks_new_admission"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run separateEffectDomainsCounterexampleTest"},{"file":"crates/ledger/tests/unit/properties.rs","pattern":"fn arbitrary_replays_restarts_and_consumption_preserve_claims"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run sharedBudgetTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalCostBoundTest"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn authored_ceiling_cannot_underreserve_the_original_wire_cost"}]},{"id":"ZeroTrustContractRefinement","witnesses":[{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem final_use_on_committed_union","declaration":"Weaver.DomainMigrationComposition.final_use_on_committed_union"},{"file":"crates/ledger/src/provider.rs","pattern":"actual.stamp != p.domains"},{"file":"crates/ledger/tests/unit/provider_domains.rs","pattern":"fn same_actual_domains_fence_original_provider_capability"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"actual migration committed; response discarded"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run committedUnionLostReplyKeepsBothOriginalsTest"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem gateway_final_use_preserves_domain_contract","declaration":"Weaver.DomainMigrationComposition.gateway_final_use_preserves_domain_contract"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem head_cas_preserves_original_obligations","declaration":"Weaver.DomainMigrationComposition.head_cas_preserves_original_obligations"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem overbooked_actual_view_cannot_supply_final_run","declaration":"Weaver.DomainMigrationComposition.overbooked_actual_view_cannot_supply_final_run"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureResearchModels"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainCommitRestartPositiveTest"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainRevocationKeepsOriginalExposureTest"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run detachedLogicalLedgerCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget","declaration":"Weaver.ProviderRpc.shared_exposure_keeps_original_budget"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework","declaration":"Weaver.ZeroTrustEnrichment.gateway_specialization_retains_generic_framework"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway","declaration":"Weaver.ZeroTrustEnrichment.retained_parent_and_selected_object_reach_gateway"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption","declaration":"Weaver.ZeroTrustEnrichment.usage_control_keeps_current_consumption"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use","declaration":"Weaver.ZeroTrustEnrichment.pending_policy_blocks_ongoing_use"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"}]},{"id":"ConsumeBeforeSend","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn final_write_requires_exact_durable_range"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run stateOnlyRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem inexact_cannot_refine_execution","declaration":"Weaver.StreamingExecution.RangeReceipt.inexact_cannot_refine_execution"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn crash_after_consumption_never_reopens_or_refunds"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run consumeBeforeSendTest"}]},{"id":"CurrentFinalGuard","witnesses":[{"file":"crates/ledger/tests/unit/serialization.rs","pattern":"fn effective_publication_cannot_overtake_the_locked_send_boundary"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run stalePermitTest"}]},{"id":"UnknownRetainsHold","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restart_never_backfills_request_claims_from_operations"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn orphaned_request_claim_cannot_admit_a_replacement_operation"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn next_stream_message_cannot_recreate_a_lost_node_claim"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn lost_message_projection_cannot_recycle_original_unknown_hold"},{"file":"crates/broker/tests/unit/https_transport.rs","pattern":"fn partial_transport_failure_is_unknown_and_never_retried"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run unknownRefundCounterexampleTest"}]},{"id":"NoImplicitRetry","witnesses":[{"file":"crates/ledger/tests/unit/concurrency.rs","pattern":"fn concurrent_consumers_invoke_once"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run duplicateRetryCounterexampleTest"}]},{"id":"DevelopmentPolicy","witnesses":[{"file":"crates/contracts/src/lib.rs","pattern":"mode = deny"}]},{"id":"MessageScopedAuthority","witnesses":[{"file":"crates/ledger/tests/unit/stream_properties.rs","pattern":"fn unknown_range_after_restart_blocks_new_nonce_and_authority"},{"file":"crates/policy/tests/unit/stream_policy.rs","pattern":"fn specification_derived_policy_is_typed_and_constrains_actual_range_facts"}]},{"id":"RangeFinalGuard","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn effective_revocation_stops_actual_next_range_and_prefix_reconnect"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run revokedBetweenBurnAndWriteTest"}]},{"id":"UnknownPrefixRecovery","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn rust_partial_write_freezes_tail_and_never_refunds"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unknown_cannot_resume"}]},{"id":"PrivateBufferCustody","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn tls_flush_cannot_release_a_tail_after_effective_revocation"},{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn recovered_old_worker_socket_cannot_use_new_custody"}]},{"id":"BoundedPerformanceWork","witnesses":[{"file":"crates/policy/tests/unit/cache_storage.rs","pattern":"fn compiled_storage_caps_slots_and_exact_hits_do_not_allocate_new_entries"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem bounded_range_copy_work"}]},{"id":"TrackedWriterDrain","witnesses":[{"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"async fn detached_executor_writer_keeps_slot_until_drain_acknowledges_completion"},{"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"fn arbitrary_disconnect_shutdown_and_drain_schedules_keep_executor_custody"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"},{"file":"dev/proofs/quint/RuntimeLifecycle.qnt","pattern":"run prematureAckCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem execution_and_drain_composition"}]},{"id":"GrpcCallerBinding","witnesses":[{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderRPCIdentityAndCancellation"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_name_is_not_key_authority"}]},{"id":"TransportSetupIsolation","witnesses":[{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run reconnectCannotUncancelOriginalStreamTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem crash_cannot_recreate_unknown_release"},{"file":"go/internal/gatewayclient/connection_test.go","pattern":"func TestConnectionSetupRetainsCallerDeadlineAndCancellation"},{"file":"go/dev/provider_startup_test.go","pattern":"func TestProviderFreshImageAndRestartStartup"},{"file":"dev/proofs/quint/GatewayComposition.qnt","pattern":"run reconnectRetainsSpentRootTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem gateway_run_preserves_original_execution_and_custody"}]},{"id":"CommittedProviderRouting","witnesses":[{"file":"go/internal/routing/provider_test.go","pattern":"func TestProviderRoutingCannotRewriteOriginalContract"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderGRPCStreamingAndArrowOption"}]},{"id":"UnambiguousProviderRequestBounds","witnesses":[{"file":"crates/contracts/tests/unit/provider_bounds.rs","pattern":"fn exactly_one_provider_cap_is_bounded"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn rejected_competing_caps_leave_no_claim_or_hold_after_restart"},{"file":"go/internal/routing/provider_test.go","pattern":"func FuzzProviderRequestBounds"},{"file":"go/dev/provider_bounds_test.go","pattern":"func TestProviderCompetingCapsCannotReachDispatch"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preferredCapPrecedenceCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem request_bounds_and_affine_execution_composition"}]},{"id":"SourceProviderProfileBinding","witnesses":[{"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceProfileAndCedarBindFinalSendAcrossRestart"},{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn concurrent_profile_registrations_cannot_fork_one_identity"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_task_registration_cannot_rebind"}]},{"id":"ClosedProviderRequestSchema","witnesses":[{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn provider_profile_cannot_fall_back_to_untyped_request_or_raw_stream"},{"file":"crates/contracts/tests/unit/provider_profiles.rs","pattern":"fn shared_closed_request_corpus_has_the_declared_semantics"},{"file":"go/api/v1/provider_profile_test.go","pattern":"func TestProviderProfileSharedClosedRequestCorpus"},{"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceCommittedExtensionsCannotBypassProfile"},{"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingSchemaGuardCounterexampleTest"}]},{"id":"RecoverableProfileFloor","witnesses":[{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn original_task_floor_prevents_missing_registry_from_rebinding_identity"},{"file":"crates/ledger/tests/unit/profile_floor_plan.rs","pattern":"fn semantic_floor_uses_two_composite_range_seeks"},{"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingFloorCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem missing_registry_cannot_erase_original_floor"}]},{"id":"CanonicalProfileConfiguration","witnesses":[{"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileJSONAndYAMLHaveOneCanonicalCommitment"},{"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileRejectsAmbiguousConfiguration"},{"file":"go/internal/config/provider_profile_test.go","pattern":"func FuzzProviderProfileConfiguration"}]},{"id":"AffineProviderAttempt","witnesses":[{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn arbitrary_provider_replays_restarts_and_release_batches_keep_original_claim"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run sdkRetryCannotConsumeAgainTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem consumed_unknown_retains_original_hold"}]},{"id":"EncodingAuthorityEquivalence","witnesses":[{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPolicyChangeDuringCapacityWait"},{"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowWireBoundDoesNotBoundDecodedText"},{"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowInvalidLaterRowReturnsNoPartialBatch"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preparedEncodingCannotSwitchTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem final_guard_checks_actual_owner_rows"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderArrowChecksEveryRow"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem arrow_cannot_weaken_row_authority"}]},{"id":"ProviderUnknownRetention","witnesses":[{"file":"crates/broker/src/provider/runtime.rs","pattern":"fn open_guarded"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn commit_provider"},{"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn failed_callback_never_enters_final_commit_and_retains_original_exposure"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn turso_applied_commit_without_ack_poison_is_not_reusable"},{"file":"go/dev/provider_commit_fault_test.go","pattern":"func TestProviderSealedTursoCommitRecovery"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run appliedLostAckPoisonsOldWorkerTest"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run durableCommitThenFenceThenLateAckTest"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run committingFailedCallbackCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem failed_callback_cannot_enter_commit","declaration":"Weaver.ProviderRpc.RequestWriteFence.failed_callback_cannot_enter_commit"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem applied_commit_without_ack_does_not_activate","declaration":"Weaver.ProviderRpc.RequestWriteFence.applied_commit_without_ack_does_not_activate"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem late_commit_ack_cannot_bypass_new_fence","declaration":"Weaver.ProviderRpc.RequestWriteFence.late_commit_ack_cannot_bypass_new_fence"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider[(]"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run individualHoldOnlyCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_provider_exposure_cannot_be_released"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem provider_exposure_strengthens_continuing_zero_trust"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerEnqueueBeforeCommitCrashCannotReplayPendingRange"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerCancellationAndReconnectRetainHistory"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run enqueueThenLostCommitRetainsUnknownTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem transport_history_preserves_original_hold"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderPartialRequestAndRestartRetainUnknownClaim"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run unknownRefundCounterexampleTest"}]},{"id":"ReservedAuthorityAdmission","witnesses":[{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run recoveryDoesNotRefreshUsageEvidenceTest"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn final_release_keeps_current_guard_and_unknown_commit_in_one_transaction"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run childOnlyPredicateDropsParentCounterexampleTest"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem continuing_uses_current_state_and_original_consumption"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem capacity_cannot_rebase_changed_floor"},{"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn waiting_capacity_does_not_hold_sql_or_authorize_after_publication"},{"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn pending_range_history_created_during_capacity_wait_cannot_be_replayed"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPositiveControlCompletesAfterCapacityReturns"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run returnedCapacityDoesNotAuthorizeStaleReleaseTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_backpressure_composition"},{"file":"crates/server/tests/unit/admission.rs","pattern":"async fn saturated_detached_execution_preserves_publication_and_observation_custody"},{"file":"go/dev/provider_capacity_test.go","pattern":"func TestProviderSaturatedExecutionPreservesRevocationAndObservation"},{"file":"dev/proofs/quint/AuthorityAdmission.qnt","pattern":"run sharedLaneStarvationCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_admission_composition"}]},{"id":"ConnectionCustodyBound","witnesses":[{"file":"crates/server/tests/unit/connections.rs","pattern":"async fn tcp_socket_owns_capacity_until_destruction_and_preserves_io_and_peer_identity"},{"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderPreTLSConnectionsAreBoundedAndExpire"},{"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderShutdownDestroysStalledTLSBeforeAcknowledgingExit"},{"file":"dev/proofs/quint/ConnectionAdmission.qnt","pattern":"run earlyReturnCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem provider_and_connection_composition"}]},{"id":"SourceIngressBinding","witnesses":[{"file":"go/dev/provider_source_test.go","pattern":"func TestProviderSourceIngressBindsCertificateCredentialAndMethod"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledCatalogRequiresExactSourceEpoch"},{"file":"go/dev/provider_capacity_test.go","pattern":"full operation ingress blocked new source session"},{"file":"crates/server/tests/unit/grpc_ingress.rs","pattern":"async fn aliased_or_empty_source_identity_is_rejected_before_serving"},{"file":"dev/proofs/quint/SourceIngress.qnt","pattern":"run forwardedCredentialCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem ingress_step_preserves_independent_custody"}]},{"id":"DurablePublicationDecision","witnesses":[{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn outcome_insert_failure_rolls_back_policy_schema_and_result_together"},{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn concurrent_same_identity_commits_only_one_revision"},{"file":"go/dev/publication_recovery_test.go","pattern":"func TestProviderPublicationLostReplyRestartAndHistoricalDecision"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run deletedOutcomeCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_and_provider_accounting_composition"}]},{"id":"OwnedSourceConnection","witnesses":[{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn cancelled_priority_wait_does_not_send_a_source_command"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn source_rotation_commits_before_queued_catalog_reads_recheck_identity"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run newCommandCanPrecedeOldReplyTest"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn completed_source_acknowledgment_returns_command_capacity"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run replyBeforeCapacityCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem command_ack_requires_returned_capacity"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn reused_source_connection_observes_other_writer_and_preserves_historical_result"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn disconnected_source_caller_keeps_capacity_until_original_sql_work_finishes"},{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn connection_reuse_rejects_an_unresolved_explicit_transaction"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run swallowedCloseErrorCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem owned_worker_and_publication_composition"}]},{"id":"FinalInvocationCancellation","witnesses":[{"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn cancellation_during_sql_wait_blocks_transport_and_keeps_spent_claim"},{"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn uncancelled_control_reaches_real_https_transport_once"},{"file":"dev/proofs/quint/DispatchCancellation.qnt","pattern":"run skippedRecheckCounterexampleTest"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run missingFinalCancellationCheckCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem cancellation_and_original_hold_composition"}]},{"id":"OriginalReleaseCapability","witnesses":[{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityBudgetHistoryChangeInvalidatesReleaseReadTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_plan_survives_batching"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn equal_batch_digests_cannot_transfer_release_between_original_nodes"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn release_encoding_cannot_change_after_preparation"},{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn release_capabilities_bind_plan_encoding_and_restart_session"},{"file":"dev/proofs/quint/ReleaseBinding.qnt","pattern":"run crossPlanCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem release_binding_and_execution_composition"}]},{"id":"SpecificSourceContracts","witnesses":[{"file":"crates/server/src/single_provider.rs","pattern":"bound: BoundSource"},{"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run governanceCannotReplaceGovernorTest"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run missingGovernorCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_cannot_replace_governor","declaration":"Weaver.PolicyBridge.governance_cannot_replace_governor"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governor_cannot_replace_governance","declaration":"Weaver.PolicyBridge.governor_cannot_replace_governance"},{"file":"scheme/governance/types.ss","pattern":"def GovernanceScopeContract\\s+\\(\\.cc \\(Record"},{"file":"scheme/gateway/contracts.ss","pattern":"def GatewayArtifact"},{"file":"t/gateway-contracts-test.ss","pattern":"def gateway-contracts-test"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityUncompiledSourceCannotRegisterTest"},{"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"},{"file":"t/gateway-contracts-test.ss","pattern":"module scopes use native POO Types and refuse evidence protocol hooks"}]},{"id":"GovernancePolicyProjection","witnesses":[{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrApprovalCannotOutliveExposureProjectionRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrCommitReplyLossAndReplayCannotMintAnotherTicketTest"},{"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn candidate_only_replay_cannot_register_for_a_real_predecessor"},{"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn replay_cannot_substitute_the_captured_predecessor"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem matched_replay_preserves_both_images"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run exactReplayPairSurvivesLostReplyAndCommitsOriginalTest"},{"file":"crates/ledger/tests/unit/source_authority.rs","pattern":"fn source_handoffs_and_old_workers_preserve_original_unknown_budget"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn consistent_whole_store_rollback_remains_a_local_authority_counterexample"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn residual_policy_schema_cannot_be_treated_as_an_empty_store_after_restart"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn first_enrollment_uses_all_durable_tables_without_temporary_aliases"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn committed_writer_before_enrollment_cannot_be_hidden_by_an_old_empty_read"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn callback_failure_after_enrollment_does_not_allow_a_replacement_identity"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem complete_catalog_refusal_preserves_original_state"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem source_enrollment_refusal_preserves_unknown_accounting"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run omittedProjectionEnrollmentCounterexampleTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateCatalogCommitMustReachDecidingGuardTest"},{"file":"go/dev/provider_source_authority_test.go","pattern":"func TestProviderPersistentSourceRotationLostReplyFencesExistingWorkerAndReissuedKey"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem retired_source_key_cannot_become_fresh"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_preserves_source_key_uniqueness"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run burnWithoutRetainedConfirmationCannotAdmitTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run cachedQualificationCannotAdmitWithZeroHeldProjectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run repairedProjectionDoesNotRecreateLostSendHandleTest"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_prefix_failure_atomically_rolls_back_burn"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_prefix_without_burn_projection_cannot_repeat_admission"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_burn_fenced_before_callback_keeps_original_unknown_exposure"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run confirmedRevocationAndHandoffRejectConsistentSourceRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run retainedRegistrationCannotReplaceAfterSnapshotRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run sameLengthArtifactReplacementCannotConfirmRetainedPrefixTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run wholeRetainedRootRollbackCanReplayQualificationCounterexampleTest"},{"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn identical_prefix_after_whole_store_restore_can_replay_dispatch_counterexample"},{"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn prefix_qualification_does_not_reconstruct_rolled_back_budget_counterexample"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run copiedRowsWithoutRecoveryQualificationCannotPublishTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateQualificationAfterRegistryAppendIsRefusedTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run recoveredNewOwnerRequalifiesOriginalArtifactTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run consistentAuthorityRollbackCanReplaySavedQualificationCounterexampleTest"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn stale_registry_read_and_reopened_worker_preserve_unknown_provider_exposure"},{"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn text_rendering_cannot_silently_replace_original_policy_ids"},{"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn actual_spec_replay_registration_persists_before_original_final_cas"},{"file":"go/dev/provider_policy_json_test.go","pattern":"func TestProviderControlNamedPolicyJSONRevocationAndRestart"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem finite_replay_does_not_certify_no_gain"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run observerRestartCannotRestoreReadCapabilityTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateRegistryReceiptAfterHandoffIsHistoricalTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run independentSnapshotRollbackResurrectsCredentialCounterexampleTest"},{"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn losing_verifier_metadata_cannot_downgrade_a_committed_served_profile"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem missing_verifier_cannot_downgrade"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run missingVerifierCannotDowngradeAfterRestartTest"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureComposition"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureRejectsFalseArithmetic"},{"file":"dev/proofs/cedar/SpecProofClosure.lean","pattern":"def proveClosedArithmetic"},{"file":"prod/policies/provider/ProviderReview.lean","pattern":"def entry"},{"file":"go/internal/specreview/producer.go","pattern":"Issue"},{"file":"crates/policy/src/qualified_delta.rs","pattern":"pub fn verify_qualified_delta"},{"file":"go/dev/provider_spec_review_test.go","pattern":"func TestProviderRealSPECReviewRevocationLostRepliesAndRestart"},{"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn historical_signature_only_nogain_is_not_semantic_qualification"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run signatureOnlyGainCounterexampleTest"},{"file":"dev/proofs/cedar/QualifiedReview.lean","pattern":"theorem qualified_execution_and_recovery_preserve_original","declaration":"Weaver.QualifiedReview.qualified_execution_and_recovery_preserve_original"},{"file":"crates/ledger/src/delta_registration.rs","pattern":"fn require_current"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"fn require"},{"file":"go/dev/provider_review_test.go","pattern":"func TestProviderReviewedPublicationLostRepliesAndRestart"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem reviewed_commit_composes_with_original_recovery"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run producerSignatureCannotReplaceQualificationTest"},{"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn consistent_snapshot_rollback_can_replace_local_registered_artifact_counterexample"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceLateCommitReplyAfterRotationRemainsHistorical"},{"file":"crates/ledger/tests/unit/publication_review.rs","pattern":"fn reviewed_prefixes_match_an_independent_model"},{"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn stage_review_requirement_and_legacy_final_cas_have_one_serial_order"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_registration_recovery_composes_without_releasing_unknown"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run latchedReviewCannotUseLegacyPublicationTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run configurationImageCannotErasePersistentRevocationTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registryAppendBetweenReadAndCASRequiresRejoinTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRollbackLostReplyRetainsUnknownConsumption"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem registrar_binding_reaches_final_cas"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run revocationBetweenValidationAndFinalCASTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run delayedIssuanceDecisionCannotReactivateOldEpochTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateRotationRecoversLostReplyAndPending"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateConfigRollbackReacceptsOldKeyCounterexample"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_recovery_keeps_original_constraints"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem durable_review_binding_survives_final_cas"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registrationLostReplyCannotPublishUnrecoveredProjectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run oldRegistrarCannotPublishAlreadyRegisteredArtifactTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderStagingLostReplyRetainsConcurrentPendingAcrossRestart"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRoleCredentialIsNotRegistrarIncarnationEvidence"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem reviewed_publication_keeps_recovery_contract"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run substitutedArtifactGetsOriginalRejectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run crossStoreReviewRollbackCounterexampleTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderPendingCommandSubstitutionAndHistoricalRecovery"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn typed_publication_does_not_yet_require_delta_evidence"},{"file":"scheme/policy/func.ss","pattern":"project-policy profile"},{"file":"scheme/policy/assets.ss","pattern":"read-policy-assets profile"},{"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"}]},{"id":"CompiledSourceStartup","witnesses":[{"file":"scheme/gateway/compiled.ss","pattern":"weaver_governance_ready_v1"},{"file":"crates/governance-build/src/application.rs","pattern":"pub fn approved"},{"file":"build.ss","pattern":"approved application root mismatch"},{"file":"crates/governance/src/program/compiler.rs","pattern":"pub fn initialize"},{"file":"crates/governance/src/catalog/configuration.rs","pattern":"pub fn from_configuration"},{"file":"crates/server/src/governance_deployment.rs","pattern":"async fn start_compiler"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRequiresRealInstallation"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"metadataAsInitializationCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem graph_membership_cannot_replace_initialization"}]},{"id":"GovernorSourceHandoff","witnesses":[{"file":"scheme/gateway/types.ss","pattern":"def GatewayProgram"},{"file":"scheme/gateway/program.ss","pattern":"def \\(make-gateway-program"},{"file":"t/gateway-source-test.ss","pattern":"program installation and close follow an irreversible lifecycle"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"caughtReentryPoisonsOuterDeliveryTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem program_result_composes_with_registered_original"},{"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"},{"file":"go/internal/controlplane/deployment_source_test.go","pattern":"func FuzzDeploymentSourceHasOneOwner"},{"file":"go/internal/controlplane/producer_deployment_test.go","pattern":"func exerciseProducerDeployment"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"deploymentCannotFallBackToFileTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem producer_deployment_keeps_registered_original"},{"file":"crates/server/src/grpc.rs","pattern":"async fn compile_source"},{"file":"go/internal/controlplane/source_compile.go","pattern":"func BootstrapProducer"},{"file":"go/internal/controlplane/approved_source_rpc_test.go","pattern":"func TestApprovedSourceMTLSBootstrap"},{"file":"go/internal/config/freeze_test.go","pattern":"func FuzzFrozenSourceDoesNotFollowCallerMutation"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem compilation_reply_keeps_registered_original"},{"file":"crates/governance/src/catalog/admission.rs","pattern":"pub struct ProducerCatalog"},{"file":"crates/governance/src/catalog/client.rs","pattern":"pub fn submit"},{"file":"crates/governance/tests/unit/catalog.rs","pattern":"changed_source_observations_and_fresh_names_cannot_select_original"},{"file":"crates/server/src/governance_owner.rs","pattern":"pub fn publish_producers"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"oldCatalogObservationStillCannotPublishThroughNewFenceTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"producer_selection_keeps_all_original_fields"},{"file":"crates/server/src/governance_owner.rs","pattern":"pub async fn start_governance"},{"file":"crates/server/src/grpc.rs","pattern":"pub async fn serve_grpc_with_runtime"},{"file":"crates/server/tests/unit/governance_owner.rs","pattern":"shared_owner_schedules_preserve_cleanup_and_terminal_admission"},{"file":"crates/server/tests/integration/governance_owner.rs","pattern":"actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"lateFactoryActivationCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_owner_join_preserves_cleanup"},{"file":"crates/governance/src/scheme_input/records.rs","pattern":"pub fn root_source"},{"file":"crates/governance/src/scheme_input/values.rs","pattern":"fn bytes"},{"file":"crates/governance/src/host/client.rs","pattern":"pub fn source_lane"},{"file":"crates/governance/src/host/owner.rs","pattern":"pub fn run"},{"file":"crates/governance/tests/unit/host.rs","pattern":"cancelled_running_work_keeps_its_slot_until_natural_return"},{"file":"crates/governance/tests/unit/host.rs","pattern":"active_compiler_observes_both_request_and_owner_cancellation"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSourceCancellationDrainsSchemeOwner"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"checkThenSendCloseRaceCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_host_delivery_requires_open_gate"},{"file":"crates/governance/src/binding.rs","pattern":"pub struct SourceExpectation"},{"file":"crates/governance/tests/unit/binding.rs","pattern":"coherent_replacements_cannot_change_original_content"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"unsafeSelfConsistentReplacementWitness"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"coherent_replacement_cannot_redefine_original"},{"file":"crates/governance/build.rs","pattern":"run_package_main"},{"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeQualificationStaysWithPreparedSchemeOwner"},{"file":"t/gateway-source-test.ss","pattern":"SDK field symbols and identifier strings cannot be interchanged"},{"file":"crates/governance/src/scheme.rs","pattern":"pub fn materialize_source"},{"file":"crates/governance/tests/integration/scheme_vm.rs","pattern":"actual_aa_capture_materializes_owned_data_before_vm_cleanup"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run unsafeEncodedBlobWitness"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem encoded_blob_cannot_claim_typed_capture"},{"file":"scheme/gateway/capture.ss","pattern":"Gateway capture requires one source emission"},{"file":"scheme/gateway/func.ss","pattern":"def \\(capture-governed-gateway"},{"file":"t/gateway-source-test.ss","pattern":"native PBT requires one completed emission"},{"file":"t/gateway-source-test.ss","pattern":"a late inherited sink cannot replace an active next capture"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run ignoredCaptureFuseCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem caught_duplicate_cannot_clear_capture_fuse"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"},{"file":"scheme/governance/capture.ss","pattern":"def \\(governance-profile-snapshot"},{"file":"t/governance-test.ss","pattern":"native PBT preserves every original assessment binding"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_assessment_snapshot_cannot_reuse_boundary"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run coordinatedLiveProfileLabelsCannotReplaceOriginalCaptureTest"},{"file":"scheme/gateway/func.ss","pattern":"assq 'open-patterns"},{"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"},{"file":"scheme/governance/types.ss","pattern":"def GovernanceAssessmentContext"},{"file":"scheme/gateway/func.ss","pattern":"same-node-set?"},{"file":"t/gateway-source-test.ss","pattern":"a false Governance assessment cannot emit a source handoff"},{"file":"t/governance-test.ss","pattern":"a typed ready assessment cannot omit an original blocking threat"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityChangedCompiledSourceCannotRecoverTest"},{"file":"scheme/policy/func.ss","pattern":"project-policy profile"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"},{"file":"t/integration/governed-control-test.ss","pattern":"def governed-control-test"},{"file":"go/internal/config/bundle_test.go","pattern":"func TestBundleRejectsSelectionAndCommitmentSubstitution"}]},{"id":"SourceStartupObservation","witnesses":[{"file":"scheme/gateway/provider-program.ss","pattern":"call-with-module-source-operation-measurement"},{"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeVerificationUsesOnlyPublicPackageEntries"},{"file":"crates/governance-build/src/program.rs","pattern":"build_program_archive_with_contract"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run releaseTagCannotRebaseCapturedSourceCounterexampleTest"},{"file":"go/internal/devrunner/retention_test.go","pattern":"func TestSchemePreparationFailureKeepsOriginalCutWithoutAmbientReceipt"},{"file":"go/internal/devrunner/retention_test.go","pattern":"func TestLateCleanupFailureCannotRetainPassingReceipt"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_preparation_cut_cannot_rebase_boundary","declaration":"Weaver.PolicyBridge.changed_preparation_cut_cannot_rebase_boundary"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run changedPackageMetadataCannotRebaseSnapshotTest"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run stalePreparationReceiptCounterexampleTest"},{"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"},{"file":"go/internal/controlplane/deployment.go","pattern":"trace\\(\"authority-reconciled\"\\)"},{"file":"scheme/gateway/func.ss","pattern":"source-selection-loaded"},{"file":"scheme/gateway/func.ss","pattern":"source-module-view-loaded"},{"file":"scheme/gateway/func.ss","pattern":"source-contracts-checked"},{"file":"scheme/gateway/func.ss","pattern":"source-advisory-derived"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"status=failed drain_ns"},{"file":"crates/governance/src/host/owner.rs","pattern":"scheme-owner-drop-begin"},{"file":"t/fixtures/governed-control.ss","pattern":"fixture-module-ready"},{"file":"go/dev/provider_control_test.go","pattern":"These unauthenticated diagnostics never replace readiness or exit checks"},{"file":"crates/governance-build/src/tooling.rs","pattern":"fn bind_package_sources"},{"file":"crates/governance-build/tests/unit/package_sources.rs","pattern":"fn native_package_inputs_follow_the_selected_store_without_overwriting_sources"}]},{"id":"PolicyCAbiIsInert","witnesses":[{"file":"scheme/policy/func.ss","pattern":"def \\(validate-policy-projection!"},{"file":"scheme/gateway/func.ss","pattern":"validate-policy-projection! projection"},{"file":"t/policy-test.ss","pattern":"real Rust preflight refuses cross-document syntax assembly"},{"file":"t/policy-projection-test.ss","pattern":"every named document precedes aggregate validation"},{"file":"crates/policy-ffi/tests/unit/validation.rs","pattern":"fn aggregate_validity_does_not_establish_complete_source_documents"},{"file":"crates/policy/tests/unit/decisions.rs","pattern":"fn default_deny_forbid_and_evaluation_error_are_fail_closed"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem incomplete_policy_document_cannot_admit"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run aggregateOnlyPolicyValidationCounterexampleTest"},{"file":"scheme/policy/source-bytes.ss","pattern":"def \\(cedar-source-utf8"},{"file":"t/policy-test.ss","pattern":"native PBT checks Unicode source bounds before the C ABI"},{"file":"crates/policy-ffi/tests/unit/abi.rs","pattern":"fn unicode_byte_limits_apply_to_each_actual_abi_region"},{"file":"crates/policy-ffi/src/abi.rs","pattern":"pub unsafe extern \"C\" fn weaver_policy_validate_v1"},{"file":"scheme/policy/cedar-ffi.ss","pattern":"def-C-lambda policy-validate/raw"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authoritySourceCommitNeverSendsTest"}]},{"id":"ControlActivationAcknowledgment","witnesses":[{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsStagingReplyLossAndRestart"},{"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlPublicationReplyLossCannotActivateOrRebase"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityLostReplyCannotActivateTest"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"}]},{"id":"ControlStreamRecoveryBinding","witnesses":[{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPartialRequestAndRestart"},{"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlCompleteStreamsShareBudgetAndRejectSDKRetry"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem profile_recovery_retains_original_hold"}]},{"id":"WorkspaceBenchmarkCoverage","witnesses":[{"file":"go/internal/devrunner/benchmark_test.go","pattern":"func TestBenchmarkEvidenceRequiresEveryCase"},{"file":"go/dev/workspace_test.go","pattern":"func TestCargoWorkspaceAndDevelopmentGates"},{"file":"crates/broker/benches/gateway.rs","pattern":"fn guarded_provider"},{"file":"go/dev/provider_bench_test.go","pattern":"func BenchmarkGatewayInspect"}]},{"id":"DurableRangeProgressJoin","witnesses":[{"file":"crates/ledger/src/stream_progress.rs","pattern":"fn message"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_message_cursor_cannot_hide_consumed_range"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_progress_cannot_release_old_writer_or_connection"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run restoredUnknownProjectionBlocksAdmissionTest"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run unknownResetDuplicatesRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unresolved_tail_blocks_admission","declaration":"Weaver.StreamingExecution.RangeProgress.unresolved_tail_blocks_admission"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem changed_progress_cannot_execute","declaration":"Weaver.StreamingExecution.RangeProgress.changed_progress_cannot_execute"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem joined_execution_preserves_safety","declaration":"Weaver.StreamingExecution.RangeProgress.joined_execution_preserves_safety"}]},{"id":"TursoAdmissionAtomicity","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"pub fn begin"},{"file":"crates/ledger/src/exposure_manifest.rs","pattern":"fn verified_members"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn failed_commit_releases_writer_and_poisoned_session_cannot_reenter"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn duplicate_claim_members_cannot_be_normalized_out_of_recovery"},{"file":"go/dev/workspace_test.go","pattern":"func TestProjectArchitectureStorageUsesMRRDataTursoOnly"},{"file":"dev/proofs/quint/TursoAdmission.qnt","pattern":"run tornCommitRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem storage_step_retains_admission_safety","declaration":"Weaver.RuntimeAdmission.Persistence.storage_step_retains_admission_safety"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem committed_consume_survives_reply_loss_and_restart","declaration":"Weaver.RuntimeAdmission.Persistence.committed_consume_survives_reply_loss_and_restart"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem commit_itself_does_not_send","declaration":"Weaver.RuntimeAdmission.Persistence.commit_itself_does_not_send"}]},{"id":"BoundedAdvisoryDerivation","witnesses":[{"file":"scheme/gateway/derivation.ss","pattern":"def \\(make-gateway-derivation"},{"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-gateway"},{"file":"t/gateway-derivation-test.ss","pattern":"generated source replacements agree with graph traversal and fresh results"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run derivedAdviceCannotChangeImageOrSpendTest"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run adviceAsOriginalCounterexampleTest"}]},{"id":"SessionWorkflowFrontier","witnesses":[{"file":"scheme/gateway/program.ss","pattern":"def \\(hard-fact-affected"},{"file":"go/dev/provider_hard_fact_test.go","pattern":"func TestProviderControlHardFactWithdrawalRestartAndABA"},{"file":"scheme/gateway/func.ss","pattern":"def \\(session-workflow-path"},{"file":"crates/server/src/governance_deployment.rs","pattern":"admits_session_workflow"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"fn bind_winner"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn provider_workflow_rechecks_prepared_floor_and_frontier_before_one_reservation"},{"file":"crates/server/src/session_workflow.rs","pattern":"async fn run_session_workflow"},{"file":"crates/server/src/single_provider.rs","pattern":"SessionTopology::prepare"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionWorkflowAutomaticallyResumes"},{"file":"scheme/gateway/func.ss","pattern":"def \\(governor-ready-steps"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"pub fn observe_workflow"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_workflow_observation"},{"file":"crates/governance/src/host/owner.rs","pattern":"cut_sha256=.*ready_sha256="},{"file":"crates/governance/src/program/compiler.rs","pattern":"topology_binding"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn governor_indices_reject_stale_binding_and_foreign_node"},{"file":"crates/server/src/session_workflow.rs","pattern":"DerivationOutput::Indices"},{"file":"crates/server/src/single_provider.rs","pattern":"topology.preopen"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn pack_governor_facts"},{"file":"t/gateway-governor-retained-test.ss","pattern":"packed facts are complete and bounded by the live binding"},{"file":"t/gateway-governor-retained-test.ss","pattern":"a compact cut must name the current binding"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"Governor transport %d expected"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched inner-join cut_sha256="},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched outer-join cut_sha256="},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionDAGConcurrentJoinAndRecovery"},{"file":"crates/ledger/src/provider_workflow_choice.rs","pattern":"fn record_result"},{"file":"go/dev/provider_workflow_choice_test.go","pattern":"func TestProviderControlSessionChoiceFromReleasedResult"},{"file":"crates/ledger/src/provider_workflow_nested.rs","pattern":"fn load"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn nested_workflow_rejects_stale_decision_and_keeps_winner_after_reopen"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSessionNestedChoiceAndParallelRecovery"},{"file":"scheme/gateway/func.ss","pattern":"WEAVER_TEST_GOVERNOR_CHANGED_SOURCES"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"unexpected Governor source replacement"},{"file":"crates/governance/src/host/client.rs","pattern":"weaver-governor-roundtrip"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"Governor roundtrip phases do not cover the call"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider_metering_with_deployment"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"a new frontier transaction must read the current deployment"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"prepare\\(tx, &proposal.predecessors, plan, current\\)"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn rooted_governor_indices_preserve_full_width_binding_and_all_64_candidates"},{"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-retained-governor-program"},{"file":"t/gateway-governor-retained-test.ss","pattern":"prepared nested rules agree with full fresh snapshots under replacement"},{"file":"t/gateway-governor-retained-test.ss","pattern":"prepared nested rules preserve source budget rejection and recovery"}]},{"id":"RustSchemeRuntimeBoundary","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"RustSchemeRuntimeBoundary"}]},{"id":"CloudAdapterAuthorityBoundary","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"CloudAdapterAuthorityBoundary"},{"file":"prod/kubernetes/provideravailability.crd.yaml","pattern":"kind: ProviderAvailability"},{"file":"prod/kubernetes/provideravailability.rbac.yaml","pattern":"resources: \\[provideravailabilities/status\\]"},{"file":"crates/server/src/kubernetes.rs","pattern":"async fn reconcile\\("},{"file":"crates/ledger/src/hard_fact.rs","pattern":"pub fn inspect_fact_feed\\("},{"file":"go/dev/provider_kubernetes_test.go","pattern":"func TestProviderKubernetesAvailability\\("}]},{"id":"GoIntegrationLeverage","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"GoIntegrationLeverage"}]},{"id":"SchemeSourceComposition","witnesses":[{"file":"scheme/gateway/provider-source.ss","pattern":"def \\(compose-provider-configuration"},{"file":"scheme/gateway/compiled.ss","pattern":"weaver_compose_source_v1"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn composition_uses_scheme_then_rust_seals_the_exact_original"},{"file":"crates/server/src/governance_deployment.rs","pattern":"from_configuration_with"},{"file":"go/internal/controlplane/source_compile.go","pattern":"config.CloneArtifact"},{"file":"t/gateway-source-test.ss","pattern":"ASCENT routing filters modules"},{"file":"go/internal/controlplane/gateway.go","pattern":"composeSourceBundle"},{"file":"go/internal/controlplane/provider_catalog.go","pattern":"func \\(g \\*Gateway\\) composeCatalog"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSchemeCompositionRevocationAndRestart"},{"file":"crates/governance/src/composition.rs","pattern":"pub fn validate_selected"},{"file":"crates/governance/tests/unit/configuration.rs","pattern":"fn source_composition_cannot_seal_a_self_consistent_scope_substitution"}]},{"id":"AdvisorySourceComposition","witnesses":[{"file":"crates/server/src/grpc.rs","pattern":"async fn compose_source"},{"file":"crates/governance/src/host/client.rs","pattern":"pub async fn compose"},{"file":"go/dev/provider_module_routing_test.go","pattern":"operation caller entered semantic composition"},{"file":"go/internal/controlplane/provider_catalog_test.go","pattern":"func TestCatalogCompositionCoalescesFourRequests"},{"file":"crates/broker/tests/unit/https_transport.rs","pattern":"fn provider_endpoint_guard_preserves_anthropic_source_path_constraints"}]},{"id":"DirectRustOperationIngress","witnesses":[{"file":"go/internal/controlplane/deployment.go","pattern":"func PrepareFromEnv"},{"file":"go/dev/controlref/main.go","pattern":"action := controlplane.PrepareFromEnv"},{"file":"crates/server/src/grpc_provider.rs","pattern":"operation_key_only"},{"file":"crates/server/src/single_provider.rs","pattern":"fn operation_plan"},{"file":"crates/server/src/provider_oauth.rs","pattern":"direct ingress cannot supply relay evidence"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderRustDirectPreparedOperationWithoutGoRelay"}]},{"id":"SourceBoundOperationPreparation","witnesses":[{"file":"crates/contracts/src/provider_routing.rs","pattern":"pub enum ProviderOperationScope"},{"file":"crates/ledger/src/provider_routing.rs","pattern":"pub fn register_provider_source"},{"file":"crates/ledger/src/provider_routing.rs","pattern":"pub fn register_routed_task"},{"file":"crates/server/src/source_owner.rs","pattern":"struct OperationResolver"},{"file":"go/dev/provider_module_routing_test.go","pattern":"func TestProviderRustDirectCatalogSelection"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderRustDirectFilePreparation"}]}] +[{"id":"ProviderAdmissionTurn","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let selected_admission"},{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn begin_driver_counters_follow_their_admission_grant"},{"file":"crates/ledger/src/persistence/driver_observer.rs","pattern":"fn observe_read"},{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct AdmissionRequest"},{"file":"crates/ledger/tests/unit/provider_admission_turn.rs","pattern":"fn queued_unaccepted_admission_preserves_old_frame_and_original_hold"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionTurnProperty"},{"file":"go/dev/provider_admission_turn_test.go","pattern":"func TestProviderAdmissionCommitRecovery"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderAdmissionTurn"},{"file":"crates/broker/src/provider/request.rs","pattern":"Stage::Tls"},{"file":"go/dev/provider_transport_phases_test.go","pattern":"func reportProviderTransport"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run eagerQueueBlocksOldFrameCounterexampleTest"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem queue_preserves_arbitrary_requirement","declaration":"Weaver.ProviderAdmissionTurn.queue_preserves_arbitrary_requirement"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem finite_queue_preserves_final_offer","declaration":"Weaver.ProviderAdmissionTurn.finite_queue_preserves_final_offer"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem open_writer_cannot_mutate","declaration":"Weaver.ProviderAdmissionTurn.open_writer_cannot_mutate"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem accepted_hard_intent_blocks","declaration":"Weaver.ProviderAdmissionTurn.accepted_hard_intent_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_outcome_blocks","declaration":"Weaver.ProviderAdmissionTurn.unknown_outcome_blocks"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem changed_image_blocks","declaration":"Weaver.ProviderAdmissionTurn.changed_image_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem queued_admission_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.queued_admission_preserves_spec_final_use"},{"file":"go/internal/controlplane/deployment.go","pattern":"if gateway.source == nil"},{"file":"go/dev/provider_control_bench_test.go","pattern":"func TestProviderGoControlMeasuredChain"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem runtime_catalog_requires_source","declaration":"Weaver.ProviderAdmissionTurn.runtime_catalog_requires_source"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem unknown_activation_blocks_source_handoff","declaration":"Weaver.ProviderAdmissionTurn.unknown_activation_blocks_source_handoff"},{"file":"dev/proofs/lean/ProviderAdmissionTurn.lean","pattern":"theorem bootstrap_source_close_preserves_actual","declaration":"Weaver.ProviderAdmissionTurn.bootstrap_source_close_preserves_actual"},{"file":"dev/proofs/quint/ProviderAdmissionTurn.qnt","pattern":"run failedBootstrapCleanupDoesNotActivateIngressTest"},{"file":"go/dev/provider_admission_overlap_bench_test.go","pattern":"func BenchmarkProviderAdmissionOverlap"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn collect_buffered"},{"file":"go/dev/provider_control_bench_test.go","pattern":"image := serverBinary"},{"file":"go/dev/provider_fixture_test.go","pattern":"test-owned Go control image sha256"},{"file":"crates/ledger/src/persistence/scope_trace.rs","pattern":"pub\\(super\\) fn observe_release"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"observed_release_covers_lease_removal_without_retaining_a_grant"},{"file":"crates/ledger/src/persistence/driver_observer.rs","pattern":"pub\\(super\\) fn observe_commit"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"commit_io_observes_native_spans_after_unobserved_setup"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"maybe_prepared\\(c, PREPARE"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn review_program_reuse_reads_replacement_and_rejects_projection_loss"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn review_program_reuse_preserves_native_receipts_and_currentness"},{"file":"go/dev/provider_control_bench_test.go","pattern":"both arms use Go forwarding"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"valid_review!\\(\"CROSS JOIN\"\\)"},{"file":"crates/ledger/src/domains/view.rs","pattern":"require_view\\(persistence::maybe_prepared"},{"file":"crates/ledger/tests/unit/driver_observer.rs","pattern":"fn manifest_programs_rebind_current_members_and_reject_divergence"}]},{"id":"ProviderReadCustody","witnesses":[{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn conflicts"},{"file":"crates/ledger/src/persistence/scheduler.rs","pattern":"fn acquire_origin"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"let shared_reads"},{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn compatible_origins_share_reads_but_an_older_writer_blocks_younger_readers"},{"file":"crates/ledger/tests/unit/provider_read_custody.rs","pattern":"fn shared_reads_keep_distinct_origin_native_writes_concurrent"},{"file":"go/dev/provider_read_custody_test.go","pattern":"func TestProviderReadCustodyProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderReadCustody"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem arbitrary_policy_preserved","declaration":"Weaver.ProviderReadCustody.arbitrary_policy_preserved"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem finite_interleaving_preserves_policy","declaration":"Weaver.ProviderReadCustody.finite_interleaving_preserves_policy"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem overlapping_writes_conflict","declaration":"Weaver.ProviderReadCustody.overlapping_writes_conflict"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessRetainsWriterAndSameOriginBarriers"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_binding_blocks","declaration":"Weaver.ProviderReadCustody.changed_binding_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_shared_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_shared_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_origin_cut_blocks","declaration":"Weaver.ProviderReadCustody.changed_origin_cut_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem changed_owner_blocks","declaration":"Weaver.ProviderReadCustody.changed_owner_blocks"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem shared_writer_conflicts","declaration":"Weaver.ProviderReadCustody.shared_writer_conflicts"},{"file":"dev/proofs/lean/ProviderReadCustody.lean","pattern":"theorem older_conflicting_writer_blocks","declaration":"Weaver.ProviderReadCustody.older_conflicting_writer_blocks"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem read_custody_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.read_custody_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderReadCustody.qnt","pattern":"run unsafeSharedMutationCounterexampleTest"}]},{"id":"ProviderLifecycleFootprint","witnesses":[{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct OriginLifecycle"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"enum Impact"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_lifecycle"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_provider_lifecycle"},{"file":"crates/ledger/tests/unit/provider_lifecycle.rs","pattern":"fn peer_lifecycle_preserves_complete_view_but_shared_admission_does_not"},{"file":"go/dev/provider_lifecycle_test.go","pattern":"func TestProviderLifecycleCommitRecovery"},{"file":"crates/ledger/tests/unit/authority_footprint.rs","pattern":"fn local_commit_retires_whole_and_own_but_preserves_peer"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem origin_commit_retires_whole_reader","declaration":"Weaver.ProviderLifecycleFootprint.origin_commit_retires_whole_reader"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem arbitrary_cedar_predicate_preserved","declaration":"Weaver.ProviderLifecycleFootprint.arbitrary_cedar_predicate_preserved"},{"file":"dev/proofs/lean/ProviderLifecycleFootprint.lean","pattern":"theorem shared_admission_requires_shared_invalidation","declaration":"Weaver.ProviderLifecycleFootprint.shared_admission_requires_shared_invalidation"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem peer_lifecycle_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.peer_lifecycle_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderLifecycleFootprint.qnt","pattern":"run unsafeNarrowAdmissionCounterexampleTest"}]},{"id":"ProviderSnapshotPublication","witnesses":[{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn release_provider_group_for_delivery"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"struct Snapshot"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn share_qualification"},{"file":"crates/ledger/src/provider.rs","pattern":"fn begin_snapshot_validation"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn take_refresh"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem pending_close_defers_renewal","declaration":"Weaver.ProviderSnapshotPublication.pending_close_defers_renewal"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn a_request_arriving_during_qualification_cannot_trigger_a_second_native_read"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn one_snapshot_requalification_covers_every_exact_frame"},{"file":"crates/ledger/tests/unit/provider_snapshot.rs","pattern":"fn post_staging_native_failure_cannot_publish_a_partial_snapshot"},{"file":"crates/broker/src/provider/range_output.rs","pattern":"fn queue_snapshot"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func awaitDeliveryCuts"},{"file":"dev/proofs/lean/ProviderSnapshotPublication.lean","pattern":"theorem final_use_joins_snapshot","declaration":"Weaver.ProviderSnapshotPublication.final_use_joins_snapshot"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem published_snapshot_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.published_snapshot_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSnapshotPublication.qnt","pattern":"run ungatedArcLoadIsCounterexampleTest"}]},{"id":"ProviderSemanticProgress","witnesses":[{"file":"crates/ledger/src/provider_scope.rs","pattern":"struct RangeProgress"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close_progress"},{"file":"crates/ledger/src/provider_release_group.rs","pattern":"fn stage_group"},{"file":"crates/ledger/tests/unit/provider_delivery.rs","pattern":"fn exact_range_progress_preserves_queued_authorization"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderSemanticProgressProperty"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_released_binding","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_released_binding"},{"file":"dev/proofs/lean/ProviderSemanticProgress.lean","pattern":"theorem finite_progress_preserves_image","declaration":"Weaver.ProviderSemanticProgress.finite_progress_preserves_image"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem range_progress_preserves_spec_final_use","declaration":"Weaver.DomainMigrationComposition.range_progress_preserves_spec_final_use"},{"file":"dev/proofs/quint/ProviderSemanticProgress.qnt","pattern":"run hiddenSemanticEditIsCounterexampleTest"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"}]},{"id":"ProviderDeliveryJoin","witnesses":[{"file":"crates/ledger/tests/unit/scope_trace.rs","pattern":"fn bounded_trace_retains_every_requalification"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeTraceChunksPreserveAllRecords"},{"file":"crates/ledger/tests/unit/persistence_owner.rs","pattern":"fn descriptor_copy_is_not_a_retained_execution_owner"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem retained_role_blocks_custody_retirement","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.retained_role_blocks_custody_retirement"},{"file":"dev/proofs/quint/ProviderDeliveryPipeline.qnt","pattern":"run threeInertFramesNeedNoStopAndWaitTest"},{"file":"crates/server/src/grpc_delivery_producer.rs","pattern":"fn reserve_guarded"},{"file":"crates/ledger/src/persistence/authority.rs","pattern":"fn close"},{"file":"crates/ledger/src/provider_delivery.rs","pattern":"pub fn poll"},{"file":"crates/server/src/grpc_delivery.rs","pattern":"impl Stream for ResponseStream"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryCommitAndReceiverRecovery"},{"file":"go/dev/provider_delivery_join_test.go","pattern":"func TestProviderDeliveryReceiverProperty"},{"file":"go/dev/provider_delivery_bench_test.go","pattern":"func BenchmarkProviderDeliveryJoin"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem orphaned_witness_cannot_activate","declaration":"Weaver.ProviderEgressWindow.DeliveryJoin.orphaned_witness_cannot_activate"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem acknowledged_delivery_preserves_same_actual_view","declaration":"Weaver.DomainMigrationComposition.acknowledged_delivery_preserves_same_actual_view"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run committedWithoutAcknowledgmentCannotAcceptTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run rollbackCannotEraseIndependentWitnessTest"},{"file":"dev/proofs/quint/ProviderDeliveryJoin.qnt","pattern":"run oldOwnerCannotRequalifyAfterRestartTest"}]},{"id":"ProviderEgressPromotion","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_close_receipt_cannot_resolve_new_intent","declaration":"Weaver.ProviderEgressWindow.Promotion.old_close_receipt_cannot_resolve_new_intent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem expired_clock_blocks_receiver","declaration":"Weaver.ProviderEgressWindow.Promotion.expired_clock_blocks_receiver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem every_effect_writer_needs_mediation","declaration":"Weaver.ProviderEgressWindow.Promotion.every_effect_writer_needs_mediation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem other_writer_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.other_writer_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem uncertain_effect_blocks_activation","declaration":"Weaver.ProviderEgressWindow.Promotion.uncertain_effect_blocks_activation"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem unchanged_database_does_not_revalidate_old_read","declaration":"Weaver.ProviderEgressWindow.Promotion.unchanged_database_does_not_revalidate_old_read"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem witness_ahead_blocks_old_image","declaration":"Weaver.ProviderEgressWindow.Promotion.witness_ahead_blocks_old_image"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem only_current_owner_can_deliver","declaration":"Weaver.ProviderEgressWindow.Promotion.only_current_owner_can_deliver"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem old_queued_frame_cannot_follow_replacement","declaration":"Weaver.ProviderEgressWindow.Promotion.old_queued_frame_cannot_follow_replacement"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem delivered_frame_cannot_be_delivered_twice","declaration":"Weaver.ProviderEgressWindow.Promotion.delivered_frame_cannot_be_delivered_twice"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem receiver_promotion_refines_interval_admission","declaration":"Weaver.ProviderEgressWindow.Promotion.receiver_promotion_refines_interval_admission"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run firstCommitCannotDeliverAnotherPendingWriterTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run independentWitnessBeforeDatabaseBlocksDeliveryTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run oldWorkerDeliveryCounterexampleTest"},{"file":"dev/proofs/quint/ProviderEgressPromotion.qnt","pattern":"run allWriterClassesUseTheSameCutTest"}]},{"id":"BoundedProviderEgressWindow","witnesses":[{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem any_accepted_trace_keeps_disjoint_prefix","declaration":"Weaver.ProviderEgressWindow.any_accepted_trace_keeps_disjoint_prefix"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem loss_and_restart_close_old_window","declaration":"Weaver.ProviderEgressWindow.loss_and_restart_close_old_window"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem matching_image_does_not_reopen_old_cut","declaration":"Weaver.ProviderEgressWindow.matching_image_does_not_reopen_old_cut"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem connected_roots_cannot_use_distinct_lanes","declaration":"Weaver.ProviderEgressWindow.connected_roots_cannot_use_distinct_lanes"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem admitted_four_turn_envelope","declaration":"Weaver.ProviderEgressWindow.admitted_four_turn_envelope"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem settlement_is_idempotent","declaration":"Weaver.ProviderEgressWindow.settlement_is_idempotent"},{"file":"dev/proofs/lean/ProviderEgressWindow.lean","pattern":"theorem holder_stage_overlap_cannot_exceed_ticket_wait","declaration":"Weaver.ProviderEgressWindow.holder_stage_overlap_cannot_exceed_ticket_wait"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run coherentStoreRollbackActuallyDuplicatesOfferTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run pendingRevocationStopsActualOfferTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run lostBurnAckSealsOriginalTest"},{"file":"dev/proofs/quint/ProviderEgressWindow.qnt","pattern":"run rehydratingOldWindowActuallyDuplicatesOfferTest"}]},{"id":"OriginalFloorDecision","witnesses":[{"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run lostCommitResponseResolvesSameOperationTest"},{"file":"dev/proofs/quint/LlmAdmissionFloor.qnt","pattern":"run unknownCommitCannotActivateTest"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"}]},{"id":"ProviderCurrentnessPerformance","witnesses":[{"file":"go/dev/provider_domain_program_test.go","pattern":"func BenchmarkProviderDomainProgram"},{"file":"go/dev/provider_domain_tail_test.go","pattern":"func BenchmarkProviderSharedLongTail"},{"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem prepared_domain_program_preserves_live_decision"}]},{"id":"ProviderSchedulerOwnership","witnesses":[{"file":"crates/ledger/tests/unit/persistence_scheduler.rs","pattern":"fn waiting_multi_root_range_precedes_younger_conflicts"},{"file":"go/dev/provider_range_scopes_test.go","pattern":"func TestProviderScopeFairnessCountsArrivalGrantInversions"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"}]},{"id":"SenderBoundProviderOAuth","witnesses":[{"file":"go/dev/provider_oauth_relay_test.go","pattern":"func TestProviderOAuthTwoHopRevocationAndRecovery"},{"file":"dev/proofs/cedar/WeaverOAuthRefinement.lean","pattern":"theorem retained_root_revocation_blocks_child"}]},{"id":"TransportAndExecutionLatencySeparation","witnesses":[{"file":"go/dev/provider_scheduler_bench_test.go","pattern":"func BenchmarkProviderScheduledEncoding"},{"file":"go/dev/provider_range_group_test.go","pattern":"func BenchmarkProviderRangePreparationGroup"}]},{"id":"TelemetryNoninterference","witnesses":[{"file":"crates/telemetry/tests/unit/metrics.rs","pattern":"fn observations_are_monotone_and_restart_local"},{"file":"go/internal/telemetry/metrics_test.go","pattern":"func TestPropertyCountersAreBoundedMonotoneAndRestartLocal"},{"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderTelemetryCannotRefundOrRedispatchUnknownSend"},{"file":"go/dev/provider_telemetry_test.go","pattern":"func TestProviderControlTelemetryObservesBothServices"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryReadsAndRestartCannotRefundTest"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run telemetryAsRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem arbitrary_observations_keep_execution","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.arbitrary_observations_keep_execution"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem telemetry_reset_keeps_unknown_hold","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.telemetry_reset_keeps_unknown_hold"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem observations_preserve_effect_safety","declaration":"Weaver.RuntimeAdmission.MVCC.Telemetry.observations_preserve_effect_safety"}]},{"id":"SharedDomainAuthority","witnesses":[{"file":"crates/ledger/src/domains/binding.rs","pattern":"fn bind"},{"file":"crates/ledger/src/domains/migration.rs","pattern":"fn migrate_execution_domains"},{"file":"crates/ledger/src/domains/view.rs","pattern":"fn require_stamp"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_cross_family_shared_history_serializes_final_use"},{"file":"crates/ledger/tests/unit/shared_domains.rs","pattern":"fn finite_families_never_split_a_shared_cap"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsProperty"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"func TestProviderSharedDomainsCedarReadsCurrentAuthority"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run overCapacityUnionKeepsOriginalDecisionTest"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run domainSplitCounterexampleTest"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_cannot_split_any_shared_pair","declaration":"Weaver.SharedDomains.union_cannot_split_any_shared_pair"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem admitted_union_conserves_capacity","declaration":"Weaver.SharedDomains.admitted_union_conserves_capacity"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_retains_history","declaration":"Weaver.SharedDomains.union_retains_history"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem union_fences_both_old_permits","declaration":"Weaver.SharedDomains.union_fences_both_old_permits"}]},{"id":"TursoMvccCustody","witnesses":[{"file":"crates/ledger/src/persistence/owner.rs","pattern":"fn open"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_family"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_final_domains_overlap_including_new_executor_connection"},{"file":"crates/ledger/tests/unit/final_domains.rs","pattern":"fn mvcc_same_budget_and_history_family_keeps_final_order"},{"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn mvcc_effect_before_failed_observation_never_releases_or_replays"},{"file":"go/dev/provider_final_domains_test.go","pattern":"func TestProviderMVCCIndependentFinalSendsAndRevocation"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run postSendCommitConflictKeepsPhysicalEffectTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem shared_final_readers_keep_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.shared_final_readers_keep_current_fence"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem failed_observation_after_send_keeps_spent_hold","declaration":"Weaver.RuntimeAdmission.MVCC.failed_observation_after_send_keeps_spent_hold"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_disjoint_admissions_have_overlapping_turso_writes"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn mvcc_process_custody_refuses_a_second_process"},{"file":"crates/ledger/tests/unit/mvcc.rs","pattern":"fn mvcc_concurrent_family_budget_has_one_original_reservation"},{"file":"go/dev/provider_mvcc_test.go","pattern":"func TestProviderMVCCExecutionBoundary"},{"file":"dev/proofs/quint/TursoMvcc.qnt","pattern":"run snapshotWriteSkewCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem disjoint_domain_commits_commute","declaration":"Weaver.RuntimeAdmission.MVCC.disjoint_domain_commits_commute"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem family_step_preserves_all_budgets","declaration":"Weaver.RuntimeAdmission.MVCC.family_step_preserves_all_budgets"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exclusive_final_use_keeps_current_fence","declaration":"Weaver.RuntimeAdmission.MVCC.exclusive_final_use_keeps_current_fence"}]},{"id":"ArchitectureViewGrammar","witnesses":[{"file":"dev/sysml/ArchitectureViews.sysml","pattern":"view zeroTrust"},{"file":"go/internal/devrunner/model_views.go","pattern":"func CaptureModelViews"},{"file":"go/internal/devrunner/model_views_test.go","pattern":"func TestModelViewsUseActualSDK"},{"file":"go/internal/devrunner/model_views_test.go","pattern":"func FuzzModelViewCaptureTracksSource"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestArchitectureDiagramsUseDifferentViewProfiles"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramProfilesAreExplicitAndLocal"},{"file":"go/internal/devrunner/diagrams.go","pattern":"func RenderDiagrams"},{"file":"dev/d2/src/render.ts","pattern":"composeFigure[(]input,composer[)]"},{"file":"dev/d2/test/model-view.test.ts","pattern":"public Library binds SDK SysML identity"},{"file":"dev/d2/src/objects.ts","pattern":"export const composeObjects"},{"file":"dev/d2/test/model-view.test.ts","pattern":"missing captured views and unsupported source ports refuse"},{"file":"dev/d2/test/vector-readability.test.ts","pattern":"Preserve the original ordered-sequence line-overlap check"},{"file":"go/internal/devrunner/diagrams_test.go","pattern":"func TestDiagramEvidenceRejectsLostNodesAndRelationships"}]},{"id":"ProductionAssetBoundary","witnesses":[{"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRuntimeAssetBoundary"},{"file":"go/dev/runtime_boundary_test.go","pattern":"func TestProjectArchitectureRejectsRuntimeDevReferences"}]},{"id":"OriginalTaskBinding","witnesses":[{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem first_birth_seal_cannot_broaden","declaration":"Weaver.TaskOrigin.first_birth_seal_cannot_broaden"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem sealed_birth_cannot_be_replaced","declaration":"Weaver.TaskOrigin.sealed_birth_cannot_be_replaced"},{"file":"crates/ledger/tests/unit/task_publication.rs","pattern":"fn lost_birth_projection_cannot_authorize_or_be_silently_repaired"},{"file":"crates/ledger/src/task_origins.rs","pattern":"fn register_original_task"},{"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn source_rotation_cannot_reallocate_task_and_lost_reply_recovers_original_commit"},{"file":"crates/ledger/tests/unit/task_origins.rs","pattern":"fn trusted_issuer_relabeling_every_identity_is_outside_local_deduplication"},{"file":"go/dev/provider_task_origin_test.go","pattern":"func TestProviderOriginalTaskOriginLostReplySourceSwitchAndRestart"},{"file":"dev/proofs/quint/TaskOrigin.qnt","pattern":"run issuerTrustCounterexampleTest"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem assigned_task_cannot_rebind","declaration":"Weaver.TaskOrigin.assigned_task_cannot_rebind"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem source_epoch_does_not_change_task_scope","declaration":"Weaver.TaskOrigin.source_epoch_does_not_change_task_scope"},{"file":"dev/proofs/lean/SharedDomains.lean","pattern":"theorem stale_source_command_cannot_commit","declaration":"Weaver.TaskOrigin.stale_source_command_cannot_commit"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn original_task_body_and_profile_cannot_be_replaced"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalBindingTest"}]},{"id":"SharedBudget","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn finite_manifest_siblings_cannot_mask_a_missing_original_member"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn maximum_manifest_cannot_replace_a_lost_sibling_after_restart"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityRecoveryGuardTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialLossFreshAuthorityFinalUseGuardTest"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn selected_message_binding_must_match_its_committed_digest_at_final_write"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn concurrent_message_admission_preserves_both_manifest_members"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exhausted_budget_cannot_publish_a_manifest_member_without_its_row"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem manifest_bound_runtime_step"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn surviving_stream_message_cannot_hide_a_lost_unknown_reservation"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn exact_message_manifest_guards_recovery_and_existing_write_handles"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run partialMessageLossCounterexampleTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run digestSubstitutionFinalUseGuardTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem exact_manifest_admission_covers_original_exposure"},{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn balanced_provider_projection_never_funds_a_different_original_plan"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_stream_projection_never_funds_the_next_logical_message"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem admission_covers_original_exposure"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run balancedProjectionCounterexampleTest"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn balanced_shrink_never_admits_a_different_node"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn require_family"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn mixed_request_and_stream_exposure_cannot_be_checked_in_separate_domains"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem orphaned_hold_blocks_new_admission"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run separateEffectDomainsCounterexampleTest"},{"file":"crates/ledger/tests/unit/properties.rs","pattern":"fn arbitrary_replays_restarts_and_consumption_preserve_claims"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run sharedBudgetTest"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run originalCostBoundTest"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn authored_ceiling_cannot_underreserve_the_original_wire_cost"}]},{"id":"ZeroTrustContractRefinement","witnesses":[{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem final_use_on_committed_union","declaration":"Weaver.DomainMigrationComposition.final_use_on_committed_union"},{"file":"crates/ledger/src/provider.rs","pattern":"actual.stamp != p.domains"},{"file":"crates/ledger/tests/unit/provider_domains.rs","pattern":"fn same_actual_domains_fence_original_provider_capability"},{"file":"go/dev/provider_shared_domains_test.go","pattern":"actual migration committed; response discarded"},{"file":"dev/proofs/quint/SharedDomains.qnt","pattern":"run committedUnionLostReplyKeepsBothOriginalsTest"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem gateway_final_use_preserves_domain_contract","declaration":"Weaver.DomainMigrationComposition.gateway_final_use_preserves_domain_contract"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem head_cas_preserves_original_obligations","declaration":"Weaver.DomainMigrationComposition.head_cas_preserves_original_obligations"},{"file":"dev/proofs/cedar/DomainMigrationComposition.lean","pattern":"theorem overbooked_actual_view_cannot_supply_final_run","declaration":"Weaver.DomainMigrationComposition.overbooked_actual_view_cannot_supply_final_run"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureResearchModels"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainCommitRestartPositiveTest"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run finiteDomainRevocationKeepsOriginalExposureTest"},{"file":"dev/proofs/quint/GatewayHeadCAS.qnt","pattern":"run detachedLogicalLedgerCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_exposure_keeps_original_budget","declaration":"Weaver.ProviderRpc.shared_exposure_keeps_original_budget"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework","declaration":"Weaver.ZeroTrustEnrichment.gateway_specialization_retains_generic_framework"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway","declaration":"Weaver.ZeroTrustEnrichment.retained_parent_and_selected_object_reach_gateway"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption","declaration":"Weaver.ZeroTrustEnrichment.usage_control_keeps_current_consumption"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use","declaration":"Weaver.ZeroTrustEnrichment.pending_policy_blocks_ongoing_use"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"}]},{"id":"ConsumeBeforeSend","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn final_write_requires_exact_durable_range"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run stateOnlyRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem inexact_cannot_refine_execution","declaration":"Weaver.StreamingExecution.RangeReceipt.inexact_cannot_refine_execution"},{"file":"crates/ledger/tests/unit/recovery.rs","pattern":"fn crash_after_consumption_never_reopens_or_refunds"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run consumeBeforeSendTest"}]},{"id":"CurrentFinalGuard","witnesses":[{"file":"crates/ledger/tests/unit/serialization.rs","pattern":"fn effective_publication_cannot_overtake_the_locked_send_boundary"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run stalePermitTest"}]},{"id":"UnknownRetainsHold","witnesses":[{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restart_never_backfills_request_claims_from_operations"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn orphaned_request_claim_cannot_admit_a_replacement_operation"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn next_stream_message_cannot_recreate_a_lost_node_claim"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn lost_message_projection_cannot_recycle_original_unknown_hold"},{"file":"crates/broker/tests/unit/https_transport.rs","pattern":"fn partial_transport_failure_is_unknown_and_never_retried"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run unknownRefundCounterexampleTest"}]},{"id":"NoImplicitRetry","witnesses":[{"file":"crates/ledger/tests/unit/concurrency.rs","pattern":"fn concurrent_consumers_invoke_once"},{"file":"dev/proofs/quint/RuntimeAdmission.qnt","pattern":"run duplicateRetryCounterexampleTest"}]},{"id":"DevelopmentPolicy","witnesses":[{"file":"crates/contracts/src/lib.rs","pattern":"mode = deny"}]},{"id":"MessageScopedAuthority","witnesses":[{"file":"crates/ledger/tests/unit/stream_properties.rs","pattern":"fn unknown_range_after_restart_blocks_new_nonce_and_authority"},{"file":"crates/policy/tests/unit/stream_policy.rs","pattern":"fn specification_derived_policy_is_typed_and_constrains_actual_range_facts"}]},{"id":"RangeFinalGuard","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn effective_revocation_stops_actual_next_range_and_prefix_reconnect"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run revokedBetweenBurnAndWriteTest"}]},{"id":"UnknownPrefixRecovery","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn rust_partial_write_freezes_tail_and_never_refunds"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unknown_cannot_resume"}]},{"id":"PrivateBufferCustody","witnesses":[{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn tls_flush_cannot_release_a_tail_after_effective_revocation"},{"file":"crates/broker/tests/unit/stream_wire.rs","pattern":"fn recovered_old_worker_socket_cannot_use_new_custody"}]},{"id":"BoundedPerformanceWork","witnesses":[{"file":"crates/policy/tests/unit/cache_storage.rs","pattern":"fn compiled_storage_caps_slots_and_exact_hits_do_not_allocate_new_entries"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem bounded_range_copy_work"}]},{"id":"TrackedWriterDrain","witnesses":[{"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"async fn detached_executor_writer_keeps_slot_until_drain_acknowledges_completion"},{"file":"crates/server/tests/unit/runtime_lifecycle.rs","pattern":"fn arbitrary_disconnect_shutdown_and_drain_schedules_keep_executor_custody"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderClientCancellationCannotReplay"},{"file":"dev/proofs/quint/RuntimeLifecycle.qnt","pattern":"run prematureAckCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem execution_and_drain_composition"}]},{"id":"GrpcCallerBinding","witnesses":[{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderRPCIdentityAndCancellation"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_name_is_not_key_authority"}]},{"id":"TransportSetupIsolation","witnesses":[{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run reconnectCannotUncancelOriginalStreamTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem crash_cannot_recreate_unknown_release"},{"file":"go/internal/gatewayclient/connection_test.go","pattern":"func TestConnectionSetupRetainsCallerDeadlineAndCancellation"},{"file":"go/dev/provider_startup_test.go","pattern":"func TestProviderFreshImageAndRestartStartup"},{"file":"dev/proofs/quint/GatewayComposition.qnt","pattern":"run reconnectRetainsSpentRootTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem gateway_run_preserves_original_execution_and_custody"}]},{"id":"CommittedProviderRouting","witnesses":[{"file":"go/internal/routing/provider_test.go","pattern":"func TestProviderRoutingCannotRewriteOriginalContract"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderGRPCStreamingAndArrowOption"}]},{"id":"UnambiguousProviderRequestBounds","witnesses":[{"file":"crates/contracts/tests/unit/provider_bounds.rs","pattern":"fn exactly_one_provider_cap_is_bounded"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn rejected_competing_caps_leave_no_claim_or_hold_after_restart"},{"file":"go/internal/routing/provider_test.go","pattern":"func FuzzProviderRequestBounds"},{"file":"go/dev/provider_bounds_test.go","pattern":"func TestProviderCompetingCapsCannotReachDispatch"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preferredCapPrecedenceCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem request_bounds_and_affine_execution_composition"}]},{"id":"SourceProviderProfileBinding","witnesses":[{"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceProfileAndCedarBindFinalSendAcrossRestart"},{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn concurrent_profile_registrations_cannot_fork_one_identity"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_task_registration_cannot_rebind"}]},{"id":"ClosedProviderRequestSchema","witnesses":[{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn provider_profile_cannot_fall_back_to_untyped_request_or_raw_stream"},{"file":"crates/contracts/tests/unit/provider_profiles.rs","pattern":"fn shared_closed_request_corpus_has_the_declared_semantics"},{"file":"go/api/v1/provider_profile_test.go","pattern":"func TestProviderProfileSharedClosedRequestCorpus"},{"file":"go/dev/provider_profiles_test.go","pattern":"func TestProviderSourceCommittedExtensionsCannotBypassProfile"},{"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingSchemaGuardCounterexampleTest"}]},{"id":"RecoverableProfileFloor","witnesses":[{"file":"crates/ledger/tests/unit/provider_profiles.rs","pattern":"fn original_task_floor_prevents_missing_registry_from_rebinding_identity"},{"file":"crates/ledger/tests/unit/profile_floor_plan.rs","pattern":"fn semantic_floor_uses_two_composite_range_seeks"},{"file":"dev/proofs/quint/ProviderProfile.qnt","pattern":"run missingFloorCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem missing_registry_cannot_erase_original_floor"}]},{"id":"CanonicalProfileConfiguration","witnesses":[{"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileJSONAndYAMLHaveOneCanonicalCommitment"},{"file":"go/internal/config/provider_profile_test.go","pattern":"func TestProviderProfileRejectsAmbiguousConfiguration"},{"file":"go/internal/config/provider_profile_test.go","pattern":"func FuzzProviderProfileConfiguration"}]},{"id":"AffineProviderAttempt","witnesses":[{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn arbitrary_provider_replays_restarts_and_release_batches_keep_original_claim"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run sdkRetryCannotConsumeAgainTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem consumed_unknown_retains_original_hold"}]},{"id":"EncodingAuthorityEquivalence","witnesses":[{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPolicyChangeDuringCapacityWait"},{"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowWireBoundDoesNotBoundDecodedText"},{"file":"go/internal/gatewayclient/arrow_test.go","pattern":"func TestArrowInvalidLaterRowReturnsNoPartialBatch"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run preparedEncodingCannotSwitchTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem final_guard_checks_actual_owner_rows"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderArrowChecksEveryRow"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem arrow_cannot_weaken_row_authority"}]},{"id":"ProviderUnknownRetention","witnesses":[{"file":"crates/broker/src/provider/runtime.rs","pattern":"fn open_guarded"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn commit_provider"},{"file":"crates/ledger/tests/unit/provider_observation.rs","pattern":"fn failed_callback_never_enters_final_commit_and_retains_original_exposure"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn turso_applied_commit_without_ack_poison_is_not_reusable"},{"file":"go/dev/provider_commit_fault_test.go","pattern":"func TestProviderSealedTursoCommitRecovery"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run appliedLostAckPoisonsOldWorkerTest"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run durableCommitThenFenceThenLateAckTest"},{"file":"dev/proofs/quint/ProviderRequestFence.qnt","pattern":"run committingFailedCallbackCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem failed_callback_cannot_enter_commit","declaration":"Weaver.ProviderRpc.RequestWriteFence.failed_callback_cannot_enter_commit"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem applied_commit_without_ack_does_not_activate","declaration":"Weaver.ProviderRpc.RequestWriteFence.applied_commit_without_ack_does_not_activate"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem late_commit_ack_cannot_bypass_new_fence","declaration":"Weaver.ProviderRpc.RequestWriteFence.late_commit_ack_cannot_bypass_new_fence"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider[(]"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn zero_trust_final_use_requires_durable_claim_and_shared_exposure"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run individualHoldOnlyCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem shared_provider_exposure_cannot_be_released"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem provider_exposure_strengthens_continuing_zero_trust"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerEnqueueBeforeCommitCrashCannotReplayPendingRange"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerCancellationAndReconnectRetainHistory"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run enqueueThenLostCommitRetainsUnknownTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem transport_history_preserves_original_hold"},{"file":"go/dev/provider_grpc_test.go","pattern":"func TestProviderPartialRequestAndRestartRetainUnknownClaim"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run unknownRefundCounterexampleTest"}]},{"id":"ReservedAuthorityAdmission","witnesses":[{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem usage_control_keeps_current_consumption"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run recoveryDoesNotRefreshUsageEvidenceTest"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run allowWithoutCurrentUsageEvidenceCounterexampleTest"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem pending_policy_blocks_ongoing_use"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn final_release_keeps_current_guard_and_unknown_commit_in_one_transaction"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem retained_parent_and_selected_object_reach_gateway"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run childOnlyPredicateDropsParentCounterexampleTest"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem gateway_specialization_retains_generic_framework"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem continuing_uses_current_state_and_original_consumption"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerRevocationRestartAndRestoredPolicyCannotReopen"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem capacity_cannot_rebase_changed_floor"},{"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn waiting_capacity_does_not_hold_sql_or_authorize_after_publication"},{"file":"crates/server/tests/unit/output_backpressure.rs","pattern":"async fn pending_range_history_created_during_capacity_wait_cannot_be_replayed"},{"file":"go/dev/provider_backpressure_test.go","pattern":"func TestProviderSlowConsumerPositiveControlCompletesAfterCapacityReturns"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run returnedCapacityDoesNotAuthorizeStaleReleaseTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_backpressure_composition"},{"file":"crates/server/tests/unit/admission.rs","pattern":"async fn saturated_detached_execution_preserves_publication_and_observation_custody"},{"file":"go/dev/provider_capacity_test.go","pattern":"func TestProviderSaturatedExecutionPreservesRevocationAndObservation"},{"file":"dev/proofs/quint/AuthorityAdmission.qnt","pattern":"run sharedLaneStarvationCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem execution_and_admission_composition"}]},{"id":"ConnectionCustodyBound","witnesses":[{"file":"crates/server/tests/unit/connections.rs","pattern":"async fn tcp_socket_owns_capacity_until_destruction_and_preserves_io_and_peer_identity"},{"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderPreTLSConnectionsAreBoundedAndExpire"},{"file":"go/dev/provider_connections_test.go","pattern":"func TestProviderShutdownDestroysStalledTLSBeforeAcknowledgingExit"},{"file":"dev/proofs/quint/ConnectionAdmission.qnt","pattern":"run earlyReturnCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem provider_and_connection_composition"}]},{"id":"SourceIngressBinding","witnesses":[{"file":"go/dev/provider_source_test.go","pattern":"func TestProviderSourceIngressBindsCertificateCredentialAndMethod"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledCatalogRequiresExactSourceEpoch"},{"file":"go/dev/provider_capacity_test.go","pattern":"full operation ingress blocked new source session"},{"file":"crates/server/tests/unit/grpc_ingress.rs","pattern":"async fn aliased_or_empty_source_identity_is_rejected_before_serving"},{"file":"dev/proofs/quint/SourceIngress.qnt","pattern":"run forwardedCredentialCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem ingress_step_preserves_independent_custody"}]},{"id":"DurablePublicationDecision","witnesses":[{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn outcome_insert_failure_rolls_back_policy_schema_and_result_together"},{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn concurrent_same_identity_commits_only_one_revision"},{"file":"go/dev/publication_recovery_test.go","pattern":"func TestProviderPublicationLostReplyRestartAndHistoricalDecision"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run deletedOutcomeCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_and_provider_accounting_composition"}]},{"id":"OwnedSourceConnection","witnesses":[{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn cancelled_priority_wait_does_not_send_a_source_command"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn source_rotation_commits_before_queued_catalog_reads_recheck_identity"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run newCommandCanPrecedeOldReplyTest"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn completed_source_acknowledgment_returns_command_capacity"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run replyBeforeCapacityCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem command_ack_requires_returned_capacity"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn reused_source_connection_observes_other_writer_and_preserves_historical_result"},{"file":"crates/server/tests/unit/source_owner.rs","pattern":"async fn disconnected_source_caller_keeps_capacity_until_original_sql_work_finishes"},{"file":"crates/ledger/tests/unit/publication.rs","pattern":"fn connection_reuse_rejects_an_unresolved_explicit_transaction"},{"file":"dev/proofs/quint/SourceOwner.qnt","pattern":"run swallowedCloseErrorCounterexampleTest"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem owned_worker_and_publication_composition"}]},{"id":"FinalInvocationCancellation","witnesses":[{"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn cancellation_during_sql_wait_blocks_transport_and_keeps_spent_claim"},{"file":"crates/broker/tests/unit/provider_dispatch.rs","pattern":"fn uncancelled_control_reaches_real_https_transport_once"},{"file":"dev/proofs/quint/DispatchCancellation.qnt","pattern":"run skippedRecheckCounterexampleTest"},{"file":"dev/proofs/quint/ProviderRpc.qnt","pattern":"run missingFinalCancellationCheckCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem cancellation_and_original_hold_composition"}]},{"id":"OriginalReleaseCapability","witnesses":[{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityBudgetHistoryChangeInvalidatesReleaseReadTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem original_plan_survives_batching"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn equal_batch_digests_cannot_transfer_release_between_original_nodes"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn release_encoding_cannot_change_after_preparation"},{"file":"crates/ledger/tests/unit/provider_properties.rs","pattern":"fn release_capabilities_bind_plan_encoding_and_restart_session"},{"file":"dev/proofs/quint/ReleaseBinding.qnt","pattern":"run crossPlanCounterexampleTest"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem release_binding_and_execution_composition"}]},{"id":"SpecificSourceContracts","witnesses":[{"file":"crates/server/src/single_provider.rs","pattern":"bound: BoundSource"},{"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run governanceCannotReplaceGovernorTest"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run missingGovernorCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_cannot_replace_governor","declaration":"Weaver.PolicyBridge.governance_cannot_replace_governor"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governor_cannot_replace_governance","declaration":"Weaver.PolicyBridge.governor_cannot_replace_governance"},{"file":"scheme/governance/types.ss","pattern":"def GovernanceScopeContract\\s+\\(\\.cc \\(Record"},{"file":"scheme/gateway/contracts.ss","pattern":"def GatewayArtifact"},{"file":"t/gateway-contracts-test.ss","pattern":"def gateway-contracts-test"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityUncompiledSourceCannotRegisterTest"},{"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"},{"file":"t/gateway-contracts-test.ss","pattern":"module scopes use native POO Types and refuse evidence protocol hooks"}]},{"id":"GovernancePolicyProjection","witnesses":[{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrApprovalCannotOutliveExposureProjectionRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run mrrCommitReplyLossAndReplayCannotMintAnotherTicketTest"},{"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn candidate_only_replay_cannot_register_for_a_real_predecessor"},{"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn replay_cannot_substitute_the_captured_predecessor"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem matched_replay_preserves_both_images"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run exactReplayPairSurvivesLostReplyAndCommitsOriginalTest"},{"file":"crates/ledger/tests/unit/source_authority.rs","pattern":"fn source_handoffs_and_old_workers_preserve_original_unknown_budget"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn consistent_whole_store_rollback_remains_a_local_authority_counterexample"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn residual_policy_schema_cannot_be_treated_as_an_empty_store_after_restart"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn first_enrollment_uses_all_durable_tables_without_temporary_aliases"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn committed_writer_before_enrollment_cannot_be_hidden_by_an_old_empty_read"},{"file":"crates/ledger/tests/unit/source_authority_storage.rs","pattern":"fn callback_failure_after_enrollment_does_not_allow_a_replacement_identity"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem complete_catalog_refusal_preserves_original_state"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem source_enrollment_refusal_preserves_unknown_accounting"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run omittedProjectionEnrollmentCounterexampleTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateCatalogCommitMustReachDecidingGuardTest"},{"file":"go/dev/provider_source_authority_test.go","pattern":"func TestProviderPersistentSourceRotationLostReplyFencesExistingWorkerAndReissuedKey"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem retired_source_key_cannot_become_fresh"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem recovery_preserves_source_key_uniqueness"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run burnWithoutRetainedConfirmationCannotAdmitTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run cachedQualificationCannotAdmitWithZeroHeldProjectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run repairedProjectionDoesNotRecreateLostSendHandleTest"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_reply_loss_and_gateway_restore_do_not_release_exposure"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_admission_prefix_failure_atomically_rolls_back_burn"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_prefix_without_burn_projection_cannot_repeat_admission"},{"file":"crates/ledger/tests/unit/retained_admission.rs","pattern":"fn retained_burn_fenced_before_callback_keeps_original_unknown_exposure"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run confirmedRevocationAndHandoffRejectConsistentSourceRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run retainedRegistrationCannotReplaceAfterSnapshotRollbackTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run sameLengthArtifactReplacementCannotConfirmRetainedPrefixTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run wholeRetainedRootRollbackCanReplayQualificationCounterexampleTest"},{"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn identical_prefix_after_whole_store_restore_can_replay_dispatch_counterexample"},{"file":"crates/ledger/tests/unit/commit_floor.rs","pattern":"fn prefix_qualification_does_not_reconstruct_rolled_back_budget_counterexample"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run copiedRowsWithoutRecoveryQualificationCannotPublishTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateQualificationAfterRegistryAppendIsRefusedTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run recoveredNewOwnerRequalifiesOriginalArtifactTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run consistentAuthorityRollbackCanReplaySavedQualificationCounterexampleTest"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn stale_registry_read_and_reopened_worker_preserve_unknown_provider_exposure"},{"file":"crates/policy/tests/unit/publication_replay.rs","pattern":"fn text_rendering_cannot_silently_replace_original_policy_ids"},{"file":"crates/ledger/tests/unit/publication_replay.rs","pattern":"fn actual_spec_replay_registration_persists_before_original_final_cas"},{"file":"go/dev/provider_policy_json_test.go","pattern":"func TestProviderControlNamedPolicyJSONRevocationAndRestart"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem finite_replay_does_not_certify_no_gain"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run observerRestartCannotRestoreReadCapabilityTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run lateRegistryReceiptAfterHandoffIsHistoricalTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run independentSnapshotRollbackResurrectsCredentialCounterexampleTest"},{"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn losing_verifier_metadata_cannot_downgrade_a_committed_served_profile"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem missing_verifier_cannot_downgrade"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run missingVerifierCannotDowngradeAfterRestartTest"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureComposition"},{"file":"go/internal/devrunner/spec_proof_integration_test.go","pattern":"func TestSPECProofClosureRejectsFalseArithmetic"},{"file":"dev/proofs/cedar/SpecProofClosure.lean","pattern":"def proveClosedArithmetic"},{"file":"prod/policies/provider/ProviderReview.lean","pattern":"def entry"},{"file":"go/internal/specreview/producer.go","pattern":"Issue"},{"file":"crates/policy/src/qualified_delta.rs","pattern":"pub fn verify_qualified_delta"},{"file":"go/dev/provider_spec_review_test.go","pattern":"func TestProviderRealSPECReviewRevocationLostRepliesAndRestart"},{"file":"crates/ledger/tests/unit/reviewed_head.rs","pattern":"fn historical_signature_only_nogain_is_not_semantic_qualification"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run signatureOnlyGainCounterexampleTest"},{"file":"dev/proofs/cedar/QualifiedReview.lean","pattern":"theorem qualified_execution_and_recovery_preserve_original","declaration":"Weaver.QualifiedReview.qualified_execution_and_recovery_preserve_original"},{"file":"crates/ledger/src/delta_registration.rs","pattern":"fn require_current"},{"file":"crates/ledger/src/reviewed_head.rs","pattern":"fn require"},{"file":"go/dev/provider_review_test.go","pattern":"func TestProviderReviewedPublicationLostRepliesAndRestart"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem reviewed_commit_composes_with_original_recovery"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run producerSignatureCannotReplaceQualificationTest"},{"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn consistent_snapshot_rollback_can_replace_local_registered_artifact_counterexample"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceLateCommitReplyAfterRotationRemainsHistorical"},{"file":"crates/ledger/tests/unit/publication_review.rs","pattern":"fn reviewed_prefixes_match_an_independent_model"},{"file":"crates/ledger/tests/unit/publication_review_storage.rs","pattern":"fn stage_review_requirement_and_legacy_final_cas_have_one_serial_order"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_registration_recovery_composes_without_releasing_unknown"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run latchedReviewCannotUseLegacyPublicationTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run configurationImageCannotErasePersistentRevocationTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registryAppendBetweenReadAndCASRequiresRejoinTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRollbackLostReplyRetainsUnknownConsumption"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem registrar_binding_reaches_final_cas"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run revocationBetweenValidationAndFinalCASTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run delayedIssuanceDecisionCannotReactivateOldEpochTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateRotationRecoversLostReplyAndPending"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceCertificateConfigRollbackReacceptsOldKeyCounterexample"},{"file":"dev/proofs/lean/PublicationRecovery.lean","pattern":"theorem review_recovery_keeps_original_constraints"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem durable_review_binding_survives_final_cas"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run registrationLostReplyCannotPublishUnrecoveredProjectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run oldRegistrarCannotPublishAlreadyRegisteredArtifactTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderStagingLostReplyRetainsConcurrentPendingAcrossRestart"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderSourceRoleCredentialIsNotRegistrarIncarnationEvidence"},{"file":"dev/proofs/cedar/ZeroTrustEnrichment.lean","pattern":"theorem reviewed_publication_keeps_recovery_contract"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run substitutedArtifactGetsOriginalRejectionTest"},{"file":"dev/proofs/quint/PublicationRecovery.qnt","pattern":"run crossStoreReviewRollbackCounterexampleTest"},{"file":"go/dev/provider_policy_pending_test.go","pattern":"func TestProviderPendingCommandSubstitutionAndHistoricalRecovery"},{"file":"crates/ledger/tests/unit/provider.rs","pattern":"fn typed_publication_does_not_yet_require_delta_evidence"},{"file":"scheme/policy/func.ss","pattern":"project-policy profile"},{"file":"scheme/policy/assets.ss","pattern":"read-policy-assets profile"},{"file":"t/policy-projection-test.ss","pattern":"Governance Cedar projection"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"}]},{"id":"CompiledSourceStartup","witnesses":[{"file":"scheme/gateway/compiled.ss","pattern":"weaver_governance_ready_v1"},{"file":"crates/governance-build/src/application.rs","pattern":"pub fn approved"},{"file":"build.ss","pattern":"approved application root mismatch"},{"file":"crates/governance/src/program/compiler.rs","pattern":"pub fn initialize"},{"file":"crates/governance/src/catalog/configuration.rs","pattern":"pub fn from_configuration"},{"file":"crates/server/src/governance_deployment.rs","pattern":"async fn start_compiler"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRequiresRealInstallation"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"metadataAsInitializationCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem graph_membership_cannot_replace_initialization"}]},{"id":"GovernorSourceHandoff","witnesses":[{"file":"scheme/gateway/types.ss","pattern":"def GatewayProgram"},{"file":"scheme/gateway/program.ss","pattern":"def \\(make-gateway-program"},{"file":"t/gateway-source-test.ss","pattern":"program installation and close follow an irreversible lifecycle"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"caughtReentryPoisonsOuterDeliveryTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem program_result_composes_with_registered_original"},{"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"},{"file":"go/internal/controlplane/deployment_source_test.go","pattern":"func FuzzDeploymentSourceHasOneOwner"},{"file":"go/internal/controlplane/producer_deployment_test.go","pattern":"func exerciseProducerDeployment"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"deploymentCannotFallBackToFileTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem producer_deployment_keeps_registered_original"},{"file":"crates/server/src/grpc.rs","pattern":"async fn compile_source"},{"file":"go/internal/controlplane/source_compile.go","pattern":"func BootstrapProducer"},{"file":"go/internal/controlplane/approved_source_rpc_test.go","pattern":"func TestApprovedSourceMTLSBootstrap"},{"file":"go/internal/config/freeze_test.go","pattern":"func FuzzFrozenSourceDoesNotFollowCallerMutation"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem compilation_reply_keeps_registered_original"},{"file":"crates/governance/src/catalog/admission.rs","pattern":"pub struct ProducerCatalog"},{"file":"crates/governance/src/catalog/client.rs","pattern":"pub fn submit"},{"file":"crates/governance/tests/unit/catalog.rs","pattern":"changed_source_observations_and_fresh_names_cannot_select_original"},{"file":"crates/server/src/governance_owner.rs","pattern":"pub fn publish_producers"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"oldCatalogObservationStillCannotPublishThroughNewFenceTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"producer_selection_keeps_all_original_fields"},{"file":"crates/server/src/governance_owner.rs","pattern":"pub async fn start_governance"},{"file":"crates/server/src/grpc.rs","pattern":"pub async fn serve_grpc_with_runtime"},{"file":"crates/server/tests/unit/governance_owner.rs","pattern":"shared_owner_schedules_preserve_cleanup_and_terminal_admission"},{"file":"crates/server/tests/integration/governance_owner.rs","pattern":"actual_scheme_vm_is_owner_local_and_cleanup_precedes_shared_drain"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"lateFactoryActivationCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_owner_join_preserves_cleanup"},{"file":"crates/governance/src/scheme_input/records.rs","pattern":"pub fn root_source"},{"file":"crates/governance/src/scheme_input/values.rs","pattern":"fn bytes"},{"file":"crates/governance/src/host/client.rs","pattern":"pub fn source_lane"},{"file":"crates/governance/src/host/owner.rs","pattern":"pub fn run"},{"file":"crates/governance/tests/unit/host.rs","pattern":"cancelled_running_work_keeps_its_slot_until_natural_return"},{"file":"crates/governance/tests/unit/host.rs","pattern":"active_compiler_observes_both_request_and_owner_cancellation"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSourceCancellationDrainsSchemeOwner"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"checkThenSendCloseRaceCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"source_host_delivery_requires_open_gate"},{"file":"crates/governance/src/binding.rs","pattern":"pub struct SourceExpectation"},{"file":"crates/governance/tests/unit/binding.rs","pattern":"coherent_replacements_cannot_change_original_content"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"unsafeSelfConsistentReplacementWitness"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"coherent_replacement_cannot_redefine_original"},{"file":"crates/governance/build.rs","pattern":"run_package_main"},{"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeQualificationStaysWithPreparedSchemeOwner"},{"file":"t/gateway-source-test.ss","pattern":"SDK field symbols and identifier strings cannot be interchanged"},{"file":"crates/governance/src/scheme.rs","pattern":"pub fn materialize_source"},{"file":"crates/governance/tests/integration/scheme_vm.rs","pattern":"actual_aa_capture_materializes_owned_data_before_vm_cleanup"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run unsafeEncodedBlobWitness"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem encoded_blob_cannot_claim_typed_capture"},{"file":"scheme/gateway/capture.ss","pattern":"Gateway capture requires one source emission"},{"file":"scheme/gateway/func.ss","pattern":"def \\(capture-governed-gateway"},{"file":"t/gateway-source-test.ss","pattern":"native PBT requires one completed emission"},{"file":"t/gateway-source-test.ss","pattern":"a late inherited sink cannot replace an active next capture"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run ignoredCaptureFuseCounterexampleTest"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem caught_duplicate_cannot_clear_capture_fuse"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"},{"file":"scheme/governance/capture.ss","pattern":"def \\(governance-profile-snapshot"},{"file":"t/governance-test.ss","pattern":"native PBT preserves every original assessment binding"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_assessment_snapshot_cannot_reuse_boundary"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run coordinatedLiveProfileLabelsCannotReplaceOriginalCaptureTest"},{"file":"scheme/gateway/func.ss","pattern":"assq 'open-patterns"},{"file":"t/gateway-source-test.ss","pattern":"upstream Governor selection cannot be replaced by a Governance callback"},{"file":"scheme/governance/types.ss","pattern":"def GovernanceAssessmentContext"},{"file":"scheme/gateway/func.ss","pattern":"same-node-set?"},{"file":"t/gateway-source-test.ss","pattern":"a false Governance assessment cannot emit a source handoff"},{"file":"t/governance-test.ss","pattern":"a typed ready assessment cannot omit an original blocking threat"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityChangedCompiledSourceCannotRecoverTest"},{"file":"scheme/policy/func.ss","pattern":"project-policy profile"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem governance_projection_and_actual_request_require_error_free_allow"},{"file":"t/integration/governed-control-test.ss","pattern":"def governed-control-test"},{"file":"go/internal/config/bundle_test.go","pattern":"func TestBundleRejectsSelectionAndCommitmentSubstitution"}]},{"id":"SourceStartupObservation","witnesses":[{"file":"scheme/gateway/provider-program.ss","pattern":"call-with-module-source-operation-measurement"},{"file":"go/internal/devrunner/scheme_tools_test.go","pattern":"func TestSchemeVerificationUsesOnlyPublicPackageEntries"},{"file":"crates/governance-build/src/program.rs","pattern":"build_program_archive_with_contract"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run releaseTagCannotRebaseCapturedSourceCounterexampleTest"},{"file":"go/internal/devrunner/retention_test.go","pattern":"func TestSchemePreparationFailureKeepsOriginalCutWithoutAmbientReceipt"},{"file":"go/internal/devrunner/retention_test.go","pattern":"func TestLateCleanupFailureCannotRetainPassingReceipt"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem changed_preparation_cut_cannot_rebase_boundary","declaration":"Weaver.PolicyBridge.changed_preparation_cut_cannot_rebase_boundary"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run changedPackageMetadataCannotRebaseSnapshotTest"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run stalePreparationReceiptCounterexampleTest"},{"file":"go/internal/controlplane/deployment_source.go","pattern":"func selectDeploymentSource"},{"file":"go/internal/controlplane/deployment.go","pattern":"trace\\(\"authority-reconciled\"\\)"},{"file":"scheme/gateway/func.ss","pattern":"source-selection-loaded"},{"file":"scheme/gateway/func.ss","pattern":"source-module-view-loaded"},{"file":"scheme/gateway/func.ss","pattern":"source-contracts-checked"},{"file":"scheme/gateway/func.ss","pattern":"source-advisory-derived"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"status=failed drain_ns"},{"file":"crates/governance/src/host/owner.rs","pattern":"scheme-owner-drop-begin"},{"file":"t/fixtures/governed-control.ss","pattern":"fixture-module-ready"},{"file":"go/dev/provider_control_test.go","pattern":"These unauthenticated diagnostics never replace readiness or exit checks"},{"file":"crates/governance-build/src/tooling.rs","pattern":"fn bind_package_sources"},{"file":"crates/governance-build/tests/unit/package_sources.rs","pattern":"fn native_package_inputs_follow_the_selected_store_without_overwriting_sources"}]},{"id":"PolicyCAbiIsInert","witnesses":[{"file":"scheme/policy/func.ss","pattern":"def \\(validate-policy-projection!"},{"file":"scheme/gateway/func.ss","pattern":"validate-policy-projection! projection"},{"file":"t/policy-test.ss","pattern":"real Rust preflight refuses cross-document syntax assembly"},{"file":"t/policy-projection-test.ss","pattern":"every named document precedes aggregate validation"},{"file":"crates/policy-ffi/tests/unit/validation.rs","pattern":"fn aggregate_validity_does_not_establish_complete_source_documents"},{"file":"crates/policy/tests/unit/decisions.rs","pattern":"fn default_deny_forbid_and_evaluation_error_are_fail_closed"},{"file":"dev/proofs/cedar/WeaverPolicyBridge.lean","pattern":"theorem incomplete_policy_document_cannot_admit"},{"file":"dev/proofs/quint/LlmPolicyContinuation.qnt","pattern":"run aggregateOnlyPolicyValidationCounterexampleTest"},{"file":"scheme/policy/source-bytes.ss","pattern":"def \\(cedar-source-utf8"},{"file":"t/policy-test.ss","pattern":"native PBT checks Unicode source bounds before the C ABI"},{"file":"crates/policy-ffi/tests/unit/abi.rs","pattern":"fn unicode_byte_limits_apply_to_each_actual_abi_region"},{"file":"crates/policy-ffi/src/abi.rs","pattern":"pub unsafe extern \"C\" fn weaver_policy_validate_v1"},{"file":"scheme/policy/cedar-ffi.ss","pattern":"def-C-lambda policy-validate/raw"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authoritySourceCommitNeverSendsTest"}]},{"id":"ControlActivationAcknowledgment","witnesses":[{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsStagingReplyLossAndRestart"},{"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlPublicationReplyLossCannotActivateOrRebase"},{"file":"dev/proofs/quint/AuthorityPublication.qnt","pattern":"run authorityLostReplyCannotActivateTest"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPublicationReplyLossAndRestart"}]},{"id":"ControlStreamRecoveryBinding","witnesses":[{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledAssetsPartialRequestAndRestart"},{"file":"go/dev/provider_control_test.go","pattern":"func TestProviderControlCompleteStreamsShareBudgetAndRejectSDKRetry"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlCompiledProgramRevocationAndRestart"},{"file":"dev/proofs/lean/ProviderRpc.lean","pattern":"theorem profile_recovery_retains_original_hold"}]},{"id":"WorkspaceBenchmarkCoverage","witnesses":[{"file":"go/internal/devrunner/benchmark_test.go","pattern":"func TestBenchmarkEvidenceRequiresEveryCase"},{"file":"go/dev/workspace_test.go","pattern":"func TestCargoWorkspaceAndDevelopmentGates"},{"file":"crates/broker/benches/gateway.rs","pattern":"fn guarded_provider"},{"file":"go/dev/provider_bench_test.go","pattern":"func BenchmarkGatewayInspect"}]},{"id":"DurableRangeProgressJoin","witnesses":[{"file":"crates/ledger/src/stream_progress.rs","pattern":"fn message"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_message_cursor_cannot_hide_consumed_range"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn restored_progress_cannot_release_old_writer_or_connection"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run restoredUnknownProjectionBlocksAdmissionTest"},{"file":"dev/proofs/quint/StreamingExecution.qnt","pattern":"run unknownResetDuplicatesRangeCounterexampleTest"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem unresolved_tail_blocks_admission","declaration":"Weaver.StreamingExecution.RangeProgress.unresolved_tail_blocks_admission"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem changed_progress_cannot_execute","declaration":"Weaver.StreamingExecution.RangeProgress.changed_progress_cannot_execute"},{"file":"dev/proofs/lean/StreamingExecution.lean","pattern":"theorem joined_execution_preserves_safety","declaration":"Weaver.StreamingExecution.RangeProgress.joined_execution_preserves_safety"}]},{"id":"TursoAdmissionAtomicity","witnesses":[{"file":"crates/ledger/src/persistence/scope.rs","pattern":"pub fn begin"},{"file":"crates/ledger/src/exposure_manifest.rs","pattern":"fn verified_members"},{"file":"crates/ledger/tests/unit/persistence_transactions.rs","pattern":"fn failed_commit_releases_writer_and_poisoned_session_cannot_reenter"},{"file":"crates/ledger/tests/unit/execution_exposure.rs","pattern":"fn duplicate_claim_members_cannot_be_normalized_out_of_recovery"},{"file":"go/dev/workspace_test.go","pattern":"func TestProjectArchitectureStorageUsesMRRDataTursoOnly"},{"file":"dev/proofs/quint/TursoAdmission.qnt","pattern":"run tornCommitRefundCounterexampleTest"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem storage_step_retains_admission_safety","declaration":"Weaver.RuntimeAdmission.Persistence.storage_step_retains_admission_safety"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem committed_consume_survives_reply_loss_and_restart","declaration":"Weaver.RuntimeAdmission.Persistence.committed_consume_survives_reply_loss_and_restart"},{"file":"dev/proofs/lean/RuntimeAdmission.lean","pattern":"theorem commit_itself_does_not_send","declaration":"Weaver.RuntimeAdmission.Persistence.commit_itself_does_not_send"}]},{"id":"BoundedAdvisoryDerivation","witnesses":[{"file":"scheme/gateway/derivation.ss","pattern":"def \\(make-gateway-derivation"},{"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-gateway"},{"file":"t/gateway-derivation-test.ss","pattern":"generated source replacements agree with graph traversal and fresh results"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run derivedAdviceCannotChangeImageOrSpendTest"},{"file":"dev/proofs/quint/GatewayProgram.qnt","pattern":"run adviceAsOriginalCounterexampleTest"}]},{"id":"SessionWorkflowFrontier","witnesses":[{"file":"scheme/gateway/program.ss","pattern":"def \\(hard-fact-affected"},{"file":"go/dev/provider_hard_fact_test.go","pattern":"func TestProviderControlHardFactWithdrawalRestartAndABA"},{"file":"scheme/gateway/func.ss","pattern":"def \\(session-workflow-path"},{"file":"crates/server/src/governance_deployment.rs","pattern":"admits_session_workflow"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"fn bind_winner"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn provider_workflow_rechecks_prepared_floor_and_frontier_before_one_reservation"},{"file":"crates/server/src/session_workflow.rs","pattern":"async fn run_session_workflow"},{"file":"crates/server/src/single_provider.rs","pattern":"SessionTopology::prepare"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionWorkflowAutomaticallyResumes"},{"file":"scheme/gateway/func.ss","pattern":"def \\(governor-ready-steps"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"pub fn observe_workflow"},{"file":"crates/ledger/src/persistence/scope.rs","pattern":"fn begin_workflow_observation"},{"file":"crates/governance/src/host/owner.rs","pattern":"cut_sha256=.*ready_sha256="},{"file":"crates/governance/src/program/compiler.rs","pattern":"topology_binding"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn governor_indices_reject_stale_binding_and_foreign_node"},{"file":"crates/server/src/session_workflow.rs","pattern":"DerivationOutput::Indices"},{"file":"crates/server/src/single_provider.rs","pattern":"topology.preopen"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn pack_governor_facts"},{"file":"t/gateway-governor-retained-test.ss","pattern":"packed facts are complete and bounded by the live binding"},{"file":"t/gateway-governor-retained-test.ss","pattern":"a compact cut must name the current binding"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"Governor transport %d expected"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched inner-join cut_sha256="},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"governor wave matched outer-join cut_sha256="},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSessionDAGConcurrentJoinAndRecovery"},{"file":"crates/ledger/src/provider_workflow_choice.rs","pattern":"fn record_result"},{"file":"go/dev/provider_workflow_choice_test.go","pattern":"func TestProviderControlSessionChoiceFromReleasedResult"},{"file":"crates/ledger/src/provider_workflow_nested.rs","pattern":"fn load"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"fn nested_workflow_rejects_stale_decision_and_keeps_winner_after_reopen"},{"file":"go/dev/provider_workflow_nested_test.go","pattern":"func TestProviderControlSessionNestedChoiceAndParallelRecovery"},{"file":"scheme/gateway/func.ss","pattern":"WEAVER_TEST_GOVERNOR_CHANGED_SOURCES"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"unexpected Governor source replacement"},{"file":"crates/governance/src/host/client.rs","pattern":"weaver-governor-roundtrip"},{"file":"go/dev/provider_governor_performance_test.go","pattern":"Governor roundtrip phases do not cover the call"},{"file":"crates/ledger/src/execution_exposure.rs","pattern":"fn provider_metering_with_deployment"},{"file":"crates/ledger/tests/unit/provider/workflow.rs","pattern":"a new frontier transaction must read the current deployment"},{"file":"crates/ledger/src/provider_workflow.rs","pattern":"prepare\\(tx, &proposal.predecessors, plan, current\\)"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn rooted_governor_indices_preserve_full_width_binding_and_all_64_candidates"},{"file":"scheme/gateway/func.ss","pattern":"def \\(prepare-retained-governor-program"},{"file":"t/gateway-governor-retained-test.ss","pattern":"prepared nested rules agree with full fresh snapshots under replacement"},{"file":"t/gateway-governor-retained-test.ss","pattern":"prepared nested rules preserve source budget rejection and recovery"}]},{"id":"RustSchemeRuntimeBoundary","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"RustSchemeRuntimeBoundary"}]},{"id":"CloudAdapterAuthorityBoundary","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"CloudAdapterAuthorityBoundary"},{"file":"prod/kubernetes/provideravailability.crd.yaml","pattern":"kind: ProviderAvailability"},{"file":"prod/kubernetes/provideravailability.rbac.yaml","pattern":"resources: \\[provideravailabilities/status\\]"},{"file":"crates/server/src/kubernetes.rs","pattern":"async fn reconcile\\("},{"file":"crates/ledger/src/hard_fact.rs","pattern":"pub fn inspect_fact_feed\\("},{"file":"go/dev/provider_kubernetes_test.go","pattern":"func TestProviderKubernetesAvailability\\("}]},{"id":"GoIntegrationLeverage","witnesses":[{"file":"docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org","pattern":"GoIntegrationLeverage"}]},{"id":"SchemeSourceComposition","witnesses":[{"file":"scheme/gateway/provider-source.ss","pattern":"def \\(compose-provider-configuration"},{"file":"scheme/gateway/compiled.ss","pattern":"weaver_compose_source_v1"},{"file":"crates/governance/src/program/compiler.rs","pattern":"fn composition_uses_scheme_then_rust_seals_the_exact_original"},{"file":"crates/server/src/governance_deployment.rs","pattern":"from_configuration_with"},{"file":"go/internal/controlplane/source_compile.go","pattern":"config.CloneArtifact"},{"file":"t/gateway-source-test.ss","pattern":"ASCENT routing filters modules"},{"file":"go/internal/controlplane/gateway.go","pattern":"composeSourceBundle"},{"file":"go/internal/controlplane/provider_catalog.go","pattern":"func \\(g \\*Gateway\\) composeCatalog"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderControlSchemeCompositionRevocationAndRestart"},{"file":"crates/governance/src/composition.rs","pattern":"pub fn validate_selected"},{"file":"crates/governance/tests/unit/configuration.rs","pattern":"fn source_composition_cannot_seal_a_self_consistent_scope_substitution"}]},{"id":"AdvisorySourceComposition","witnesses":[{"file":"crates/server/src/grpc.rs","pattern":"async fn compose_source"},{"file":"crates/governance/src/host/client.rs","pattern":"pub async fn compose"},{"file":"go/dev/provider_module_routing_test.go","pattern":"operation caller entered semantic composition"},{"file":"go/internal/controlplane/provider_catalog_test.go","pattern":"func TestCatalogCompositionCoalescesFourRequests"},{"file":"crates/broker/tests/unit/https_transport.rs","pattern":"fn provider_endpoint_guard_preserves_anthropic_source_path_constraints"}]},{"id":"DirectRustOperationIngress","witnesses":[{"file":"go/internal/controlplane/deployment.go","pattern":"func PrepareFromEnv"},{"file":"go/dev/controlref/main.go","pattern":"action := controlplane.PrepareFromEnv"},{"file":"crates/server/src/grpc_provider.rs","pattern":"operation_key_only"},{"file":"crates/server/src/single_provider.rs","pattern":"fn operation_plan"},{"file":"crates/server/src/provider_oauth.rs","pattern":"direct ingress cannot supply relay evidence"},{"file":"go/dev/provider_program_deployment_test.go","pattern":"func TestProviderRustDirectPreparedOperationWithoutGoRelay"}]},{"id":"SourceBoundOperationPreparation","witnesses":[{"file":"crates/contracts/src/provider_routing.rs","pattern":"pub enum ProviderOperationScope"},{"file":"crates/ledger/src/provider_routing.rs","pattern":"pub fn register_provider_source"},{"file":"crates/ledger/src/provider_routing.rs","pattern":"pub fn register_routed_task"},{"file":"crates/server/src/source_owner.rs","pattern":"struct OperationResolver"},{"file":"go/dev/provider_module_routing_test.go","pattern":"func TestProviderRustDirectCatalogSelection"},{"file":"go/dev/provider_file_preparation_test.go","pattern":"func TestProviderRustDirectFilePreparation"},{"file":"go/dev/provider_file_preparation_test.go","pattern":"func TestProviderRustDirectFixedPlanSurvivesSourceHandoff"}]}] diff --git a/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org b/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org index 222d7c96..6e1164ab 100644 --- a/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org +++ b/docs/50-59-research-program/59-provider-rpc/59.87-spec-upgrade-and-delivery-plan.org @@ -356,6 +356,7 @@ review issuer have separate key custody and consumers. R5 acceptance uses the existing =go/dev= integration entry with =TestProviderRustDirectFilePreparation=, +=TestProviderRustDirectFilePreparationLostReplies=, =TestProviderRustDirectCatalogSelection= and =TestProviderRustDirectReviewedCatalogImport=. The cases cover signed JSON and TOML-selected YAML sources, catalog replacement and guarded execution, and an @@ -366,11 +367,14 @@ coordinates. Metering application and review recovery are separate integration cases. The Go entry list and the production asset boundary verify which packages remain reachable from =weaver-meter=. -The offline import case passed against a Rust release built with =arrow,kubernetes= -and no Scheme program. The positive JSON/YAML controls matched the Go proposal. -Duplicate keys, custom YAML tags and trailing documents failed without emitting a -proposal. Scheme-backed file preparation and catalog execution are separate -release controls. +On the same Rust release built with =arrow,kubernetes= at =0fe24eb0=, the +ordinary integration suite passed signed JSON and TOML-selected YAML +preparation, staging and publication reply-loss recovery, and warm, cold and +restart lookups of an unused fixed node after publisher handoff. It also +passed independent review and metering, and the offline JSON/YAML import +matched the Go proposal. Duplicate keys, custom tags and trailing documents +failed without emitting a proposal. Compiled Scheme preparation and dynamic +catalog execution still require the Scheme release. Verification source, fixtures and acceptance commands are versioned with the implementation. Release executables and generated receipts remain local diff --git a/go/dev/provider_file_preparation_test.go b/go/dev/provider_file_preparation_test.go new file mode 100644 index 00000000..3bc3a02f --- /dev/null +++ b/go/dev/provider_file_preparation_test.go @@ -0,0 +1,224 @@ +// SPDX-FileCopyrightText: 2026 hardenedlinux Linux Team and Contributors +// +// SPDX-License-Identifier: LGPL-2.1-or-later AND Apache-2.0 + +//go:build integration && !windows + +package dev + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "io" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + "testing" + "time" + + pb "github.com/HardenedLinux/weaver/go/api/gateway/v1" + v1 "github.com/HardenedLinux/weaver/go/api/v1" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func sourceTOMLCommand(t *testing.T, control *controlProcess, command *exec.Cmd, kubernetes ...string) *exec.Cmd { + t.Helper() + settings := make(map[string]string) + environment := command.Env[:0] + for _, value := range command.Env { + name, text, _ := strings.Cut(value, "=") + if strings.HasPrefix(name, "WEAVER_CONTROL_") { + settings[name] = text + continue + } + environment = append(environment, value) + } + const tokenEnv = "WEAVER_TEST_PREPARATION_TOKEN" + var config strings.Builder + config.WriteString("[source]\n") + for _, field := range []struct{ key, env string }{ + {"producer", "WEAVER_CONTROL_PRODUCER"}, + {"file", "WEAVER_CONTROL_CONFIG"}, + {"address", "WEAVER_CONTROL_AUTHORITY_SOURCE_ADDRESS"}, + {"server_name", "WEAVER_CONTROL_AUTHORITY_SERVER_NAME"}, + {"ca", "WEAVER_CONTROL_AUTHORITY_CA"}, + {"certificate", "WEAVER_CONTROL_AUTHORITY_SOURCE_CERT"}, + {"key", "WEAVER_CONTROL_AUTHORITY_SOURCE_KEY"}, + } { + value := settings[field.env] + if (field.key == "producer" || field.key == "file") && (len(kubernetes) != 0 || value == "") { + continue + } + if field.key == "ca" || field.key == "certificate" || field.key == "key" || field.key == "file" { + var err error + value, err = filepath.Rel(control.directory, value) + if err != nil { + t.Fatal(err) + } + } + config.WriteString(field.key + " = " + strconv.Quote(value) + "\n") + } + config.WriteString("token_env = " + strconv.Quote(tokenEnv) + "\n") + for _, section := range kubernetes { + config.WriteString(section) + } + path := filepath.Join(control.directory, "weaver.toml") + if err := os.WriteFile(path, []byte(config.String()), 0600); err != nil { + t.Fatal(err) + } + command.Args = append(command.Args, "--config", path) + command.Env = append(environment, tokenEnv+"="+settings["WEAVER_CONTROL_AUTHORITY_SOURCE_TOKEN"]) + return command +} + +// File source preparation also retains exact plans for direct operation keys; +// it does not rely on the optional compiled single-provider retirement profile. +func TestProviderRustDirectFilePreparation(t *testing.T) { + for _, format := range []string{"json", "yaml"} { + t.Run(format, func(t *testing.T) { checkDirectFilePreparation(t, format) }) + } +} + +func TestProviderRustDirectFilePreparationLostReplies(t *testing.T) { + t.Run("staging", func(t *testing.T) { + exerciseSourceReplyLoss(t, nil, true, controlPolicySources{}, serverBinary) + }) + t.Run("publication", func(t *testing.T) { + exerciseSourceReplyLoss(t, nil, false, controlPolicySources{}, serverBinary) + }) +} + +func checkDirectFilePreparation(t *testing.T, format string) { + t.Helper() + f := newFixture(t, completeSSE, false) + bundle := controlBundle(t, f) + originalPolicy := bundle.Publication.Policy + bundle.Publication.Policy += ` +forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { context.family == "control" && context.node == "next" };` + control := newControlProcess(t, f, writeControlBundle(t, f, bundle, format)) + if format == "yaml" { + ctx, cancel := context.WithTimeout(t.Context(), 15*time.Second) + command := sourceTOMLCommand(t, control, control.prepareCommand(ctx, serverBinary, "prepare")) + output, err := command.CombinedOutput() + cancel() + if err != nil { + t.Fatalf("source-only preparation from TOML file: %v: %s", err, output) + } + } else { + control.prepareUsing(t, serverBinary, "prepare") + } + ctx, cancel := context.WithTimeout(t.Context(), 12*time.Second) + defer cancel() + run := func() error { + stream, err := f.client.RPC.ExecuteProvider(f.client.Context(ctx), &pb.ProviderRequest{Plan: &pb.ProviderPlan{Family: "control", Node: "infer"}, Encoding: pb.Encoding_PROTOBUF, BatchRows: 1}) + if err != nil { + return err + } + count := 0 + text := "" + for { + frame, err := stream.Recv() + if err == io.EOF { + if count != 5 || text != "hello world" { + t.Fatalf("incomplete direct file stream: count=%d text=%q", count, text) + } + return nil + } + if err != nil { + return err + } + count++ + text += frame.GetEvent().GetText() + } + } + if err := run(); err != nil { + t.Fatal(err) + } + if f.primary.Load() != 1 || control.child != nil { + t.Fatal("direct file operation path", f.primary.Load()) + } + deniedNext := func() { + stream, err := f.client.RPC.ExecuteProvider(f.client.Context(ctx), &pb.ProviderRequest{Plan: &pb.ProviderPlan{Family: "control", Node: "next"}, Encoding: pb.Encoding_PROTOBUF, BatchRows: 1}) + if err == nil { + _, err = stream.Recv() + } + if status.Code(err) != codes.FailedPrecondition || f.primary.Load() != 1 { + t.Fatalf("fixed projection used stale authority: %v", err) + } + } + deniedNext() // Warm exact immutable data while Cedar denies execution. + for index, policy := range []string{originalPolicy, bundle.Publication.Policy} { + publication := bundle.Publication.Clone() + revision := uint64(index + 1) + publication.OperationID = "fixed-policy-" + strconv.Itoa(index) + publication.ExpectedRevision = &revision + publication.Fence = uint64(index + 2) + publication.Policy = policy + if _, err := f.admin.Publish(ctx, publication); err != nil { + t.Fatal(err) + } + deniedNext() // Even newly allowing Cedar cannot rebase the old plan. + } + f.stop(t) + f.start(t) + if err := run(); err == nil || f.primary.Load() != 1 { + t.Fatal("restart replayed file original", err) + } +} + +func TestProviderRustDirectFixedPlanSurvivesSourceHandoff(t *testing.T) { + for _, mode := range []string{"warm", "cold", "restart"} { + t.Run(mode, func(t *testing.T) { + f := newFixture(t, completeSSE, false) + bundle := controlBundle(t, f) + newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")).prepareUsing(t, serverBinary, "prepare") + ctx, cancel := context.WithTimeout(t.Context(), 12*time.Second) + defer cancel() + call := func(catalog string) error { + stream, err := f.client.RPC.ExecuteProvider(f.client.Context(ctx), &pb.ProviderRequest{ + Plan: &pb.ProviderPlan{Family: "control", Node: "next"}, BatchRows: 1, CatalogVersion: catalog, + }) + if err != nil { + return err + } + for { + frame, err := stream.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + if frame.GetEvent() == nil { + t.Fatal("expected protobuf event") + } + } + } + if mode == "warm" { + // Resolve the original while rejecting the caller's catalog precondition. + if err := call(strings.Repeat("a", 64)); status.Code(err) != codes.FailedPrecondition || f.primary.Load() != 0 { + t.Fatalf("catalog precondition consumed fixed plan: %v", err) + } + } + next := secondaryClient(t, f.pki) + token := sha256.Sum256([]byte(f.admin.Token)) + rotation := v1.SourceRotation{OperationID: "fixed-source-handoff", ExpectedEpoch: 0, NextCertificate: next.Certificate[0], NextCredentialSHA256: hex.EncodeToString(token[:])} + if receipt, err := f.admin.RotateSource(ctx, rotation); err != nil || receipt.GetAuthority().GetEpoch() != 1 { + t.Fatalf("source handoff: %v %v", receipt, err) + } + if _, err := f.admin.SourceAuthority(ctx); status.Code(err) != codes.PermissionDenied { + t.Fatalf("retired source retained mutation identity: %v", err) + } + if mode == "restart" { + restartWithSourceCertificate(t, f, next) + } + if err := call(""); err != nil || f.primary.Load() != 1 || f.backup.Load() != 0 { + t.Fatalf("fixed publication changed after source handoff: sends=%d error=%v", f.primary.Load(), err) + } + }) + } +} diff --git a/go/dev/provider_program_deployment_test.go b/go/dev/provider_program_deployment_test.go index d7c19d85..de2f1c24 100644 --- a/go/dev/provider_program_deployment_test.go +++ b/go/dev/provider_program_deployment_test.go @@ -942,192 +942,3 @@ func checkDirectPreparedOperation(t *testing.T, preparationImage string, useTOML t.Fatal("restart replayed completed original", err) } } - -func sourceTOMLCommand(t *testing.T, control *controlProcess, command *exec.Cmd, kubernetes ...string) *exec.Cmd { - t.Helper() - settings := make(map[string]string) - environment := command.Env[:0] - for _, value := range command.Env { - name, text, _ := strings.Cut(value, "=") - if strings.HasPrefix(name, "WEAVER_CONTROL_") { - settings[name] = text - continue - } - environment = append(environment, value) - } - const tokenEnv = "WEAVER_TEST_PREPARATION_TOKEN" - var config strings.Builder - config.WriteString("[source]\n") - for _, field := range []struct{ key, env string }{ - {"producer", "WEAVER_CONTROL_PRODUCER"}, - {"file", "WEAVER_CONTROL_CONFIG"}, - {"address", "WEAVER_CONTROL_AUTHORITY_SOURCE_ADDRESS"}, - {"server_name", "WEAVER_CONTROL_AUTHORITY_SERVER_NAME"}, - {"ca", "WEAVER_CONTROL_AUTHORITY_CA"}, - {"certificate", "WEAVER_CONTROL_AUTHORITY_SOURCE_CERT"}, - {"key", "WEAVER_CONTROL_AUTHORITY_SOURCE_KEY"}, - } { - value := settings[field.env] - if (field.key == "producer" || field.key == "file") && (len(kubernetes) != 0 || value == "") { - continue - } - if field.key == "ca" || field.key == "certificate" || field.key == "key" || field.key == "file" { - var err error - value, err = filepath.Rel(control.directory, value) - if err != nil { - t.Fatal(err) - } - } - config.WriteString(field.key + " = " + strconv.Quote(value) + "\n") - } - config.WriteString("token_env = " + strconv.Quote(tokenEnv) + "\n") - for _, section := range kubernetes { - config.WriteString(section) - } - path := filepath.Join(control.directory, "weaver.toml") - if err := os.WriteFile(path, []byte(config.String()), 0600); err != nil { - t.Fatal(err) - } - command.Args = append(command.Args, "--config", path) - command.Env = append(environment, tokenEnv+"="+settings["WEAVER_CONTROL_AUTHORITY_SOURCE_TOKEN"]) - return command -} - -// File source preparation also retains exact plans for direct operation keys; -// it does not rely on the optional compiled single-provider retirement profile. -func TestProviderRustDirectFilePreparation(t *testing.T) { - for _, format := range []string{"json", "yaml"} { - t.Run(format, func(t *testing.T) { checkDirectFilePreparation(t, format) }) - } -} - -func checkDirectFilePreparation(t *testing.T, format string) { - t.Helper() - f := newFixture(t, completeSSE, false) - bundle := controlBundle(t, f) - originalPolicy := bundle.Publication.Policy - bundle.Publication.Policy += ` -forbid(principal, action == Weaver::Action::"invokeProvider", resource) when { context.family == "control" && context.node == "next" };` - control := newControlProcess(t, f, writeControlBundle(t, f, bundle, format)) - if format == "yaml" { - ctx, cancel := context.WithTimeout(t.Context(), 15*time.Second) - command := sourceTOMLCommand(t, control, control.prepareCommand(ctx, serverBinary, "prepare")) - output, err := command.CombinedOutput() - cancel() - if err != nil { - t.Fatalf("source-only preparation from TOML file: %v: %s", err, output) - } - } else { - control.prepareUsing(t, serverBinary, "prepare") - } - ctx, cancel := context.WithTimeout(t.Context(), 12*time.Second) - defer cancel() - run := func() error { - stream, err := f.client.RPC.ExecuteProvider(f.client.Context(ctx), &pb.ProviderRequest{Plan: &pb.ProviderPlan{Family: "control", Node: "infer"}, Encoding: pb.Encoding_PROTOBUF, BatchRows: 1}) - if err != nil { - return err - } - count := 0 - text := "" - for { - frame, err := stream.Recv() - if err == io.EOF { - if count != 5 || text != "hello world" { - t.Fatalf("incomplete direct file stream: count=%d text=%q", count, text) - } - return nil - } - if err != nil { - return err - } - count++ - text += frame.GetEvent().GetText() - } - } - if err := run(); err != nil { - t.Fatal(err) - } - if f.primary.Load() != 1 || control.child != nil { - t.Fatal("direct file operation path", f.primary.Load()) - } - deniedNext := func() { - stream, err := f.client.RPC.ExecuteProvider(f.client.Context(ctx), &pb.ProviderRequest{Plan: &pb.ProviderPlan{Family: "control", Node: "next"}, Encoding: pb.Encoding_PROTOBUF, BatchRows: 1}) - if err == nil { - _, err = stream.Recv() - } - if status.Code(err) != codes.FailedPrecondition || f.primary.Load() != 1 { - t.Fatalf("fixed projection used stale authority: %v", err) - } - } - deniedNext() // Warm exact immutable data while Cedar denies execution. - for index, policy := range []string{originalPolicy, bundle.Publication.Policy} { - publication := bundle.Publication.Clone() - revision := uint64(index + 1) - publication.OperationID = "fixed-policy-" + strconv.Itoa(index) - publication.ExpectedRevision = &revision - publication.Fence = uint64(index + 2) - publication.Policy = policy - if _, err := f.admin.Publish(ctx, publication); err != nil { - t.Fatal(err) - } - deniedNext() // Even newly allowing Cedar cannot rebase the old plan. - } - f.stop(t) - f.start(t) - if err := run(); err == nil || f.primary.Load() != 1 { - t.Fatal("restart replayed file original", err) - } -} - -func TestProviderRustDirectFixedPlanSurvivesSourceHandoff(t *testing.T) { - for _, mode := range []string{"warm", "cold", "restart"} { - t.Run(mode, func(t *testing.T) { - f := newFixture(t, completeSSE, false) - bundle := controlBundle(t, f) - newControlProcess(t, f, writeControlBundle(t, f, bundle, "json")).prepare(t) - ctx, cancel := context.WithTimeout(t.Context(), 12*time.Second) - defer cancel() - call := func(catalog string) error { - stream, err := f.client.RPC.ExecuteProvider(f.client.Context(ctx), &pb.ProviderRequest{ - Plan: &pb.ProviderPlan{Family: "control", Node: "next"}, BatchRows: 1, CatalogVersion: catalog, - }) - if err != nil { - return err - } - for { - frame, err := stream.Recv() - if err == io.EOF { - return nil - } - if err != nil { - return err - } - if frame.GetEvent() == nil { - t.Fatal("expected protobuf event") - } - } - } - if mode == "warm" { - // Resolve the original while rejecting the caller's catalog precondition. - if err := call(strings.Repeat("a", 64)); status.Code(err) != codes.FailedPrecondition || f.primary.Load() != 0 { - t.Fatalf("catalog precondition consumed fixed plan: %v", err) - } - } - next := secondaryClient(t, f.pki) - token := sha256.Sum256([]byte(f.admin.Token)) - rotation := v1.SourceRotation{OperationID: "fixed-source-handoff", ExpectedEpoch: 0, NextCertificate: next.Certificate[0], NextCredentialSHA256: hex.EncodeToString(token[:])} - if receipt, err := f.admin.RotateSource(ctx, rotation); err != nil || receipt.GetAuthority().GetEpoch() != 1 { - t.Fatalf("source handoff: %v %v", receipt, err) - } - if _, err := f.admin.SourceAuthority(ctx); status.Code(err) != codes.PermissionDenied { - t.Fatalf("retired source retained mutation identity: %v", err) - } - if mode == "restart" { - restartWithSourceCertificate(t, f, next) - } - if err := call(""); err != nil || f.primary.Load() != 1 || f.backup.Load() != 0 { - t.Fatalf("fixed publication changed after source handoff: sends=%d error=%v", f.primary.Load(), err) - } - }) - } -} diff --git a/go/dev/publication_recovery_test.go b/go/dev/publication_recovery_test.go index bc182a65..28908ae8 100644 --- a/go/dev/publication_recovery_test.go +++ b/go/dev/publication_recovery_test.go @@ -56,6 +56,11 @@ func (s *publicationReplyLoss) InspectSourceAuthority(ctx context.Context, in *p return source.RPC.InspectSourceAuthority(source.Context(ctx), in) } +func (s *publicationReplyLoss) ComposeSource(ctx context.Context, in *pb.SourceCompositionRequest) (*pb.SourceCompositionReply, error) { + source := s.sourceClient() + return source.RPC.ComposeSource(source.Context(ctx), in) +} + func (s *publicationReplyLoss) InspectPublication(ctx context.Context, key *pb.PublicationKey) (*pb.PublicationReceipt, error) { s.inspections.Add(1) source := s.sourceClient()