Skip to main content

heddle_api/
native_witness.rs

1//! Job-free native witness closure. This layer checks transport commitments and
2//! signatures; callers still verify native models, independently selected owner
3//! authority, policy, causal closure and boundary intent before durable mutation.
4use crate::foreign_dependencies::thread;
5use crate::heddle::api::{common as host, v1alpha2 as api};
6use crate::hybrid_codec::{Reject, canonical, field, hash, key_id, record, signing_digest, width};
7use crate::import_authority as import;
8use prost::Message;
9
10pub const GENESIS_DOMAIN: &str = "heddle-native-genesis-authority-v1";
11pub const SIGNED_GENESIS_DOMAIN: &str = "heddle-signed-native-genesis-authority-v1";
12record!(api::NativeGenesisAuthorityV1, format_version:u, identity:m, owner_kind:e,
13    genesis_digest:b, original_signatures_digest:b, creator_public_key:b,
14    creator_authority_envelope_digest:b, owner_chain_digest:b, publisher_key_id:b);
15record!(api::SignedNativeGenesisAuthorityV1, body:m, creator_signature:m);
16record!(api::NativeGenesisWitnessV1, format_version:u, kind:e, binding:m,
17    original_genesis:m, creator_authority_envelope:b, boundary_acceptance:o);
18
19pub fn signed_genesis_digest(v: &api::SignedNativeGenesisAuthorityV1) -> Result<Vec<u8>, Reject> {
20    signing_digest(SIGNED_GENESIS_DOMAIN, v)
21}
22#[derive(serde::Deserialize)]
23#[serde(rename_all = "snake_case")]
24enum NativeOwner {
25    Account(Vec<u8>),
26    LocalKey([u8; 32]),
27}
28#[derive(serde::Deserialize)]
29struct GenesisSelectors {
30    version: u16,
31    spool: String,
32    creator: [u8; 32],
33    owner: NativeOwner,
34}
35fn spool_uuid(text: &str) -> Result<Vec<u8>, Reject> {
36    if text.len() != 36
37        || [8, 13, 18, 23].iter().any(|&i| text.as_bytes()[i] != b'-')
38        || text.bytes().enumerate().any(|(i, b)| {
39            ![8, 13, 18, 23].contains(&i) && !b.is_ascii_digit() && !(b'a'..=b'f').contains(&b)
40        })
41    {
42        return Err(Reject::Canonical);
43    }
44    hex::decode(text.replace('-', "")).map_err(|_| Reject::Canonical)
45}
46/// Exact creator signature, original signature, immutable owner variant and
47/// envelope match. Verify the returned binding against separately selected
48/// native authority using StartThread's method; no import permission is read.
49pub fn verify_genesis_authority(
50    signed: &api::SignedNativeGenesisAuthorityV1,
51    original: &api::SignedRecord,
52    envelope: &[u8],
53) -> Result<(), Reject> {
54    let b = signed.body.as_ref().ok_or(Reject::GenesisBinding)?;
55    if b.format_version != 1 {
56        return Err(Reject::Version);
57    }
58    let id = b.identity.as_ref().ok_or(Reject::Canonical)?;
59    for v in [&id.spool_uuid, &id.owner_account_uuid] {
60        width(v, 16)?;
61        if v.iter().all(|v| *v == 0) {
62            return Err(Reject::Canonical);
63        }
64    }
65    for v in [
66        &id.spool_genesis_digest,
67        &id.owner_id,
68        &id.owner_state_hash,
69        &b.genesis_digest,
70        &b.original_signatures_digest,
71        &b.creator_public_key,
72        &b.creator_authority_envelope_digest,
73        &b.owner_chain_digest,
74        &b.publisher_key_id,
75    ] {
76        width(v, 32)?;
77    }
78    if envelope.len() > import::MAX_RECORD_BYTES {
79        return Err(Reject::Bounds);
80    }
81    import::verify_native(original, "heddle-thread-genesis-v1")?;
82    let g: GenesisSelectors =
83        rmp_serde::from_slice(&original.canonical_record).map_err(|_| Reject::Canonical)?;
84    if g.version != 1
85        || spool_uuid(&g.spool)? != id.spool_uuid
86        || g.creator.as_slice() != b.creator_public_key
87        || original.signatures.len() != 1
88        || original.signatures[0].public_key != b.creator_public_key
89        || import::native_id(original) != b.genesis_digest
90        || import::original_signatures(&[original], &[])? != b.original_signatures_digest
91        || hash(&[envelope]) != b.creator_authority_envelope_digest
92        || key_id(&b.creator_public_key) != b.publisher_key_id
93    {
94        return Err(Reject::GenesisBinding);
95    }
96    match (&g.owner, b.owner_kind) {
97        (NativeOwner::Account(account), 1) if !envelope.is_empty() => {
98            let authority = crate::writer_authority::decode_authority(envelope)?;
99            crate::writer_authority::verify_account_binding(
100                &authority,
101                account,
102                &id.owner_account_uuid,
103                &id.owner_id,
104            )?;
105        }
106        (NativeOwner::LocalKey(key), 2) if key == &g.creator && envelope.is_empty() => (),
107        _ => return Err(Reject::GenesisBinding),
108    }
109    import::verify_authorization_signature(
110        &b.creator_public_key,
111        GENESIS_DOMAIN,
112        b,
113        signed.creator_signature.as_ref().ok_or(Reject::Signature)?,
114    )
115}
116pub fn verify_genesis_payload(
117    s: &host::HostedWitnessStatementV1,
118    p: &api::NativeGenesisWitnessV1,
119) -> Result<(), Reject> {
120    if p.format_version != 1 || p.kind != 2 {
121        return Err(Reject::Version);
122    }
123    let binding = p.binding.as_ref().ok_or(Reject::GenesisBinding)?;
124    let original = p.original_genesis.as_ref().ok_or(Reject::Canonical)?;
125    verify_genesis_authority(binding, original, &p.creator_authority_envelope)?;
126    let b = binding.body.as_ref().ok_or(Reject::GenesisBinding)?;
127    let id = b.identity.as_ref().ok_or(Reject::Canonical)?;
128    import::match_boundary(
129        s,
130        &p.boundary_acceptance.iter().cloned().collect::<Vec<_>>(),
131    )?;
132    if (s.basis == 2) != p.boundary_acceptance.is_some() {
133        return Err(Reject::BoundaryAcceptance);
134    }
135    if let Some(e) = &p.boundary_acceptance {
136        import::boundary_original(e, original)?;
137    }
138    if s.purpose != 1
139        || s.spool_uuid != id.spool_uuid
140        || s.spool_genesis_digest != id.spool_genesis_digest
141        || (s.basis == 1
142            && (s.owner_id != id.owner_id
143                || s.owner_state_hash != id.owner_state_hash
144                || s.ownership_transfer_sequence != id.ownership_transfer_sequence))
145        || s.canonical_payload != canonical(p)?
146        || s.authority_digest != signed_genesis_digest(binding)?
147        || s.original_signatures_digest != b.original_signatures_digest
148        || s.publisher_key_id != b.publisher_key_id
149    {
150        return Err(Reject::Scope);
151    }
152    if s.canonical_payload.len() > import::MAX_RECORD_BYTES {
153        return Err(Reject::Bounds);
154    }
155    Ok(())
156}
157fn sorted<T>(values: &[T], digest: impl Fn(&T) -> Result<Vec<u8>, Reject>) -> Result<(), Reject> {
158    let mut previous = None;
159    for v in values {
160        let h = digest(v)?;
161        if previous.as_ref().is_some_and(|p| p >= &h) {
162            return Err(Reject::Canonical);
163        }
164        previous = Some(h);
165    }
166    Ok(())
167}
168fn authority_payload_digest(p: &api::ImportAuthorityWitnessV1) -> Result<Vec<u8>, Reject> {
169    signing_digest("heddle-import-authority-witness-payload-v1", p)
170}
171/// Reference completeness, including a statement for every sidecar, a witnessed
172/// genesis for every original/dependency and an explicit claim for LocalKey.
173/// Presence is never permission. Call verify_bundle_witnesses with a
174/// separately authenticated fresh set, then native owner/model verification.
175pub fn validate_public_bundle(b: &api::NativePublicProofBundleV1) -> Result<(), Reject> {
176    crate::writer_authority::validate_owner_histories(&b.owner_histories)?;
177    if b.format_version != 1 {
178        return Err(Reject::Version);
179    }
180    if b.encoded_len() > import::MAX_BUNDLE_BYTES
181        || b.owner_histories.len() > 64
182        || b.ownership_transfers.len() > 64
183        || b.owner_chains.is_empty()
184        || b.owner_chains.len() > 64
185        || b.policies.len() > 256
186        || b.genesis_witnesses.is_empty()
187        || b.genesis_witnesses.len() > 256
188        || b.authority_witnesses.len() > 256
189        || b.landing_witnesses.len() > 256
190        || b.statements.len() > 1024
191        || b.history_proofs.len() > 1024
192    {
193        return Err(Reject::Bounds);
194    }
195    let mut foreign = crate::foreign_dependencies::References::new(
196        &b.foreign_dependencies,
197        api::ForeignDependencyOrigin::Native,
198    )?;
199    let owner = b
200        .owner_genesis
201        .as_ref()
202        .and_then(|o| o.genesis.as_ref())
203        .ok_or(Reject::Canonical)?;
204    sorted(&b.owner_chains, import::owner_chain_digest)?;
205    let chain = b.owner_chains.first().ok_or(Reject::Canonical)?;
206    b.witness_set.as_ref().ok_or(Reject::Canonical)?;
207    for retained in &b.owner_chains {
208        if retained.spool_genesis_digest != chain.spool_genesis_digest
209            || retained
210                .owner_state_hashes
211                .iter()
212                .any(|h| !b.owner_histories.iter().any(|o| o.state_hash == *h))
213            || retained.transfer_audit_hashes.iter().any(|h| {
214                !b.ownership_transfers
215                    .iter()
216                    .any(|t| t.audit_record_hash == *h)
217            })
218        {
219            return Err(Reject::Scope);
220        }
221    }
222    sorted(&b.genesis_witnesses, |p| {
223        signed_genesis_digest(p.binding.as_ref().ok_or(Reject::GenesisBinding)?)
224    })?;
225    sorted(&b.authority_witnesses, authority_payload_digest)?;
226    sorted(&b.landing_witnesses, |p| {
227        signing_digest("heddle-hosted-landing-witness-payload-v1", p)
228    })?;
229    sorted(&b.statements, |s| {
230        crate::witness_trust::statement_signing_digest(s.body.as_ref().ok_or(Reject::Canonical)?)
231    })?;
232    for p in &b.genesis_witnesses {
233        let binding = p.binding.as_ref().ok_or(Reject::GenesisBinding)?;
234        let g = binding.body.as_ref().ok_or(Reject::GenesisBinding)?;
235        let id = g.identity.as_ref().ok_or(Reject::Canonical)?;
236        verify_genesis_authority(
237            binding,
238            p.original_genesis.as_ref().ok_or(Reject::Canonical)?,
239            &p.creator_authority_envelope,
240        )?;
241        if id.spool_uuid != owner.spool_uuid
242            || id.spool_genesis_digest != chain.spool_genesis_digest
243            || !b
244                .owner_chains
245                .iter()
246                .any(|c| import::owner_chain_digest(c).is_ok_and(|h| h == g.owner_chain_digest))
247            || !b.owner_histories.iter().any(|h| {
248                h.state_hash == id.owner_state_hash
249                    && h.root
250                        .as_ref()
251                        .and_then(|r| r.root.as_ref())
252                        .is_some_and(|r| {
253                            r.owner_id == id.owner_id && r.account_uuid == id.owner_account_uuid
254                        })
255            })
256        {
257            return Err(Reject::Scope);
258        }
259        if g.owner_kind == 2
260            && !b.authority_witnesses.iter().any(|a| {
261                a.kind == 2
262                    && a.original
263                        .as_ref()
264                        .is_some_and(|o| thread(o).is_ok_and(|t| t == g.genesis_digest))
265            })
266        {
267            return Err(Reject::Scope);
268        }
269        require_statement(b, 1, &canonical(p)?)?;
270    }
271    for p in &b.authority_witnesses {
272        require_statement(b, 2, &canonical(p)?)?;
273        if !requires_authority(p.original.as_ref().ok_or(Reject::Canonical)?)? {
274            return Err(Reject::Scope);
275        }
276        let subject_thread = thread(p.original.as_ref().ok_or(Reject::Canonical)?)?;
277        if !b.genesis_witnesses.iter().any(|g| {
278            g.original_genesis
279                .as_ref()
280                .is_some_and(|g| import::native_id(g) == subject_thread)
281        }) {
282            return Err(Reject::Scope);
283        }
284        for original in p.original.iter().chain(p.dependencies.iter()) {
285            if [
286                "heddle-thread-genesis-v1",
287                "heddle-thread-operation-v1",
288                "heddle-thread-ownership-claim-v1",
289                "heddle-thread-ownership-resolution-v1",
290            ]
291            .contains(&original.format.as_str())
292            {
293                let t = thread(original)?;
294                if !b.genesis_witnesses.iter().any(|g| {
295                    g.original_genesis
296                        .as_ref()
297                        .is_some_and(|o| import::native_id(o) == t)
298                }) {
299                    foreign.require(original)?;
300                    continue;
301                }
302                if original.format == "heddle-thread-genesis-v1"
303                    && !b
304                        .genesis_witnesses
305                        .iter()
306                        .any(|g| g.original_genesis.as_ref() == Some(original))
307                {
308                    return Err(Reject::Scope);
309                }
310                if original.format != "heddle-thread-genesis-v1"
311                    && p.original.as_ref() != Some(original)
312                {
313                    require_native_dependency(b, original, &mut foreign)?;
314                }
315            } else if ![
316                "heddle-original-boundary-acceptance-v1",
317                "heddle-thread-genesis-admission-v2",
318                "heddle-thread-authority-admission-v3",
319            ]
320            .contains(&original.format.as_str())
321            {
322                return Err(Reject::Version);
323            }
324        }
325    }
326    for p in &b.landing_witnesses {
327        require_statement(b, 4, &canonical(p)?)?;
328        let execution = p.execution.as_ref().ok_or(Reject::Canonical)?;
329        let op: OperationSelectors =
330            rmp_serde::from_slice(&execution.canonical_record).map_err(|_| Reject::Canonical)?;
331        if execution.format != "heddle-thread-operation-v1" || op.body.kind != "integration" {
332            return Err(Reject::Scope);
333        }
334        if !b.genesis_witnesses.iter().any(|g| {
335            g.original_genesis
336                .as_ref()
337                .is_some_and(|o| thread(execution).is_ok_and(|t| import::native_id(o) == t))
338        }) {
339            return Err(Reject::Scope);
340        }
341        for original in p.source_operation.iter().chain(p.review_evidence.iter()) {
342            require_native_dependency(b, original, &mut foreign)?;
343        }
344    }
345    for signed in &b.statements {
346        let s = signed.body.as_ref().ok_or(Reject::Canonical)?;
347        if s.spool_uuid != owner.spool_uuid
348            || s.spool_genesis_digest != chain.spool_genesis_digest
349            || !b.owner_histories.iter().any(|h| {
350                h.state_hash == s.owner_state_hash
351                    && h.root
352                        .as_ref()
353                        .and_then(|r| r.root.as_ref())
354                        .is_some_and(|r| r.owner_id == s.owner_id)
355            })
356        {
357            return Err(Reject::Scope);
358        }
359        // Reuse the unchanged policy chain completeness contract.
360        import::require_policy_history(
361            &b.policies,
362            &s.spool_uuid,
363            s.policy_sequence,
364            &s.policy_state_hash,
365        )?;
366        match s.purpose {
367            1 => {
368                let p = b
369                    .genesis_witnesses
370                    .iter()
371                    .find(|p| canonical(*p).is_ok_and(|v| v == s.canonical_payload))
372                    .ok_or(Reject::Scope)?;
373                verify_genesis_payload(s, p)?;
374                crate::writer_authority::check_witness_writer(
375                    s,
376                    &p.creator_authority_envelope,
377                    &b.owner_histories,
378                    &b.policies,
379                    crate::writer_authority::spool_account_for_statement(
380                        s,
381                        b.genesis_witnesses
382                            .iter()
383                            .filter_map(|p| p.binding.as_ref()?.body.as_ref()?.identity.as_ref()),
384                        &b.ownership_transfers,
385                    )?,
386                    &[],
387                    p.boundary_acceptance.as_ref(),
388                )?;
389            }
390            2 => {
391                let p = b
392                    .authority_witnesses
393                    .iter()
394                    .find(|p| canonical(*p).is_ok_and(|v| v == s.canonical_payload))
395                    .ok_or(Reject::Scope)?;
396                import::verify_witness_payload(s, import::WitnessPayload::Authority(p))?;
397                crate::writer_authority::check_witness_writer(
398                    s,
399                    &p.authority_envelope,
400                    &b.owner_histories,
401                    &b.policies,
402                    crate::writer_authority::spool_account_for_statement(
403                        s,
404                        b.genesis_witnesses
405                            .iter()
406                            .filter_map(|p| p.binding.as_ref()?.body.as_ref()?.identity.as_ref()),
407                        &b.ownership_transfers,
408                    )?,
409                    p.original
410                        .as_ref()
411                        .filter(|_| p.kind == 2 || p.kind == 3)
412                        .map(|r| r.signatures.as_slice())
413                        .unwrap_or(&[]),
414                    p.boundary_acceptances
415                        .iter()
416                        .find(|e| e.binding == s.boundary_acceptance),
417                )?;
418            }
419            4 => {
420                let p = b
421                    .landing_witnesses
422                    .iter()
423                    .find(|p| canonical(*p).is_ok_and(|v| v == s.canonical_payload))
424                    .ok_or(Reject::Scope)?;
425                import::verify_witness_payload(s, import::WitnessPayload::Landing(p))?;
426                crate::writer_authority::check_witness_writer(
427                    s,
428                    &p.authority_envelope,
429                    &b.owner_histories,
430                    &b.policies,
431                    crate::writer_authority::spool_account_for_statement(
432                        s,
433                        b.genesis_witnesses
434                            .iter()
435                            .filter_map(|p| p.binding.as_ref()?.body.as_ref()?.identity.as_ref()),
436                        &b.ownership_transfers,
437                    )?,
438                    &[],
439                    None,
440                )?;
441            }
442            _ => return Err(Reject::Version),
443        }
444    }
445    foreign.finish()
446}
447#[derive(serde::Deserialize)]
448struct OperationSelectors {
449    body: OperationBodySelectors,
450}
451#[derive(serde::Deserialize)]
452struct OperationBodySelectors {
453    kind: String,
454}
455#[derive(serde::Deserialize)]
456struct CaptureOperationSelectors {
457    body: CaptureBodySelectors,
458}
459#[derive(serde::Deserialize)]
460struct CaptureBodySelectors {
461    canonical: CaptureSelectors,
462}
463#[derive(serde::Deserialize)]
464struct CaptureSelectors {
465    author: OperationBodySelectors,
466}
467#[derive(serde::Deserialize)]
468struct LocalIntegrationOperationSelectors {
469    body: LocalIntegrationBodySelectors,
470}
471#[derive(serde::Deserialize)]
472struct LocalIntegrationBodySelectors {
473    canonical: Vec<u8>,
474}
475fn requires_authority(record: &api::SignedRecord) -> Result<bool, Reject> {
476    if record.format != "heddle-thread-operation-v1" {
477        return Ok(true);
478    }
479    let op: OperationSelectors =
480        rmp_serde::from_slice(&record.canonical_record).map_err(|_| Reject::Canonical)?;
481    if op.body.kind == "integration" {
482        return Ok(false);
483    }
484    match op.body.kind.as_str() {
485        "capture" => {
486            let op: CaptureOperationSelectors =
487                rmp_serde::from_slice(&record.canonical_record).map_err(|_| Reject::Canonical)?;
488            Ok(op.body.canonical.author.kind != "local_key")
489        }
490        "local_integration" => {
491            let op: LocalIntegrationOperationSelectors =
492                rmp_serde::from_slice(&record.canonical_record).map_err(|_| Reject::Canonical)?;
493            let integration: CaptureSelectors =
494                rmp_serde::from_slice(&op.body.canonical).map_err(|_| Reject::Canonical)?;
495            Ok(integration.author.kind != "local_key")
496        }
497        _ => Ok(true),
498    }
499}
500fn require_native_dependency(
501    b: &api::NativePublicProofBundleV1,
502    original: &api::SignedRecord,
503    foreign: &mut crate::foreign_dependencies::References<'_>,
504) -> Result<(), Reject> {
505    let t = thread(original)?;
506    if !b.genesis_witnesses.iter().any(|g| {
507        g.original_genesis
508            .as_ref()
509            .is_some_and(|o| import::native_id(o) == t)
510    }) {
511        return foreign.require(original);
512    }
513    if requires_authority(original)? {
514        let p = b
515            .authority_witnesses
516            .iter()
517            .find(|p| p.original.as_ref() == Some(original))
518            .ok_or(Reject::Scope)?;
519        return require_statement(b, 2, &canonical(p)?);
520    }
521    let op: OperationSelectors =
522        rmp_serde::from_slice(&original.canonical_record).map_err(|_| Reject::Canonical)?;
523    if op.body.kind == "integration" {
524        let p = b
525            .landing_witnesses
526            .iter()
527            .find(|p| p.execution.as_ref() == Some(original))
528            .ok_or(Reject::Scope)?;
529        return require_statement(b, 4, &canonical(p)?);
530    }
531    // Local captures and LocalKey integrations retain native proof and the
532    // thread's exact hosted ownership claim, never an authority/landing receipt.
533    // This establishes reference closure only. Native authorization must bind
534    // publisher to genesis.owner.local_key and enforce the selected signed cutoff.
535    import::verify_native(original, "heddle-thread-operation-v1")?;
536    let t = thread(original)?;
537    let claim = b
538        .authority_witnesses
539        .iter()
540        .find(|p| {
541            p.kind == 2
542                && p.original
543                    .as_ref()
544                    .is_some_and(|o| thread(o).is_ok_and(|id| id == t))
545        })
546        .ok_or(Reject::Scope)?;
547    require_statement(b, 2, &canonical(claim)?)
548}
549fn require_statement(
550    b: &api::NativePublicProofBundleV1,
551    purpose: i32,
552    payload: &[u8],
553) -> Result<(), Reject> {
554    if b.statements
555        .iter()
556        .filter(|s| {
557            s.body
558                .as_ref()
559                .is_some_and(|s| s.purpose == purpose && s.canonical_payload == payload)
560        })
561        .count()
562        != 1
563    {
564        return Err(Reject::Scope);
565    }
566    Ok(())
567}
568/// Authenticate every exact statement against a separately selected fresh set.
569/// RETIRED statements require exact proofs; carrier sets cannot select roots.
570pub fn verify_bundle_witnesses(
571    b: &api::NativePublicProofBundleV1,
572    set: &crate::witness_trust::VerifiedWitnessSet,
573    now_ms: i64,
574    forbidden_landing_keys: &[Vec<u8>],
575) -> Result<(), Reject> {
576    validate_public_bundle(b)?;
577    for p in &b.landing_witnesses {
578        import::verify_landing_key_roles(p, set.known_job_keys(), forbidden_landing_keys)?;
579    }
580    let carried = b.witness_set.as_ref().ok_or(Reject::Canonical)?;
581    if carried.body.as_ref() != Some(set.body()) || carried.body_digest != set.digest() {
582        return Err(Reject::StaleContext);
583    }
584    for signed in &b.statements {
585        match crate::witness_trust::resolve_statement(set, signed, None, false, now_ms) {
586            Ok(_) => continue,
587            Err(Reject::Proof) => (),
588            Err(e) => return Err(e),
589        }
590        let statement = signed.body.as_ref().ok_or(Reject::Canonical)?;
591        let entry = set
592            .body()
593            .entries
594            .iter()
595            .find(|e| e.executor_id == statement.executor_id)
596            .ok_or(Reject::Root)?;
597        let leaf = crate::witness_trust::leaf_digest(
598            statement.purpose,
599            &canonical(statement)?,
600            &signed.signature,
601        )?;
602        // Search exact Merkle paths without repeating signature verification
603        // for every candidate. Only the matching proof is resolved finally.
604        let proof = b
605            .history_proofs
606            .iter()
607            .find(|p| {
608                p.purpose == statement.purpose
609                    && crate::witness_trust::verify_inclusion(&leaf, p, entry).is_ok()
610            })
611            .ok_or(Reject::Proof)?;
612        crate::witness_trust::resolve_statement(set, signed, Some(proof), false, now_ms)?;
613    }
614    Ok(())
615}
616/// Select a LocalKey original's own-origin proof cutoff from an independently
617/// verified native carrier. Native causal/owner verification remains required.
618/// The caller supplies the dependent statement's authenticated admission order.
619/// Later admissions are ignored for both conflict selection and the maximum.
620pub fn local_work_cutoff(
621    b: &api::NativePublicProofBundleV1,
622    original: &api::SignedRecord,
623    dependent_admission_order: u64,
624) -> Result<u64, Reject> {
625    let subject = thread(original)?;
626    let mut genesis_count = 0;
627    let mut orders = Vec::new();
628    let mut claims = Vec::new();
629    let mut resolutions = Vec::new();
630    for signed in &b.statements {
631        let s = signed.body.as_ref().ok_or(Reject::Canonical)?;
632        if s.admission_order > dependent_admission_order {
633            continue;
634        }
635        if s.purpose == 1 {
636            for p in &b.genesis_witnesses {
637                let binding = p
638                    .binding
639                    .as_ref()
640                    .and_then(|v| v.body.as_ref())
641                    .ok_or(Reject::Canonical)?;
642                if binding.genesis_digest == subject && s.canonical_payload == canonical(p)? {
643                    if binding.owner_kind != 2 {
644                        return Err(Reject::Scope);
645                    }
646                    genesis_count += 1;
647                    orders.push(s.admission_order);
648                }
649            }
650        } else if s.purpose == 2 {
651            for p in &b.authority_witnesses {
652                if ![2, 3].contains(&p.kind) || s.canonical_payload != canonical(p)? {
653                    continue;
654                }
655                let r = p.original.as_ref().ok_or(Reject::Canonical)?;
656                if thread(r)? != subject {
657                    continue;
658                }
659                orders.push(s.admission_order);
660                if p.kind == 2 {
661                    claims.push(import::native_id(r));
662                } else {
663                    resolutions.push(r);
664                }
665            }
666        }
667    }
668    if genesis_count != 1 {
669        return Err(Reject::Scope);
670    }
671    match resolutions.as_slice() {
672        [] if claims.len() == 1 => (),
673        [r] => {
674            #[derive(serde::Deserialize)]
675            struct Resolution {
676                winning_claim: Vec<u8>,
677                conflicting_claims: Vec<Vec<u8>>,
678            }
679            let r: Resolution =
680                rmp_serde::from_slice(&r.canonical_record).map_err(|_| Reject::Canonical)?;
681            claims.sort();
682            if claims != r.conflicting_claims || !claims.contains(&r.winning_claim) {
683                return Err(Reject::Scope);
684            }
685        }
686        _ => return Err(Reject::Scope),
687    }
688    orders
689        .into_iter()
690        .max()
691        .filter(|v| *v > 0)
692        .ok_or(Reject::Scope)
693}
694/// Transport dispatch is explicit and rejects dual arms before staging. Missing
695/// import delegation remains an import rejection, never native fallback.
696pub fn validate_carriers(
697    imported: Option<&api::ImportPublicProofBundleV1>,
698    native: Option<&api::NativePublicProofBundleV1>,
699) -> Result<(), Reject> {
700    match (imported, native) {
701        (Some(_), Some(_)) => Err(Reject::Protocol),
702        (Some(b), None) => import::validate_public_bundle(b),
703        (None, Some(b)) => validate_public_bundle(b),
704        (None, None) => Ok(()), // Purely local; hosted mandatory gate is a caller gate.
705    }
706}