Skip to main content

saddle/
application.rs

1use std::{marker::PhantomData, net::SocketAddr, sync::Arc};
2
3use saddle_core::ErrorKind;
4use saddle_db::{
5    DatabaseConfig,
6    internal::{StartupManagedDatabaseFactory, StartupManagedDatabaseOwner},
7};
8use saddle_observability::ObserverConfig;
9use saddle_runtime::startup_assembly::{
10    ActualStartupOwners, BootstrapBatchSeal, BootstrapInstallAdapter, BootstrapOwnerView,
11    BootstrapTransaction, PreparedBootstrapBatch, PreparedBootstrapInstall, ReadyBootstrapInstall,
12    StartupBootstrapOwners, run_with_actual_startup_owners,
13};
14
15use crate::{
16    Result, SaddleError,
17    http1::{
18        bootstrap::{
19            GeneratedApplicationBootstrap, GeneratedBootstrapToken, GeneratedCompiledAdapter,
20            GeneratedContextFactory, ProductionBundleFacts, ProductionServiceBundle,
21            generated_bootstrap_type_identity,
22        },
23        production::{
24            BoundPreparedHttp1, GeneratedTransportBinding, PreparedHttp1, ProductionHttp1,
25            StagedHttp1, stage,
26        },
27    },
28};
29
30/// Facade-issued seal proving that one generated application owner was
31/// synchronously split before any managed component was constructed.
32pub struct GeneratedApplicationSeal {
33    _private: (),
34}
35
36/// The two non-replayable halves emitted by one generated application owner.
37///
38/// Fields stay private so generated code can only construct this value through
39/// the facade-issued seal.
40pub struct GeneratedApplicationParts<B> {
41    bootstrap: B,
42    runtime_preflight: saddle_runtime::capacity_leaf::VerifiedRuntimeLayoutPreflight,
43    termination: FacadeGeneratedTermination,
44    continuation: FacadeGeneratedContinuation,
45}
46
47pub type GeneratedBoundApplicationParts<A, C, const ROUTES: usize> =
48    GeneratedApplicationParts<GeneratedProductionBootstrap<A, C, ROUTES>>;
49
50#[derive(Clone, Copy, Debug, Eq, PartialEq)]
51pub enum GeneratedApplicationBindingError {
52    ForeignGeneration,
53    ForeignBootstrapType,
54    RouteCountMismatch,
55    MissingIdentity,
56    PreflightFailed,
57}
58
59/// Facade-owned opaque coordinator input. It exposes no Runtime, calibration,
60/// resource or deployment observation to generated code.
61pub struct FacadeBootstrapCoordinator {
62    config: SaddleConfig,
63    adapter_provenance: [u8; 32],
64}
65
66mod generated_bootstrap_sealed {
67    pub trait Sealed {}
68}
69
70/// Sealed type-level bridge from one generated owner to the existing generic
71/// bootstrap. Only the Facade implementation can invoke the generic consumer.
72trait GeneratedProductionBootstrapCapability:
73    generated_bootstrap_sealed::Sealed + Send + 'static
74{
75    fn run<R, H>(
76        self,
77        coordinator: FacadeBootstrapCoordinator,
78        actual: ActualStartupOwners<StartupManagedDatabaseFactory>,
79        continuation: saddle_admission::LateStartupContinuationOwner<FacadeGeneratedContinuation>,
80        authorization: PendingListenerAuthorization<R, H>,
81        candidate: crate::startup_candidate::PreparedStartupCandidateTransaction,
82    ) -> Result<()>
83    where
84        R: ApprovedBundleNonceReservation,
85        H: ListenerAuthorityProvider;
86}
87
88/// Private-field, non-Clone capability carrying the fully checked staged HTTP
89/// graph, concrete Rust types, fixed route count and binder identity.
90///
91/// ```compile_fail
92/// # use saddle::GeneratedProductionBootstrap;
93/// fn replay<A, C, const N: usize>(value: GeneratedProductionBootstrap<A, C, N>) {
94///     let _copy = value.clone();
95/// }
96/// ```
97///
98/// ```compile_fail
99/// # use saddle::GeneratedProductionBootstrap;
100/// let _forged: GeneratedProductionBootstrap<(), (), 6> =
101///     GeneratedProductionBootstrap { generation: 1, type_identity: [1; 32], _types: core::marker::PhantomData };
102/// ```
103pub struct GeneratedProductionBootstrap<A, C, const ROUTES: usize>
104where
105    A: GeneratedCompiledAdapter,
106    C: GeneratedContextFactory<A::Context>,
107{
108    generation: u64,
109    type_identity: [u8; 32],
110    staged: StagedHttp1<A, C>,
111}
112
113impl<A, C, const ROUTES: usize> generated_bootstrap_sealed::Sealed
114    for GeneratedProductionBootstrap<A, C, ROUTES>
115where
116    A: GeneratedCompiledAdapter,
117    C: GeneratedContextFactory<A::Context>,
118{
119}
120
121impl<A, C, const ROUTES: usize> GeneratedProductionBootstrapCapability
122    for GeneratedProductionBootstrap<A, C, ROUTES>
123where
124    A: ProductionServiceBundle,
125    C: GeneratedContextFactory<A::Context>,
126{
127    fn run<R, H>(
128        self,
129        coordinator: FacadeBootstrapCoordinator,
130        actual: ActualStartupOwners<StartupManagedDatabaseFactory>,
131        continuation: saddle_admission::LateStartupContinuationOwner<FacadeGeneratedContinuation>,
132        authorization: PendingListenerAuthorization<R, H>,
133        candidate: crate::startup_candidate::PreparedStartupCandidateTransaction,
134    ) -> Result<()>
135    where
136        R: ApprovedBundleNonceReservation,
137        H: ListenerAuthorityProvider,
138    {
139        let _binding = (self.generation, self.type_identity);
140        run_with_actual_startup_owners(
141            actual,
142            FacadeContinuationAdapter {
143                provenance: coordinator.adapter_provenance,
144            },
145            continuation,
146            move |owners, runtime_profile| async move {
147                let transaction = BootstrapTransaction::new(owners);
148                let prepared = transaction
149                    .prepare(ProductionInstall {
150                        config: coordinator.config,
151                        staged: self.staged,
152                        runtime_profile,
153                        candidate,
154                    })
155                    .map_err(|failure| {
156                        failure.into_runner_failure(startup_error(
157                            "saddle.production_bootstrap_prepare_failed",
158                        ))
159                    })?;
160                let prepared = prepared.prepare_observability().await?;
161                let mut prepared = prepared;
162                if prepared.prepare_install().await.is_err() {
163                    return Err(
164                        prepared.fail(startup_error("saddle.production_listener_prepare_failed"))
165                    );
166                }
167                let prepared = prepared.verify_post_driver_binding().map_err(|failure| {
168                    failure.into_runner_failure(startup_error(
169                        "saddle.production_post_driver_binding_failed",
170                    ))
171                })?;
172                let prepared = authorize_listener(
173                    prepared,
174                    authorization.binding,
175                    authorization.reservation,
176                    authorization.authority,
177                )
178                .map_err(|error| error.value.fail(error.error))?;
179                let prepared = prepared.finish_prepare_install();
180                Ok(prepared.commit())
181            },
182        )
183    }
184}
185
186struct FacadeContinuationAdapter {
187    provenance: [u8; 32],
188}
189
190impl saddle_admission::StartupContinuationAdapter for FacadeContinuationAdapter {
191    type ContinuationOwner =
192        saddle_admission::LateStartupContinuationOwner<FacadeGeneratedContinuation>;
193
194    fn adapter_provenance(&self) -> [u8; 32] {
195        self.provenance
196    }
197}
198
199struct ProductionInstall<A, C>
200where
201    A: GeneratedCompiledAdapter,
202    C: GeneratedContextFactory<A::Context>,
203{
204    config: SaddleConfig,
205    staged: StagedHttp1<A, C>,
206    runtime_profile: saddle_runtime::startup_assembly::VerifiedTransportRuntimeProfile,
207    candidate: crate::startup_candidate::PreparedStartupCandidateTransaction,
208}
209
210struct PreparedProductionInstall<A, C>
211where
212    A: GeneratedCompiledAdapter,
213    C: GeneratedContextFactory<A::Context>,
214{
215    config: SaddleConfig,
216    prepared: PreparedHttp1<A, C>,
217    listener: Option<tokio::net::TcpListener>,
218    candidate: crate::startup_candidate::PreparedStartupCandidateTransaction,
219}
220
221struct ReadyProductionInstall<A, C>
222where
223    A: GeneratedCompiledAdapter,
224    C: GeneratedContextFactory<A::Context>,
225{
226    config: SaddleConfig,
227    prepared: BoundPreparedHttp1<A, C>,
228    candidate: crate::startup_candidate::PreparedStartupCandidateTransaction,
229}
230
231impl<A, C, B> BootstrapInstallAdapter<StartupManagedDatabaseOwner, B> for ProductionInstall<A, C>
232where
233    A: GeneratedCompiledAdapter,
234    C: GeneratedContextFactory<A::Context>,
235    B: Send + 'static,
236{
237    type Prepared = PreparedProductionInstall<A, C>;
238    type Error = SaddleError;
239
240    fn prepare(
241        self,
242        _owners: BootstrapOwnerView<'_, StartupManagedDatabaseOwner, B>,
243    ) -> std::result::Result<Self::Prepared, Self::Error> {
244        Ok(PreparedProductionInstall {
245            config: self.config,
246            prepared: self.staged.prepare(self.runtime_profile)?,
247            listener: None,
248            candidate: self.candidate,
249        })
250    }
251}
252
253impl<A, C, B> PreparedBootstrapInstall<StartupManagedDatabaseOwner, B>
254    for PreparedProductionInstall<A, C>
255where
256    A: GeneratedCompiledAdapter,
257    C: GeneratedContextFactory<A::Context>,
258    B: Send + 'static,
259{
260    type Ready = ReadyProductionInstall<A, C>;
261    type Error = SaddleError;
262
263    fn component_names(&self) -> &'static [&'static str] {
264        &["observability", "database", "http1-production"]
265    }
266
267    async fn prepare_install(&mut self) -> std::result::Result<(), Self::Error> {
268        self.listener = Some(
269            tokio::net::TcpListener::bind(self.config.listen)
270                .await
271                .map_err(|_| startup_error("saddle.production_listener_bind_failed"))?,
272        );
273        Ok(())
274    }
275
276    fn into_ready(self) -> Self::Ready {
277        ReadyProductionInstall {
278            config: self.config,
279            prepared: self
280                .prepared
281                .bind_owned(self.listener.unwrap_or_else(|| std::process::abort())),
282            candidate: self.candidate,
283        }
284    }
285}
286
287impl<A, C, B> ReadyBootstrapInstall<StartupManagedDatabaseOwner, B> for ReadyProductionInstall<A, C>
288where
289    A: GeneratedCompiledAdapter,
290    C: GeneratedContextFactory<A::Context>,
291    B: Send + 'static,
292{
293    fn install(
294        self,
295        owners: StartupBootstrapOwners<StartupManagedDatabaseOwner, B>,
296        mut seal: BootstrapBatchSeal,
297    ) -> PreparedBootstrapBatch {
298        let (
299            database_owner,
300            db_domain,
301            tokio_domain,
302            allocation,
303            ledger,
304            _termination,
305            bound,
306            _transport_binding,
307            observability,
308        ) = owners.into_parts();
309        let (database_owner, database) = database_owner.bootstrap(|database| database.existing());
310        let publish = bound.into_publish_token();
311        let (listener, prepared) = self.prepared.into_parts();
312        let assembly = prepared.attach(database, ledger, tokio_domain, allocation, db_domain);
313        let server = ProductionHttp1::from_staged(
314            listener,
315            assembly,
316            publish,
317            seal.take_driver_finalizer(),
318            self.candidate.commit(),
319        );
320        let observability: Arc<dyn saddle_core::ComponentLifecycle> = match observability {
321            Some(saddle_runtime::startup_assembly::StartupObservabilityOwner::Started(owner)) => {
322                owner
323            }
324            Some(saddle_runtime::startup_assembly::StartupObservabilityOwner::Prepared(_)) => {
325                std::process::abort()
326            }
327            None => std::process::abort(),
328        };
329        let components: Vec<Arc<dyn saddle_core::ComponentLifecycle>> =
330            vec![observability, Arc::new(database_owner), Arc::new(server)];
331        let _application = self.config.application;
332        seal.install(components)
333    }
334}
335
336struct FacadeGeneratedContinuation {
337    common: [[u8; 32]; 3],
338    generation: u64,
339}
340
341impl saddle_admission::PreflightGeneratedStaticContinuationOwner for FacadeGeneratedContinuation {
342    fn build_identity(&self) -> [u8; 32] {
343        self.common[0]
344    }
345    fn artifact_identity(&self) -> [u8; 32] {
346        self.common[1]
347    }
348    fn route_set_identity(&self) -> [u8; 32] {
349        self.common[2]
350    }
351    fn owner_generation(&self) -> u64 {
352        self.generation
353    }
354}
355
356struct FacadeGeneratedTermination {
357    common: [[u8; 32]; 3],
358    generation: u64,
359    topology: [u64; 4],
360}
361
362fn facade_generated_identity(common: [[u8; 32]; 3], tag: u8) -> [u8; 32] {
363    let mut identity = common[0];
364    for (index, byte) in identity.iter_mut().enumerate() {
365        *byte ^= common[1][index].rotate_left(1) ^ common[2][index].rotate_left(2) ^ tag;
366    }
367    identity
368}
369
370impl saddle_admission::GeneratedTerminationTopologyWorkOwner for FacadeGeneratedTermination {
371    fn leaf_identity(&self) -> [u8; 32] {
372        facade_generated_identity(self.common, 0x71)
373    }
374    fn common_identities(&self) -> [[u8; 32]; 3] {
375        self.common
376    }
377    fn owner_generation(&self) -> u64 {
378        self.generation
379    }
380    fn termination_topology(&self) -> [u64; 4] {
381        self.topology
382    }
383    fn termination_topology_identity(&self) -> [u8; 32] {
384        facade_generated_identity(self.common, 0x72)
385    }
386    fn db_return_work_identity(&self) -> [u8; 32] {
387        saddle_db::internal::db_normal_return_work_proof().identity()
388    }
389    fn writer_work_identity(&self) -> [u8; 32] {
390        saddle_observability::file::writer_component_work_proof().identity()
391    }
392    fn runtime_work_identity(&self) -> [u8; 32] {
393        saddle_runtime::termination_service::runtime_component_work_proof().identity()
394    }
395}
396
397struct FacadeRuntimeLayouts<F, C, const OUTPUT: usize> {
398    common: [[u8; 32]; 3],
399    generation: u64,
400    routes: Box<[u64]>,
401    types: PhantomData<fn() -> (F, C)>,
402}
403
404impl<F, C, const OUTPUT: usize> saddle_runtime::capacity_leaf::RuntimeMonomorphizedLayoutSource
405    for FacadeRuntimeLayouts<F, C, OUTPUT>
406where
407    F: Send + 'static,
408    C: Send + 'static,
409{
410    fn common_identities(&self) -> [[u8; 32]; 3] {
411        self.common
412    }
413    fn owner_generation(&self) -> u64 {
414        self.generation
415    }
416    fn solver_schema_identity(&self) -> [u8; 32] {
417        saddle_admission::admission_capacity_contract_identities()[0]
418    }
419    fn admission_layout_identity(&self) -> [u8; 32] {
420        saddle_admission::admission_capacity_contract_identities()[2]
421    }
422    fn measure(
423        self,
424        seal: saddle_runtime::capacity_leaf::RuntimeLayoutSeal,
425    ) -> std::result::Result<
426        Box<[saddle_runtime::capacity_leaf::RuntimeRouteLayout]>,
427        saddle_runtime::capacity_leaf::RuntimeCapacityLeafError,
428    > {
429        self.routes
430            .into_iter()
431            .map(|route| {
432                seal.measure::<F, C, saddle_admission::ManagedResponse, [u8; OUTPUT]>(route)
433            })
434            .collect()
435    }
436}
437
438impl GeneratedApplicationSeal {
439    fn issue() -> Self {
440        Self { _private: () }
441    }
442
443    /// Issues the sole token used by generated code for fallible preflight.
444    /// The token contains no deployment or Runtime observation.
445    pub fn preflight_token(&self) -> GeneratedBootstrapToken {
446        GeneratedBootstrapToken::issue()
447    }
448
449    /// Consumes Service's indivisible same-freeze execution/capacity bundle.
450    /// Runtime layout, termination and continuation proofs are Facade-issued.
451    pub fn bind<E, BC, F, C, const BODY: usize, const OUTPUT: usize, const ROUTES: usize>(
452        self,
453        generated: GeneratedApplicationBootstrap<
454            saddle_service::internal::CompiledExecutionWithCapacityLeaf<E, BC, F, BODY, OUTPUT>,
455            C,
456            ROUTES,
457        >,
458    ) -> std::result::Result<
459        GeneratedBoundApplicationParts<
460            saddle_service::internal::CompiledExecutionWithCapacityLeaf<E, BC, F, BODY, OUTPUT>,
461            C,
462            ROUTES,
463        >,
464        GeneratedApplicationBindingError,
465    >
466    where
467        E: Fn(
468                usize,
469                BC,
470                saddle_admission::ManagedBytes,
471                saddle_service::internal::CompiledDbPermit,
472                saddle_admission::ManagedResponseBuilder,
473            ) -> F
474            + Send
475            + Sync
476            + 'static,
477        BC: Send + Unpin + 'static,
478        F: std::future::Future<
479                Output = std::result::Result<
480                    saddle_admission::ManagedResponse,
481                    saddle_service::internal::ExecutionError,
482                >,
483            > + Send
484            + 'static,
485        C: GeneratedContextFactory<BC>,
486    {
487        let ProductionBundleFacts {
488            common,
489            generation,
490            routes,
491            termination_topology: topology,
492        } = generated.production_bundle_facts();
493        let type_identity = generated_bootstrap_type_identity::<
494            saddle_service::internal::CompiledExecutionWithCapacityLeaf<E, BC, F, BODY, OUTPUT>,
495            C,
496            ROUTES,
497        >();
498        if generation == 0
499            || ROUTES == 0
500            || routes.len() != ROUTES
501            || [common[0], common[1], common[2], type_identity].contains(&[0; 32])
502        {
503            return Err(GeneratedApplicationBindingError::MissingIdentity);
504        }
505        let runtime_preflight = saddle_runtime::capacity_leaf::verify_runtime_layout_preflight(
506            saddle_runtime::capacity_leaf::runtime_capacity_component_proof(),
507            FacadeRuntimeLayouts::<F, BC, OUTPUT> {
508                common,
509                generation,
510                routes,
511                types: PhantomData,
512            },
513        )
514        .map_err(|_| GeneratedApplicationBindingError::PreflightFailed)?;
515        let staged = stage(
516            generated,
517            GeneratedTransportBinding {
518                generation,
519                build_identity: common[0],
520                route_set_identity: common[2],
521                static_layout_identity: type_identity,
522            },
523        )
524        .map_err(|_| GeneratedApplicationBindingError::PreflightFailed)?;
525        Ok(GeneratedApplicationParts {
526            bootstrap: GeneratedProductionBootstrap {
527                generation,
528                type_identity,
529                staged,
530            },
531            runtime_preflight,
532            termination: FacadeGeneratedTermination {
533                common,
534                generation,
535                topology,
536            },
537            continuation: FacadeGeneratedContinuation { common, generation },
538        })
539    }
540}
541
542mod generated_consumer_sealed {
543    pub trait Sealed {}
544}
545
546/// Facade-owned inversion point. Generated code chooses `A/C/ROUTES` inside
547/// its method body and immediately moves the private staged capability here;
548/// the anonymous dispatcher Future never appears in an associated type.
549#[doc(hidden)]
550pub trait GeneratedApplicationConsumer: generated_consumer_sealed::Sealed {
551    fn consume<E, BC, F, C, const BODY: usize, const OUTPUT: usize, const ROUTES: usize>(
552        self,
553        parts: GeneratedBoundApplicationParts<
554            saddle_service::internal::CompiledExecutionWithCapacityLeaf<E, BC, F, BODY, OUTPUT>,
555            C,
556            ROUTES,
557        >,
558    ) -> Result<()>
559    where
560        E: Fn(
561                usize,
562                BC,
563                saddle_admission::ManagedBytes,
564                saddle_service::internal::CompiledDbPermit,
565                saddle_admission::ManagedResponseBuilder,
566            ) -> F
567            + Send
568            + Sync
569            + 'static,
570        BC: Send + Unpin + 'static,
571        F: std::future::Future<
572                Output = std::result::Result<
573                    saddle_admission::ManagedResponse,
574                    saddle_service::internal::ExecutionError,
575                >,
576            > + Send
577            + 'static,
578        C: GeneratedContextFactory<BC>;
579}
580
581/// The sole generated application owner accepted by the 0.2 facade.
582///
583/// There is deliberately no blanket implementation for closures.
584///
585/// ```compile_fail
586/// # use saddle::GeneratedApplicationOwner;
587/// fn require_generated_owner<T: GeneratedApplicationOwner>(_: T) {}
588/// require_generated_owner(|| ());
589/// ```
590///
591/// ```compile_fail
592/// # use saddle_admission::{ComposedGeneratedStartupFactsOwner, ServiceCapacitySourceLeaf};
593/// fn require_service_leaf<T: ServiceCapacitySourceLeaf>(_: T) {}
594/// fn old_combined_owner(owner: ComposedGeneratedStartupFactsOwner) {
595///     require_service_leaf(owner);
596/// }
597/// ```
598pub trait GeneratedApplicationOwner: Send + 'static {
599    fn consume<K>(self, seal: GeneratedApplicationSeal, consumer: K) -> Result<()>
600    where
601        K: GeneratedApplicationConsumer;
602}
603
604/// Facade-issued seal for the independently Gate-owned deployment halves.
605pub struct FacadeDeploymentSeal {
606    _private: (),
607}
608
609pub struct FacadeDeploymentParts<C, E, D, F, S, U> {
610    calibration: C,
611    envelope: E,
612    db_service: D,
613    filesystem_service: F,
614    scheduler_service: S,
615    supervisor_service: U,
616    policy: saddle_runtime::resource_envelope::FiniteStartupPolicy,
617    adapter_provenance: [u8; 32],
618}
619
620pub type FacadeDeploymentOwnerParts<O> = FacadeDeploymentParts<
621    <O as FacadeDeploymentOwner>::Calibration,
622    <O as FacadeDeploymentOwner>::Envelope,
623    <O as FacadeDeploymentOwner>::DbService,
624    <O as FacadeDeploymentOwner>::FilesystemService,
625    <O as FacadeDeploymentOwner>::SchedulerService,
626    <O as FacadeDeploymentOwner>::SupervisorService,
627>;
628
629impl FacadeDeploymentSeal {
630    fn issue() -> Self {
631        Self { _private: () }
632    }
633
634    #[allow(clippy::too_many_arguments)]
635    pub fn bind<C, E, D, F, S, U>(
636        self,
637        calibration: C,
638        envelope: E,
639        db_service: D,
640        filesystem_service: F,
641        scheduler_service: S,
642        supervisor_service: U,
643        policy: saddle_runtime::resource_envelope::FiniteStartupPolicy,
644        adapter_provenance: [u8; 32],
645    ) -> FacadeDeploymentParts<C, E, D, F, S, U>
646    where
647        C: saddle_admission::RuntimeCapacityCalibrationSourceLeaf,
648        E: Into<saddle_runtime::resource_envelope::VerifiedResourceEnvelope>,
649        D: saddle_admission::VerifiedDbTerminationServiceProofOwner,
650        F: Send + 'static,
651        S: saddle_admission::VerifiedSchedulerTerminationServiceProofOwner,
652        U: saddle_admission::VerifiedSupervisorTerminationServiceProofOwner,
653    {
654        FacadeDeploymentParts {
655            calibration,
656            envelope,
657            db_service,
658            filesystem_service,
659            scheduler_service,
660            supervisor_service,
661            policy,
662            adapter_provenance,
663        }
664    }
665}
666
667/// The Gate/deployment owner is independent from generated business artifacts.
668/// There is no closure blanket implementation.
669///
670/// ```compile_fail
671/// # use saddle::FacadeDeploymentOwner;
672/// fn require_deployment<T: FacadeDeploymentOwner>(_: T) {}
673/// require_deployment(|| ());
674/// ```
675pub trait FacadeDeploymentOwner: Send + 'static {
676    type Calibration: saddle_admission::RuntimeCapacityCalibrationSourceLeaf;
677    type Envelope: Into<saddle_runtime::resource_envelope::VerifiedResourceEnvelope>;
678    type DbService: saddle_admission::VerifiedDbTerminationServiceProofOwner;
679    type FilesystemService: Send + 'static;
680    type SchedulerService: saddle_admission::VerifiedSchedulerTerminationServiceProofOwner;
681    type SupervisorService: saddle_admission::VerifiedSupervisorTerminationServiceProofOwner;
682
683    fn split(self, seal: FacadeDeploymentSeal) -> FacadeDeploymentOwnerParts<Self>;
684}
685
686/// Deployment-provided verifier for one opaque signed evidence bundle.
687///
688/// Implementations own their key distribution, trusted clock, nonce store and
689/// actual service observations. The facade accepts only the typed owners and
690/// binding identities returned through [`ApprovedExternalBundleSeal`]. There
691/// is no default implementation, built-in production credential or unsigned
692/// byte constructor.
693pub trait ApprovedExternalBundle: Sized {
694    type Reservation: ApprovedBundleNonceReservation;
695    type Authority: ListenerAuthorityProvider;
696
697    fn verify(
698        self,
699        seal: ApprovedExternalBundleSeal,
700    ) -> Result<ApprovedExternalBundleVerification<Self::Reservation, Self::Authority>>;
701}
702
703/// Linear nonce reservation held until listener authority has also verified.
704/// A deployment implementation must make `commit` atomically single-success
705/// across processes/threads for its signed nonce.
706pub trait ApprovedBundleNonceReservation: Send + 'static {
707    fn commit(self) -> Result<()>;
708}
709
710/// Independent deployment-provided listener/startup authority verifier.
711/// Verification permission from the evidence bundle is not listener authority.
712pub trait ListenerAuthorityProvider: Sized {
713    fn verify(self, seal: ListenerAuthoritySeal) -> Result<VerifiedListenerAuthority>;
714}
715
716/// One-shot facade seal passed only through [`ProductionLauncher::verify`].
717/// Raw bundle bytes and manifest fields cannot be stored in this value.
718#[doc(hidden)]
719pub struct ApprovedExternalBundleSeal {
720    _private: (),
721}
722
723/// One-shot facade seal for the independent listener authority provider.
724pub struct ListenerAuthoritySeal {
725    _private: (),
726}
727
728#[derive(Clone, Copy, Debug, Eq, PartialEq)]
729struct ExternalBundleBinding {
730    bundle: [u8; 32],
731    nonce: [u8; 32],
732    binary: [u8; 32],
733    deployment: [u8; 32],
734    calibration: [u8; 32],
735}
736
737/// Verified seven-owner result. Fields are private and raw evidence is absent.
738pub struct ApprovedExternalBundleVerification<R, L> {
739    deployment: VerifiedLauncherDeployment,
740    binding: ExternalBundleBinding,
741    reservation: R,
742    authority: L,
743}
744
745/// Recoverable failure of the final signed-filesystem/applicability pairing.
746/// The aggregate remains whole; neither half is exposed independently.
747pub struct ApprovedExternalBundleApplicabilityFailure {
748    signed_filesystem: saddle_observability::file::VerifiedSignedProviderFilesystemBundle,
749}
750
751impl ApprovedExternalBundleApplicabilityFailure {
752    /// Returns the still-whole aggregate for a corrected atomic retry.
753    pub fn into_signed_filesystem(
754        self,
755    ) -> saddle_observability::file::VerifiedSignedProviderFilesystemBundle {
756        self.signed_filesystem
757    }
758}
759
760/// Verified independent listener authority. Fields are private and non-Clone.
761pub struct VerifiedListenerAuthority {
762    binding: ExternalBundleBinding,
763}
764
765struct VerifiedFacadeDeployment {
766    calibration: saddle_runtime::capacity_leaf::VerifiedRuntimeBuildCalibrationOwner,
767    envelope: saddle_runtime::resource_envelope::VerifiedResourceEnvelope,
768    db_service: saddle_db::internal::DbReturnServiceProof,
769    filesystem_service: saddle_observability::file::PairedSignedProviderFilesystemEvidence,
770    scheduler_service: saddle_runtime::termination_service::VerifiedSchedulerDeploymentOwner,
771    supervisor_service: saddle_runtime::termination_service::VerifiedSupervisorServiceOwner,
772    policy: saddle_runtime::resource_envelope::FiniteStartupPolicy,
773    adapter_provenance: [u8; 32],
774}
775
776enum VerifiedLauncherDeployment {
777    Production(VerifiedFacadeDeployment),
778    GoldenC8(VerifiedGoldenC8Compose),
779}
780
781#[allow(dead_code)]
782struct VerifiedGoldenC8Compose {
783    applicability: saddle_core::VerifiedGoldenC8ApplicabilityOwner,
784    calibration: saddle_runtime::capacity_leaf::VerifiedRuntimeBuildCalibrationOwner,
785    envelope: saddle_runtime::resource_envelope::VerifiedResourceEnvelope,
786    db_service: saddle_db::internal::DbReturnServiceProof,
787    filesystem_service: saddle_observability::file::WriterTerminationProof,
788    scheduler_service: saddle_runtime::termination_service::VerifiedSchedulerDeploymentOwner,
789    supervisor_service: saddle_runtime::termination_service::VerifiedSupervisorServiceOwner,
790    policy: saddle_runtime::resource_envelope::FiniteStartupPolicy,
791    adapter_provenance: [u8; 32],
792}
793
794#[derive(Clone, Copy)]
795struct VerifiedDeploymentIdentitySet {
796    runtime_common: [[u8; 32]; 3],
797    calibration_common: [[u8; 32]; 3],
798    runtime_generation: u64,
799    calibration_generation: u64,
800    expected_provenance: [[u8; 32]; 9],
801    calibration_provenance: [[u8; 32]; 9],
802    envelope_build: [u8; 32],
803    envelope_gate: [u8; 32],
804    envelope_supervisor: [u8; 32],
805    environment: [u8; 32],
806    db_build: [u8; 32],
807    supervisor_build: [u8; 32],
808    db_gate: [u8; 32],
809    supervisor_gate: [u8; 32],
810    supervisor_identity: [u8; 32],
811    supervisor_environment: [u8; 32],
812    required_identities: [[u8; 32]; 13],
813}
814
815fn validate_verified_deployment_identities(facts: VerifiedDeploymentIdentitySet) -> Result<()> {
816    if facts.required_identities.contains(&[0; 32])
817        || facts.runtime_common.contains(&[0; 32])
818        || facts.runtime_common != facts.calibration_common
819        || facts.runtime_generation == 0
820        || facts.runtime_generation != facts.calibration_generation
821        || facts.expected_provenance != facts.calibration_provenance
822        || facts.envelope_build != facts.db_build
823        || facts.envelope_build != facts.supervisor_build
824        || facts.envelope_gate != facts.db_gate
825        || facts.envelope_gate != facts.supervisor_gate
826        || facts.envelope_supervisor != facts.supervisor_identity
827        || facts.environment != facts.supervisor_environment
828    {
829        return Err(startup_error("saddle.approved_bundle_identity_mismatch"));
830    }
831    Ok(())
832}
833
834fn preflight_verified_deployment_without_filesystem(
835    calibration: &saddle_runtime::capacity_leaf::VerifiedRuntimeBuildCalibrationOwner,
836    envelope: &saddle_runtime::resource_envelope::VerifiedResourceEnvelope,
837    db_service: &saddle_db::internal::DbReturnServiceProof,
838    scheduler_service: saddle_runtime::termination_service::VerifiedSchedulerServiceOwner,
839    supervisor_service: &saddle_runtime::termination_service::VerifiedSupervisorServiceOwner,
840    adapter_provenance: [u8; 32],
841    binding: ExternalBundleBinding,
842) -> Result<saddle_runtime::termination_service::VerifiedSchedulerDeploymentOwner> {
843    let calibration_common =
844        saddle_admission::RuntimeCapacityCalibrationSourceLeaf::common_identities(calibration);
845    let calibration_generation =
846        saddle_admission::RuntimeCapacityCalibrationSourceLeaf::owner_generation(calibration);
847    let calibration_provenance =
848        saddle_admission::RuntimeCapacityCalibrationSourceLeaf::calibration_provenance(calibration);
849    let envelope_build = saddle_admission::VerifiedStartupEnvelopeOwner::build_identity(envelope);
850    let envelope_gate = saddle_admission::VerifiedStartupEnvelopeOwner::gate_identity(envelope);
851    let envelope_resource =
852        saddle_admission::VerifiedStartupEnvelopeOwner::resource_attestation(envelope);
853    let envelope_supervisor =
854        saddle_admission::VerifiedStartupEnvelopeOwner::supervisor_attestation(envelope);
855    let environment = db_service.environment_identity();
856    validate_verified_deployment_identities(VerifiedDeploymentIdentitySet {
857        runtime_common: calibration_common,
858        calibration_common,
859        runtime_generation: calibration_generation,
860        calibration_generation,
861        expected_provenance: calibration_provenance,
862        calibration_provenance,
863        envelope_build,
864        envelope_gate,
865        envelope_supervisor,
866        environment,
867        db_build: db_service.build_identity(),
868        supervisor_build: supervisor_service.build_identity(),
869        db_gate: db_service.gate_identity(),
870        supervisor_gate: supervisor_service.gate_identity(),
871        supervisor_identity: supervisor_service.supervisor_identity(),
872        supervisor_environment: supervisor_service.environment_identity(),
873        required_identities: [
874            adapter_provenance,
875            binding.bundle,
876            binding.nonce,
877            binding.binary,
878            binding.deployment,
879            binding.calibration,
880            envelope_build,
881            envelope_gate,
882            envelope_resource,
883            envelope_supervisor,
884            environment,
885            db_service.service_attestation(),
886            supervisor_service.service_attestation(),
887        ],
888    })?;
889    saddle_runtime::termination_service::bind_scheduler_deployment_owner(
890        scheduler_service,
891        envelope,
892    )
893    .map_err(|_| startup_error("saddle.approved_bundle_identity_mismatch"))
894}
895
896impl ApprovedExternalBundleSeal {
897    /// Golden/C8-only COMPOSE entry. The opaque applicability is bound to the
898    /// frozen artifact pair, A/B, environment and single run. It cannot enter
899    /// the production signed-filesystem path or authorize listener opening.
900    #[doc(hidden)]
901    #[allow(clippy::too_many_arguments)]
902    pub fn bind_verified_for_golden_c8<R, L>(
903        self,
904        applicability: saddle_core::VerifiedGoldenC8ApplicabilityOwner,
905        calibration: saddle_runtime::capacity_leaf::VerifiedRuntimeBuildCalibrationOwner,
906        envelope: saddle_runtime::resource_envelope::VerifiedResourceEnvelope,
907        db_service: saddle_db::internal::DbReturnServiceProof,
908        filesystem_service: saddle_observability::file::WriterTerminationProof,
909        scheduler_service: saddle_runtime::termination_service::VerifiedSchedulerServiceOwner,
910        supervisor_service: saddle_runtime::termination_service::VerifiedSupervisorServiceOwner,
911        policy: saddle_runtime::resource_envelope::FiniteStartupPolicy,
912        adapter_provenance: [u8; 32],
913        bundle_identity: [u8; 32],
914        nonce_identity: [u8; 32],
915        binary_identity: [u8; 32],
916        deployment_identity: [u8; 32],
917        calibration_identity: [u8; 32],
918        reservation: R,
919        authority: L,
920    ) -> Result<ApprovedExternalBundleVerification<R, L>>
921    where
922        R: ApprovedBundleNonceReservation,
923        L: ListenerAuthorityProvider,
924    {
925        let binding = ExternalBundleBinding {
926            bundle: bundle_identity,
927            nonce: nonce_identity,
928            binary: binary_identity,
929            deployment: deployment_identity,
930            calibration: calibration_identity,
931        };
932        let scheduler_service = preflight_verified_deployment_without_filesystem(
933            &calibration,
934            &envelope,
935            &db_service,
936            scheduler_service,
937            &supervisor_service,
938            adapter_provenance,
939            binding,
940        )?;
941        if filesystem_service.environment_identity()
942            != saddle_db::internal::DbReturnServiceProof::environment_identity(&db_service)
943            || filesystem_service.build_identity()
944                != saddle_admission::VerifiedStartupEnvelopeOwner::build_identity(&envelope)
945        {
946            return Err(startup_error("saddle.golden_c8_applicability_foreign"));
947        }
948        Ok(ApprovedExternalBundleVerification {
949            deployment: VerifiedLauncherDeployment::GoldenC8(VerifiedGoldenC8Compose {
950                applicability,
951                calibration,
952                envelope,
953                db_service,
954                filesystem_service,
955                scheduler_service,
956                supervisor_service,
957                policy,
958                adapter_provenance,
959            }),
960            binding,
961            reservation,
962            authority,
963        })
964    }
965
966    /// Production entry: the seven component owners cannot be bound unless
967    /// core has already verified the signed deployment applicability bundle.
968    #[allow(clippy::too_many_arguments)]
969    pub fn bind_verified_with_applicability<R, L>(
970        self,
971        signed_filesystem: saddle_observability::file::VerifiedSignedProviderFilesystemBundle,
972        application_identity: [u8; 32],
973        source_identity: [u8; 32],
974        artifact_identity: [u8; 32],
975        routes_identity: [u8; 32],
976        calibration: saddle_runtime::capacity_leaf::VerifiedRuntimeBuildCalibrationOwner,
977        envelope: saddle_runtime::resource_envelope::VerifiedResourceEnvelope,
978        db_service: saddle_db::internal::DbReturnServiceProof,
979        scheduler_service: saddle_runtime::termination_service::VerifiedSchedulerServiceOwner,
980        supervisor_service: saddle_runtime::termination_service::VerifiedSupervisorServiceOwner,
981        policy: saddle_runtime::resource_envelope::FiniteStartupPolicy,
982        adapter_provenance: [u8; 32],
983        bundle_identity: [u8; 32],
984        nonce_identity: [u8; 32],
985        binary_identity: [u8; 32],
986        deployment_identity: [u8; 32],
987        calibration_identity: [u8; 32],
988        reservation: R,
989        authority: L,
990    ) -> std::result::Result<
991        ApprovedExternalBundleVerification<R, L>,
992        ApprovedExternalBundleApplicabilityFailure,
993    >
994    where
995        R: ApprovedBundleNonceReservation,
996        L: ListenerAuthorityProvider,
997    {
998        let binding = ExternalBundleBinding {
999            bundle: bundle_identity,
1000            nonce: nonce_identity,
1001            binary: binary_identity,
1002            deployment: deployment_identity,
1003            calibration: calibration_identity,
1004        };
1005        let scheduler_service = match preflight_verified_deployment_without_filesystem(
1006            &calibration,
1007            &envelope,
1008            &db_service,
1009            scheduler_service,
1010            &supervisor_service,
1011            adapter_provenance,
1012            binding,
1013        ) {
1014            Ok(owner) => owner,
1015            Err(_) => {
1016                return Err(ApprovedExternalBundleApplicabilityFailure { signed_filesystem });
1017            }
1018        };
1019        let filesystem_service = signed_filesystem
1020            .verify_deployment_pair(
1021                bundle_identity,
1022                adapter_provenance,
1023                application_identity,
1024                binary_identity,
1025                saddle_admission::VerifiedStartupEnvelopeOwner::build_identity(&envelope),
1026                source_identity,
1027                artifact_identity,
1028                routes_identity,
1029                deployment_identity,
1030                saddle_db::internal::DbReturnServiceProof::environment_identity(&db_service),
1031                nonce_identity,
1032                calibration_identity,
1033            )
1034            .map_err(
1035                |signed_filesystem| ApprovedExternalBundleApplicabilityFailure {
1036                    signed_filesystem,
1037                },
1038            )?;
1039        Ok(self
1040            .bind_verified_inner(
1041                calibration,
1042                envelope,
1043                db_service,
1044                filesystem_service,
1045                scheduler_service,
1046                supervisor_service,
1047                policy,
1048                adapter_provenance,
1049                bundle_identity,
1050                nonce_identity,
1051                binary_identity,
1052                deployment_identity,
1053                calibration_identity,
1054                reservation,
1055                authority,
1056            )
1057            .unwrap_or_else(|_| {
1058                unreachable!("signed filesystem issuer and component preflight are closed")
1059            }))
1060    }
1061
1062    /// Packages the exact typed outputs of the component verifiers. The Gate
1063    /// adapter must finish signature, B0 and attestation checks before calling
1064    /// this method; no raw bytes or numeric manifest fields cross this call.
1065    #[allow(clippy::too_many_arguments)]
1066    #[cfg(test)]
1067    pub fn bind_verified<R, L>(
1068        self,
1069        calibration: saddle_runtime::capacity_leaf::VerifiedRuntimeBuildCalibrationOwner,
1070        envelope: saddle_runtime::resource_envelope::VerifiedResourceEnvelope,
1071        db_service: saddle_db::internal::DbReturnServiceProof,
1072        filesystem_service: saddle_observability::file::PairedSignedProviderFilesystemEvidence,
1073        scheduler_service: saddle_runtime::termination_service::VerifiedSchedulerServiceOwner,
1074        supervisor_service: saddle_runtime::termination_service::VerifiedSupervisorServiceOwner,
1075        policy: saddle_runtime::resource_envelope::FiniteStartupPolicy,
1076        adapter_provenance: [u8; 32],
1077        bundle_identity: [u8; 32],
1078        nonce_identity: [u8; 32],
1079        binary_identity: [u8; 32],
1080        deployment_identity: [u8; 32],
1081        calibration_identity: [u8; 32],
1082        reservation: R,
1083        authority: L,
1084    ) -> Result<ApprovedExternalBundleVerification<R, L>>
1085    where
1086        R: ApprovedBundleNonceReservation,
1087        L: ListenerAuthorityProvider,
1088    {
1089        let scheduler_service =
1090            saddle_runtime::termination_service::bind_scheduler_deployment_owner(
1091                scheduler_service,
1092                &envelope,
1093            )
1094            .map_err(|_| startup_error("saddle.approved_bundle_identity_mismatch"))?;
1095        self.bind_verified_inner(
1096            calibration,
1097            envelope,
1098            db_service,
1099            filesystem_service,
1100            scheduler_service,
1101            supervisor_service,
1102            policy,
1103            adapter_provenance,
1104            bundle_identity,
1105            nonce_identity,
1106            binary_identity,
1107            deployment_identity,
1108            calibration_identity,
1109            reservation,
1110            authority,
1111        )
1112    }
1113
1114    #[allow(clippy::too_many_arguments)]
1115    fn bind_verified_inner<R, L>(
1116        self,
1117        calibration: saddle_runtime::capacity_leaf::VerifiedRuntimeBuildCalibrationOwner,
1118        envelope: saddle_runtime::resource_envelope::VerifiedResourceEnvelope,
1119        db_service: saddle_db::internal::DbReturnServiceProof,
1120        filesystem_service: saddle_observability::file::PairedSignedProviderFilesystemEvidence,
1121        scheduler_service: saddle_runtime::termination_service::VerifiedSchedulerDeploymentOwner,
1122        supervisor_service: saddle_runtime::termination_service::VerifiedSupervisorServiceOwner,
1123        policy: saddle_runtime::resource_envelope::FiniteStartupPolicy,
1124        adapter_provenance: [u8; 32],
1125        bundle_identity: [u8; 32],
1126        nonce_identity: [u8; 32],
1127        binary_identity: [u8; 32],
1128        deployment_identity: [u8; 32],
1129        calibration_identity: [u8; 32],
1130        reservation: R,
1131        authority: L,
1132    ) -> Result<ApprovedExternalBundleVerification<R, L>>
1133    where
1134        R: ApprovedBundleNonceReservation,
1135        L: ListenerAuthorityProvider,
1136    {
1137        let calibration_common =
1138            saddle_admission::RuntimeCapacityCalibrationSourceLeaf::common_identities(&calibration);
1139        let calibration_generation =
1140            saddle_admission::RuntimeCapacityCalibrationSourceLeaf::owner_generation(&calibration);
1141        let envelope_build =
1142            saddle_admission::VerifiedStartupEnvelopeOwner::build_identity(&envelope);
1143        let envelope_gate =
1144            saddle_admission::VerifiedStartupEnvelopeOwner::gate_identity(&envelope);
1145        let envelope_resource =
1146            saddle_admission::VerifiedStartupEnvelopeOwner::resource_attestation(&envelope);
1147        let envelope_supervisor =
1148            saddle_admission::VerifiedStartupEnvelopeOwner::supervisor_attestation(&envelope);
1149        let environment = db_service.environment_identity();
1150        let binding = ExternalBundleBinding {
1151            bundle: bundle_identity,
1152            nonce: nonce_identity,
1153            binary: binary_identity,
1154            deployment: deployment_identity,
1155            calibration: calibration_identity,
1156        };
1157        let required_identities = [
1158            adapter_provenance,
1159            binding.bundle,
1160            binding.nonce,
1161            binding.binary,
1162            binding.deployment,
1163            binding.calibration,
1164            envelope_build,
1165            envelope_gate,
1166            envelope_resource,
1167            envelope_supervisor,
1168            environment,
1169            db_service.service_attestation(),
1170            supervisor_service.service_attestation(),
1171        ];
1172        validate_verified_deployment_identities(VerifiedDeploymentIdentitySet {
1173            runtime_common: calibration_common,
1174            calibration_common,
1175            runtime_generation: calibration_generation,
1176            calibration_generation,
1177            expected_provenance:
1178                saddle_admission::RuntimeCapacityCalibrationSourceLeaf::calibration_provenance(
1179                    &calibration,
1180                ),
1181            calibration_provenance:
1182                saddle_admission::RuntimeCapacityCalibrationSourceLeaf::calibration_provenance(
1183                    &calibration,
1184                ),
1185            envelope_build,
1186            envelope_gate,
1187            envelope_supervisor,
1188            environment,
1189            db_build: db_service.build_identity(),
1190            supervisor_build: supervisor_service.build_identity(),
1191            db_gate: db_service.gate_identity(),
1192            supervisor_gate: supervisor_service.gate_identity(),
1193            supervisor_identity: supervisor_service.supervisor_identity(),
1194            supervisor_environment: supervisor_service.environment_identity(),
1195            required_identities,
1196        })?;
1197        if !filesystem_service.matches_deployment(environment, envelope_build) {
1198            return Err(startup_error("saddle.approved_bundle_identity_mismatch"));
1199        }
1200        Ok(ApprovedExternalBundleVerification {
1201            deployment: VerifiedLauncherDeployment::Production(VerifiedFacadeDeployment {
1202                calibration,
1203                envelope,
1204                db_service,
1205                filesystem_service,
1206                scheduler_service,
1207                supervisor_service,
1208                policy,
1209                adapter_provenance,
1210            }),
1211            binding,
1212            reservation,
1213            authority,
1214        })
1215    }
1216}
1217
1218impl ListenerAuthoritySeal {
1219    /// Binds an independently verified listener authority to the exact signed
1220    /// bundle/nonce/executable/deployment/calibration tuple.
1221    pub fn bind_verified(
1222        self,
1223        bundle_identity: [u8; 32],
1224        nonce_identity: [u8; 32],
1225        binary_identity: [u8; 32],
1226        deployment_identity: [u8; 32],
1227        calibration_identity: [u8; 32],
1228    ) -> Result<VerifiedListenerAuthority> {
1229        let binding = ExternalBundleBinding {
1230            bundle: bundle_identity,
1231            nonce: nonce_identity,
1232            binary: binary_identity,
1233            deployment: deployment_identity,
1234            calibration: calibration_identity,
1235        };
1236        if [
1237            binding.bundle,
1238            binding.nonce,
1239            binding.binary,
1240            binding.deployment,
1241            binding.calibration,
1242        ]
1243        .contains(&[0; 32])
1244        {
1245            return Err(startup_error("saddle.listener_authority_missing_identity"));
1246        }
1247        Ok(VerifiedListenerAuthority { binding })
1248    }
1249}
1250
1251impl FacadeDeploymentOwner for VerifiedFacadeDeployment {
1252    type Calibration = saddle_runtime::capacity_leaf::VerifiedRuntimeBuildCalibrationOwner;
1253    type Envelope = saddle_runtime::resource_envelope::VerifiedResourceEnvelope;
1254    type DbService = saddle_db::internal::DbReturnServiceProof;
1255    type FilesystemService = saddle_observability::file::PairedSignedProviderFilesystemEvidence;
1256    type SchedulerService = saddle_runtime::termination_service::VerifiedSchedulerDeploymentOwner;
1257    type SupervisorService = saddle_runtime::termination_service::VerifiedSupervisorServiceOwner;
1258
1259    fn split(self, seal: FacadeDeploymentSeal) -> FacadeDeploymentOwnerParts<Self> {
1260        seal.bind(
1261            self.calibration,
1262            self.envelope,
1263            self.db_service,
1264            self.filesystem_service,
1265            self.scheduler_service,
1266            self.supervisor_service,
1267            self.policy,
1268            self.adapter_provenance,
1269        )
1270    }
1271}
1272
1273/// Fixed 0.2 process facts. Capacity/profile values remain private candidate
1274/// inputs until the final Gate freeze.
1275pub struct SaddleConfig {
1276    application: saddle_core::ApplicationId,
1277    database: Option<DatabaseConfig>,
1278    listen: SocketAddr,
1279    _observability: ObserverConfig,
1280}
1281
1282impl SaddleConfig {
1283    pub fn new(
1284        application: impl Into<saddle_core::ApplicationId>,
1285        database_url: impl Into<String>,
1286        listen: SocketAddr,
1287    ) -> Self {
1288        Self {
1289            application: application.into(),
1290            database: Some(DatabaseConfig::new(database_url)),
1291            listen,
1292            _observability: ObserverConfig::default(),
1293        }
1294    }
1295
1296    /// Creates a deployment configuration whose verified startup plan must
1297    /// derive a zero DB profile. No pool is constructed for this form.
1298    pub fn without_database(
1299        application: impl Into<saddle_core::ApplicationId>,
1300        listen: SocketAddr,
1301    ) -> Self {
1302        Self {
1303            application: application.into(),
1304            database: None,
1305            listen,
1306            _observability: ObserverConfig::default(),
1307        }
1308    }
1309}
1310
1311/// Fixed process entry for one Skill-generated 0.2 application.
1312struct Saddle;
1313
1314/// Opaque, non-Clone permission to start the sole production assembly.
1315///
1316/// ```compile_fail
1317/// # use saddle::ProductionLauncher;
1318/// fn replay(launcher: &ProductionLauncher) {
1319///     let _copy = (*launcher).clone();
1320/// }
1321/// ```
1322///
1323/// ```compile_fail
1324/// # use saddle::ProductionLauncher;
1325/// let _forged = ProductionLauncher { deployment: () };
1326/// ```
1327///
1328/// The public launch shape has no deployment third parameter:
1329///
1330/// ```no_run
1331/// # use saddle::{ApprovedExternalBundle, GeneratedApplicationOwner, ProductionLauncher,
1332/// #     Result, SaddleConfig};
1333/// fn launch<B, O>(bundle: B, config: SaddleConfig, generated: O) -> Result<()>
1334/// where
1335///     B: ApprovedExternalBundle,
1336///     O: GeneratedApplicationOwner,
1337/// {
1338///     ProductionLauncher::verify(bundle)?.run(config, generated)
1339/// }
1340/// ```
1341pub struct ProductionLauncher {
1342    _private: (),
1343}
1344
1345/// Opaque verified bundle whose listener authority and nonce remain pending
1346/// until generated layout preflight has paired with calibration.
1347#[doc(hidden)]
1348pub struct VerifiedProductionLauncher<R, L> {
1349    deployment: VerifiedLauncherDeployment,
1350    binding: ExternalBundleBinding,
1351    reservation: R,
1352    authority: L,
1353}
1354
1355impl ProductionLauncher {
1356    /// Consumes the sole approved external bundle. Failure occurs before the
1357    /// deployment owner reaches Observer, DB, Tokio or listener construction.
1358    pub fn verify<B>(bundle: B) -> Result<VerifiedProductionLauncher<B::Reservation, B::Authority>>
1359    where
1360        B: ApprovedExternalBundle,
1361    {
1362        let verified = bundle.verify(ApprovedExternalBundleSeal { _private: () })?;
1363        Ok(VerifiedProductionLauncher {
1364            deployment: verified.deployment,
1365            binding: verified.binding,
1366            reservation: verified.reservation,
1367            authority: verified.authority,
1368        })
1369    }
1370}
1371
1372impl<R, L> VerifiedProductionLauncher<R, L>
1373where
1374    R: ApprovedBundleNonceReservation,
1375    L: ListenerAuthorityProvider,
1376{
1377    /// The only public production launch path. Deployment owners remain
1378    /// private and are consumed exactly once with this launcher.
1379    pub fn run<O>(self, config: SaddleConfig, generated: O) -> Result<()>
1380    where
1381        O: GeneratedApplicationOwner,
1382    {
1383        match self.deployment {
1384            VerifiedLauncherDeployment::Production(deployment) => Saddle::run_with_deployment(
1385                config,
1386                generated,
1387                deployment,
1388                PendingListenerAuthorization {
1389                    binding: self.binding,
1390                    reservation: self.reservation,
1391                    authority: self.authority,
1392                },
1393            ),
1394            VerifiedLauncherDeployment::GoldenC8(compose) => Saddle::run_with_golden_c8(
1395                config,
1396                generated,
1397                compose,
1398                PendingListenerAuthorization {
1399                    binding: self.binding,
1400                    reservation: self.reservation,
1401                    authority: self.authority,
1402                },
1403            ),
1404        }
1405    }
1406}
1407
1408struct GoldenC8GeneratedConsumer<R, L> {
1409    config: SaddleConfig,
1410    compose: VerifiedGoldenC8Compose,
1411    authorization: PendingListenerAuthorization<R, L>,
1412}
1413
1414impl<R, L> generated_consumer_sealed::Sealed for GoldenC8GeneratedConsumer<R, L>
1415where
1416    R: ApprovedBundleNonceReservation,
1417    L: ListenerAuthorityProvider,
1418{
1419}
1420
1421impl<R, L> GeneratedApplicationConsumer for GoldenC8GeneratedConsumer<R, L>
1422where
1423    R: ApprovedBundleNonceReservation,
1424    L: ListenerAuthorityProvider,
1425{
1426    fn consume<E, BC, F, C, const BODY: usize, const OUTPUT: usize, const ROUTES: usize>(
1427        self,
1428        parts: GeneratedBoundApplicationParts<
1429            saddle_service::internal::CompiledExecutionWithCapacityLeaf<E, BC, F, BODY, OUTPUT>,
1430            C,
1431            ROUTES,
1432        >,
1433    ) -> Result<()>
1434    where
1435        E: Fn(
1436                usize,
1437                BC,
1438                saddle_admission::ManagedBytes,
1439                saddle_service::internal::CompiledDbPermit,
1440                saddle_admission::ManagedResponseBuilder,
1441            ) -> F
1442            + Send
1443            + Sync
1444            + 'static,
1445        BC: Send + Unpin + 'static,
1446        F: std::future::Future<
1447                Output = std::result::Result<
1448                    saddle_admission::ManagedResponse,
1449                    saddle_service::internal::ExecutionError,
1450                >,
1451            > + Send
1452            + 'static,
1453        C: GeneratedContextFactory<BC>,
1454    {
1455        let approved = saddle_core::verify_golden_c8_startup_assembly_input(
1456            saddle_core::approved_golden_c8_startup_assembly_input(),
1457        )
1458        .map_err(|_| startup_error("saddle.golden_c8_startup_assembly_rejected"))?;
1459        let GeneratedApplicationParts {
1460            termination,
1461            continuation,
1462            bootstrap,
1463            runtime_preflight,
1464        } = parts;
1465        // Gate already binds this exact generated whole, deployment compose
1466        // and current startup transaction. GeneratedApplicationSeal issued
1467        // this private continuation and staged HTTP graph from the same
1468        // checked common identities and generation. Golden/C8 consumes that
1469        // already-preflighted HTTP owner only after listener preclosure; it
1470        // neither binds a socket nor invokes production composition.
1471        let continuation = (
1472            approved,
1473            continuation,
1474            bootstrap,
1475            runtime_preflight,
1476            termination,
1477            self.compose,
1478            self.config,
1479        );
1480        let PendingListenerAuthorization {
1481            binding,
1482            reservation,
1483            authority,
1484        } = self.authorization;
1485        let listener_preclosure = authorize_listener(continuation, binding, reservation, authority)
1486            .map_err(|failure| failure.error)?;
1487        let (
1488            approved,
1489            continuation,
1490            GeneratedProductionBootstrap {
1491                generation,
1492                type_identity,
1493                staged,
1494            },
1495            runtime_preflight,
1496            termination,
1497            compose,
1498            config,
1499        ) = listener_preclosure;
1500        let http_preclosure = (
1501            approved,
1502            continuation,
1503            generation,
1504            type_identity,
1505            staged,
1506            runtime_preflight,
1507            termination,
1508            compose,
1509            config,
1510        );
1511        // The Golden/C8 transaction already carries the verified DB service
1512        // and database configuration inside the private compose/config pair.
1513        // Consuming the HTTP preclosure here preserves that whole linear
1514        // state for the commit check without connecting to DB or creating a
1515        // second assembly path.
1516        let db_commit_preclosure = http_preclosure;
1517        // Golden/C8 rollback validation consumes the same private database
1518        // preclosure as commit validation.  This is still a pure ownership
1519        // transition: no connection is opened and no database callback is
1520        // invoked before the later system-acceptance stages authorize it.
1521        let db_rollback_preclosure = db_commit_preclosure;
1522        let shutdown_preclosure = db_rollback_preclosure;
1523        // Shutdown preclosure consumes the same private Golden/C8 transaction
1524        // after both database paths have been checked.  It remains a pure
1525        // ownership transition: no supervisor callback, listener, or runtime
1526        // shutdown is invoked before system acceptance authorizes it.
1527        let resource_zero_preclosure = shutdown_preclosure;
1528        // RESOURCE_ZERO preclosure consumes the same private transaction
1529        // after shutdown has been checked. This remains a pure ownership
1530        // transition: it does not inspect resources, run a destructor, open
1531        // a listener, or grant C8/production/release/publish authority.
1532        let c8_acceptance_preclosure = resource_zero_preclosure;
1533        // C8 acceptance consumes the same private, fully preclosed Golden
1534        // transaction.  Acceptance is only a final ownership transition: it
1535        // opens no listener, executes no application work, and grants no
1536        // production, release, or publish authority.
1537        let _accepted = c8_acceptance_preclosure;
1538        Ok(())
1539    }
1540}
1541
1542#[doc(hidden)]
1543pub struct PendingListenerAuthorization<R, L> {
1544    binding: ExternalBundleBinding,
1545    reservation: R,
1546    authority: L,
1547}
1548
1549fn authorize_listener<T, R, L>(
1550    value: T,
1551    binding: ExternalBundleBinding,
1552    reservation: R,
1553    authority: L,
1554) -> std::result::Result<T, ListenerAuthorizationFailure<T>>
1555where
1556    R: ApprovedBundleNonceReservation,
1557    L: ListenerAuthorityProvider,
1558{
1559    let mut value = Some(value);
1560    let listener = authority
1561        .verify(ListenerAuthoritySeal { _private: () })
1562        .map_err(|error| ListenerAuthorizationFailure {
1563            value: value.take().expect("authorization value is present"),
1564            error,
1565        })?;
1566    if binding != listener.binding {
1567        return Err(ListenerAuthorizationFailure {
1568            value: value.take().expect("authorization value is present"),
1569            error: startup_error("saddle.listener_authority_binding_mismatch"),
1570        });
1571    }
1572    reservation
1573        .commit()
1574        .map_err(|error| ListenerAuthorizationFailure {
1575            value: value.take().expect("authorization value is present"),
1576            error,
1577        })?;
1578    Ok(value.take().expect("authorization value is present"))
1579}
1580
1581struct ListenerAuthorizationFailure<T> {
1582    value: T,
1583    error: SaddleError,
1584}
1585
1586struct FacadeGeneratedConsumer<D, R, L>
1587where
1588    D: FacadeDeploymentOwner<
1589            Calibration = saddle_runtime::capacity_leaf::VerifiedRuntimeBuildCalibrationOwner,
1590            FilesystemService = saddle_observability::file::PairedSignedProviderFilesystemEvidence,
1591        >,
1592{
1593    config: SaddleConfig,
1594    deployment: FacadeDeploymentOwnerParts<D>,
1595    authorization: PendingListenerAuthorization<R, L>,
1596}
1597
1598impl<D, R, L> generated_consumer_sealed::Sealed for FacadeGeneratedConsumer<D, R, L>
1599where
1600    D: FacadeDeploymentOwner<
1601            Calibration = saddle_runtime::capacity_leaf::VerifiedRuntimeBuildCalibrationOwner,
1602            FilesystemService = saddle_observability::file::PairedSignedProviderFilesystemEvidence,
1603        >,
1604    R: ApprovedBundleNonceReservation,
1605    L: ListenerAuthorityProvider,
1606{
1607}
1608
1609impl<D, R, L> GeneratedApplicationConsumer for FacadeGeneratedConsumer<D, R, L>
1610where
1611    D: FacadeDeploymentOwner<
1612            Calibration = saddle_runtime::capacity_leaf::VerifiedRuntimeBuildCalibrationOwner,
1613            FilesystemService = saddle_observability::file::PairedSignedProviderFilesystemEvidence,
1614        >,
1615    R: ApprovedBundleNonceReservation,
1616    L: ListenerAuthorityProvider,
1617{
1618    fn consume<E, BC, F, C, const BODY: usize, const OUTPUT: usize, const ROUTES: usize>(
1619        self,
1620        parts: GeneratedBoundApplicationParts<
1621            saddle_service::internal::CompiledExecutionWithCapacityLeaf<E, BC, F, BODY, OUTPUT>,
1622            C,
1623            ROUTES,
1624        >,
1625    ) -> Result<()>
1626    where
1627        E: Fn(
1628                usize,
1629                BC,
1630                saddle_admission::ManagedBytes,
1631                saddle_service::internal::CompiledDbPermit,
1632                saddle_admission::ManagedResponseBuilder,
1633            ) -> F
1634            + Send
1635            + Sync
1636            + 'static,
1637        BC: Send + Unpin + 'static,
1638        F: std::future::Future<
1639                Output = std::result::Result<
1640                    saddle_admission::ManagedResponse,
1641                    saddle_service::internal::ExecutionError,
1642                >,
1643            > + Send
1644            + 'static,
1645        C: GeneratedContextFactory<BC>,
1646    {
1647        let GeneratedApplicationParts {
1648            termination,
1649            continuation,
1650            bootstrap,
1651            runtime_preflight,
1652        } = parts;
1653        let candidate = crate::startup_candidate::prepare_production_candidate_transaction(
1654            bootstrap
1655                .staged
1656                .service_production_fact_input()
1657                .map_err(|_| startup_error("saddle.service_production_fact_failed"))?,
1658        )?;
1659        let FacadeDeploymentParts {
1660            calibration,
1661            envelope,
1662            db_service,
1663            filesystem_service,
1664            scheduler_service,
1665            supervisor_service,
1666            policy,
1667            adapter_provenance,
1668        } = self.deployment;
1669        let (runtime, _runtime_termination, calibration) =
1670            saddle_runtime::capacity_leaf::verify_runtime_capacity_leaf_from_preflight(
1671                runtime_preflight,
1672                calibration,
1673            )
1674            .map_err(|_| startup_error("saddle.runtime_layout_calibration_pair_failed"))?;
1675        let (staged, generated) = bootstrap
1676            .staged
1677            .compose_generated(runtime, calibration, termination)
1678            .map_err(|_| startup_error("saddle.generated_facts_composition_failed"))?;
1679        let bootstrap = GeneratedProductionBootstrap {
1680            staged,
1681            ..bootstrap
1682        };
1683        let (generated, continuation) =
1684            saddle_admission::seal_generated_startup_continuation(continuation, generated)
1685                .map_err(|_| startup_error("saddle.generated_continuation_foreign"))?
1686                .into_parts();
1687        let (filesystem_service, generated) = filesystem_service
1688            .pair_component_generation(generated)
1689            .map_err(|_| startup_error("saddle.component_generation_foreign"))?;
1690        let (pending, physical) =
1691            saddle_runtime::resource_envelope::create_runtime_startup_plan_with_filesystem_bundle(
1692                policy,
1693                adapter_provenance,
1694                envelope.into(),
1695                generated,
1696                db_service,
1697                filesystem_service,
1698                scheduler_service,
1699                supervisor_service,
1700            )
1701            .map_err(|failure| {
1702                let _ = failure.consume_for_application_error();
1703                startup_error("saddle.startup_plan_creation_failed")
1704            })?;
1705        let factory = StartupManagedDatabaseFactory::awaiting_started_observability(
1706            self.config.database.clone(),
1707        );
1708        let owners = saddle_runtime::startup_assembly::assemble_actual_startup_owners(
1709            pending,
1710            factory,
1711            saddle_runtime::startup_assembly::StartupObservabilityInput::Production(physical),
1712        )
1713        .map_err(|_| startup_error("saddle.startup_actual_owner_assembly_failed"))?;
1714        bootstrap.run(
1715            FacadeBootstrapCoordinator {
1716                config: self.config,
1717                adapter_provenance,
1718            },
1719            owners,
1720            continuation,
1721            self.authorization,
1722            candidate,
1723        )
1724    }
1725}
1726
1727impl Saddle {
1728    fn run_with_golden_c8<O, R, L>(
1729        config: SaddleConfig,
1730        generated: O,
1731        compose: VerifiedGoldenC8Compose,
1732        authorization: PendingListenerAuthorization<R, L>,
1733    ) -> Result<()>
1734    where
1735        O: GeneratedApplicationOwner,
1736        R: ApprovedBundleNonceReservation,
1737        L: ListenerAuthorityProvider,
1738    {
1739        generated.consume(
1740            GeneratedApplicationSeal::issue(),
1741            GoldenC8GeneratedConsumer {
1742                config,
1743                compose,
1744                authorization,
1745            },
1746        )
1747    }
1748
1749    /// Private continuation after the launcher consumed verified deployment.
1750    fn run_with_deployment<O, D, R, L>(
1751        config: SaddleConfig,
1752        generated: O,
1753        deployment: D,
1754        authorization: PendingListenerAuthorization<R, L>,
1755    ) -> Result<()>
1756    where
1757        O: GeneratedApplicationOwner,
1758        D: FacadeDeploymentOwner<
1759            Calibration = saddle_runtime::capacity_leaf::VerifiedRuntimeBuildCalibrationOwner,
1760            FilesystemService = saddle_observability::file::PairedSignedProviderFilesystemEvidence,
1761        >,
1762        R: ApprovedBundleNonceReservation,
1763        L: ListenerAuthorityProvider,
1764    {
1765        let deployment = deployment.split(FacadeDeploymentSeal::issue());
1766        generated.consume(
1767            GeneratedApplicationSeal::issue(),
1768            FacadeGeneratedConsumer::<D, R, L> {
1769                config,
1770                deployment,
1771                authorization,
1772            },
1773        )
1774    }
1775}
1776
1777pub(crate) fn startup_error(code: &'static str) -> SaddleError {
1778    SaddleError::new(
1779        ErrorKind::Infrastructure,
1780        code,
1781        "Saddle application initialization failed",
1782    )
1783}
1784
1785#[cfg(test)]
1786mod generated_bootstrap_contract_tests {
1787    use super::*;
1788    use std::sync::{
1789        Arc,
1790        atomic::{AtomicBool, AtomicUsize, Ordering},
1791    };
1792
1793    static REJECTED_BUNDLES: AtomicUsize = AtomicUsize::new(0);
1794
1795    fn binding(seed: u8) -> ExternalBundleBinding {
1796        ExternalBundleBinding {
1797            bundle: [seed; 32],
1798            nonce: [seed.wrapping_add(1); 32],
1799            binary: [seed.wrapping_add(2); 32],
1800            deployment: [seed.wrapping_add(3); 32],
1801            calibration: [seed.wrapping_add(4); 32],
1802        }
1803    }
1804
1805    struct ReferenceAuthority(ExternalBundleBinding);
1806
1807    impl ListenerAuthorityProvider for ReferenceAuthority {
1808        fn verify(self, seal: ListenerAuthoritySeal) -> Result<VerifiedListenerAuthority> {
1809            seal.bind_verified(
1810                self.0.bundle,
1811                self.0.nonce,
1812                self.0.binary,
1813                self.0.deployment,
1814                self.0.calibration,
1815            )
1816        }
1817    }
1818
1819    struct CountingAuthority {
1820        binding: ExternalBundleBinding,
1821        calls: Arc<AtomicUsize>,
1822    }
1823
1824    impl ListenerAuthorityProvider for CountingAuthority {
1825        fn verify(self, seal: ListenerAuthoritySeal) -> Result<VerifiedListenerAuthority> {
1826            self.calls.fetch_add(1, Ordering::SeqCst);
1827            seal.bind_verified(
1828                self.binding.bundle,
1829                self.binding.nonce,
1830                self.binding.binary,
1831                self.binding.deployment,
1832                self.binding.calibration,
1833            )
1834        }
1835    }
1836
1837    struct CountingReservation {
1838        calls: Arc<AtomicUsize>,
1839    }
1840
1841    impl ApprovedBundleNonceReservation for CountingReservation {
1842        fn commit(self) -> Result<()> {
1843            self.calls.fetch_add(1, Ordering::SeqCst);
1844            Ok(())
1845        }
1846    }
1847
1848    struct RejectingAuthority {
1849        calls: Arc<AtomicUsize>,
1850    }
1851
1852    impl ListenerAuthorityProvider for RejectingAuthority {
1853        fn verify(self, _seal: ListenerAuthoritySeal) -> Result<VerifiedListenerAuthority> {
1854            self.calls.fetch_add(1, Ordering::SeqCst);
1855            Err(startup_error("test.listener_authority_rejected"))
1856        }
1857    }
1858
1859    struct RejectingReservation {
1860        calls: Arc<AtomicUsize>,
1861    }
1862
1863    impl ApprovedBundleNonceReservation for RejectingReservation {
1864        fn commit(self) -> Result<()> {
1865            self.calls.fetch_add(1, Ordering::SeqCst);
1866            Err(startup_error("test.bundle_nonce_commit_rejected"))
1867        }
1868    }
1869
1870    fn pending_counting_authorization(
1871        authority_calls: &Arc<AtomicUsize>,
1872        commit_calls: &Arc<AtomicUsize>,
1873    ) -> PendingListenerAuthorization<CountingReservation, CountingAuthority> {
1874        let binding = binding(40);
1875        PendingListenerAuthorization {
1876            binding,
1877            reservation: CountingReservation {
1878                calls: Arc::clone(commit_calls),
1879            },
1880            authority: CountingAuthority {
1881                binding,
1882                calls: Arc::clone(authority_calls),
1883            },
1884        }
1885    }
1886
1887    struct ReferenceReservation(Arc<AtomicBool>);
1888
1889    impl ApprovedBundleNonceReservation for ReferenceReservation {
1890        fn commit(self) -> Result<()> {
1891            self.0
1892                .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
1893                .map(|_| ())
1894                .map_err(|_| startup_error("test.bundle_nonce_replay"))
1895        }
1896    }
1897
1898    struct OwnerAggregate(Arc<AtomicUsize>);
1899
1900    impl Drop for OwnerAggregate {
1901        fn drop(&mut self) {
1902            self.0.fetch_add(1, Ordering::SeqCst);
1903        }
1904    }
1905
1906    struct RejectedBundle;
1907    struct RejectedReservation;
1908    struct RejectedAuthority;
1909
1910    impl ApprovedBundleNonceReservation for RejectedReservation {
1911        fn commit(self) -> Result<()> {
1912            panic!("rejected bundle cannot reserve a nonce")
1913        }
1914    }
1915
1916    impl ApprovedExternalBundle for RejectedBundle {
1917        type Reservation = RejectedReservation;
1918        type Authority = RejectedAuthority;
1919
1920        fn verify(
1921            self,
1922            _seal: ApprovedExternalBundleSeal,
1923        ) -> Result<ApprovedExternalBundleVerification<Self::Reservation, Self::Authority>>
1924        {
1925            REJECTED_BUNDLES.fetch_add(1, Ordering::SeqCst);
1926            Err(startup_error("test.bundle_rejected"))
1927        }
1928    }
1929
1930    impl ListenerAuthorityProvider for RejectedAuthority {
1931        fn verify(self, _seal: ListenerAuthoritySeal) -> Result<VerifiedListenerAuthority> {
1932            panic!("listener authority must not run after bundle rejection")
1933        }
1934    }
1935
1936    #[test]
1937    fn rejected_bundle_returns_before_any_launcher_exists() {
1938        let before = REJECTED_BUNDLES.load(Ordering::SeqCst);
1939        assert!(ProductionLauncher::verify(RejectedBundle).is_err());
1940        assert_eq!(REJECTED_BUNDLES.load(Ordering::SeqCst), before + 1);
1941    }
1942
1943    fn matching_deployment_identities() -> VerifiedDeploymentIdentitySet {
1944        VerifiedDeploymentIdentitySet {
1945            runtime_common: [[1; 32], [2; 32], [3; 32]],
1946            calibration_common: [[1; 32], [2; 32], [3; 32]],
1947            runtime_generation: 7,
1948            calibration_generation: 7,
1949            expected_provenance: [[4; 32]; 9],
1950            calibration_provenance: [[4; 32]; 9],
1951            envelope_build: [5; 32],
1952            envelope_gate: [6; 32],
1953            envelope_supervisor: [8; 32],
1954            environment: [9; 32],
1955            db_build: [5; 32],
1956            supervisor_build: [5; 32],
1957            db_gate: [6; 32],
1958            supervisor_gate: [6; 32],
1959            supervisor_identity: [8; 32],
1960            supervisor_environment: [9; 32],
1961            required_identities: [[10; 32]; 13],
1962        }
1963    }
1964
1965    #[test]
1966    fn matching_seven_owner_identities_reach_the_launcher_boundary() {
1967        assert!(validate_verified_deployment_identities(matching_deployment_identities()).is_ok());
1968    }
1969
1970    #[test]
1971    fn missing_foreign_drift_and_replay_generation_fail_before_launcher() {
1972        let mut missing = matching_deployment_identities();
1973        missing.required_identities[4] = [0; 32];
1974        assert!(validate_verified_deployment_identities(missing).is_err());
1975
1976        let mut foreign = matching_deployment_identities();
1977        foreign.supervisor_environment = [11; 32];
1978        assert!(validate_verified_deployment_identities(foreign).is_err());
1979
1980        let mut drift = matching_deployment_identities();
1981        drift.supervisor_gate = [12; 32];
1982        assert!(validate_verified_deployment_identities(drift).is_err());
1983
1984        let mut replay = matching_deployment_identities();
1985        replay.calibration_generation += 1;
1986        assert!(validate_verified_deployment_identities(replay).is_err());
1987    }
1988
1989    #[test]
1990    fn reference_authority_commits_matching_nonce_once() {
1991        let committed = Arc::new(AtomicBool::new(false));
1992        let expected = binding(10);
1993        assert!(
1994            authorize_listener(
1995                (),
1996                expected,
1997                ReferenceReservation(Arc::clone(&committed)),
1998                ReferenceAuthority(expected),
1999            )
2000            .is_ok()
2001        );
2002        assert!(committed.load(Ordering::SeqCst));
2003        assert!(
2004            authorize_listener(
2005                (),
2006                expected,
2007                ReferenceReservation(Arc::clone(&committed)),
2008                ReferenceAuthority(expected),
2009            )
2010            .is_err()
2011        );
2012    }
2013
2014    #[test]
2015    fn concurrent_nonce_commit_has_exactly_one_success() {
2016        let committed = Arc::new(AtomicBool::new(false));
2017        let expected = binding(20);
2018        let threads: Vec<_> = (0..8)
2019            .map(|_| {
2020                let committed = Arc::clone(&committed);
2021                std::thread::spawn(move || {
2022                    authorize_listener(
2023                        (),
2024                        expected,
2025                        ReferenceReservation(committed),
2026                        ReferenceAuthority(expected),
2027                    )
2028                    .is_ok()
2029                })
2030            })
2031            .collect();
2032        assert_eq!(
2033            threads
2034                .into_iter()
2035                .map(|thread| thread.join().unwrap())
2036                .filter(|success| *success)
2037                .count(),
2038            1
2039        );
2040    }
2041
2042    #[test]
2043    fn authority_drift_drops_owner_aggregate_without_committing_nonce() {
2044        let committed = Arc::new(AtomicBool::new(false));
2045        let drops = Arc::new(AtomicUsize::new(0));
2046        let expected = binding(30);
2047        assert!(
2048            authorize_listener(
2049                OwnerAggregate(Arc::clone(&drops)),
2050                expected,
2051                ReferenceReservation(Arc::clone(&committed)),
2052                ReferenceAuthority(binding(31)),
2053            )
2054            .is_err()
2055        );
2056        assert_eq!(drops.load(Ordering::SeqCst), 1);
2057        assert!(!committed.load(Ordering::SeqCst));
2058    }
2059
2060    #[test]
2061    fn authority_failure_returns_prepared_owner_without_nonce_commit() {
2062        let authority_calls = Arc::new(AtomicUsize::new(0));
2063        let commit_calls = Arc::new(AtomicUsize::new(0));
2064        let drops = Arc::new(AtomicUsize::new(0));
2065        let result = authorize_listener(
2066            OwnerAggregate(Arc::clone(&drops)),
2067            binding(35),
2068            CountingReservation {
2069                calls: Arc::clone(&commit_calls),
2070            },
2071            RejectingAuthority {
2072                calls: Arc::clone(&authority_calls),
2073            },
2074        );
2075        assert!(result.is_err());
2076        drop(result);
2077        assert_eq!(authority_calls.load(Ordering::SeqCst), 1);
2078        assert_eq!(commit_calls.load(Ordering::SeqCst), 0);
2079        assert_eq!(drops.load(Ordering::SeqCst), 1);
2080    }
2081
2082    #[test]
2083    fn nonce_commit_failure_returns_prepared_owner_before_listener_install() {
2084        let authority_calls = Arc::new(AtomicUsize::new(0));
2085        let commit_calls = Arc::new(AtomicUsize::new(0));
2086        let drops = Arc::new(AtomicUsize::new(0));
2087        let expected = binding(36);
2088        let result = authorize_listener(
2089            OwnerAggregate(Arc::clone(&drops)),
2090            expected,
2091            RejectingReservation {
2092                calls: Arc::clone(&commit_calls),
2093            },
2094            CountingAuthority {
2095                binding: expected,
2096                calls: Arc::clone(&authority_calls),
2097            },
2098        );
2099        assert!(result.is_err());
2100        drop(result);
2101        assert_eq!(authority_calls.load(Ordering::SeqCst), 1);
2102        assert_eq!(commit_calls.load(Ordering::SeqCst), 1);
2103        assert_eq!(drops.load(Ordering::SeqCst), 1);
2104    }
2105
2106    #[test]
2107    fn composition_failure_discards_pending_authorization_without_side_effects() {
2108        let authority_calls = Arc::new(AtomicUsize::new(0));
2109        let commit_calls = Arc::new(AtomicUsize::new(0));
2110        let pending = pending_counting_authorization(&authority_calls, &commit_calls);
2111
2112        let composition: Result<()> = Err(startup_error("test.composition_failed"));
2113        assert!(composition.is_err());
2114        drop(pending);
2115
2116        assert_eq!(authority_calls.load(Ordering::SeqCst), 0);
2117        assert_eq!(commit_calls.load(Ordering::SeqCst), 0);
2118    }
2119
2120    #[test]
2121    fn late_prepare_failure_discards_pending_authorization_without_side_effects() {
2122        let authority_calls = Arc::new(AtomicUsize::new(0));
2123        let commit_calls = Arc::new(AtomicUsize::new(0));
2124        let pending = pending_counting_authorization(&authority_calls, &commit_calls);
2125
2126        let late_prepare: Result<()> = Err(startup_error("test.http1_prepare_failed"));
2127        assert!(late_prepare.is_err());
2128        drop(pending);
2129
2130        assert_eq!(authority_calls.load(Ordering::SeqCst), 0);
2131        assert_eq!(commit_calls.load(Ordering::SeqCst), 0);
2132    }
2133
2134    #[test]
2135    fn facade_issues_distinct_termination_and_continuation_proofs() {
2136        use saddle_admission::{
2137            GeneratedTerminationTopologyWorkOwner, PreflightGeneratedStaticContinuationOwner,
2138        };
2139
2140        let common = [[0xb2; 32], [0xa2; 32], [0xd2; 32]];
2141        let termination = FacadeGeneratedTermination {
2142            common,
2143            generation: 9,
2144            topology: [5, 1, 1, 3],
2145        };
2146        let continuation = FacadeGeneratedContinuation {
2147            common,
2148            generation: 9,
2149        };
2150        let identities = [
2151            termination.leaf_identity(),
2152            termination.termination_topology_identity(),
2153            termination.db_return_work_identity(),
2154            termination.writer_work_identity(),
2155            termination.runtime_work_identity(),
2156        ];
2157        assert!(!identities.contains(&[0; 32]));
2158        for (index, identity) in identities.iter().enumerate() {
2159            assert!(!identities[index + 1..].contains(identity));
2160            assert!(!common.contains(identity));
2161        }
2162        assert_eq!(termination.termination_topology(), [5, 1, 1, 3]);
2163        assert_eq!(continuation.build_identity(), common[0]);
2164        assert_eq!(continuation.artifact_identity(), common[1]);
2165        assert_eq!(continuation.route_set_identity(), common[2]);
2166        assert_eq!(continuation.owner_generation(), 9);
2167    }
2168}