ASELSANMicrokernel
S545 · SOURCE-BOUND GATE EVIDENCE

S545 · R1 reachable-producer candidate freeze ve pre-arm sözleşmesi

tam S545 implementation modülü → Operations --test hedefi ile bağlı tam focused test → ayrı Operations kaydı Bu sayfa yalnız S545 kapısına aittir; komşu kapıların kaynakları bu kabulün içine katılmaz.

S545Focused kod testiOperations id exactsource SHA exacttest target exact

operation: g8l-s545-r1-reachable-producer-candidate-freeze-prearm-contract

uygulama/model · focused test · Operations · 3 exact excerpt

sequence-bound=true · implementation-bound=true
01 · Yürütme / doğrulama kodu

Kapının gerçek repository sözleşmesi

tam dosyaL1–L1043
kernel/src/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s545_r1_reachable_producer_candidate_freeze_prearm_contract.rs::S545 r1 reachable producer candidate freeze prearm contract implementation
//! S545 models the host-only freeze of the first RPi5 candidate that contains
//! the S544 reachable CPU1 readiness producer hook, and pins the pre-arm
//! contract that a later S546 physical run must bind before any device
//! operation.
//!
//! The freeze itself was executed by the integrator on the host with the
//! read-only layout verifier and the freeze tool.  This module records the
//! resulting identities as constants and re-derives the freeze receipt from a
//! structured observation: two isolated `CARGO_INCREMENTAL=0` builds with
//! byte-identical ELF and flat image, a read-only machine/layout audit that
//! left the input ELF unchanged, a four-entry `0444` package with a
//! grammar-checked `SHA256SUMS` manifest, exact marker membership, and the
//! `MARKER_LITERAL_MERGED` disposition of the `[R1:S536] BOOT_TO_UI_READY`
//! literal.
//!
//! It performs no device operation, does not rerun S543, opens no serial
//! descriptor, writes no SD card, and reports no power transition.  It is not
//! wired into any boot, IRQ, scheduler or driver path.  The pre-arm contract
//! for S546 is contract-only: `execution_permit` is always `false`, and the
//! authorization token is parsed and compared, never acted upon.
//!
//! Predecessor: S544 (reachable readiness producer remediation).  Next gate:
//! S546 (third authorized physical boot/UART run with this exact package,
//! pending explicit operator authority; not automatic).

pub const S545_SEQUENCE: usize = 545;
pub const S545_EXPECTED_PREDECESSOR: usize = 544;
pub const S545_NEXT_SEQUENCE: usize = 546;
pub const S545_R1_STAGE: u8 = 1;
pub const S545_R1_RANGE_FIRST: usize = 536;
pub const S545_R1_RANGE_LAST: usize = 568;
pub const S545_SUPPORTED_PROFILE_RUNTIME_OBSERVATIONS: usize = 0;
pub const S545_PHYSICAL_OBSERVATIONS: usize = 0;
pub const S545_PHYSICAL_OR_DEVICE_OPERATIONS: usize = 0;
pub const S545_SD_WRITES: usize = 0;
pub const S545_UART_OPENS: usize = 0;
pub const S545_POWER_TRANSITIONS: usize = 0;
pub const S545_NEW_IMMUTABLE_RAW_CAPTURES: usize = 0;
pub const S545_S540_PHYSICAL_VERDICT_RETAINED_RED: bool = true;
pub const S545_S543_PHYSICAL_VERDICT_RETAINED_RED: bool = true;
pub const S545_AUTOMATIC_PROMOTION: bool = false;
pub const S545_BOOT_TO_UI_PHYSICALLY_OBSERVED: bool = false;
pub const S545_HARDWARE_PRESENT: bool = false;
pub const S545_R1_ACCEPTANCE_COMPLETE: bool = false;
pub const S545_EXECUTION_PERMIT: bool = false;
pub const RUNBOOK_EXECUTED_IN_S545: bool = false;

// Isolated build facts (host, integrator-executed).
pub const S545_CANDIDATE_PROFILE: &str = "board-rpi5";
pub const S545_CARGO_FEATURE_FLAGS: &str = "--no-default-features --features board-rpi5";
pub const S545_CARGO_INCREMENTAL: u8 = 0;
pub const S545_ISOLATED_BUILD_COUNT: usize = 2;
pub const S545_ELF_BYTES: u64 = 18_438_504;
pub const S545_ELF_SHA256: &str =
    "6ce50d295e0aa97ab599cfa3cf567944ca7ed36d59d1b988e733be48b826c1c5";
pub const S545_BUILD_A_LOG_BYTES: u64 = 1_135_955;
pub const S545_BUILD_A_LOG_SHA256: &str =
    "5aa11909f47b6ebe27b0dd18aa036573a48b37f05a966831aa089d3a3b6e73be";
pub const S545_BUILD_B_LOG_BYTES: u64 = 1_135_948;
pub const S545_BUILD_B_LOG_SHA256: &str =
    "61160d45cc3114360a6107a96c557282ae9eaab76b13d3b8347c63b516468670";
pub const S545_BUILD_WARNING_HEADERS_EACH: usize = 2_865;
pub const S545_ZERO_WARNING_CLAIMED: bool = false;

// Flat image and the superseded S542 image it must not equal.
pub const S545_IMAGE_BYTES: u64 = 945_760;
pub const S545_IMAGE_SHA256: &str =
    "ed1901a991e2f9e9ae3c16f254147a2b0180686a8d70ca5d7353374fee08d467";
pub const S545_SUPERSEDED_S542_IMAGE_BYTES: u64 = 941_392;
pub const S545_SUPERSEDED_S542_IMAGE_SHA256: &str =
    "aa0c459b987c3f4c143b4eb14ce0ed655c2812e2a36516793e7bd8b27b60d87c";

// Frozen package.
pub const S545_PACKAGE_DIRECTORY: &str = "evidence/rpi5/r1/sequence-545-candidate-freeze/package";
pub const S545_PACKAGE_ENTRIES: usize = 4;
pub const S545_PACKAGE_MODE: u32 = 0o444;
pub const S545_PACKAGE_NLINK: u32 = 1;
pub const S545_IMAGE_NAME: &str = "aselsanos-rpi5.img";
pub const S545_DTB_NAME: &str = "bcm2712-rpi-5-b.dtb";
pub const S545_CONFIG_NAME: &str = "config.txt";
pub const S545_MANIFEST_NAME: &str = "SHA256SUMS";
pub const S545_DTB_BYTES: u64 = 78_703;
pub const S545_DTB_SHA256: &str =
    "40a2fbe9c29e8b9a4912cf726a943068defb779fc052ec38e457a79c58abca00";
pub const S545_CONFIG_BYTES: u64 = 420;
pub const S545_CONFIG_SHA256: &str =
    "aef848bf6e0c324148eade5054a15c71a1e8c04814a3ed2e680056f87c1f9bba";
pub const S545_MANIFEST_BYTES: u64 = 248;
pub const S545_MANIFEST_SHA256: &str =
    "4accd201849f68107db4d21e4657b1510f043d7f900f713c383bd8909d33e586";
pub const S545_MANIFEST_LINES: usize = 3;
pub const S545_CONFIG_REQUIRED_DIRECTIVES: [&str; 4] = [
    "kernel=aselsanos-rpi5.img",
    "arm_64bit=1",
    "kernel_address=0x80000",
    "uart_2ndstage=0",
];
pub const S545_CONFIG_FORBIDDEN_DIRECTIVE: &str = "uart_2ndstage=1";

// Host tools (read-only audit and freeze; no disk, serial or power command).
pub const S545_LAYOUT_VERIFIER_PATH: &str = "scripts/verify-rpi5-s545-layout.sh";
pub const S545_LAYOUT_VERIFIER_BYTES: u64 = 11_150;
pub const S545_LAYOUT_VERIFIER_SHA256: &str =
    "7a23bf574cda06d0fb4710d0c97427c0a743c7df4a3628d31077a220ad4140cd";
pub const S545_FREEZE_TOOL_PATH: &str = "scripts/freeze-rpi5-s545-r1-candidate.sh";
pub const S545_FREEZE_TOOL_BYTES: u64 = 9_175;
pub const S545_FREEZE_TOOL_SHA256: &str =
    "ddd0f3baf1c2e47c26e97d1ee33d8ce00746dc6f5b64149489a63ff9cb42cfcd";
pub const S545_FIRMWARE_CONFIG_PATH: &str = "firmware/config-r1-s545.txt";

// Read-only machine/layout audit expectations.
pub const S545_ENTRY_ADDRESS: u64 = 0x80000;
pub const S545_KERNEL_START: u64 = 0x80000;
pub const S545_KERNEL_END: u64 = 0x11f_8000;
pub const S545_LINKED_SPAN: u64 = 18_317_312;
pub const S545_CPU1_TEXT_ORDER: [&str; 6] = [
    "validate_identity_or_fail",
    "service_s431_to_s535_production_acceptance_gate_on_cpu1",
    "service_s536_r1_physical_boot_uart_evidence_contract_on_cpu1",
    "service_s537_r1_physical_boot_uart_evidence_request_on_cpu1",
    "service_s541_readiness_handoff_on_cpu1",
    "service_s544_model_reachable_readiness_producer",
];
pub const S545_CPU0_TEXT_ORDER: [&str; 3] = [
    "rpi5_g8h_prerequisite_complete",
    "enter_s541_readiness_handoff_then_s538_boot_ui_on_cpu0",
    "enter_s538_boot_ui_marker_runtime_on_cpu0",
];
pub const S545_S544_INLINED_SYMBOLS: [&str; 2] = [
    "service_s544_model_reachable_readiness_producer",
    "S544_PRODUCTION_STATE",
];

// Marker membership in the flat image (`strings | grep -c`).
pub const S545_MARKER_COUNT: usize = 7;
pub const S545_S541_HANDOFF_MARKER: &str = "ASELSAN/S541 HANDOFF=CPU1_PREFLIGHT_ARMED";
pub const S545_S541_ERROR_MARKER: &str = "ASELSAN/S541ERR";
pub const S545_BOOT_TO_UI_MARKER: &str = "[R1:S536] BOOT_TO_UI_READY";
pub const S545_S538_ROUTE_MARKER: &str = "ASELSAN/S538 ROUTE=PRIOR_BOOT_TO_UI";
pub const S545_S538_ERROR_MARKER: &str = "ASELSAN/S538ERR";
pub const S545_S538_CANDIDATE_TAG: &str = "ASELSAN-R1-S538-BOARD-RPI5";
pub const S545_BOOT8H_MARKER: &str = "ASELSAN/BOOT8H";
pub const S545_BOOT_TO_UI_MARKER_S542_COUNT: usize = 2;
pub const S545_BOOT_TO_UI_MARKER_SOURCE_REFERENCES: usize = 2;

// Pre-arm contract literals for S546 (contract only; no permit, no execution).
pub const S545_PREARM_CARD_SERIAL: u32 = 0x425001fa;
pub const S545_PREARM_CARD_SERIAL_HEX: &str = "0x425001fa";
pub const S545_PREARM_CARD_RAW_CID: &str = "009f5449534436344761425001fa01a1";
pub const S545_PREARM_CARD_BYTES: u64 = 62_549_655_552;
pub const S545_PREARM_CARD_NAME: &str = "TISD64G";
pub const S545_PREARM_VOLUME_LABEL: &str = "ASELSANBOOT";
pub const S545_PREARM_DEBUG_PROBE_SERIAL: &str = "E6647C74033F9131";
/// Last resolved serial path; S546 must freshly re-resolve it, never reuse it.
pub const S545_PREARM_SERIAL_PATH_LAST_RESOLVED: &str = "/dev/cu.usbmodem21302";
pub const S545_PREARM_UART_BAUD: u32 = 115_200;
pub const S545_PREARM_UART_DATA_BITS: u8 = 8;
pub const S545_PREARM_UART_STOP_BITS: u8 = 1;
pub const S545_PREARM_AUTHORIZATION_TOKEN: &str =
    "S546_AUTHORIZE_SD_WRITE_READBACK_EJECT_UART_PREARM_ONE_POWER_ON_ed1901a9_425001fa_62549655552";
pub const S545_PREARM_AUTHORIZATION_PREFIX: &str =
    "S546_AUTHORIZE_SD_WRITE_READBACK_EJECT_UART_PREARM_ONE_POWER_ON";

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS545ArtifactIdentity {
    pub bytes: u64,
    pub sha256: &'static str,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS545IsolatedBuildObservation {
    pub cargo_incremental: u8,
    pub profile: &'static str,
    pub feature_flags: &'static str,
    pub target_root_isolated: bool,
    pub elf: G8lS545ArtifactIdentity,
    pub log: G8lS545ArtifactIdentity,
    pub warning_headers: usize,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS545ReproducibilityObservation {
    pub isolated_builds: usize,
    pub build_a: G8lS545IsolatedBuildObservation,
    pub build_b: G8lS545IsolatedBuildObservation,
    pub image: G8lS545ArtifactIdentity,
    pub superseded_s542_image: G8lS545ArtifactIdentity,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS545LayoutAuditObservation {
    pub entry: u64,
    pub kernel_start: u64,
    pub kernel_end: u64,
    pub cpu1_text_lines: [u32; 6],
    pub cpu1_call_counts: [u32; 6],
    pub s544_inlined_symbol_counts: [u32; 2],
    pub cpu0_text_lines: [u32; 3],
    pub ldaxr_present: bool,
    pub stlxr_present: bool,
    pub dsb_ishst_count: u32,
    pub sev_count: u32,
    pub ldar_count: u32,
    pub elf_before: G8lS545ArtifactIdentity,
    pub elf_after: G8lS545ArtifactIdentity,
    pub objcopy_invoked: bool,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS545PackageEntryObservation {
    pub name: &'static str,
    pub identity: G8lS545ArtifactIdentity,
    pub mode: u32,
    pub nlink: u32,
    pub inode: u64,
    pub regular_non_symlink: bool,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS545ToolObservation {
    pub layout_verifier: G8lS545ArtifactIdentity,
    pub freeze_tool: G8lS545ArtifactIdentity,
    pub firmware_config: G8lS545ArtifactIdentity,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS545FreezeInput<'a> {
    pub s544_source_gate_passed: bool,
    pub reproducibility: G8lS545ReproducibilityObservation,
    pub layout: G8lS545LayoutAuditObservation,
    pub package: [G8lS545PackageEntryObservation; 4],
    pub manifest_text: &'a str,
    pub config_text: &'a str,
    pub marker_counts: [usize; 7],
    pub tools: G8lS545ToolObservation,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS545MarkerDisposition {
    ExactOnce,
    MarkerLiteralMerged { source_references: usize },
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS545MarkerExpectation {
    pub literal: &'static str,
    pub expected_count: usize,
    pub disposition: G8lS545MarkerDisposition,
}

pub const S545_MARKER_TABLE: [G8lS545MarkerExpectation; S545_MARKER_COUNT] = [
    G8lS545MarkerExpectation {
        literal: S545_S541_HANDOFF_MARKER,
        expected_count: 1,
        disposition: G8lS545MarkerDisposition::ExactOnce,
    },
    G8lS545MarkerExpectation {
        literal: S545_S541_ERROR_MARKER,
        expected_count: 1,
        disposition: G8lS545MarkerDisposition::ExactOnce,
    },
    G8lS545MarkerExpectation {
        literal: S545_BOOT_TO_UI_MARKER,
        expected_count: 1,
        disposition: G8lS545MarkerDisposition::MarkerLiteralMerged {
            source_references: S545_BOOT_TO_UI_MARKER_SOURCE_REFERENCES,
        },
    },
    G8lS545MarkerExpectation {
        literal: S545_S538_ROUTE_MARKER,
        expected_count: 1,
        disposition: G8lS545MarkerDisposition::ExactOnce,
    },
    G8lS545MarkerExpectation {
        literal: S545_S538_ERROR_MARKER,
        expected_count: 1,
        disposition: G8lS545MarkerDisposition::ExactOnce,
    },
    G8lS545MarkerExpectation {
        literal: S545_S538_CANDIDATE_TAG,
        expected_count: 1,
        disposition: G8lS545MarkerDisposition::ExactOnce,
    },
    G8lS545MarkerExpectation {
        literal: S545_BOOT8H_MARKER,
        expected_count: 1,
        disposition: G8lS545MarkerDisposition::ExactOnce,
    },
];

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS545CandidateFreezeReceipt {
    pub sequence: usize,
    pub predecessor_sequence: usize,
    pub next_sequence: usize,
    pub elf: G8lS545ArtifactIdentity,
    pub image: G8lS545ArtifactIdentity,
    pub superseded_s542_image_sha256: &'static str,
    pub isolated_builds: usize,
    pub warning_headers_each: usize,
    pub zero_warning_claimed: bool,
    pub linked_span: u64,
    pub package_entries: usize,
    pub package_mode: u32,
    pub package_inode_signature: u64,
    pub manifest_lines: usize,
    pub marker_literals_merged: usize,
    pub candidate_frozen: bool,
    pub s544_hook_present: bool,
    pub image_differs_from_s542: bool,
    pub input_elf_immutable: bool,
    pub execution_permit: bool,
    pub device_operations: usize,
    pub sd_writes: usize,
    pub uart_opens: usize,
    pub power_transitions: usize,
    pub supported_profile_runtime_observations: usize,
    pub physical_observations: usize,
    pub runbook_executed: bool,
}

#[derive(Debug)]
pub struct G8lS545CandidateFreezeState {
    receipt: Option<G8lS545CandidateFreezeReceipt>,
}

impl G8lS545CandidateFreezeState {
    pub const fn new() -> Self {
        Self { receipt: None }
    }

    pub const fn receipt(&self) -> Option<G8lS545CandidateFreezeReceipt> {
        self.receipt
    }
}

impl Default for G8lS545CandidateFreezeState {
    fn default() -> Self {
        Self::new()
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS545CandidateFreezeOutcome {
    CandidateFrozen(G8lS545CandidateFreezeReceipt),
    CandidateRetained(G8lS545CandidateFreezeReceipt),
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS545CandidateFreezeError {
    PredecessorNotAccepted,
    IsolatedBuildCountDrift,
    BuildIsolationDrift,
    ElfIdentityDrift,
    BuildsNotByteIdentical,
    BuildLogIdentityDrift,
    WarningHeaderCountDrift,
    ImageIdentityDrift,
    ImageRetriesRejectedCandidate,
    LayoutEntryDrift,
    LayoutSpanDrift,
    LayoutCallOrderDrift,
    LayoutSymbolCountDrift,
    LayoutBarrierDrift,
    ElfMutatedDuringAudit,
    PackageEntryNameDrift,
    PackageEntryIdentityDrift,
    PackageModeDrift,
    PackageHardLink,
    PackageInodeCollision,
    PackageInodeSignatureOverflow,
    ManifestLineCountDrift,
    ManifestDigestGrammar,
    ManifestSeparatorDrift,
    ManifestFileNameDrift,
    ManifestDigestMismatch,
    ConfigDirectiveDrift,
    MarkerCountDrift,
    ToolIdentityDrift,
    FrozenStateDrift,
    AuthorizationTokenDrift,
    AuthorizationTargetDrift,
    PrearmSequenceDrift,
    CandidateDrift,
}

impl G8lS545CandidateFreezeError {
    pub const fn diagnostic_code(self) -> u64 {
        match self {
            Self::PredecessorNotAccepted => 1,
            Self::IsolatedBuildCountDrift => 2,
            Self::BuildIsolationDrift => 3,
            Self::ElfIdentityDrift => 4,
            Self::BuildsNotByteIdentical => 5,
            Self::BuildLogIdentityDrift => 6,
            Self::WarningHeaderCountDrift => 7,
            Self::ImageIdentityDrift => 8,
            Self::ImageRetriesRejectedCandidate => 9,
            Self::LayoutEntryDrift => 10,
            Self::LayoutSpanDrift => 11,
            Self::LayoutCallOrderDrift => 12,
            Self::LayoutSymbolCountDrift => 13,
            Self::LayoutBarrierDrift => 14,
            Self::ElfMutatedDuringAudit => 15,
            Self::PackageEntryNameDrift => 16,
            Self::PackageEntryIdentityDrift => 17,
            Self::PackageModeDrift => 18,
            Self::PackageHardLink => 19,
            Self::PackageInodeCollision => 20,
            Self::ManifestLineCountDrift => 21,
            Self::ManifestDigestGrammar => 22,
            Self::ManifestSeparatorDrift => 23,
            Self::ManifestFileNameDrift => 24,
            Self::ManifestDigestMismatch => 25,
            Self::ConfigDirectiveDrift => 26,
            Self::MarkerCountDrift => 27,
            Self::ToolIdentityDrift => 28,
            Self::FrozenStateDrift => 29,
            Self::AuthorizationTokenDrift => 30,
            Self::AuthorizationTargetDrift => 31,
            Self::PrearmSequenceDrift => 32,
            Self::CandidateDrift => 33,
            Self::PackageInodeSignatureOverflow => 34,
        }
    }
}

const fn str_eq(left: &str, right: &str) -> bool {
    let left = left.as_bytes();
    let right = right.as_bytes();
    if left.len() != right.len() {
        return false;
    }
    let mut index = 0;
    while index < left.len() {
        if left[index] != right[index] {
            return false;
        }
        index += 1;
    }
    true
}

const fn identity_eq(left: G8lS545ArtifactIdentity, right: G8lS545ArtifactIdentity) -> bool {
    left.bytes == right.bytes && str_eq(left.sha256, right.sha256)
}

const fn is_lower_hex(byte: u8) -> bool {
    matches!(byte, b'0'..=b'9' | b'a'..=b'f')
}

pub const fn s545_identity(bytes: u64, sha256: &'static str) -> G8lS545ArtifactIdentity {
    G8lS545ArtifactIdentity { bytes, sha256 }
}

pub const fn s545_expected_package_identity(name: &str) -> Option<G8lS545ArtifactIdentity> {
    if str_eq(name, S545_IMAGE_NAME) {
        Some(s545_identity(S545_IMAGE_BYTES, S545_IMAGE_SHA256))
    } else if str_eq(name, S545_DTB_NAME) {
        Some(s545_identity(S545_DTB_BYTES, S545_DTB_SHA256))
    } else if str_eq(name, S545_CONFIG_NAME) {
        Some(s545_identity(S545_CONFIG_BYTES, S545_CONFIG_SHA256))
    } else if str_eq(name, S545_MANIFEST_NAME) {
        Some(s545_identity(S545_MANIFEST_BYTES, S545_MANIFEST_SHA256))
    } else {
        None
    }
}

/// Reproducibility predicate: two isolated, non-incremental builds of the same
/// profile must emit byte-identical ELF and image; the logs may differ only in
/// their isolated target roots and are therefore bound by identity, not equality.
pub const fn s545_reproducibility_holds(observation: &G8lS545ReproducibilityObservation) -> bool {
    let a = observation.build_a;
    let b = observation.build_b;
    observation.isolated_builds == S545_ISOLATED_BUILD_COUNT
        && a.cargo_incremental == S545_CARGO_INCREMENTAL
        && b.cargo_incremental == S545_CARGO_INCREMENTAL
        && str_eq(a.profile, S545_CANDIDATE_PROFILE)
        && str_eq(b.profile, S545_CANDIDATE_PROFILE)
        && str_eq(a.feature_flags, S545_CARGO_FEATURE_FLAGS)
        && str_eq(b.feature_flags, S545_CARGO_FEATURE_FLAGS)
        && a.target_root_isolated
        && b.target_root_isolated
        && identity_eq(a.elf, s545_identity(S545_ELF_BYTES, S545_ELF_SHA256))
        && identity_eq(a.elf, b.elf)
        && identity_eq(
            a.log,
            s545_identity(S545_BUILD_A_LOG_BYTES, S545_BUILD_A_LOG_SHA256),
        )
        && identity_eq(
            b.log,
            s545_identity(S545_BUILD_B_LOG_BYTES, S545_BUILD_B_LOG_SHA256),
        )
        && a.warning_headers == S545_BUILD_WARNING_HEADERS_EACH
        && b.warning_headers == S545_BUILD_WARNING_HEADERS_EACH
        && identity_eq(
            observation.image,
            s545_identity(S545_IMAGE_BYTES, S545_IMAGE_SHA256),
        )
        && identity_eq(
            observation.superseded_s542_image,
            s545_identity(
                S545_SUPERSEDED_S542_IMAGE_BYTES,
                S545_SUPERSEDED_S542_IMAGE_SHA256,
            ),
        )
        && !identity_eq(observation.image, observation.superseded_s542_image)
}

fn check_reproducibility(
    observation: &G8lS545ReproducibilityObservation,
) -> Result<(), G8lS545CandidateFreezeError> {
    use G8lS545CandidateFreezeError as E;
    let a = observation.build_a;
    let b = observation.build_b;
    if observation.isolated_builds != S545_ISOLATED_BUILD_COUNT {
        return Err(E::IsolatedBuildCountDrift);
    }
    for build in [a, b] {
        if build.cargo_incremental != S545_CARGO_INCREMENTAL
            || !build.target_root_isolated
            || build.profile != S545_CANDIDATE_PROFILE
            || build.feature_flags != S545_CARGO_FEATURE_FLAGS
        {
            return Err(E::BuildIsolationDrift);
        }
    }
    if a.elf != s545_identity(S545_ELF_BYTES, S545_ELF_SHA256) {
        return Err(E::ElfIdentityDrift);
    }
    if a.elf != b.elf {
        return Err(E::BuildsNotByteIdentical);
    }
    if a.log != s545_identity(S545_BUILD_A_LOG_BYTES, S545_BUILD_A_LOG_SHA256)
        || b.log != s545_identity(S545_BUILD_B_LOG_BYTES, S545_BUILD_B_LOG_SHA256)
    {
        return Err(E::BuildLogIdentityDrift);
    }
    if a.warning_headers != S545_BUILD_WARNING_HEADERS_EACH
        || b.warning_headers != S545_BUILD_WARNING_HEADERS_EACH
    {
        return Err(E::WarningHeaderCountDrift);
    }
    if observation.image.sha256 == S545_SUPERSEDED_S542_IMAGE_SHA256
        || observation.image == observation.superseded_s542_image
    {
        return Err(E::ImageRetriesRejectedCandidate);
    }
    if observation.image != s545_identity(S545_IMAGE_BYTES, S545_IMAGE_SHA256)
        || observation.superseded_s542_image
            != s545_identity(
                S545_SUPERSEDED_S542_IMAGE_BYTES,
                S545_SUPERSEDED_S542_IMAGE_SHA256,
            )
    {
        return Err(E::ImageIdentityDrift);
    }
    if !s545_reproducibility_holds(observation) {
        return Err(E::BuildsNotByteIdentical);
    }
    Ok(())
}

fn strictly_increasing(lines: &[u32]) -> bool {
    lines.windows(2).all(|pair| pair[0] < pair[1])
}

/// Returns the linked span when the read-only layout audit matches the frozen
/// candidate exactly.
pub fn check_s545_layout_audit(
    layout: &G8lS545LayoutAuditObservation,
) -> Result<u64, G8lS545CandidateFreezeError> {
    use G8lS545CandidateFreezeError as E;
    if layout.entry != S545_ENTRY_ADDRESS {
        return Err(E::LayoutEntryDrift);
    }
    if layout.kernel_start != S545_KERNEL_START || layout.kernel_end != S545_KERNEL_END {
        return Err(E::LayoutSpanDrift);
    }
    let span = layout
        .kernel_end
        .checked_sub(layout.kernel_start)
        .ok_or(E::LayoutSpanDrift)?;
    if span != S545_LINKED_SPAN {
        return Err(E::LayoutSpanDrift);
    }
    if layout.cpu1_call_counts.iter().any(|&count| count != 1)
        || layout
            .s544_inlined_symbol_counts
            .iter()
            .any(|&count| count != 1)
    {
        return Err(E::LayoutSymbolCountDrift);
    }
    if !strictly_increasing(&layout.cpu1_text_lines)
        || !strictly_increasing(&layout.cpu0_text_lines)
    {
        return Err(E::LayoutCallOrderDrift);
    }
    if !layout.ldaxr_present
        || !layout.stlxr_present
        || layout.dsb_ishst_count != 1
        || layout.sev_count != 1
        || layout.ldar_count < 1
    {
        return Err(E::LayoutBarrierDrift);
    }
    if layout.objcopy_invoked
        || layout.elf_before != layout.elf_after
        || layout.elf_before != s545_identity(S545_ELF_BYTES, S545_ELF_SHA256)
    {
        return Err(E::ElfMutatedDuringAudit);
    }
    Ok(span)
}

/// Returns the entry count and a device-independent inode signature: the
/// checked sum of the four distinct inode numbers, each weighted by its
/// canonical position.  A re-created package therefore yields a different
/// receipt even when its bytes are identical.
pub fn check_s545_package_entries(
    package: &[G8lS545PackageEntryObservation; 4],
) -> Result<(usize, u64), G8lS545CandidateFreezeError> {
    use G8lS545CandidateFreezeError as E;
    let expected_names = [
        S545_IMAGE_NAME,
        S545_DTB_NAME,
        S545_CONFIG_NAME,
        S545_MANIFEST_NAME,
    ];
    let mut inodes = [0u64; 4];
    let mut signature = 0u64;
    for (index, entry) in package.iter().enumerate() {
        if entry.name != expected_names[index] || !entry.regular_non_symlink {
            return Err(E::PackageEntryNameDrift);
        }
        let expected =
            s545_expected_package_identity(entry.name).ok_or(E::PackageEntryNameDrift)?;
        if entry.identity != expected {
            return Err(E::PackageEntryIdentityDrift);
        }
        if entry.mode & 0o777 != S545_PACKAGE_MODE {
            return Err(E::PackageModeDrift);
        }
        if entry.nlink != S545_PACKAGE_NLINK {
            return Err(E::PackageHardLink);
        }
        if inodes[..index].contains(&entry.inode) {
            return Err(E::PackageInodeCollision);
        }
        inodes[index] = entry.inode;
        let weight = u64::try_from(index).map_err(|_| E::PackageInodeSignatureOverflow)? + 1;
        signature = entry
            .inode
            .checked_mul(weight)
            .and_then(|weighted| signature.checked_add(weighted))
            .ok_or(E::PackageInodeSignatureOverflow)?;
    }
    Ok((package.len(), signature))
}

/// `SHA256SUMS` grammar: exactly three `\n`-terminated lines, each a 64-char
/// lowercase-hex digest, two spaces, and one of the three payload names in
/// canonical order, with digests equal to the frozen constants.
pub fn validate_s545_manifest(text: &str) -> Result<usize, G8lS545CandidateFreezeError> {
    use G8lS545CandidateFreezeError as E;
    let expected: [(&str, &str); 3] = [
        (S545_IMAGE_NAME, S545_IMAGE_SHA256),
        (S545_DTB_NAME, S545_DTB_SHA256),
        (S545_CONFIG_NAME, S545_CONFIG_SHA256),
    ];
    if !text.ends_with('\n') || text.len() as u64 != S545_MANIFEST_BYTES {
        return Err(E::ManifestLineCountDrift);
    }
    let mut lines = 0usize;
    for (index, line) in text.split_terminator('\n').enumerate() {
        lines = lines.checked_add(1).ok_or(E::ManifestLineCountDrift)?;
        if index >= S545_MANIFEST_LINES {
            return Err(E::ManifestLineCountDrift);
        }
        let bytes = line.as_bytes();
        if bytes.len() < 66 || !bytes[..64].iter().all(|&byte| is_lower_hex(byte)) {
            return Err(E::ManifestDigestGrammar);
        }
        if &bytes[64..66] != b"  " {
            return Err(E::ManifestSeparatorDrift);
        }
        let (digest, name) = (&line[..64], &line[66..]);
        let (expected_name, expected_digest) = expected[index];
        if name != expected_name {
            return Err(E::ManifestFileNameDrift);
        }
        if digest != expected_digest {
            return Err(E::ManifestDigestMismatch);
        }
    }
    if lines != S545_MANIFEST_LINES {
        return Err(E::ManifestLineCountDrift);
    }
    Ok(lines)
}

/// Each required directive must appear exactly once as a whole line; the
/// second-stage UART enable must be absent.
pub fn validate_s545_config_directives(text: &str) -> Result<usize, G8lS545CandidateFreezeError> {
    use G8lS545CandidateFreezeError as E;
    let mut counts = [0usize; 4];
    for line in text.lines() {
        let line = line.trim();
        if line == S545_CONFIG_FORBIDDEN_DIRECTIVE {
            return Err(E::ConfigDirectiveDrift);
        }
        for (index, directive) in S545_CONFIG_REQUIRED_DIRECTIVES.iter().enumerate() {
            if line == *directive {
                counts[index] = counts[index]
                    .checked_add(1)
                    .ok_or(E::ConfigDirectiveDrift)?;
            }
        }
    }
    if counts.iter().any(|&count| count != 1) {
        return Err(E::ConfigDirectiveDrift);
    }
    Ok(counts.len())
}

/// Returns the number of literals recorded as `MARKER_LITERAL_MERGED`.
pub fn check_s545_marker_membership(
    counts: &[usize; S545_MARKER_COUNT],
) -> Result<usize, G8lS545CandidateFreezeError> {
    let mut merged = 0usize;
    for (expectation, &count) in S545_MARKER_TABLE.iter().zip(counts.iter()) {
        if count != expectation.expected_count {
            return Err(G8lS545CandidateFreezeError::MarkerCountDrift);
        }
        if let G8lS545MarkerDisposition::MarkerLiteralMerged { source_references } =
            expectation.disposition
        {
            if source_references <= count {
                return Err(G8lS545CandidateFreezeError::MarkerCountDrift);
            }
            merged += 1;
        }
    }
    Ok(merged)
}

fn check_tools(tools: &G8lS545ToolObservation) -> Result<(), G8lS545CandidateFreezeError> {
    if tools.layout_verifier
        != s545_identity(S545_LAYOUT_VERIFIER_BYTES, S545_LAYOUT_VERIFIER_SHA256)
        || tools.freeze_tool != s545_identity(S545_FREEZE_TOOL_BYTES, S545_FREEZE_TOOL_SHA256)
        || tools.firmware_config != s545_identity(S545_CONFIG_BYTES, S545_CONFIG_SHA256)
    {
        return Err(G8lS545CandidateFreezeError::ToolIdentityDrift);
    }
    Ok(())
}

pub fn service_s545_model_candidate_freeze(
    state: &mut G8lS545CandidateFreezeState,
    input: &G8lS545FreezeInput<'_>,
) -> Result<G8lS545CandidateFreezeOutcome, G8lS545CandidateFreezeError> {
    if !input.s544_source_gate_passed {
        return Err(G8lS545CandidateFreezeError::PredecessorNotAccepted);
    }
    check_reproducibility(&input.reproducibility)?;
    let linked_span = check_s545_layout_audit(&input.layout)?;
    let (package_entries, package_inode_signature) = check_s545_package_entries(&input.package)?;
    let manifest_lines = validate_s545_manifest(input.manifest_text)?;
    validate_s545_config_directives(input.config_text)?;
    let marker_literals_merged = check_s545_marker_membership(&input.marker_counts)?;
    check_tools(&input.tools)?;
    let receipt = G8lS545CandidateFreezeReceipt {
        sequence: S545_SEQUENCE,
        predecessor_sequence: S545_EXPECTED_PREDECESSOR,
        next_sequence: S545_NEXT_SEQUENCE,
        elf: input.reproducibility.build_a.elf,
        image: input.reproducibility.image,
        superseded_s542_image_sha256: input.reproducibility.superseded_s542_image.sha256,
        isolated_builds: input.reproducibility.isolated_builds,
        warning_headers_each: input.reproducibility.build_a.warning_headers,
        zero_warning_claimed: S545_ZERO_WARNING_CLAIMED,
        linked_span,
        package_entries,
        package_mode: S545_PACKAGE_MODE,
        package_inode_signature,
        manifest_lines,
        marker_literals_merged,
        candidate_frozen: true,
        s544_hook_present: true,
        image_differs_from_s542: true,
        input_elf_immutable: true,
        execution_permit: S545_EXECUTION_PERMIT,
        device_operations: S545_PHYSICAL_OR_DEVICE_OPERATIONS,
        sd_writes: S545_SD_WRITES,
        uart_opens: S545_UART_OPENS,
        power_transitions: S545_POWER_TRANSITIONS,
        supported_profile_runtime_observations: S545_SUPPORTED_PROFILE_RUNTIME_OBSERVATIONS,
        physical_observations: S545_PHYSICAL_OBSERVATIONS,
        runbook_executed: RUNBOOK_EXECUTED_IN_S545,
    };
    if let Some(frozen) = state.receipt {
        if frozen != receipt {
            return Err(G8lS545CandidateFreezeError::FrozenStateDrift);
        }
        return Ok(G8lS545CandidateFreezeOutcome::CandidateRetained(frozen));
    }
    state.receipt = Some(receipt);
    Ok(G8lS545CandidateFreezeOutcome::CandidateFrozen(receipt))
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS545AuthorizationTokenFields {
    pub image_sha256_prefix: [u8; 8],
    pub card_serial: u32,
    pub card_bytes: u64,
}

fn parse_hex_u32(text: &str) -> Option<u32> {
    let bytes = text.as_bytes();
    if bytes.len() != 8 {
        return None;
    }
    let mut value = 0u32;
    for &byte in bytes {
        let digit = match byte {
            b'0'..=b'9' => byte - b'0',
            b'a'..=b'f' => byte - b'a' + 10,
            _ => return None,
        };
        value = value.checked_shl(4)?.checked_add(u32::from(digit))?;
    }
    Some(value)
}

fn parse_decimal_u64(text: &str) -> Option<u64> {
    let bytes = text.as_bytes();
    if bytes.is_empty() || bytes.len() > 20 || (bytes.len() > 1 && bytes[0] == b'0') {
        return None;
    }
    let mut value = 0u64;
    for &byte in bytes {
        if !byte.is_ascii_digit() {
            return None;
        }
        value = value.checked_mul(10)?.checked_add(u64::from(byte - b'0'))?;
    }
    Some(value)
}

/// Decodes `PREFIX_<8 hex image prefix>_<8 hex card serial>_<decimal card bytes>`
/// and binds every field to the frozen candidate and expected card.
pub fn parse_s546_authorization_token(
    token: &str,
) -> Result<G8lS545AuthorizationTokenFields, G8lS545CandidateFreezeError> {
    use G8lS545CandidateFreezeError as E;
    let suffix = token
        .strip_prefix(S545_PREARM_AUTHORIZATION_PREFIX)
        .and_then(|rest| rest.strip_prefix('_'))
        .ok_or(E::AuthorizationTokenDrift)?;
    let mut parts = suffix.split('_');
    let image_prefix = parts.next().ok_or(E::AuthorizationTokenDrift)?;
    let serial = parts.next().ok_or(E::AuthorizationTokenDrift)?;
    let card_bytes = parts.next().ok_or(E::AuthorizationTokenDrift)?;
    if parts.next().is_some() {
        return Err(E::AuthorizationTokenDrift);
    }
    let prefix_bytes = image_prefix.as_bytes();
    if prefix_bytes.len() != 8 || !prefix_bytes.iter().all(|&byte| is_lower_hex(byte)) {
        return Err(E::AuthorizationTokenDrift);
    }
    let mut image_sha256_prefix = [0u8; 8];
    image_sha256_prefix.copy_from_slice(prefix_bytes);
    let fields = G8lS545AuthorizationTokenFields {
        image_sha256_prefix,
        card_serial: parse_hex_u32(serial).ok_or(E::AuthorizationTokenDrift)?,
        card_bytes: parse_decimal_u64(card_bytes).ok_or(E::AuthorizationTokenDrift)?,
    };
    if fields.image_sha256_prefix != S545_IMAGE_SHA256.as_bytes()[..8]
        || fields.card_serial != S545_PREARM_CARD_SERIAL
        || fields.card_bytes != S545_PREARM_CARD_BYTES
    {
        return Err(E::AuthorizationTargetDrift);
    }
    Ok(fields)
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS545PrearmRequest {
    pub requested_sequence: usize,
    pub authorization_token: &'static str,
    pub card_serial: u32,
    pub card_raw_cid: &'static str,
    pub card_bytes: u64,
    pub card_name: &'static str,
    pub volume_label: &'static str,
    pub debug_probe_serial: &'static str,
    pub serial_path_freshly_resolved: bool,
    pub uart_baud: u32,
    pub uart_data_bits: u8,
    pub uart_stop_bits: u8,
    pub uart_parity_none: bool,
    pub uart_flow_control_none: bool,
    pub exclusive_tiocexcl: bool,
    pub tciflush_before_capture: bool,
    pub fresh_o_excl_raw: bool,
    pub capture_armed_before_power_on: bool,
    pub power_transitions_operator_reported_only: bool,
    pub operator_asserts_pi_unpowered: bool,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct G8lS545PrearmContract {
    pub sequence: usize,
    pub target_sequence: usize,
    pub candidate_image: G8lS545ArtifactIdentity,
    pub token_fields: G8lS545AuthorizationTokenFields,
    pub card_serial: u32,
    pub card_raw_cid: &'static str,
    pub card_bytes: u64,
    pub card_name: &'static str,
    pub volume_label: &'static str,
    pub debug_probe_serial: &'static str,
    pub uart_baud: u32,
    pub uart_data_bits: u8,
    pub uart_stop_bits: u8,
    pub uart_parity_none: bool,
    pub uart_flow_control_none: bool,
    pub exclusive_tiocexcl: bool,
    pub tciflush_before_capture: bool,
    pub fresh_o_excl_raw: bool,
    pub capture_armed_before_power_on: bool,
    pub power_transitions_operator_reported_only: bool,
    pub contract_ready: bool,
    pub execution_permit: bool,
    pub host_execution_started: bool,
    pub device_operations: usize,
    pub sd_writes: usize,
    pub uart_opens: usize,
    pub power_transitions: usize,
    pub new_raw_captures: usize,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum G8lS545PrearmOutcome {
    AwaitingFrozenCandidate,
    StoppedAwaitingExplicitAuthorization,
    StoppedAwaitingPowerOffAssertion,
    StoppedAwaitingCompleteDiscipline,
    ContractReadyExecutionPermitWithheld(G8lS545PrearmContract),
}

pub fn evaluate_s545_model_prearm_contract(
    candidate: Option<G8lS545CandidateFreezeReceipt>,
    request: Option<G8lS545PrearmRequest>,
) -> Result<G8lS545PrearmOutcome, G8lS545CandidateFreezeError> {
    use G8lS545CandidateFreezeError as E;
    let Some(candidate) = candidate else {
        return Ok(G8lS545PrearmOutcome::AwaitingFrozenCandidate);
    };
    if candidate.sequence != S545_SEQUENCE
        || candidate.predecessor_sequence != S545_EXPECTED_PREDECESSOR
        || candidate.image != s545_identity(S545_IMAGE_BYTES, S545_IMAGE_SHA256)
        || candidate.superseded_s542_image_sha256 != S545_SUPERSEDED_S542_IMAGE_SHA256
        || !candidate.candidate_frozen
        || !candidate.s544_hook_present
        || !candidate.image_differs_from_s542
        || !candidate.input_elf_immutable
        || candidate.execution_permit
        || candidate.device_operations != 0
        || candidate.physical_observations != 0
        || candidate.runbook_executed
    {
        return Err(E::CandidateDrift);
    }
    let Some(request) = request else {
        return Ok(G8lS545PrearmOutcome::StoppedAwaitingExplicitAuthorization);
    };
    if request.requested_sequence != S545_NEXT_SEQUENCE {
        return Err(E::PrearmSequenceDrift);
    }
    let token_fields = parse_s546_authorization_token(request.authorization_token)?;
    if request.card_serial != S545_PREARM_CARD_SERIAL
        || request.card_raw_cid != S545_PREARM_CARD_RAW_CID
        || request.card_bytes != S545_PREARM_CARD_BYTES
        || request.card_name != S545_PREARM_CARD_NAME
        || request.volume_label != S545_PREARM_VOLUME_LABEL
        || request.debug_probe_serial != S545_PREARM_DEBUG_PROBE_SERIAL
        || request.uart_baud != S545_PREARM_UART_BAUD
        || request.uart_data_bits != S545_PREARM_UART_DATA_BITS
        || request.uart_stop_bits != S545_PREARM_UART_STOP_BITS
        || !request.uart_parity_none
        || !request.uart_flow_control_none
    {
        return Err(E::AuthorizationTargetDrift);
    }
    if !request.operator_asserts_pi_unpowered {
        return Ok(G8lS545PrearmOutcome::StoppedAwaitingPowerOffAssertion);
    }
    if !request.serial_path_freshly_resolved
        || !request.exclusive_tiocexcl
        || !request.tciflush_before_capture
        || !request.fresh_o_excl_raw
        || !request.capture_armed_before_power_on
        || !request.power_transitions_operator_reported_only
    {
        return Ok(G8lS545PrearmOutcome::StoppedAwaitingCompleteDiscipline);
    }
    Ok(G8lS545PrearmOutcome::ContractReadyExecutionPermitWithheld(
        G8lS545PrearmContract {
            sequence: S545_SEQUENCE,
            target_sequence: S545_NEXT_SEQUENCE,
            candidate_image: candidate.image,
            token_fields,
            card_serial: S545_PREARM_CARD_SERIAL,
            card_raw_cid: S545_PREARM_CARD_RAW_CID,
            card_bytes: S545_PREARM_CARD_BYTES,
            card_name: S545_PREARM_CARD_NAME,
            volume_label: S545_PREARM_VOLUME_LABEL,
            debug_probe_serial: S545_PREARM_DEBUG_PROBE_SERIAL,
            uart_baud: S545_PREARM_UART_BAUD,
            uart_data_bits: S545_PREARM_UART_DATA_BITS,
            uart_stop_bits: S545_PREARM_UART_STOP_BITS,
            uart_parity_none: true,
            uart_flow_control_none: true,
            exclusive_tiocexcl: true,
            tciflush_before_capture: true,
            fresh_o_excl_raw: true,
            capture_armed_before_power_on: true,
            power_transitions_operator_reported_only: true,
            contract_ready: true,
            execution_permit: S545_EXECUTION_PERMIT,
            host_execution_started: false,
            device_operations: S545_PHYSICAL_OR_DEVICE_OPERATIONS,
            sd_writes: S545_SD_WRITES,
            uart_opens: S545_UART_OPENS,
            power_transitions: S545_POWER_TRANSITIONS,
            new_raw_captures: S545_NEW_IMMUTABLE_RAW_CAPTURES,
        },
    ))
}
snippet sha256: 4ecd2ef5b35dfile sha256: 4ecd2ef5b35d
02 · Doğrulayan test kodu

Operations komutuna bağlı focused test

tam dosyaL1–L946
simulation/tests/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s545_r1_reachable_producer_candidate_freeze_prearm_contract.rs::S545 r1 reachable producer candidate freeze prearm contract focused tests
use aselsan_microkernel_simulation::g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s545_r1_reachable_producer_candidate_freeze_prearm_contract::*;
use sha2::{Digest, Sha256};
use std::collections::{BTreeSet, HashSet};
use std::fs;
use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::path::{Path, PathBuf};

const SOURCE: &str = include_str!(
    "../../kernel/src/g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s545_r1_reachable_producer_candidate_freeze_prearm_contract.rs"
);
const MAIN: &str = include_str!("../../kernel/src/main.rs");
const SIMULATION_LIB: &str = include_str!("../src/lib.rs");
const PACKAGE_IMAGE: &[u8] =
    include_bytes!("../../evidence/rpi5/r1/sequence-545-candidate-freeze/package/aselsanos-rpi5.img");
const PACKAGE_DTB: &[u8] =
    include_bytes!("../../evidence/rpi5/r1/sequence-545-candidate-freeze/package/bcm2712-rpi-5-b.dtb");
const PACKAGE_CONFIG: &[u8] =
    include_bytes!("../../evidence/rpi5/r1/sequence-545-candidate-freeze/package/config.txt");
const PACKAGE_MANIFEST_BYTES: &[u8] =
    include_bytes!("../../evidence/rpi5/r1/sequence-545-candidate-freeze/package/SHA256SUMS");
const PACKAGE_MANIFEST: &str =
    include_str!("../../evidence/rpi5/r1/sequence-545-candidate-freeze/package/SHA256SUMS");
const FIRMWARE_CONFIG: &str = include_str!("../../firmware/config-r1-s545.txt");
const LAYOUT_VERIFIER: &str = include_str!("../../scripts/verify-rpi5-s545-layout.sh");
const FREEZE_TOOL: &str = include_str!("../../scripts/freeze-rpi5-s545-r1-candidate.sh");

fn sha256(bytes: &[u8]) -> String {
    format!("{:x}", Sha256::digest(bytes))
}

fn repository_root() -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR")).join("..")
}

fn package_root() -> PathBuf {
    repository_root().join(S545_PACKAGE_DIRECTORY)
}

fn count_bytes(haystack: &[u8], needle: &[u8]) -> usize {
    haystack.windows(needle.len()).filter(|window| *window == needle).count()
}

fn build(log_bytes: u64, log_sha256: &'static str) -> G8lS545IsolatedBuildObservation {
    G8lS545IsolatedBuildObservation {
        cargo_incremental: 0,
        profile: S545_CANDIDATE_PROFILE,
        feature_flags: S545_CARGO_FEATURE_FLAGS,
        target_root_isolated: true,
        elf: s545_identity(S545_ELF_BYTES, S545_ELF_SHA256),
        log: s545_identity(log_bytes, log_sha256),
        warning_headers: S545_BUILD_WARNING_HEADERS_EACH,
    }
}

fn reproducibility() -> G8lS545ReproducibilityObservation {
    G8lS545ReproducibilityObservation {
        isolated_builds: 2,
        build_a: build(S545_BUILD_A_LOG_BYTES, S545_BUILD_A_LOG_SHA256),
        build_b: build(S545_BUILD_B_LOG_BYTES, S545_BUILD_B_LOG_SHA256),
        image: s545_identity(S545_IMAGE_BYTES, S545_IMAGE_SHA256),
        superseded_s542_image: s545_identity(
            S545_SUPERSEDED_S542_IMAGE_BYTES,
            S545_SUPERSEDED_S542_IMAGE_SHA256,
        ),
    }
}

fn layout() -> G8lS545LayoutAuditObservation {
    G8lS545LayoutAuditObservation {
        entry: 0x80000,
        kernel_start: 0x80000,
        kernel_end: 0x11f8000,
        cpu1_text_lines: [40, 88, 131, 175, 210, 262],
        cpu1_call_counts: [1; 6],
        s544_inlined_symbol_counts: [1; 2],
        cpu0_text_lines: [51, 97, 140],
        ldaxr_present: true,
        stlxr_present: true,
        dsb_ishst_count: 1,
        sev_count: 1,
        ldar_count: 2,
        elf_before: s545_identity(S545_ELF_BYTES, S545_ELF_SHA256),
        elf_after: s545_identity(S545_ELF_BYTES, S545_ELF_SHA256),
        objcopy_invoked: false,
    }
}

fn package() -> [G8lS545PackageEntryObservation; 4] {
    let entry = |name: &'static str, inode: u64| G8lS545PackageEntryObservation {
        name,
        identity: s545_expected_package_identity(name).unwrap(),
        mode: 0o444,
        nlink: 1,
        inode,
        regular_non_symlink: true,
    };
    [
        entry(S545_IMAGE_NAME, 33_927_657),
        entry(S545_DTB_NAME, 33_927_716),
        entry(S545_CONFIG_NAME, 33_927_718),
        entry(S545_MANIFEST_NAME, 33_927_719),
    ]
}

fn tools() -> G8lS545ToolObservation {
    G8lS545ToolObservation {
        layout_verifier: s545_identity(S545_LAYOUT_VERIFIER_BYTES, S545_LAYOUT_VERIFIER_SHA256),
        freeze_tool: s545_identity(S545_FREEZE_TOOL_BYTES, S545_FREEZE_TOOL_SHA256),
        firmware_config: s545_identity(S545_CONFIG_BYTES, S545_CONFIG_SHA256),
    }
}

fn canonical_input() -> G8lS545FreezeInput<'static> {
    G8lS545FreezeInput {
        s544_source_gate_passed: true,
        reproducibility: reproducibility(),
        layout: layout(),
        package: package(),
        manifest_text: PACKAGE_MANIFEST,
        config_text: FIRMWARE_CONFIG,
        marker_counts: [1; 7],
        tools: tools(),
    }
}

fn freeze(
    state: &mut G8lS545CandidateFreezeState,
) -> Result<G8lS545CandidateFreezeOutcome, G8lS545CandidateFreezeError> {
    service_s545_model_candidate_freeze(state, &canonical_input())
}

fn frozen_receipt() -> G8lS545CandidateFreezeReceipt {
    let mut state = G8lS545CandidateFreezeState::new();
    let G8lS545CandidateFreezeOutcome::CandidateFrozen(receipt) = freeze(&mut state).unwrap()
    else {
        panic!("first S545 freeze must publish")
    };
    receipt
}

fn prearm_request() -> G8lS545PrearmRequest {
    G8lS545PrearmRequest {
        requested_sequence: 546,
        authorization_token: S545_PREARM_AUTHORIZATION_TOKEN,
        card_serial: 0x425001fa,
        card_raw_cid: S545_PREARM_CARD_RAW_CID,
        card_bytes: 62_549_655_552,
        card_name: "TISD64G",
        volume_label: "ASELSANBOOT",
        debug_probe_serial: "E6647C74033F9131",
        serial_path_freshly_resolved: true,
        uart_baud: 115_200,
        uart_data_bits: 8,
        uart_stop_bits: 1,
        uart_parity_none: true,
        uart_flow_control_none: true,
        exclusive_tiocexcl: true,
        tciflush_before_capture: true,
        fresh_o_excl_raw: true,
        capture_armed_before_power_on: true,
        power_transitions_operator_reported_only: true,
        operator_asserts_pi_unpowered: true,
    }
}

#[test]
fn sequence_scope_and_nonpromotion_are_exact() {
    assert_eq!(S545_SEQUENCE, 545);
    assert_eq!(S545_EXPECTED_PREDECESSOR, 544);
    assert_eq!(S545_NEXT_SEQUENCE, 546);
    assert_eq!(S545_R1_STAGE, 1);
    assert_eq!(S545_R1_RANGE_FIRST, 536);
    assert_eq!(S545_R1_RANGE_LAST, 568);
    assert_eq!(S545_SUPPORTED_PROFILE_RUNTIME_OBSERVATIONS, 0);
    assert_eq!(S545_PHYSICAL_OBSERVATIONS, 0);
    assert_eq!(S545_PHYSICAL_OR_DEVICE_OPERATIONS, 0);
    assert_eq!(S545_SD_WRITES, 0);
    assert_eq!(S545_UART_OPENS, 0);
    assert_eq!(S545_POWER_TRANSITIONS, 0);
    assert_eq!(S545_NEW_IMMUTABLE_RAW_CAPTURES, 0);
    assert!(S545_S540_PHYSICAL_VERDICT_RETAINED_RED);
    assert!(S545_S543_PHYSICAL_VERDICT_RETAINED_RED);
    assert!(!S545_AUTOMATIC_PROMOTION);
    assert!(!S545_BOOT_TO_UI_PHYSICALLY_OBSERVED);
    assert!(!S545_HARDWARE_PRESENT);
    assert!(!S545_R1_ACCEPTANCE_COMPLETE);
    assert!(!S545_EXECUTION_PERMIT);
    assert!(!RUNBOOK_EXECUTED_IN_S545);
    assert_eq!(S545_ISOLATED_BUILD_COUNT, 2);
    assert_eq!(S545_CARGO_INCREMENTAL, 0);
    assert_eq!(S545_ELF_BYTES, 18_438_504);
    assert_eq!(S545_IMAGE_BYTES, 945_760);
    assert_eq!(S545_SUPERSEDED_S542_IMAGE_BYTES, 941_392);
    assert_eq!(S545_BUILD_WARNING_HEADERS_EACH, 2_865);
    assert!(!S545_ZERO_WARNING_CLAIMED);
    assert_eq!(S545_LINKED_SPAN, S545_KERNEL_END - S545_KERNEL_START);
    assert_eq!(S545_PACKAGE_ENTRIES, 4);
    assert_eq!(S545_PACKAGE_MODE, 0o444);
    assert_eq!(S545_PREARM_CARD_SERIAL, 0x425001fa);
    assert_eq!(S545_PREARM_CARD_BYTES, 62_549_655_552);
}

#[test]
fn module_is_registered_in_kernel_and_simulation() {
    let module = "g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s545_r1_reachable_producer_candidate_freeze_prearm_contract";
    assert!(MAIN.contains(&format!("mod {module};")));
    assert!(SIMULATION_LIB.contains(&format!("pub mod {module};")));
}

#[test]
fn source_has_no_device_execution_or_uart_emission_surface() {
    for forbidden in [
        "unsafe",
        "asm!",
        "write_volatile",
        "crate::uart",
        "crate::arch",
        "#[no_mangle]",
        "spin::",
        "std::",
        "std::process::Command",
        "/dev/disk",
        "diskutil",
        "dd if=",
        "crate::kprintln!",
    ] {
        assert!(!SOURCE.contains(forbidden), "forbidden token: {forbidden}");
    }
    assert!(SOURCE.contains("performs no device operation"));
    assert!(SOURCE.contains("does not rerun S543"));
    assert!(SOURCE.contains("not\n//! wired into any boot, IRQ, scheduler or driver path"));
    assert!(SOURCE.contains("S545_SUPPORTED_PROFILE_RUNTIME_OBSERVATIONS: usize = 0"));
    assert!(SOURCE.contains("S545_PHYSICAL_OBSERVATIONS: usize = 0"));
    assert!(SOURCE.contains("S545_PHYSICAL_OR_DEVICE_OPERATIONS: usize = 0"));
    assert!(SOURCE.contains("S545_R1_ACCEPTANCE_COMPLETE: bool = false"));
    assert!(SOURCE.contains("S545_EXECUTION_PERMIT: bool = false"));
    assert!(SOURCE.contains("RUNBOOK_EXECUTED_IN_S545: bool = false"));
}

#[test]
fn diagnostic_codes_are_nonzero_and_unique() {
    use G8lS545CandidateFreezeError as E;
    let errors = [
        E::PredecessorNotAccepted,
        E::IsolatedBuildCountDrift,
        E::BuildIsolationDrift,
        E::ElfIdentityDrift,
        E::BuildsNotByteIdentical,
        E::BuildLogIdentityDrift,
        E::WarningHeaderCountDrift,
        E::ImageIdentityDrift,
        E::ImageRetriesRejectedCandidate,
        E::LayoutEntryDrift,
        E::LayoutSpanDrift,
        E::LayoutCallOrderDrift,
        E::LayoutSymbolCountDrift,
        E::LayoutBarrierDrift,
        E::ElfMutatedDuringAudit,
        E::PackageEntryNameDrift,
        E::PackageEntryIdentityDrift,
        E::PackageModeDrift,
        E::PackageHardLink,
        E::PackageInodeCollision,
        E::PackageInodeSignatureOverflow,
        E::ManifestLineCountDrift,
        E::ManifestDigestGrammar,
        E::ManifestSeparatorDrift,
        E::ManifestFileNameDrift,
        E::ManifestDigestMismatch,
        E::ConfigDirectiveDrift,
        E::MarkerCountDrift,
        E::ToolIdentityDrift,
        E::FrozenStateDrift,
        E::AuthorizationTokenDrift,
        E::AuthorizationTargetDrift,
        E::PrearmSequenceDrift,
        E::CandidateDrift,
    ];
    let codes: BTreeSet<_> = errors.into_iter().map(E::diagnostic_code).collect();
    assert_eq!(codes.len(), errors.len());
    assert_eq!(codes.len(), 34);
    assert!(!codes.contains(&0));
}

#[test]
fn exact_observation_freezes_the_reachable_producer_candidate() {
    let mut state = G8lS545CandidateFreezeState::new();
    assert_eq!(state.receipt(), None);
    let receipt = frozen_receipt();
    assert_eq!(freeze(&mut state), Ok(G8lS545CandidateFreezeOutcome::CandidateFrozen(receipt)));
    assert_eq!(state.receipt(), Some(receipt));
    assert_eq!(receipt.sequence, 545);
    assert_eq!(receipt.predecessor_sequence, 544);
    assert_eq!(receipt.next_sequence, 546);
    assert_eq!(receipt.elf, s545_identity(18_438_504, S545_ELF_SHA256));
    assert_eq!(receipt.image, s545_identity(945_760, S545_IMAGE_SHA256));
    assert_eq!(receipt.superseded_s542_image_sha256, S545_SUPERSEDED_S542_IMAGE_SHA256);
    assert_eq!(receipt.isolated_builds, 2);
    assert_eq!(receipt.warning_headers_each, 2_865);
    assert!(!receipt.zero_warning_claimed);
    assert_eq!(receipt.linked_span, 18_317_312);
    assert_eq!(receipt.package_entries, 4);
    assert_eq!(receipt.package_mode, 0o444);
    assert_eq!(
        receipt.package_inode_signature,
        33_927_657 + 2 * 33_927_716 + 3 * 33_927_718 + 4 * 33_927_719
    );
    assert_eq!(receipt.manifest_lines, 3);
    assert_eq!(receipt.marker_literals_merged, 1);
    assert!(receipt.candidate_frozen);
    assert!(receipt.s544_hook_present);
    assert!(receipt.image_differs_from_s542);
    assert!(receipt.input_elf_immutable);
    assert!(!receipt.execution_permit);
    assert_eq!(receipt.device_operations, 0);
    assert_eq!(receipt.sd_writes, 0);
    assert_eq!(receipt.uart_opens, 0);
    assert_eq!(receipt.power_transitions, 0);
    assert_eq!(receipt.supported_profile_runtime_observations, 0);
    assert_eq!(receipt.physical_observations, 0);
    assert!(!receipt.runbook_executed);
    assert!(s545_reproducibility_holds(&reproducibility()));
}

#[test]
fn exact_replay_retains_the_same_receipt() {
    let mut state = G8lS545CandidateFreezeState::default();
    let G8lS545CandidateFreezeOutcome::CandidateFrozen(receipt) = freeze(&mut state).unwrap()
    else {
        panic!("first freeze missing")
    };
    assert_eq!(
        freeze(&mut state),
        Ok(G8lS545CandidateFreezeOutcome::CandidateRetained(receipt))
    );
    assert_eq!(
        freeze(&mut state),
        Ok(G8lS545CandidateFreezeOutcome::CandidateRetained(receipt))
    );
    assert_eq!(state.receipt(), Some(receipt));
}

#[test]
fn divergent_input_after_publication_fails_closed() {
    let mut state = G8lS545CandidateFreezeState::new();
    let receipt = match freeze(&mut state).unwrap() {
        G8lS545CandidateFreezeOutcome::CandidateFrozen(receipt) => receipt,
        other => panic!("unexpected {other:?}"),
    };
    let mut drift = canonical_input();
    drift.reproducibility.build_b.elf.sha256 = S545_IMAGE_SHA256;
    assert_eq!(
        service_s545_model_candidate_freeze(&mut state, &drift),
        Err(G8lS545CandidateFreezeError::BuildsNotByteIdentical)
    );
    let mut merged_twice = canonical_input();
    merged_twice.marker_counts[2] = 2;
    assert_eq!(
        service_s545_model_candidate_freeze(&mut state, &merged_twice),
        Err(G8lS545CandidateFreezeError::MarkerCountDrift)
    );
    let mut recreated = canonical_input();
    for (entry, inode) in recreated.package.iter_mut().zip([1u64, 2, 3, 4]) {
        entry.inode = inode;
    }
    assert_eq!(check_s545_package_entries(&recreated.package), Ok((4, 30)));
    assert_eq!(
        service_s545_model_candidate_freeze(&mut state, &recreated),
        Err(G8lS545CandidateFreezeError::FrozenStateDrift)
    );
    assert_eq!(state.receipt(), Some(receipt));
    let mut fresh = G8lS545CandidateFreezeState::new();
    assert!(matches!(
        service_s545_model_candidate_freeze(&mut fresh, &recreated),
        Ok(G8lS545CandidateFreezeOutcome::CandidateFrozen(_))
    ));
}

#[test]
fn reproducibility_predicate_rejects_non_identical_builds_and_s542_retry() {
    use G8lS545CandidateFreezeError as E;
    let mut state = G8lS545CandidateFreezeState::new();
    let cases: [(fn(&mut G8lS545FreezeInput<'static>), E); 8] = [
        (|input| input.reproducibility.isolated_builds = 1, E::IsolatedBuildCountDrift),
        (|input| input.reproducibility.build_a.cargo_incremental = 1, E::BuildIsolationDrift),
        (|input| input.reproducibility.build_b.target_root_isolated = false, E::BuildIsolationDrift),
        (|input| input.reproducibility.build_a.elf.bytes += 8, E::ElfIdentityDrift),
        (|input| input.reproducibility.build_b.elf.bytes -= 8, E::BuildsNotByteIdentical),
        (|input| input.reproducibility.build_b.log.sha256 = S545_BUILD_A_LOG_SHA256, E::BuildLogIdentityDrift),
        (|input| input.reproducibility.build_a.warning_headers = 0, E::WarningHeaderCountDrift),
        (|input| input.reproducibility.image.bytes = 945_761, E::ImageIdentityDrift),
    ];
    for (mutate, expected) in cases {
        let mut input = canonical_input();
        mutate(&mut input);
        assert!(!s545_reproducibility_holds(&input.reproducibility));
        assert_eq!(service_s545_model_candidate_freeze(&mut state, &input), Err(expected));
    }
    let mut retry = canonical_input();
    retry.reproducibility.image = retry.reproducibility.superseded_s542_image;
    assert_eq!(
        service_s545_model_candidate_freeze(&mut state, &retry),
        Err(E::ImageRetriesRejectedCandidate)
    );
    let mut retry_sha_only = canonical_input();
    retry_sha_only.reproducibility.image.sha256 = S545_SUPERSEDED_S542_IMAGE_SHA256;
    assert_eq!(
        service_s545_model_candidate_freeze(&mut state, &retry_sha_only),
        Err(E::ImageRetriesRejectedCandidate)
    );
    let mut same = canonical_input();
    same.reproducibility.superseded_s542_image = same.reproducibility.image;
    assert_eq!(
        service_s545_model_candidate_freeze(&mut state, &same),
        Err(E::ImageRetriesRejectedCandidate)
    );
    let mut superseded_drift = canonical_input();
    superseded_drift.reproducibility.superseded_s542_image.bytes = 941_393;
    assert_eq!(
        service_s545_model_candidate_freeze(&mut state, &superseded_drift),
        Err(E::ImageIdentityDrift)
    );
    assert_ne!(S545_IMAGE_SHA256, S545_SUPERSEDED_S542_IMAGE_SHA256);
    assert_ne!(S545_IMAGE_BYTES, S545_SUPERSEDED_S542_IMAGE_BYTES);
    assert_eq!(state.receipt(), None);
}

#[test]
fn layout_audit_fails_closed_on_entry_span_order_symbol_barrier_and_elf_mutation() {
    use G8lS545CandidateFreezeError as E;
    assert_eq!(check_s545_layout_audit(&layout()), Ok(18_317_312));
    let cases: [(fn(&mut G8lS545LayoutAuditObservation), E); 12] = [
        (|l| l.entry = 0x80004, E::LayoutEntryDrift),
        (|l| l.kernel_end = 0x11f8008, E::LayoutSpanDrift),
        (|l| l.kernel_start = 0x11f8000, E::LayoutSpanDrift),
        (|l| l.cpu1_text_lines = [40, 88, 175, 131, 210, 262], E::LayoutCallOrderDrift),
        (|l| l.cpu1_text_lines[5] = 210, E::LayoutCallOrderDrift),
        (|l| l.cpu0_text_lines = [97, 51, 140], E::LayoutCallOrderDrift),
        (|l| l.cpu1_call_counts[5] = 2, E::LayoutSymbolCountDrift),
        (|l| l.s544_inlined_symbol_counts[1] = 0, E::LayoutSymbolCountDrift),
        (|l| l.dsb_ishst_count = 2, E::LayoutBarrierDrift),
        (|l| l.ldar_count = 0, E::LayoutBarrierDrift),
        (|l| l.elf_after.bytes = 18_438_505, E::ElfMutatedDuringAudit),
        (|l| l.objcopy_invoked = true, E::ElfMutatedDuringAudit),
    ];
    for (mutate, expected) in cases {
        let mut observation = layout();
        mutate(&mut observation);
        assert_eq!(check_s545_layout_audit(&observation), Err(expected));
        let mut input = canonical_input();
        input.layout = observation;
        let mut state = G8lS545CandidateFreezeState::new();
        assert_eq!(service_s545_model_candidate_freeze(&mut state, &input), Err(expected));
    }
    let mut underflow = layout();
    underflow.kernel_start = u64::MAX;
    underflow.kernel_end = 0;
    assert_eq!(check_s545_layout_audit(&underflow), Err(E::LayoutSpanDrift));
}

#[test]
fn package_entries_fail_closed_on_name_identity_mode_hardlink_and_inode() {
    use G8lS545CandidateFreezeError as E;
    assert_eq!(
        check_s545_package_entries(&package()),
        Ok((4, 33_927_657 + 2 * 33_927_716 + 3 * 33_927_718 + 4 * 33_927_719))
    );
    let mut overflow = package();
    overflow[3].inode = u64::MAX;
    assert_eq!(
        check_s545_package_entries(&overflow),
        Err(E::PackageInodeSignatureOverflow)
    );
    let cases: [(fn(&mut [G8lS545PackageEntryObservation; 4]), E); 7] = [
        (|p| p.swap(0, 1), E::PackageEntryNameDrift),
        (|p| p[3].name = "SHA512SUMS", E::PackageEntryNameDrift),
        (|p| p[1].regular_non_symlink = false, E::PackageEntryNameDrift),
        (|p| p[2].identity.bytes = 415, E::PackageEntryIdentityDrift),
        (|p| p[0].mode = 0o644, E::PackageModeDrift),
        (|p| p[1].nlink = 2, E::PackageHardLink),
        (|p| p[3].inode = p[0].inode, E::PackageInodeCollision),
    ];
    for (mutate, expected) in cases {
        let mut observation = package();
        mutate(&mut observation);
        assert_eq!(check_s545_package_entries(&observation), Err(expected));
    }
    assert_eq!(s545_expected_package_identity("kernel8.img"), None);
    assert_eq!(
        s545_expected_package_identity("SHA256SUMS"),
        Some(s545_identity(248, S545_MANIFEST_SHA256))
    );
}

#[test]
fn manifest_grammar_validator_accepts_exact_and_rejects_malformed() {
    use G8lS545CandidateFreezeError as E;
    assert_eq!(validate_s545_manifest(PACKAGE_MANIFEST), Ok(3));
    let lines: Vec<&str> = PACKAGE_MANIFEST.lines().collect();
    let two_lines = format!("{}\n{}\n", lines[0], lines[1]);
    assert_eq!(validate_s545_manifest(&two_lines), Err(E::ManifestLineCountDrift));
    let four_lines = format!("{PACKAGE_MANIFEST}{}\n", lines[2]);
    assert_eq!(validate_s545_manifest(&four_lines), Err(E::ManifestLineCountDrift));
    let no_newline = PACKAGE_MANIFEST.trim_end_matches('\n').to_string();
    assert_eq!(validate_s545_manifest(&no_newline), Err(E::ManifestLineCountDrift));
    let uppercase = PACKAGE_MANIFEST.replacen("ed1901a9", "ED1901A9", 1);
    assert_eq!(validate_s545_manifest(&uppercase), Err(E::ManifestDigestGrammar));
    let single_space = format!(
        "{} \n{}\n{}\n",
        lines[0].replacen("  ", " ", 1),
        lines[1],
        lines[2]
    );
    assert_eq!(validate_s545_manifest(&single_space), Err(E::ManifestSeparatorDrift));
    let renamed = PACKAGE_MANIFEST.replacen("config.txt", "config.tx1", 1);
    assert_eq!(validate_s545_manifest(&renamed), Err(E::ManifestFileNameDrift));
    let reordered = format!("{}\n{}\n{}\n", lines[1], lines[0], lines[2]);
    assert_eq!(validate_s545_manifest(&reordered), Err(E::ManifestFileNameDrift));
    let s542_digest = PACKAGE_MANIFEST.replacen(S545_IMAGE_SHA256, S545_SUPERSEDED_S542_IMAGE_SHA256, 1);
    assert_eq!(validate_s545_manifest(&s542_digest), Err(E::ManifestDigestMismatch));
    assert_eq!(validate_s545_manifest(""), Err(E::ManifestLineCountDrift));
}

#[test]
fn config_directive_validator_requires_exact_lines() {
    use G8lS545CandidateFreezeError as E;
    assert_eq!(validate_s545_config_directives(FIRMWARE_CONFIG), Ok(4));
    assert_eq!(
        validate_s545_config_directives(&FIRMWARE_CONFIG.replacen("uart_2ndstage=0", "uart_2ndstage=1", 1)),
        Err(E::ConfigDirectiveDrift)
    );
    assert_eq!(
        validate_s545_config_directives(&format!("{FIRMWARE_CONFIG}\nuart_2ndstage=1\n")),
        Err(E::ConfigDirectiveDrift)
    );
    assert_eq!(
        validate_s545_config_directives(&format!("{FIRMWARE_CONFIG}\narm_64bit=1\n")),
        Err(E::ConfigDirectiveDrift)
    );
    assert_eq!(
        validate_s545_config_directives(&FIRMWARE_CONFIG.replacen("kernel_address=0x80000", "kernel_address=0x200000", 1)),
        Err(E::ConfigDirectiveDrift)
    );
    assert_eq!(
        validate_s545_config_directives(&FIRMWARE_CONFIG.replacen("kernel=aselsanos-rpi5.img", "kernel=kernel8.img", 1)),
        Err(E::ConfigDirectiveDrift)
    );
    assert_eq!(validate_s545_config_directives(""), Err(E::ConfigDirectiveDrift));
    assert_eq!(FIRMWARE_CONFIG.as_bytes(), PACKAGE_CONFIG);
}

#[test]
fn marker_table_records_merged_literal_not_lost_reference() {
    assert_eq!(S545_MARKER_TABLE.len(), 7);
    assert_eq!(check_s545_marker_membership(&[1; 7]), Ok(1));
    let merged = S545_MARKER_TABLE[2];
    assert_eq!(merged.literal, "[R1:S536] BOOT_TO_UI_READY");
    assert_eq!(merged.expected_count, 1);
    assert_eq!(
        merged.disposition,
        G8lS545MarkerDisposition::MarkerLiteralMerged { source_references: 2 }
    );
    assert_eq!(S545_BOOT_TO_UI_MARKER_S542_COUNT, 2);
    for (index, expectation) in S545_MARKER_TABLE.iter().enumerate() {
        if index != 2 {
            assert_eq!(expectation.disposition, G8lS545MarkerDisposition::ExactOnce);
        }
        assert_eq!(expectation.expected_count, 1);
        let mut counts = [1usize; 7];
        counts[index] = 0;
        assert_eq!(
            check_s545_marker_membership(&counts),
            Err(G8lS545CandidateFreezeError::MarkerCountDrift)
        );
        counts[index] = 2;
        assert_eq!(
            check_s545_marker_membership(&counts),
            Err(G8lS545CandidateFreezeError::MarkerCountDrift)
        );
    }
    let literals: HashSet<&str> = S545_MARKER_TABLE.iter().map(|m| m.literal).collect();
    assert_eq!(literals.len(), 7);
}

#[test]
fn authorization_token_decoder_binds_image_card_and_bytes() {
    use G8lS545CandidateFreezeError as E;
    let fields = parse_s546_authorization_token(S545_PREARM_AUTHORIZATION_TOKEN).unwrap();
    assert_eq!(&fields.image_sha256_prefix, b"ed1901a9");
    assert_eq!(fields.card_serial, 0x425001fa);
    assert_eq!(fields.card_bytes, 62_549_655_552);
    assert_eq!(
        S545_PREARM_AUTHORIZATION_TOKEN,
        "S546_AUTHORIZE_SD_WRITE_READBACK_EJECT_UART_PREARM_ONE_POWER_ON_ed1901a9_425001fa_62549655552"
    );
    let prefix = S545_PREARM_AUTHORIZATION_PREFIX;
    let cases: Vec<(String, E)> = vec![
        (String::new(), E::AuthorizationTokenDrift),
        (prefix.to_string(), E::AuthorizationTokenDrift),
        (
            "S545_AUTHORIZE_SD_WRITE_READBACK_EJECT_UART_PREARM_ONE_POWER_ON_ed1901a9_425001fa_62549655552".to_string(),
            E::AuthorizationTokenDrift,
        ),
        (format!("{prefix}_ed1901a9_425001fa"), E::AuthorizationTokenDrift),
        (format!("{prefix}_ed1901a9_425001fa_62549655552_extra"), E::AuthorizationTokenDrift),
        (format!("{prefix}_ED1901A9_425001fa_62549655552"), E::AuthorizationTokenDrift),
        (format!("{prefix}_ed1901a_425001fa_62549655552"), E::AuthorizationTokenDrift),
        (format!("{prefix}_ed1901a9_425001fa9_62549655552"), E::AuthorizationTokenDrift),
        (format!("{prefix}_ed1901a9_425001FA_62549655552"), E::AuthorizationTokenDrift),
        (format!("{prefix}_ed1901a9_425001fa_062549655552"), E::AuthorizationTokenDrift),
        (format!("{prefix}_ed1901a9_425001fa_184467440737095516160"), E::AuthorizationTokenDrift),
        (format!("{prefix}_ed1901a9_425001fa_18446744073709551616"), E::AuthorizationTokenDrift),
        (format!("{prefix}_ed1901a9_425001fa_6254965555x"), E::AuthorizationTokenDrift),
        (format!("{prefix}_aa0c459b_425001fa_62549655552"), E::AuthorizationTargetDrift),
        (format!("{prefix}_ed1901a9_425001fb_62549655552"), E::AuthorizationTargetDrift),
        (format!("{prefix}_ed1901a9_425001fa_62549655553"), E::AuthorizationTargetDrift),
    ];
    for (token, expected) in cases {
        assert_eq!(parse_s546_authorization_token(&token), Err(expected), "{token}");
    }
    assert_eq!(
        parse_s546_authorization_token(&format!("{prefix}_ed1901a9_425001fa_18446744073709551615")),
        Err(E::AuthorizationTargetDrift)
    );
}

#[test]
fn prearm_contract_never_publishes_execution_permit() {
    use G8lS545CandidateFreezeError as E;
    let receipt = frozen_receipt();
    assert_eq!(
        evaluate_s545_model_prearm_contract(None, Some(prearm_request())),
        Ok(G8lS545PrearmOutcome::AwaitingFrozenCandidate)
    );
    assert_eq!(
        evaluate_s545_model_prearm_contract(Some(receipt), None),
        Ok(G8lS545PrearmOutcome::StoppedAwaitingExplicitAuthorization)
    );
    let mut unpowered_unknown = prearm_request();
    unpowered_unknown.operator_asserts_pi_unpowered = false;
    assert_eq!(
        evaluate_s545_model_prearm_contract(Some(receipt), Some(unpowered_unknown)),
        Ok(G8lS545PrearmOutcome::StoppedAwaitingPowerOffAssertion)
    );
    for mutate in [
        (|r: &mut G8lS545PrearmRequest| r.serial_path_freshly_resolved = false) as fn(&mut G8lS545PrearmRequest),
        |r| r.exclusive_tiocexcl = false,
        |r| r.tciflush_before_capture = false,
        |r| r.fresh_o_excl_raw = false,
        |r| r.capture_armed_before_power_on = false,
        |r| r.power_transitions_operator_reported_only = false,
    ] {
        let mut request = prearm_request();
        mutate(&mut request);
        assert_eq!(
            evaluate_s545_model_prearm_contract(Some(receipt), Some(request)),
            Ok(G8lS545PrearmOutcome::StoppedAwaitingCompleteDiscipline)
        );
    }
    let G8lS545PrearmOutcome::ContractReadyExecutionPermitWithheld(contract) =
        evaluate_s545_model_prearm_contract(Some(receipt), Some(prearm_request())).unwrap()
    else {
        panic!("exact request must produce the contract")
    };
    assert_eq!(contract.sequence, 545);
    assert_eq!(contract.target_sequence, 546);
    assert_eq!(contract.candidate_image, receipt.image);
    assert_eq!(contract.card_serial, 0x425001fa);
    assert_eq!(contract.card_raw_cid, "009f5449534436344761425001fa01a1");
    assert_eq!(contract.card_bytes, 62_549_655_552);
    assert_eq!(contract.card_name, "TISD64G");
    assert_eq!(contract.volume_label, "ASELSANBOOT");
    assert_eq!(contract.debug_probe_serial, "E6647C74033F9131");
    assert_eq!(contract.uart_baud, 115_200);
    assert_eq!(contract.uart_data_bits, 8);
    assert_eq!(contract.uart_stop_bits, 1);
    assert!(contract.uart_parity_none && contract.uart_flow_control_none);
    assert!(contract.exclusive_tiocexcl && contract.tciflush_before_capture);
    assert!(contract.fresh_o_excl_raw && contract.capture_armed_before_power_on);
    assert!(contract.power_transitions_operator_reported_only);
    assert!(contract.contract_ready);
    assert!(!contract.execution_permit);
    assert!(!contract.host_execution_started);
    assert_eq!(contract.device_operations, 0);
    assert_eq!(contract.sd_writes, 0);
    assert_eq!(contract.uart_opens, 0);
    assert_eq!(contract.power_transitions, 0);
    assert_eq!(contract.new_raw_captures, 0);

    let mut early = prearm_request();
    early.requested_sequence = 545;
    assert_eq!(
        evaluate_s545_model_prearm_contract(Some(receipt), Some(early)),
        Err(E::PrearmSequenceDrift)
    );
    let mut late = prearm_request();
    late.requested_sequence = 547;
    assert_eq!(
        evaluate_s545_model_prearm_contract(Some(receipt), Some(late)),
        Err(E::PrearmSequenceDrift)
    );
    let mut wrong_probe = prearm_request();
    wrong_probe.debug_probe_serial = "E6647C74033F9132";
    assert_eq!(
        evaluate_s545_model_prearm_contract(Some(receipt), Some(wrong_probe)),
        Err(E::AuthorizationTargetDrift)
    );
    let mut wrong_cid = prearm_request();
    wrong_cid.card_raw_cid = "009f5449534436344761425001fa01a2";
    assert_eq!(
        evaluate_s545_model_prearm_contract(Some(receipt), Some(wrong_cid)),
        Err(E::AuthorizationTargetDrift)
    );
    let mut flow = prearm_request();
    flow.uart_flow_control_none = false;
    assert_eq!(
        evaluate_s545_model_prearm_contract(Some(receipt), Some(flow)),
        Err(E::AuthorizationTargetDrift)
    );
    let mut bad_token = prearm_request();
    bad_token.authorization_token = "S546_AUTHORIZE";
    assert_eq!(
        evaluate_s545_model_prearm_contract(Some(receipt), Some(bad_token)),
        Err(E::AuthorizationTokenDrift)
    );
    let mut permitted = receipt;
    permitted.execution_permit = true;
    assert_eq!(
        evaluate_s545_model_prearm_contract(Some(permitted), Some(prearm_request())),
        Err(E::CandidateDrift)
    );
    let mut s542 = receipt;
    s542.image = s545_identity(S545_SUPERSEDED_S542_IMAGE_BYTES, S545_SUPERSEDED_S542_IMAGE_SHA256);
    assert_eq!(
        evaluate_s545_model_prearm_contract(Some(s542), Some(prearm_request())),
        Err(E::CandidateDrift)
    );
}

#[test]
fn predecessor_gate_and_tool_identity_drift_fail_closed() {
    use G8lS545CandidateFreezeError as E;
    let mut state = G8lS545CandidateFreezeState::new();
    let mut unaccepted = canonical_input();
    unaccepted.s544_source_gate_passed = false;
    assert_eq!(
        service_s545_model_candidate_freeze(&mut state, &unaccepted),
        Err(E::PredecessorNotAccepted)
    );
    let mut verifier = canonical_input();
    verifier.tools.layout_verifier.bytes = 11_151;
    assert_eq!(service_s545_model_candidate_freeze(&mut state, &verifier), Err(E::ToolIdentityDrift));
    let mut tool = canonical_input();
    tool.tools.freeze_tool.sha256 = S545_LAYOUT_VERIFIER_SHA256;
    assert_eq!(service_s545_model_candidate_freeze(&mut state, &tool), Err(E::ToolIdentityDrift));
    let mut config = canonical_input();
    config.tools.firmware_config.bytes = 415;
    assert_eq!(service_s545_model_candidate_freeze(&mut state, &config), Err(E::ToolIdentityDrift));
    let mut manifest = canonical_input();
    manifest.manifest_text = "";
    assert_eq!(
        service_s545_model_candidate_freeze(&mut state, &manifest),
        Err(E::ManifestLineCountDrift)
    );
    let mut directives = canonical_input();
    directives.config_text = "uart_2ndstage=1\n";
    assert_eq!(
        service_s545_model_candidate_freeze(&mut state, &directives),
        Err(E::ConfigDirectiveDrift)
    );
    assert_eq!(state.receipt(), None);
}

#[test]
fn frozen_package_files_have_exact_identities_modes_and_manifest() {
    assert_eq!(PACKAGE_IMAGE.len() as u64, S545_IMAGE_BYTES);
    assert_eq!(sha256(PACKAGE_IMAGE), S545_IMAGE_SHA256);
    assert_eq!(PACKAGE_DTB.len() as u64, S545_DTB_BYTES);
    assert_eq!(sha256(PACKAGE_DTB), S545_DTB_SHA256);
    assert_eq!(PACKAGE_CONFIG.len() as u64, S545_CONFIG_BYTES);
    assert_eq!(sha256(PACKAGE_CONFIG), S545_CONFIG_SHA256);
    assert_eq!(PACKAGE_MANIFEST_BYTES.len() as u64, S545_MANIFEST_BYTES);
    assert_eq!(sha256(PACKAGE_MANIFEST_BYTES), S545_MANIFEST_SHA256);
    assert_eq!(PACKAGE_MANIFEST.as_bytes(), PACKAGE_MANIFEST_BYTES);
    assert_eq!(
        PACKAGE_MANIFEST,
        "ed1901a991e2f9e9ae3c16f254147a2b0180686a8d70ca5d7353374fee08d467  aselsanos-rpi5.img\n40a2fbe9c29e8b9a4912cf726a943068defb779fc052ec38e457a79c58abca00  bcm2712-rpi-5-b.dtb\naef848bf6e0c324148eade5054a15c71a1e8c04814a3ed2e680056f87c1f9bba  config.txt\n"
    );
    let mut inodes = HashSet::new();
    let mut entries = 0usize;
    for name in [S545_IMAGE_NAME, S545_DTB_NAME, S545_CONFIG_NAME, S545_MANIFEST_NAME] {
        let metadata = fs::symlink_metadata(package_root().join(name)).unwrap();
        assert!(metadata.is_file(), "{name} regular");
        assert_eq!(metadata.permissions().mode() & 0o777, 0o444, "{name} mode");
        assert_eq!(metadata.nlink(), 1, "{name} link count");
        assert!(inodes.insert((metadata.dev(), metadata.ino())), "{name} inode");
        assert_eq!(metadata.len(), s545_expected_package_identity(name).unwrap().bytes);
        entries += 1;
    }
    assert_eq!(entries, S545_PACKAGE_ENTRIES);
    assert_eq!(fs::read_dir(package_root()).unwrap().count(), S545_PACKAGE_ENTRIES);
    assert_eq!(PACKAGE_CONFIG, FIRMWARE_CONFIG.as_bytes());
    assert_eq!(FIRMWARE_CONFIG.matches("uart_2ndstage=0").count(), 1);
    assert_eq!(FIRMWARE_CONFIG.matches("uart_2ndstage=1").count(), 0);
    assert_eq!(FIRMWARE_CONFIG.matches("kernel=aselsanos-rpi5.img").count(), 1);
    assert_eq!(FIRMWARE_CONFIG.matches("kernel_address=0x80000").count(), 1);
    assert_eq!(FIRMWARE_CONFIG.matches("arm_64bit=1").count(), 1);
}

#[test]
fn frozen_image_contains_exact_marker_membership() {
    for expectation in S545_MARKER_TABLE {
        assert_eq!(
            count_bytes(PACKAGE_IMAGE, expectation.literal.as_bytes()),
            expectation.expected_count,
            "{}",
            expectation.literal
        );
    }
    assert_eq!(count_bytes(PACKAGE_IMAGE, b"[R1:S536] BOOT_TO_UI_READY"), 1);
    assert_eq!(count_bytes(PACKAGE_IMAGE, b"ASELSAN/BOOT8H"), 1);
    assert!(LAYOUT_VERIFIER.contains("MARKER_LITERAL_MERGED=1"));
    assert!(FREEZE_TOOL.contains("R1 marker merged literal is not exact-once"));
}

#[test]
fn host_tools_are_read_only_and_pin_the_frozen_identities() {
    assert_eq!(LAYOUT_VERIFIER.len() as u64, S545_LAYOUT_VERIFIER_BYTES);
    assert_eq!(sha256(LAYOUT_VERIFIER.as_bytes()), S545_LAYOUT_VERIFIER_SHA256);
    assert_eq!(FREEZE_TOOL.len() as u64, S545_FREEZE_TOOL_BYTES);
    assert_eq!(sha256(FREEZE_TOOL.as_bytes()), S545_FREEZE_TOOL_SHA256);
    for tool in [LAYOUT_VERIFIER, FREEZE_TOOL] {
        for required in [
            "EXPECTED_ELF_BYTES=18438504",
            "EXPECTED_ELF_SHA256=6ce50d295e0aa97ab599cfa3cf567944ca7ed36d59d1b988e733be48b826c1c5",
            "EXPECTED_IMAGE_BYTES=945760",
            "EXPECTED_IMAGE_SHA256=ed1901a991e2f9e9ae3c16f254147a2b0180686a8d70ca5d7353374fee08d467",
            "set -eu",
        ] {
            assert!(tool.contains(required), "{required}");
        }
        for forbidden in ["diskutil", "/dev/disk", "/dev/cu.", "/dev/tty.", "stty", "dd if="] {
            assert!(!tool.contains(forbidden), "{forbidden}");
        }
    }
    for required in [
        "EXPECTED_LINKED_SPAN=18317312",
        "[ \"$entry\" = 0x80000 ]",
        "[ \"$start_hex\" = 0000000000080000 ]",
        "[ \"$end_hex\" = 00000000011f8000 ]",
        "require_call_count \"$secondary\" service_s544_model_reachable_readiness_producer 1",
        "symbol_count '::S544_PRODUCTION_STATE'",
        "symbol_count '::service_s544_model_reachable_readiness_producer'",
        "require_marker_count '[R1:S536] BOOT_TO_UI_READY' 1",
        "dsb[[:space:]]+ishst$",
        "sev$",
        "ldaxr",
        "stlxr",
        "ldar",
        "ELF SHA-256 changed during audit",
        "RUNBOOK_EXECUTED_IN_S545=NO",
        "never invokes llvm-objcopy",
    ] {
        assert!(LAYOUT_VERIFIER.contains(required), "{required}");
    }
    assert!(!LAYOUT_VERIFIER.contains("\"$objcopy\""));
    for required in [
        "EXPECTED_DTB_BYTES=78703",
        "EXPECTED_DTB_SHA256=40a2fbe9c29e8b9a4912cf726a943068defb779fc052ec38e457a79c58abca00",
        "EXPECTED_CONFIG_BYTES=420",
        "EXPECTED_CONFIG_SHA256=aef848bf6e0c324148eade5054a15c71a1e8c04814a3ed2e680056f87c1f9bba",
        "EXPECTED_SUMS_BYTES=248",
        "EXPECTED_SUMS_SHA256=4accd201849f68107db4d21e4657b1510f043d7f900f713c383bd8909d33e586",
        "EXPECTED_PACKAGE_ENTRIES=4",
        "EXPECTED_FILE_MODE=444",
        "EXPECTED_LAYOUT_VERIFIER_BYTES=11150",
        "EXPECTED_LAYOUT_VERIFIER_SHA256=7a23bf574cda06d0fb4710d0c97427c0a743c7df4a3628d31077a220ad4140cd",
        "uart_2ndstage=0",
        "uart_2ndstage=1",
        "S545_CANDIDATE_FREEZE=PASS",
        "DEVICE_OPERATIONS=0 SD_WRITES=0 UART_OPENS=0 POWER_TRANSITIONS=0",
        "EXECUTION_PERMIT=0",
        "/bin/chmod 0444",
        "config-r1-s545.txt",
    ] {
        assert!(FREEZE_TOOL.contains(required), "{required}");
    }
    let firmware = fs::read(repository_root().join(S545_FIRMWARE_CONFIG_PATH)).unwrap();
    assert_eq!(firmware.len() as u64, S545_CONFIG_BYTES);
    assert_eq!(sha256(&firmware), S545_CONFIG_SHA256);
}

#[test]
fn isolated_build_logs_have_exact_identities_and_warning_headers() {
    let evidence = repository_root().join("evidence/rpi5/r1/sequence-545-candidate-freeze");
    for (name, bytes, digest) in [
        ("build-a.log", S545_BUILD_A_LOG_BYTES, S545_BUILD_A_LOG_SHA256),
        ("build-b.log", S545_BUILD_B_LOG_BYTES, S545_BUILD_B_LOG_SHA256),
    ] {
        let log = fs::read(evidence.join(name)).unwrap();
        assert_eq!(log.len() as u64, bytes, "{name} bytes");
        assert_eq!(sha256(&log), digest, "{name} SHA-256");
        let text = String::from_utf8_lossy(&log);
        assert_eq!(
            text.lines().filter(|line| line.starts_with("warning")).count(),
            S545_BUILD_WARNING_HEADERS_EACH,
            "{name} warning headers"
        );
        assert_eq!(text.lines().filter(|line| line.starts_with("error")).count(), 0);
    }
    assert_ne!(S545_BUILD_A_LOG_SHA256, S545_BUILD_B_LOG_SHA256);
    assert_eq!(S545_BUILD_A_LOG_BYTES - S545_BUILD_B_LOG_BYTES, 7);
}

#[test]
fn immutable_s540_and_s543_raws_remain_unchanged_and_unpromoted() {
    let s540 = fs::read(
        repository_root().join("evidence/rpi5/r1/sequence-540-physical-boot-uart/s540-uart.raw"),
    )
    .unwrap();
    assert_eq!(s540.len(), 20_525);
    assert_eq!(
        sha256(&s540),
        "fc3f934543ab5d829ad8a16e2b332dd2bdc35a81c6c0f6423256101448e45114"
    );
    let s543 = fs::read(
        repository_root()
            .join("evidence/rpi5/r1/sequence-543-remediated-physical-retry/s543-uart.raw"),
    )
    .unwrap();
    assert_eq!(s543.len(), 20_509);
    assert_eq!(
        sha256(&s543),
        "1f1111a1a39ab6263b505b0889d025df19d5c48bb2f84e30708412b0da47dc11"
    );
    for raw in [&s540, &s543] {
        assert_eq!(count_bytes(raw, b"[R1:S536] BOOT_TO_UI_READY"), 0);
        assert_eq!(count_bytes(raw, b"ASELSAN/S538 ROUTE=PRIOR_BOOT_TO_UI"), 0);
    }
    assert_eq!(count_bytes(&s543, b"ASELSAN/S541ERR Cpu0ReadinessTimeout"), 1);
    assert!(S545_S540_PHYSICAL_VERDICT_RETAINED_RED);
    assert!(S545_S543_PHYSICAL_VERDICT_RETAINED_RED);
    assert!(!S545_AUTOMATIC_PROMOTION);
    assert!(!S545_BOOT_TO_UI_PHYSICALLY_OBSERVED);
}
snippet sha256: 13e364c18394file sha256: 13e364c18394
03 · Kapı kimlik kaydı

Operations sıra, kimlik ve başlık bağı

tam Operations kaydıL3232–L3291
website/src/lib/operations.ts::g8l-s545-r1-reachable-producer-candidate-freeze-prearm-contract
  {
    id: "g8l-s545-r1-reachable-producer-candidate-freeze-prearm-contract",
    date: "2026-08-30",
    sequence: 545,
    status: "passed",
    umbrella_status: "partial",
    title: "S545 · R1 reachable-producer candidate freeze ve pre-arm sözleşmesi",
    summary:
      "S545 host-only kapısı PASS'tir: S544 reachable CPU1 readiness producer hook'unu içeren board-rpi5 candidate'ı iki izole CARGO_INCREMENTAL=0 build ile byte-exact yeniden üretildi (ELF 18438504 B / 6ce50d29…c1c5, flat image 945760 B / ed1901a9…8d467) ve dört dosyalı 0444 paket olarak donduruldu; reddedilen S542 imajından (941392 B / aa0c459b…d87c) farklıdır. Read-only layout auditi entry 0x80000, linked span 18317312, CPU1 identity→S431–S535→S536→S537→S541→S544 exact-once sırasını ve ldaxr/stlxr/dsb ishst/sev/ldar disiplinini doğruladı; [R1:S536] BOOT_TO_UI_READY literal'i linker tarafından birleştirildiği için MARKER_LITERAL_MERGED olarak kaydedildi, kayıp referans değildir. S546 pre-arm sözleşmesi (kart 0x425001fa / TISD64G / ASELSANBOOT, Debug Probe E6647C74033F9131, exclusive 115200/8N1) yalnız sözleşmedir; execution_permit=false'tur. Focused 21/21 PASS'tir. S540 ve S543 fiziksel RED immutable kalır; runtime/physical observation=0/0, device operation=0, SD/UART/power=0/0/0, RUNBOOK_EXECUTED_IN_S545=NO, Boot-to-UI=false ve R1 acceptance=false'tur. S546 bu exact paketle üçüncü yetkili fiziksel boot/UART koşusudur; açık operatör yetkisi bekler ve otomatik değildir.",
    evidence: [
      "S545 host-only bir kaynak/model kapısıdır: donanım, panel, modem, board, SD kart, UART veya güç gözlemi yoktur; entegratörün hostta yürüttüğü freeze'in kimlikleri modele sabit olarak kodlanmış ve focused testte doğrulanmıştır.",
      "İki izole CARGO_INCREMENTAL=0 board-rpi5 build (--no-default-features --features board-rpi5) byte-exact ELF üretti: 18438504 B / 6ce50d295e0aa97ab599cfa3cf567944ca7ed36d59d1b988e733be48b826c1c5.",
      "Build logları yalnız izole target root'ları nedeniyle farklıdır: build-a 1135955 B / 5aa11909f47b6ebe27b0dd18aa036573a48b37f05a966831aa089d3a3b6e73be, build-b 1135948 B / 61160d45cc3114360a6107a96c557282ae9eaab76b13d3b8347c63b516468670; her birinde 2865 warning başlığı sayılmıştır ve zero-warning iddiası kurulmaz.",
      "Flat image (llvm-objcopy -O binary) 945760 B / ed1901a991e2f9e9ae3c16f254147a2b0180686a8d70ca5d7353374fee08d467'dir; önceki S542 imajı 941392 B / aa0c459b987c3f4c143b4eb14ce0ed655c2812e2a36516793e7bd8b27b60d87c'den hem byte hem SHA-256 olarak farklıdır, bu nedenle reddedilen imajın retry'ı değildir.",
      "Paket evidence/rpi5/r1/sequence-545-candidate-freeze/package dört girdidir (mode 0444, nlink 1, ayrık inode): aselsanos-rpi5.img; bcm2712-rpi-5-b.dtb 78703 B / 40a2fbe9c29e8b9a4912cf726a943068defb779fc052ec38e457a79c58abca00; config.txt 420 B / aef848bf6e0c324148eade5054a15c71a1e8c04814a3ed2e680056f87c1f9bba; SHA256SUMS 248 B / 4accd201849f68107db4d21e4657b1510f043d7f900f713c383bd8909d33e586.",
      "config.txt exact kernel=aselsanos-rpi5.img, kernel_address=0x80000, arm_64bit=1 ve tek uart_2ndstage=0 içerir, uart_2ndstage=1 içermez; firmware/config-r1-s545.txt paket config.txt ile byte-exact aynıdır.",
      "Read-only layout auditi (scripts/verify-rpi5-s545-layout.sh 11150 B / 7a23bf574cda06d0fb4710d0c97427c0a743c7df4a3628d31077a220ad4140cd) entry 0x80000, __kernel_start 0x80000, __kernel_end 0x11f8000 ve linked span 18317312'yi; CPU1 secondary-run text sırasını identity → S431–S535 gate → S536 → S537 → S541 → S544 model call exact-once olarak; inlined S544 wrapper nedeniyle service_s544_model_reachable_readiness_producer ve S544_PRODUCTION_STATE sembollerinin exact-once olduğunu; CPU0 prior-boot → S541 → S538 sırasını; ldaxr/stlxr, exact-once dsb ishst, exact-once sev ve ldar'ı ve ELF'in audit öncesi/sonrası değişmediğini doğruladı.",
      "Freeze aracı scripts/freeze-rpi5-s545-r1-candidate.sh 9175 B / ddd0f3baf1c2e47c26e97d1ee33d8ce00746dc6f5b64149489a63ff9cb42cfcd'dir; disk, seri port veya güç komutu içermez ve focused test onu çalıştırmaz, yalnız içeriğini ve kimliğini doğrular.",
      "Marker üyeliği (strings | grep -c): ASELSAN/S541 HANDOFF=CPU1_PREFLIGHT_ARMED 1, ASELSAN/S541ERR 1, [R1:S536] BOOT_TO_UI_READY 1, ASELSAN/S538 ROUTE=PRIOR_BOOT_TO_UI 1, ASELSAN/S538ERR 1, ASELSAN-R1-S538-BOARD-RPI5 1, ASELSAN/BOOT8H 1. S542 Boot-to-UI literal'ini 2 saymıştı; bu build'de linker özdeş literal'i birleştirdiği için tablo MARKER_LITERAL_MERGED (source_references=2) olarak kaydeder, kayıp referans olarak değil.",
      "Model freeze receipt, reproducibility predicate'i, SHA256SUMS grammar validator'ı (üç satır, 64 lowercase-hex, çift boşluk, canonical dosya sırası, exact digest), config directive validator'ı, marker-membership tablosu, checked inode signature'ı ve execution_permit=false pre-arm sözleşmesi struct'ını içerir; predecessor, build, ELF/image, layout, paket, manifest, config, marker, tool ve authorization drift'lerinin her biri fail-closed ayrı hata kodudur (34 nonzero unique kod).",
      "Exact replay CandidateRetained ile aynı receipt'i döndürür; yayından sonra yeniden oluşturulmuş bir paket (farklı inode'lar) FrozenStateDrift ile reddedilir; S542 imajına eşit candidate ImageRetriesRejectedCandidate ile reddedilir.",
      "S546 pre-arm sözleşmesi yalnız sözleşmedir: kart seri 0x425001fa / CID 009f5449534436344761425001fa01a1 / 62549655552 B / TISD64G / volume ASELSANBOOT; Debug Probe E6647C74033F9131 son çözümlenen /dev/cu.usbmodem21302 (S546 taze çözümlemelidir); exclusive TIOCEXCL 115200/8N1 parity yok flow yok, TCIFLUSH, fresh O_EXCL raw, güç verilmeden önce armed capture; yalnız operatör raporlu güç geçişleri; token literal S546_AUTHORIZE_SD_WRITE_READBACK_EJECT_UART_PREARM_ONE_POWER_ON_ed1901a9_425001fa_62549655552 decode edilip candidate ve karta bağlanır; exact istek bile ContractReadyExecutionPermitWithheld döndürür ve execution_permit=false, host_execution_started=false, tüm sayaçlar 0 kalır.",
      "Focused test dört paket dosyasını, SHA256SUMS metnini, firmware config'i ve iki host aracını include_bytes!/include_str! ile gömer, byte uzunluklarını ve SHA-256 digest'lerini doğrular, iki build logunu yeniden okuyup her birinde 2865 warning başlığı sayar ve paket mode/nlink/inode'larını diskte kontrol eder.",
      "Focused target 1 grup / 21 passed / 0 failed / 0 ignored / 0 filtered verdi; ilk derlenen koşu 20/21 idi ve tek fark test beklentisiydi (model doğru olarak ImageRetriesRejectedCandidate döndürdü), model davranışı değişmedi.",
      "Implementation 40040 B / 4ecd2ef5b35d61fb2efca8a6cb28b215481854ed09bc6214e2e93d505ea866ab; focused test 40697 B / 13e364c18394f72d18f77b56fc82eb32b7294f47a16ea3c3c9acf5dbfd849483 SHA-256'dır.",
      "Proof 9014 B'dır; evidence/rpi5/r1/sequence-545-candidate-freeze/README.md tüm kimlikleri ve closeout satırlarını kaydeder.",
      "S540 immutable raw 20525 B / fc3f934543ab5d829ad8a16e2b332dd2bdc35a81c6c0f6423256101448e45114 ve S543 immutable raw 20509 B / 1f1111a1a39ab6263b505b0889d025df19d5c48bb2f84e30708412b0da47dc11 byte-exact korunur; her iki fiziksel verdict RED'dir, automatic promotion=false ve rerun=false'tur.",
      "RUNBOOK_EXECUTED_IN_S545=NO; supported-profile runtime observations=0, physical observations=0, device operations=0, SD writes=0, UART opens=0, power transitions=0, new immutable raw=0, hardware present=false, Boot-to-UI physically observed=false ve R1 acceptance=false'tur.",
      "S546 bu exact paketle (ed1901a9…8d467) üçüncü yetkili fiziksel boot/UART koşusudur; yalnız açık operatör yetkisiyle ve ayrı kapı olarak yürütülebilir, S545 onu ne planlar ne de izin verir.",
    ],
    commands: [
      "CARGO_INCREMENTAL=0 cargo test -p aselsan_microkernel_simulation --test g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s545_r1_reachable_producer_candidate_freeze_prearm_contract -- --test-threads=1",
    ],
    terminalSessions: [
      {
        id: "s545-focused",
        title: "S545 candidate freeze ve pre-arm sözleşmesi focused",
        commandLines: [
          "CARGO_INCREMENTAL=0 cargo test -p aselsan_microkernel_simulation --test g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s545_r1_reachable_producer_candidate_freeze_prearm_contract -- --test-threads=1",
        ],
        outputLines: [
          "test result: ok. 21 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s",
          "S545 focused=1 group / 21 passed / 0 failed",
          "hardware=none physical=0 runbook=NO",
        ],
        exitCode: 0,
        outputMode: "complete",
      },
    ],
    terminalSessionsNote:
      "S545 host-only freeze ve pre-arm sözleşmesi PASS'tir; supported-profile runtime veya fiziksel PASS değildir. S540 ve S543 RED raw'ları ve kararları değişmez; execution permit yayımlanmaz.",
    limitations: [
      "S545 yalnız host üzerinde candidate freeze ve sözleşme modelidir; hiçbir donanım/panel/modem/board gözlemi yoktur.",
      "S540 ve S543 fiziksel RED immutable kalır; S545 bunları yeniden yorumlamaz, yeniden koşmaz ve yükseltmez.",
      "BOOT_TO_UI_READY gerçek UART'ta görülmedi; Boot-to-UI ve R1 acceptance false kalır.",
      "S546 pre-arm sözleşmesi execution permit değildir; SD write/read-back/eject, UART açma ve güç geçişi S545'te sıfırdır ve yetkilendirilmemiştir.",
      "Fresh build warning sayıları (2865) sıfır değildir; zero-warning iddiası yoktur.",
      "S546 bu exact paketle üçüncü yetkili fiziksel boot/UART koşusu için ayrı kapı, taze target revalidation, açık operatör yetkisi ve yeni immutable raw ister; otomatik değildir.",
    ],
  },
snippet sha256: 4dbde9bfac66file sha256: 9726dbf00f84
Focused test komutu
CARGO_INCREMENTAL=0 cargo test -p aselsan_microkernel_simulation --test g8l_target_dispatch_scheduler_owner_scheduler_mutation_production_migration_lifecycle_s545_r1_reachable_producer_candidate_freeze_prearm_contract -- --test-threads=1
proof: docs/M8.1-RPi5-G8l-S545-R1-Reachable-Producer-Candidate-Freeze-Prearm-Contract-Proof.md
Registry schema v5 · generator website/scripts/generate-code-gates.mjs · Tam SHA-256: 3050638b71a684d8f8f947a8a6faa237a17fa8db5dc0db04fb207b668b462af9