#include "glove/container/receipt_producer.hpp" #include #include #include #include #include #include #include #include #include #include #include #include namespace { #define REQUIRE(cond) \ do { \ if (!(cond)) { \ std::fprintf(stderr, "REQUIRE failed: %s @ %s:%d\n", #cond, __FILE__, __LINE__); \ return 1; \ } \ } while (0) constexpr std::string_view audit_key = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"; constexpr std::string_view controller_plan_digest = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; constexpr std::string_view profile_digest = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"; class temporary_directory { public: temporary_directory() { std::string pattern = "/tmp/glove-receipt-producer-test-XXXXXX"; char* created = ::mkdtemp(pattern.data()); if (created != nullptr) { root_ = created; } } temporary_directory(const temporary_directory&) = delete; auto operator=(const temporary_directory&) -> temporary_directory& = delete; ~temporary_directory() { std::error_code error; std::filesystem::remove_all(root_, error); } [[nodiscard]] auto root() const -> const std::filesystem::path& { return root_; } private: std::filesystem::path root_; }; auto write_key(const std::filesystem::path& path, std::string_view value, mode_t mode = 0600) -> bool { std::ofstream output{path, std::ios::binary | std::ios::trunc}; output << value << '\n'; output.flush(); return output.good() && ::chmod(path.c_str(), mode) == 0; } auto append_byte(const std::filesystem::path& path) -> bool { std::ofstream output{path, std::ios::binary | std::ios::app}; output.put('x'); output.flush(); return output.good(); } auto receipt(std::uint64_t cpu_time_ms = 500) -> glove::container::resource_enforcement_receipt { return { .schema_version = 1, .profile_digest = std::string{profile_digest}, .backend = glove::container::sandbox_backend::linux_production, .backend_id = "linux-production:cgroup-v2-v1", .configured_limits = { .cpu_time_ms = 60'000, .memory_bytes = std::uint64_t{512} * 1024U * 1024U, .pids = 128, .wall_time_ms = 120'000, .disk_bytes = std::uint64_t{1024} * 1024U * 1024U, .terminal_output_bytes = std::uint64_t{16} * 1024U * 1024U, }, .mechanisms = { .cpu_time = glove::container::enforcement_mechanism::cgroup_v2, .memory = glove::container::enforcement_mechanism::cgroup_v2, .pids = glove::container::enforcement_mechanism::cgroup_v2, .wall_time = glove::container::enforcement_mechanism::watchdog, .disk = glove::container::enforcement_mechanism::filesystem_quota, .terminal_output = glove::container::enforcement_mechanism::byte_counter, .receipt_schema_version = 1, }, .observed = { .cpu_time_ms = cpu_time_ms, .peak_memory_bytes = std::uint64_t{16} * 1024U * 1024U, .peak_pids = 2, .wall_time_ms = 750, .disk_bytes = 4096, .terminal_output_bytes = 1024, }, .termination_cause = glove::container::resource_termination_cause::exited, .exit_code = 0, .started_at_ms = 1'000, .finished_at_ms = 1'750, .library_projections = {}, .retained_changes = {}, }; } auto bootstrap_reconciliation_and_durable_commit() -> int { temporary_directory temp; REQUIRE(!temp.root().empty()); const auto key_path = temp.root() / "audit.key"; const auto journal_path = temp.root() / "receipts.journal"; REQUIRE(write_key(key_path, audit_key)); const glove::container::receipt_audit_producer_config config{ .key_path = key_path, .journal_path = journal_path, }; auto producer = glove::container::receipt_audit_producer::initialize(config); REQUIRE(producer.has_value()); const auto genesis = (*producer)->anchor(); REQUIRE(genesis.sequence == 0); REQUIRE(!(*producer)->bootstrap_reconciled()); REQUIRE(!(*producer)->reserve_terminal().has_value()); auto forged = genesis; forged.head_hmac[0] = '1'; REQUIRE(!(*producer)->acknowledge_bootstrap(forged).has_value()); REQUIRE(!(*producer)->bootstrap_reconciled()); REQUIRE((*producer)->acknowledge_bootstrap(genesis).has_value()); REQUIRE((*producer)->bootstrap_reconciled()); REQUIRE(!glove::container::receipt_audit_producer::recover(config, genesis).has_value()); auto reservation = (*producer)->reserve_terminal(); REQUIRE(reservation.has_value()); auto first = (*producer)->commit_terminal( std::move(*reservation), "session-1", controller_plan_digest, receipt() ); REQUIRE(first.has_value()); REQUIRE(first->sequence == 1); const auto first_anchor = (*producer)->anchor(); auto page = (*producer)->page_after(genesis, 10); REQUIRE(page.has_value()); REQUIRE(page->envelopes.size() == 1); REQUIRE(page->envelopes[0] == *first); producer->reset(); auto recovered = glove::container::receipt_audit_producer::recover(config, genesis); REQUIRE(recovered.has_value()); REQUIRE(!(*recovered)->bootstrap_reconciled()); REQUIRE(!(*recovered)->reserve_terminal().has_value()); auto pending = (*recovered)->page_after(genesis, 10); REQUIRE(pending.has_value()); REQUIRE(pending->envelopes.size() == 1); REQUIRE((*recovered)->acknowledge_bootstrap(first_anchor).has_value()); REQUIRE((*recovered)->bootstrap_reconciled()); auto second_reservation = (*recovered)->reserve_terminal(); REQUIRE(second_reservation.has_value()); auto second = (*recovered) ->commit_terminal( std::move(*second_reservation), "session-2", controller_plan_digest, receipt(501) ); REQUIRE(second.has_value()); const auto second_anchor = (*recovered)->anchor(); recovered->reset(); auto caught_up = glove::container::receipt_audit_producer::recover(config, second_anchor); REQUIRE(caught_up.has_value()); REQUIRE((*caught_up)->bootstrap_reconciled()); auto caught_up_page = (*caught_up)->page_after(second_anchor, 10); REQUIRE(caught_up_page.has_value()); REQUIRE(caught_up_page->envelopes.empty()); caught_up->reset(); auto ahead = second_anchor; ++ahead.sequence; REQUIRE(!glove::container::receipt_audit_producer::recover(config, ahead).has_value()); auto divergent = second_anchor; divergent.head_hmac[0] = divergent.head_hmac[0] == 'a' ? 'b' : 'a'; REQUIRE(!glove::container::receipt_audit_producer::recover(config, divergent).has_value()); return 0; } auto concurrent_terminal_commits_are_serialized() -> int { temporary_directory temp; REQUIRE(!temp.root().empty()); const auto key_path = temp.root() / "audit.key"; REQUIRE(write_key(key_path, audit_key)); const glove::container::receipt_audit_producer_config config{ .key_path = key_path, .journal_path = temp.root() / "receipts.journal", }; auto producer = glove::container::receipt_audit_producer::initialize(config); REQUIRE(producer.has_value()); REQUIRE((*producer)->acknowledge_bootstrap((*producer)->anchor()).has_value()); std::atomic committed = 0; { std::vector workers; workers.reserve(8); for (std::uint64_t index = 0; index < 8; ++index) { workers.emplace_back([&, index] { auto reservation = (*producer)->reserve_terminal(); if (!reservation) { return; } const auto session = "session-" + std::to_string(index); if ((*producer)->commit_terminal( std::move(*reservation), session, controller_plan_digest, receipt(500U + index) )) { committed.fetch_add(1, std::memory_order_relaxed); } }); } for (auto& worker : workers) { worker.join(); } } REQUIRE(committed.load(std::memory_order_relaxed) == 8); REQUIRE((*producer)->anchor().sequence == 8); return 0; } auto capacity_is_reserved_before_a_session() -> int { temporary_directory temp; REQUIRE(!temp.root().empty()); const auto key_path = temp.root() / "audit.key"; REQUIRE(write_key(key_path, audit_key)); const glove::container::receipt_audit_producer_config config{ .key_path = key_path, .journal_path = temp.root() / "receipts.journal", .max_journal_bytes = glove::container::max_receipt_journal_record_bytes, }; auto producer = glove::container::receipt_audit_producer::initialize(config); REQUIRE(producer.has_value()); REQUIRE((*producer)->acknowledge_bootstrap((*producer)->anchor()).has_value()); REQUIRE(!(*producer)->reserve_terminal().has_value()); REQUIRE((*producer)->anchor().sequence == 0); return 0; } auto abandoned_capacity_reservation_is_released() -> int { temporary_directory temp; REQUIRE(!temp.root().empty()); const auto key_path = temp.root() / "audit.key"; REQUIRE(write_key(key_path, audit_key)); const glove::container::receipt_audit_producer_config config{ .key_path = key_path, .journal_path = temp.root() / "receipts.journal", .max_journal_bytes = glove::container::max_receipt_journal_record_bytes + 128U, }; auto producer = glove::container::receipt_audit_producer::initialize(config); REQUIRE(producer.has_value()); REQUIRE((*producer)->acknowledge_bootstrap((*producer)->anchor()).has_value()); { auto reservation = (*producer)->reserve_terminal(); REQUIRE(reservation.has_value()); REQUIRE(!(*producer)->reserve_terminal().has_value()); } REQUIRE((*producer)->reserve_terminal().has_value()); return 0; } auto execution_bound_reservation_is_single_profile_authority() -> int { temporary_directory temp; REQUIRE(!temp.root().empty()); const auto key_path = temp.root() / "audit.key"; REQUIRE(write_key(key_path, audit_key)); const glove::container::receipt_audit_producer_config config{ .key_path = key_path, .journal_path = temp.root() / "receipts.journal", }; auto producer = glove::container::receipt_audit_producer::initialize(config); REQUIRE(producer.has_value()); const auto genesis = (*producer)->anchor(); REQUIRE((*producer)->acknowledge_bootstrap(genesis).has_value()); auto reservation = (*producer)->reserve_terminal("session-bound", controller_plan_digest, profile_digest); REQUIRE(reservation.has_value()); REQUIRE( reservation->matches_execution("session-bound", controller_plan_digest, profile_digest) ); REQUIRE( !reservation->matches_execution("session-other", controller_plan_digest, profile_digest) ); REQUIRE(!(*producer) ->commit_terminal( std::move(*reservation), "session-other", controller_plan_digest, receipt() ) .has_value()); REQUIRE((*producer)->anchor() == genesis); auto retry = (*producer)->reserve_terminal("session-bound", controller_plan_digest, profile_digest); REQUIRE(retry.has_value()); auto committed = (*producer)->commit_terminal( std::move(*retry), "session-bound", controller_plan_digest, receipt() ); REQUIRE(committed.has_value()); REQUIRE(committed->session_id == "session-bound"); REQUIRE(committed->receipt.profile_digest == profile_digest); auto confirmed = (*producer)->confirms_terminal(*committed); REQUIRE(confirmed.has_value()); REQUIRE(*confirmed); auto lookup = (*producer)->terminal_for_execution( "session-bound", controller_plan_digest, profile_digest ); REQUIRE(lookup.has_value()); REQUIRE(lookup->has_value()); REQUIRE(**lookup == *committed); auto missing = (*producer)->terminal_for_execution( "session-missing", controller_plan_digest, profile_digest ); REQUIRE(missing.has_value()); REQUIRE(!missing->has_value()); auto tampered = *committed; tampered.receipt_digest = std::string(64, 'f'); auto tampered_confirmation = (*producer)->confirms_terminal(tampered); REQUIRE(tampered_confirmation.has_value()); REQUIRE(!*tampered_confirmation); const auto committed_anchor = (*producer)->anchor(); producer->reset(); auto recovered = glove::container::receipt_audit_producer::recover(config, committed_anchor); REQUIRE(recovered.has_value()); auto recovered_confirmation = (*recovered)->confirms_terminal(*committed); REQUIRE(recovered_confirmation.has_value()); REQUIRE(*recovered_confirmation); auto recovered_lookup = (*recovered) ->terminal_for_execution("session-bound", controller_plan_digest, profile_digest); REQUIRE(recovered_lookup.has_value()); REQUIRE(recovered_lookup->has_value()); REQUIRE(**recovered_lookup == *committed); return 0; } auto append_failure_never_acknowledges_terminal_success() -> int { temporary_directory temp; REQUIRE(!temp.root().empty()); const auto key_path = temp.root() / "audit.key"; const auto journal_path = temp.root() / "receipts.journal"; REQUIRE(write_key(key_path, audit_key)); const glove::container::receipt_audit_producer_config config{ .key_path = key_path, .journal_path = journal_path, }; auto producer = glove::container::receipt_audit_producer::initialize(config); REQUIRE(producer.has_value()); const auto genesis = (*producer)->anchor(); REQUIRE((*producer)->acknowledge_bootstrap(genesis).has_value()); auto reservation = (*producer)->reserve_terminal(); REQUIRE(reservation.has_value()); REQUIRE(append_byte(journal_path)); REQUIRE(!(*producer) ->commit_terminal( std::move(*reservation), "session-1", controller_plan_digest, receipt() ) .has_value()); REQUIRE((*producer)->anchor() == genesis); producer->reset(); auto repaired = glove::container::receipt_audit_producer::recover(config, genesis); REQUIRE(repaired.has_value()); REQUIRE((*repaired)->anchor() == genesis); return 0; } auto key_file_is_fail_closed() -> int { temporary_directory temp; REQUIRE(!temp.root().empty()); const auto key_path = temp.root() / "audit.key"; const auto journal_path = temp.root() / "receipts.journal"; REQUIRE(write_key(key_path, audit_key, 0644)); const glove::container::receipt_audit_producer_config config{ .key_path = key_path, .journal_path = journal_path, }; REQUIRE(!glove::container::receipt_audit_producer::initialize(config).has_value()); REQUIRE(!std::filesystem::exists(journal_path)); REQUIRE(::chmod(key_path.c_str(), 0600) == 0); const auto symlink_path = temp.root() / "audit-link.key"; std::filesystem::create_symlink(key_path, symlink_path); auto symlink_config = config; symlink_config.key_path = symlink_path; REQUIRE(!glove::container::receipt_audit_producer::initialize(symlink_config).has_value()); const auto hardlink_path = temp.root() / "audit-hardlink.key"; std::filesystem::create_hard_link(key_path, hardlink_path); REQUIRE(!glove::container::receipt_audit_producer::initialize(config).has_value()); auto hardlink_config = config; hardlink_config.key_path = hardlink_path; REQUIRE(!glove::container::receipt_audit_producer::initialize(hardlink_config).has_value()); const auto short_key_path = temp.root() / "short.key"; REQUIRE(write_key(short_key_path, "abcd")); auto short_config = config; short_config.key_path = short_key_path; REQUIRE(!glove::container::receipt_audit_producer::initialize(short_config).has_value()); REQUIRE(!std::filesystem::exists(journal_path)); return 0; } auto run() -> int { REQUIRE(bootstrap_reconciliation_and_durable_commit() == 0); REQUIRE(concurrent_terminal_commits_are_serialized() == 0); REQUIRE(capacity_is_reserved_before_a_session() == 0); REQUIRE(abandoned_capacity_reservation_is_released() == 0); REQUIRE(execution_bound_reservation_is_single_profile_authority() == 0); REQUIRE(append_failure_never_acknowledges_terminal_success() == 0); REQUIRE(key_file_is_fail_closed() == 0); return 0; } } // namespace auto main() -> int { return run(); }