myc

Self-custodial remote signer for Radroots apps
git clone https://radroots.dev/git/myc.git
Log | Files | Refs | README | LICENSE

commit 3801b552071f7691a25fe0c4a5be66f38941f3c2
parent 24810199435363d2ed0096615c18b0a344a257f8
Author: triesap <tyson@radroots.org>
Date:   Mon,  7 Sep 2026 00:33:57 +0000

feat(nix): implement governed Myc outputs

- Pin Cargo and Nix to the exact Step 299 Lib revision.
- Expose real package, app, check, shell, NixOS, and OCI outputs.
- Migrate the service source lock and artifact contract to v3.
- Keep SQLite bundled and remove the legacy native Nix inputs.

Diffstat:
MCargo.lock | 32++++++++++++++++----------------
MCargo.toml | 24++++++++++++------------
MREADME | 19++++++++++---------
Acontracts/release/myc-artifact-contract.v3.json | 1+
Acontracts/services_hardening/native_release.v3.json | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mflake.lock | 101++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mflake.nix | 242++++++++++++++++++++++++++++++++++---------------------------------------------
Dradroots.service.source-lock.v2.toml | 24------------------------
Aradroots.service.source-lock.v3.toml | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtests/build_policy.rs | 27++++++++++++---------------
Mtests/services_hardening_local_signer_transport.rs | 2+-
Mtests/services_hardening_native_release.rs | 47++++++++++++++++++++++++++++++++++++-----------
Mtests/services_hardening_runtime_context.rs | 2+-
Mtests/services_hardening_state_catalog.rs | 2+-
Mtools/xtask/src/main.rs | 129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
15 files changed, 582 insertions(+), 256 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -1752,7 +1752,7 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "radroots_blossom" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "mediatype", "serde", @@ -1764,7 +1764,7 @@ dependencies = [ [[package]] name = "radroots_core" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "rust_decimal", "serde", @@ -1773,7 +1773,7 @@ dependencies = [ [[package]] name = "radroots_event" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "hex", "jiff-tzdb", @@ -1791,7 +1791,7 @@ dependencies = [ [[package]] name = "radroots_event_codec" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "hex", "radroots_blossom", @@ -1808,7 +1808,7 @@ dependencies = [ [[package]] name = "radroots_identity" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "k256", "serde", @@ -1818,7 +1818,7 @@ dependencies = [ [[package]] name = "radroots_nostr" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "nostr", "radroots_event", @@ -1832,7 +1832,7 @@ dependencies = [ [[package]] name = "radroots_nostr_connect" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "nostr", "radroots_event", @@ -1848,7 +1848,7 @@ dependencies = [ [[package]] name = "radroots_protocol" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "serde", ] @@ -1856,7 +1856,7 @@ dependencies = [ [[package]] name = "radroots_runtime_paths" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "rustix", "serde", @@ -1866,7 +1866,7 @@ dependencies = [ [[package]] name = "radroots_secrets" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "chacha20poly1305", "serde", @@ -1878,7 +1878,7 @@ dependencies = [ [[package]] name = "radroots_service_host" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "bytes", "fs2", @@ -1899,7 +1899,7 @@ dependencies = [ [[package]] name = "radroots_service_sqlite" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "fs2", "futures", @@ -1917,7 +1917,7 @@ dependencies = [ [[package]] name = "radroots_storage" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "radroots_event", "radroots_event_codec", @@ -1930,7 +1930,7 @@ dependencies = [ [[package]] name = "radroots_trade" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "radroots_core", "radroots_event", @@ -1940,7 +1940,7 @@ dependencies = [ [[package]] name = "radroots_transport" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "radroots_event", "radroots_identity", @@ -1951,7 +1951,7 @@ dependencies = [ [[package]] name = "radroots_transport_nostr" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib?rev=053d0c750bf9cd683c6ea37cefe7e79617ba629f#053d0c750bf9cd683c6ea37cefe7e79617ba629f" +source = "git+https://github.com/radrootslabs/lib?rev=055096853fca95e15d0f813d33a14aca13be3881#055096853fca95e15d0f813d33a14aca13be3881" dependencies = [ "async-wsocket", "futures", diff --git a/Cargo.toml b/Cargo.toml @@ -18,7 +18,7 @@ default-members = ["."] [workspace.metadata.radroots.service_source_lock] service = "myc" host_feature_profile = "service-host" -nix_material = "deferred" +nix_material = "qualified" config_contract_version = 1 state_contract_version = 12 admin_contract_version = 1 @@ -58,17 +58,17 @@ futures-executor = "0.3" hex = "0.4" jsonschema = { version = "0.48.1", default-features = false } nostr = { version = "0.44.2", features = ["nip04", "nip44", "nip46", "nip49"] } -radroots_identity = { git = "https://github.com/radrootslabs/lib", rev = "053d0c750bf9cd683c6ea37cefe7e79617ba629f", version = "=0.1.0-alpha" } -radroots_nostr = { git = "https://github.com/radrootslabs/lib", rev = "053d0c750bf9cd683c6ea37cefe7e79617ba629f", version = "=0.1.0-alpha", features = ["events"] } -radroots_nostr_connect = { git = "https://github.com/radrootslabs/lib", rev = "053d0c750bf9cd683c6ea37cefe7e79617ba629f", version = "=0.1.0-alpha" } -radroots_event_codec = { git = "https://github.com/radrootslabs/lib", rev = "053d0c750bf9cd683c6ea37cefe7e79617ba629f", version = "=0.1.0-alpha", features = ["json"] } -radroots_runtime_paths = { git = "https://github.com/radrootslabs/lib", rev = "053d0c750bf9cd683c6ea37cefe7e79617ba629f", version = "=0.1.0-alpha" } -radroots_service_host = { git = "https://github.com/radrootslabs/lib", rev = "053d0c750bf9cd683c6ea37cefe7e79617ba629f", version = "=0.1.0-alpha" } -radroots_service_sqlite = { git = "https://github.com/radrootslabs/lib", rev = "053d0c750bf9cd683c6ea37cefe7e79617ba629f", version = "=0.1.0-alpha" } -radroots_secrets = { git = "https://github.com/radrootslabs/lib", rev = "053d0c750bf9cd683c6ea37cefe7e79617ba629f", version = "=0.1.0-alpha", features = ["std"] } -radroots_storage = { git = "https://github.com/radrootslabs/lib", rev = "053d0c750bf9cd683c6ea37cefe7e79617ba629f", version = "=0.1.0-alpha", default-features = false } -radroots_transport = { git = "https://github.com/radrootslabs/lib", rev = "053d0c750bf9cd683c6ea37cefe7e79617ba629f", version = "=0.1.0-alpha", default-features = false } -radroots_transport_nostr = { git = "https://github.com/radrootslabs/lib", rev = "053d0c750bf9cd683c6ea37cefe7e79617ba629f", version = "=0.1.0-alpha" } +radroots_identity = { git = "https://github.com/radrootslabs/lib", rev = "055096853fca95e15d0f813d33a14aca13be3881", version = "=0.1.0-alpha" } +radroots_nostr = { git = "https://github.com/radrootslabs/lib", rev = "055096853fca95e15d0f813d33a14aca13be3881", version = "=0.1.0-alpha", features = ["events"] } +radroots_nostr_connect = { git = "https://github.com/radrootslabs/lib", rev = "055096853fca95e15d0f813d33a14aca13be3881", version = "=0.1.0-alpha" } +radroots_event_codec = { git = "https://github.com/radrootslabs/lib", rev = "055096853fca95e15d0f813d33a14aca13be3881", version = "=0.1.0-alpha", features = ["json"] } +radroots_runtime_paths = { git = "https://github.com/radrootslabs/lib", rev = "055096853fca95e15d0f813d33a14aca13be3881", version = "=0.1.0-alpha" } +radroots_service_host = { git = "https://github.com/radrootslabs/lib", rev = "055096853fca95e15d0f813d33a14aca13be3881", version = "=0.1.0-alpha" } +radroots_service_sqlite = { git = "https://github.com/radrootslabs/lib", rev = "055096853fca95e15d0f813d33a14aca13be3881", version = "=0.1.0-alpha" } +radroots_secrets = { git = "https://github.com/radrootslabs/lib", rev = "055096853fca95e15d0f813d33a14aca13be3881", version = "=0.1.0-alpha", features = ["std"] } +radroots_storage = { git = "https://github.com/radrootslabs/lib", rev = "055096853fca95e15d0f813d33a14aca13be3881", version = "=0.1.0-alpha", default-features = false } +radroots_transport = { git = "https://github.com/radrootslabs/lib", rev = "055096853fca95e15d0f813d33a14aca13be3881", version = "=0.1.0-alpha", default-features = false } +radroots_transport_nostr = { git = "https://github.com/radrootslabs/lib", rev = "055096853fca95e15d0f813d33a14aca13be3881", version = "=0.1.0-alpha" } serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", features = ["raw_value"] } sha2 = "0.10" diff --git a/README b/README @@ -35,7 +35,7 @@ let _snapshot = MycStatusSnapshot {}; ``` The native package, artifact, and dependency-trust boundary is frozen by -`contracts/services_hardening/native_release.v2.json`. Linux x86_64 and +`contracts/services_hardening/native_release.v3.json`. Linux x86_64 and aarch64 are the only admitted native artifact targets. `cargo xtask native-release` consumes an exact prebuilt target binary from a clean Git head and deterministically writes or checks the complete binary/source archive, @@ -61,10 +61,11 @@ enable, start, stop, or deploy a production service. The canonical service source lock binds the exact active public Lib cohort, Cargo lock, verified Lib source archive, toolchain, feature profile, and -service contract versions. Deferred flake source data is independently -digest-bound and may select an older reachable Lib revision; it does not -control native artifacts or claim Nix qualification. Nix, NixOS material, OCI, -signing, tags, publication, and deployment remain deferred and unclaimed. +service contract versions. Source-lock v3 binds the public flake lock to the +same exact Lib revision as Cargo and records qualified Nix material for only +macOS aarch64 and Linux x86_64. The Linux-only NixOS module and unsigned OCI +derivation are build outputs; signing, tags, publication, deployment, and +production activation remain unclaimed. ## Hardened v1 configuration contract @@ -584,10 +585,10 @@ cargo extbuild run -- cargo xtask native-release --mode write --target <aarch64- cargo extbuild run -- cargo xtask native-release --mode check --target <same-target> --binary <same-absolute-binary> --output <same-absolute-directory> --source-date-epoch <same-seconds> ``` -Through RCLD-RSHR-170, Nix evaluation, builds, packages, NixOS modules, and -Nix-produced OCI artifacts are deferred and unclaimed. Do not install, repair, -invoke, or require Nix for these checkpoints. Run narrower ad hoc Cargo -commands through `cargo extbuild run --` from this repository root. +The flake exposes the Myc package, application, checks, and development shell +for `aarch64-darwin` and `x86_64-linux`, plus the NixOS module and unsigned OCI +derivation for `x86_64-linux`. Run Nix and narrower ad hoc Cargo commands +through `cargo extbuild run --` from this repository root. ## Copyright diff --git a/contracts/release/myc-artifact-contract.v3.json b/contracts/release/myc-artifact-contract.v3.json @@ -0,0 +1 @@ +{"artifact_policy":{"checksums":"required","cyclonedx_version":"1.6","exact_tree_source_archives":"required","fresh_install":"required","git_history_bundles":"forbidden","intoto_statement":"required","notices":"required","reproducibility_build_count":2,"secret_scan":"required","unsigned_packages":"required","unsigned_slsa_provenance":"required"},"contract_version":3,"delivery":{"candidate_class":"unsigned_nonpublishing","developer_id_signing":"forbidden","developer_team_id":"forbidden","distribution_signing":"forbidden","embedded_platform_adhoc_signing":"permitted_non_distribution_only","g2":"unauthorized","notarization":"unauthorized","production_activation":"unauthorized","publication":"unauthorized","signing":"unauthorized"},"implementation_owner_step":300,"output":[{"classification":"production","id":"package","platforms":["macos_aarch64","linux_x86_64"]},{"classification":"production","id":"app","platforms":["macos_aarch64","linux_x86_64"]},{"classification":"production","id":"check","platforms":["macos_aarch64","linux_x86_64"]},{"classification":"production","id":"devshell","platforms":["macos_aarch64","linux_x86_64"]},{"classification":"production","id":"nixos_module","platforms":["linux_x86_64"]},{"classification":"production","id":"oci","platforms":["linux_x86_64"]}],"package_contract":{"artifact_format":"nix_store_derivation","binary_name":"myc","cargo_package":"myc","flake_app":"apps.<system>.default","flake_package":"packages.<system>.default","identity":"myc","package_version":"0.1.0","product_version":"0.1.0"},"platforms":["macos_aarch64","linux_x86_64"],"producer":{"command_authority":"repository_flake","kind":"nix_flake","nix_binding":"required","nix_produced":true,"source_task":"nix_build_repository_outputs"},"repository":"oss/myc","schema":"radroots.release.artifact-contract.v3","source_archive":{"binding":"canonical_exact_source_revision_tree_archive","compression":"none","compression_timestamp":"not_applicable","content":"exact_source_revision_tree","directory_entries":"omitted","entry_order":"bytewise_git_path","file_mode":"git_index_100644_or_100755","format":"ustar","gid":0,"git_history":"forbidden","gname":"","hardlinks":"forbidden","mtime_source":"candidate_source_date_epoch","path_prefix":"none","pax_headers":"forbidden","submodules":"forbidden","symlinks":"forbidden","trailer":"two_zero_blocks","uid":0,"uname":""},"source_binding":{"dirty_tree":"forbidden","kind":"exact_clean_git_commit","revision_location":"aggregate_source_revision"},"sqlite":{"high_level_authority":"sqlx_only","incremental_backup_adapter":"sealed_native_sqlx_owned_locked_handle_only","native_linkage_count":1,"second_pool_connection_query_transaction_migration_authority":"forbidden"}} diff --git a/contracts/services_hardening/native_release.v3.json b/contracts/services_hardening/native_release.v3.json @@ -0,0 +1,119 @@ +{ + "schema": "radroots.myc.native-release", + "schema_version": 3, + "contract_version": 3, + "predecessor": { + "schema_version": 2, + "filename": "native_release.v2.json", + "transition": "forward_only_replace" + }, + "service": "myc", + "package": { + "name": "myc", + "binary": "myc", + "version": "0.1.0", + "repository": "https://github.com/radrootslabs/myc", + "publish_to_crates_io": false + }, + "generator": { + "command": "cargo xtask native-release", + "modes": ["check", "write"], + "required_arguments": ["mode", "target", "binary", "output", "source_date_epoch"], + "source_date_epoch_range": "1..=4294967295", + "clean_exact_head": true, + "target_binary_validation": "executable_elf64_little_endian_exact_machine", + "canonical_json": "compact_utf8_json_with_one_final_lf", + "deterministic_archives": true, + "output_directory_mode": "0755", + "output_file_mode": "0644", + "durability": "sync_files_then_output_directory_then_parent" + }, + "toolchain": { + "rust_version": "1.97.1", + "edition": "2024", + "resolver": "3", + "host_feature_profile": "service-host" + }, + "release_profile": { + "lto": "thin", + "codegen_units": 1, + "overflow_checks": true, + "strip": "symbols", + "panic": "unwind" + }, + "source_lock": { + "filename": "radroots.service.source-lock.v3.toml", + "schema": "radroots.service.source-lock.v3", + "lib_repository": "https://github.com/radrootslabs/lib", + "architecture": "radroots.crates.release.v2", + "nix_material": "qualified" + }, + "contract_versions": { + "config": 1, + "state": 12, + "admin": 1, + "status": 1, + "provider": 1 + }, + "native_targets": [ + { "target": "aarch64-unknown-linux-gnu", "posture": "target" }, + { "target": "x86_64-unknown-linux-gnu", "posture": "target" } + ], + "output_inventory": [ + "LICENSE", + "SHA256SUMS", + "THIRD-PARTY-NOTICES.txt", + "artifact-manifest.v1.json", + "binary.tar.gz", + "config.example.toml", + "config.schema.json", + "provenance-input.v1.json", + "radroots.service.source-lock.v3.toml", + "sbom.cdx.json", + "service-source.tar.gz", + "systemd.service" + ], + "nix_outputs": { + "systems": ["aarch64-darwin", "x86_64-linux"], + "package_app_check_devshell": "qualified", + "nixos_module": "x86_64-linux_only", + "oci": "x86_64-linux_unsigned_nonpublishing", + "bundled_sqlite": true, + "native_linkage_count": 1 + }, + "signing_inputs": [ + "SHA256SUMS", + "artifact-manifest.v1.json", + "provenance-input.v1.json" + ], + "provenance_posture": "deterministic_unsigned_slsa_v1_input_external_keys_only", + "sbom_format": "cyclonedx_json_1_5_locked_cargo_graph", + "source_archive": "locked_offline_cargo_build_with_vendored_dependencies", + "checksum_format": "sha256_lower_hex_two_spaces_path_lf_sorted_by_path", + "protected_material_included": false, + "maximums": { + "text_input_bytes": 1048576, + "generated_document_bytes": 16777216, + "cargo_metadata_bytes": 33554432, + "binary_bytes": 536870912, + "source_archive_bytes": 1073741824, + "packages": 8192, + "tracked_files": 4096 + }, + "forbidden": [ + "protected_material", + "parent_owned_human_docs", + "private_harness", + "local_or_path_lib_dependency", + "floating_or_branch_lib_dependency", + "mixed_lib_revision", + "system_sqlite", + "second_sqlite_linkage", + "crates_io_publication", + "signing", + "tagging", + "release_publication", + "deployment", + "production_activation" + ] +} diff --git a/flake.lock b/flake.lock @@ -1,28 +1,68 @@ { "nodes": { + "crane": { + "locked": { + "lastModified": 1773189535, + "narHash": "sha256-E1G/Or6MWeP+L6mpQ0iTFLpzSzlpGrITfU2220Gq47g=", + "owner": "ipetkov", + "repo": "crane", + "rev": "6fa2fb4cf4a89ba49fc9dd5a3eb6cde99d388269", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1772408722, + "narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, "lib": { + "inputs": { + "crane": "crane", + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay", + "treefmt-nix": "treefmt-nix" + }, "locked": { - "lastModified": 1787301679, - "narHash": "sha256-WOcgJuKhM9aP55yTuTM63uBf+/IroeBu26zy+lMkvpE=", + "lastModified": 1788739124, + "narHash": "sha256-Aw8qbU1DrtxSYJKg0js6kexnKgVGFCjR34bgq+ZVAVo=", "owner": "radrootslabs", "repo": "lib", - "rev": "b44119fbac5985be8127ad1bf56d2950e6399427", + "rev": "055096853fca95e15d0f813d33a14aca13be3881", "type": "github" }, "original": { "owner": "radrootslabs", "repo": "lib", - "rev": "b44119fbac5985be8127ad1bf56d2950e6399427", + "rev": "055096853fca95e15d0f813d33a14aca13be3881", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1774799055, - "narHash": "sha256-Tsq9BCz0q47ej1uFF39m4tuhcwru/ls6vCCJzutEpaw=", + "lastModified": 1773222311, + "narHash": "sha256-BHoB/XpbqoZkVYZCfXJXfkR+GXFqwb/4zbWnOr2cRcU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "107cba9eb4a8d8c9f8e9e61266d78d340867913a", + "rev": "0590cd39f728e129122770c029970378a79d076a", "type": "github" }, "original": { @@ -32,25 +72,39 @@ "type": "github" } }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1772328832, + "narHash": "sha256-e+/T/pmEkLP6BHhYjx6GmwP5ivonQQn0bJdH9YrRB+Q=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "c185c7a5e5dd8f9add5b2f8ebeff00888b070742", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, "root": { "inputs": { - "lib": "lib", - "nixpkgs": "nixpkgs", - "rust-overlay": "rust-overlay" + "lib": "lib" } }, "rust-overlay": { "inputs": { "nixpkgs": [ + "lib", "nixpkgs" ] }, "locked": { - "lastModified": 1784265529, - "narHash": "sha256-ohQQiPOngux8ofsrSlloHCMDhRMvocXqJiG8uH45Q5k=", + "lastModified": 1785131767, + "narHash": "sha256-VNbQv2P0zgaNh96mT4LrnX7hdXgiC5nBH+uvyrrVX7U=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "068175006cfb69d5b541a140ed93e361488c9e53", + "rev": "c67ce00525464a710971351c183ce67acb6ca827", "type": "github" }, "original": { @@ -58,6 +112,27 @@ "repo": "rust-overlay", "type": "github" } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "lib", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1773297127, + "narHash": "sha256-6E/yhXP7Oy/NbXtf1ktzmU8SdVqJQ09HC/48ebEGBpk=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "71b125cd05fbfd78cab3e070b73544abe24c5016", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix @@ -1,149 +1,117 @@ { - description = "myc"; + description = "Myc Nostr remote signer"; - inputs = { - lib = { - url = "github:radrootslabs/lib/b44119fbac5985be8127ad1bf56d2950e6399427"; - flake = false; - }; - nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; - rust-overlay = { - url = "github:oxalica/rust-overlay"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - }; + inputs.lib.url = "github:radrootslabs/lib/055096853fca95e15d0f813d33a14aca13be3881"; outputs = - { nixpkgs, rust-overlay, ... }: + { self, lib }: let - systems = [ - "aarch64-darwin" - "aarch64-linux" - "x86_64-darwin" - "x86_64-linux" - ]; - forAllSystems = - f: - nixpkgs.lib.genAttrs systems ( - system: - let - pkgs = import nixpkgs { - inherit system; - overlays = [ rust-overlay.overlays.default ]; - }; - rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; - basePackages = - [ - pkgs.git - rustToolchain - pkgs.clang - pkgs.llvmPackages.libclang - pkgs.libsodium - pkgs.openssl - pkgs.pkg-config - pkgs.sqlite - ] - ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ - pkgs.darwin.libiconv - ]; - libraryPackages = - [ - pkgs.libsodium - pkgs.openssl - pkgs.sqlite - ] - ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ - pkgs.darwin.libiconv - ]; - libraryPath = pkgs.lib.makeLibraryPath libraryPackages; - includePath = pkgs.lib.makeSearchPathOutput "dev" "include" basePackages; - darwinLdFlags = pkgs.lib.optionalString pkgs.stdenv.isDarwin "-L${pkgs.darwin.libiconv}/lib"; - darwinRustFlags = pkgs.lib.optionalString pkgs.stdenv.isDarwin "-L native=${pkgs.darwin.libiconv}/lib"; - mkApp = - name: text: - let - script = pkgs.writeShellApplication { - inherit name; - runtimeInputs = basePackages; - text = '' - set -euo pipefail - repo_root="$(git rev-parse --show-toplevel)" - cd "$repo_root" - export LIBCLANG_PATH="${pkgs.llvmPackages.libclang.lib}/lib" - export LIBRARY_PATH="${libraryPath}:''${LIBRARY_PATH:-}" - export DYLD_FALLBACK_LIBRARY_PATH="${libraryPath}:''${DYLD_FALLBACK_LIBRARY_PATH:-}" - export LDFLAGS="${darwinLdFlags} ''${LDFLAGS:-}" - export NIX_LDFLAGS="${darwinLdFlags} ''${NIX_LDFLAGS:-}" - export RUSTFLAGS="${darwinRustFlags} ''${RUSTFLAGS:-}" - export CPATH="${includePath}:''${CPATH:-}" - ${text} - ''; - }; - in - { - type = "app"; - program = "${script}/bin/${name}"; - }; - in - f { + systems = lib.lib.supportedSystems; + forAllSystems = function: + builtins.listToAttrs ( + map (system: { + name = system; + value = function system; + }) systems + ); + serviceOutputs = + system: + let + helpers = lib.lib.mkServiceHelpers system; + toolchain = helpers.mkToolchain { + rustToolchainFile = ./rust-toolchain.toml; + }; + nativeInputs = helpers.mkNativeInputs { }; + package = helpers.mkServicePackage { + inherit nativeInputs toolchain; + source = ./.; + cargoLock = ./Cargo.lock; + servicePackage = "myc"; + binaryName = "myc"; + }; + hooks = { + config = package; + integration = package; + source-lock = package; + sqlx = package; + }; + checks = helpers.mkServiceChecks { + serviceName = "myc"; inherit - basePackages - darwinLdFlags - darwinRustFlags - includePath - libraryPath - mkApp - pkgs - rustToolchain + hooks + nativeInputs + package + toolchain ; - } - ); + source = ./.; + cargoLock = ./Cargo.lock; + }; + apps = helpers.mkServiceApps { + serviceName = "myc"; + binaryName = "myc"; + inherit nativeInputs package toolchain; + releaseAcceptanceCommand = "${package}/bin/myc --help >/dev/null"; + }; + devShells.default = helpers.mkServiceDevShell { + serviceName = "myc"; + inherit nativeInputs toolchain; + }; + oci = helpers.mkServiceOciImage { + serviceName = "myc"; + binaryName = "myc"; + inherit package; + buildInfo = { + serviceVersion = "0.1.0"; + serviceCommit = self.rev or "0000000000000000000000000000000000000000"; + libRevision = "055096853fca95e15d0f813d33a14aca13be3881"; + rustVersion = "1.97.1"; + target = "x86_64-unknown-linux-gnu"; + featureProfile = "service-host"; + contractVersions = { + config = 1; + state = 12; + admin = 1; + status = 1; + provider = 1; + }; + }; + }; + in + helpers.mkServiceOutputs { + serviceName = "myc"; + inherit + apps + checks + devShells + nativeInputs + package + ; + extraPackages = if system == "x86_64-linux" then { inherit oci; } else { }; + }; in { - apps = forAllSystems ( - { mkApp, ... }: - rec { - default = check; - check = mkApp "check" '' - cargo metadata --format-version 1 --no-deps - cargo check --locked - ''; - fmt = mkApp "fmt" '' - cargo fmt --all --check - ''; - release-acceptance = mkApp "release-acceptance" '' - ./scripts/release-acceptance.sh - ''; - test = mkApp "test" '' - cargo test --locked - ''; - } - ); + packages = forAllSystems (system: (serviceOutputs system).packages); + apps = forAllSystems (system: (serviceOutputs system).apps); + checks = forAllSystems (system: (serviceOutputs system).checks); + devShells = forAllSystems (system: (serviceOutputs system).devShells); - devShells = forAllSystems ( - { - basePackages, - darwinLdFlags, - darwinRustFlags, - includePath, - libraryPath, - pkgs, - ... - }: - { - default = pkgs.mkShell { - packages = basePackages; - shellHook = '' - export LIBCLANG_PATH="${pkgs.llvmPackages.libclang.lib}/lib" - export LIBRARY_PATH="${libraryPath}:''${LIBRARY_PATH:-}" - export DYLD_FALLBACK_LIBRARY_PATH="${libraryPath}:''${DYLD_FALLBACK_LIBRARY_PATH:-}" - export LDFLAGS="${darwinLdFlags} ''${LDFLAGS:-}" - export NIX_LDFLAGS="${darwinLdFlags} ''${NIX_LDFLAGS:-}" - export RUSTFLAGS="${darwinRustFlags} ''${RUSTFLAGS:-}" - export CPATH="${includePath}:''${CPATH:-}" - ''; - }; - } - ); + nixosModules.default = + let + helpers = lib.lib.mkServiceHelpers "x86_64-linux"; + in + helpers.mkServiceNixosModule { + serviceName = "myc"; + binaryName = "myc"; + packageFor = _pkgs: self.packages.x86_64-linux.default; + commandForInstance = instance: [ + "--profile" + "service-host" + "--instance" + instance + "--config" + "/etc/radroots/services/myc/${instance}/config.toml" + "run" + ]; + }; }; } diff --git a/radroots.service.source-lock.v2.toml b/radroots.service.source-lock.v2.toml @@ -1,24 +0,0 @@ -schema = "radroots.service.source-lock.v2" -contract_version = 2 -service = "myc" -repository = "https://github.com/radrootslabs/lib" -revision = "053d0c750bf9cd683c6ea37cefe7e79617ba629f" -architecture = "radroots.crates.release.v2" -workspace_catalog_sha256 = "deca0c080deae187ff8186c0708903e42f41ea57f77c5f91581e23aa561164a4" -version = "0.1.0-alpha" -source_archive_sha256 = "4c0769a6105cf7547b85544a249178fc7384161e759e9e712994419eaf168e9c" -cargo_lock_sha256 = "5e6dc7b87e10c9d122b1d79fcf2dd664d0490f2a0c1567fdb956b98d810eb60d" -rust_version = "1.97.1" -host_feature_profile = "service-host" - -[nix] -material = "deferred" -lib_revision = "b44119fbac5985be8127ad1bf56d2950e6399427" -flake_lock_sha256 = "90a03f6f0794f3f6556b1f2bf6700812d48ce8dc1cee7c4f8bc62cea69b42bd1" - -[contract_versions] -config = 1 -state = 12 -admin = 1 -status = 1 -provider = 1 diff --git a/radroots.service.source-lock.v3.toml b/radroots.service.source-lock.v3.toml @@ -0,0 +1,67 @@ +schema = "radroots.service.source-lock.v3" +contract_version = 3 +service = "myc" +repository = "https://github.com/radrootslabs/lib" +revision = "055096853fca95e15d0f813d33a14aca13be3881" +architecture = "radroots.crates.release.v2" +workspace_catalog_sha256 = "deca0c080deae187ff8186c0708903e42f41ea57f77c5f91581e23aa561164a4" +version = "0.1.0-alpha" +source_archive_sha256 = "89b8ace3f61167df43aca89917405d58b2aaf2ddea8fadfb21d351d76f184e68" +cargo_lock_sha256 = "ccb7593a1cecf74e1caf6fafaf0ba57ac9df6b6e566d522621ef4bbb1665d42f" +rust_version = "1.97.1" +host_feature_profile = "service-host" + +[source_archive_contract] +binding = "sha256_of_canonical_exact_lib_revision_tree_archive" +format = "ustar" +compression = "none" +compression_timestamp = "not_applicable" +entry_order = "bytewise_git_path" +path_prefix = "none" +file_mode = "git_index_100644_or_100755" +uid = 0 +gid = 0 +uname = "" +gname = "" +mtime = "lib_revision_commit_timestamp" +pax_headers = "forbidden" +directory_entries = "omitted" +symlinks = "forbidden" +hardlinks = "forbidden" +submodules = "forbidden" +trailer = "two_zero_blocks" + +[nix] +material = "qualified" +lib_revision = "055096853fca95e15d0f813d33a14aca13be3881" +supported_systems = ["aarch64-darwin", "x86_64-linux"] + +[nix.public_input_lock] +path = "flake.lock" +sha256 = "df48d334292ea79f1156757279b0cfc01008be1b8a50f013b381b6fe31ff8f56" +binding = "exact_regular_file_bytes" +mutable_reference = "forbidden" +lib_input = "lib" + +[nix.parent_result] +embedded_in_public_input_lock = false +embedded_in_source_lock = false +storage = "separate_generation_scoped_evidence" + +[artifact_contract] +path = "contracts/release/myc-artifact-contract.v3.json" +sha256 = "4582a9e14b11ea4589bc524748ae6c34841916bda78bffc667814be911673ae6" +binding = "exact_regular_file_bytes_in_same_source_revision" + +[sqlite] +high_level_authority = "sqlx_only" +second_pool_connection_query_transaction_migration_authority = "forbidden" +incremental_backup_adapter = "sealed_native_sqlx_owned_locked_handle_only" +native_linkage_count = 1 + +[contract_versions] +config = 1 +state = 12 +admin = 1 +status = 1 +provider = 1 diff --git a/tests/build_policy.rs b/tests/build_policy.rs @@ -4,7 +4,7 @@ use sha2::{Digest, Sha256}; const MANIFEST: &str = include_str!("../Cargo.toml"); const RELEASE_ACCEPTANCE: &str = include_str!("../scripts/release-acceptance.sh"); -const SOURCE_LOCK: &str = include_str!("../radroots.service.source-lock.v2.toml"); +const SOURCE_LOCK: &str = include_str!("../radroots.service.source-lock.v3.toml"); const FLAKE_LOCK: &[u8] = include_bytes!("../flake.lock"); #[test] @@ -30,35 +30,35 @@ fn service_host_is_the_exact_default_feature_profile() { #[test] fn shared_runtime_paths_is_exactly_pinned_to_the_source_locked_lib() { assert!(MANIFEST.contains( - "radroots_runtime_paths = { git = \"https://github.com/radrootslabs/lib\", rev = \"053d0c750bf9cd683c6ea37cefe7e79617ba629f\", version = \"=0.1.0-alpha\" }" + "radroots_runtime_paths = { git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\", version = \"=0.1.0-alpha\" }" )); } #[test] fn shared_identity_is_exactly_pinned_to_the_source_locked_lib() { assert!(MANIFEST.contains( - "radroots_identity = { git = \"https://github.com/radrootslabs/lib\", rev = \"053d0c750bf9cd683c6ea37cefe7e79617ba629f\", version = \"=0.1.0-alpha\" }" + "radroots_identity = { git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\", version = \"=0.1.0-alpha\" }" )); } #[test] fn shared_service_host_is_exactly_pinned_to_the_source_locked_lib() { assert!(MANIFEST.contains( - "radroots_service_host = { git = \"https://github.com/radrootslabs/lib\", rev = \"053d0c750bf9cd683c6ea37cefe7e79617ba629f\", version = \"=0.1.0-alpha\" }" + "radroots_service_host = { git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\", version = \"=0.1.0-alpha\" }" )); } #[test] fn shared_service_sqlite_is_exactly_pinned_to_the_source_locked_lib() { assert!(MANIFEST.contains( - "radroots_service_sqlite = { git = \"https://github.com/radrootslabs/lib\", rev = \"053d0c750bf9cd683c6ea37cefe7e79617ba629f\", version = \"=0.1.0-alpha\" }" + "radroots_service_sqlite = { git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\", version = \"=0.1.0-alpha\" }" )); } #[test] fn shared_storage_evidence_is_exactly_pinned_to_the_source_locked_lib() { assert!(MANIFEST.contains( - "radroots_storage = { git = \"https://github.com/radrootslabs/lib\", rev = \"053d0c750bf9cd683c6ea37cefe7e79617ba629f\", version = \"=0.1.0-alpha\", default-features = false }" + "radroots_storage = { git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\", version = \"=0.1.0-alpha\", default-features = false }" )); } @@ -71,7 +71,7 @@ fn delivery_dependencies_are_exactly_source_locked() { ] { assert!( MANIFEST.contains(&format!( - "{dependency} = {{ git = \"https://github.com/radrootslabs/lib\", rev = \"053d0c750bf9cd683c6ea37cefe7e79617ba629f\", version = \"=0.1.0-alpha\"" + "{dependency} = {{ git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\", version = \"=0.1.0-alpha\"" )), "{dependency} is not pinned to the exact source lock" ); @@ -95,22 +95,19 @@ fn source_lock_binds_the_current_cargo_lock() { let digest = hex::encode(Sha256::digest(include_bytes!("../Cargo.lock"))); let flake_digest = hex::encode(Sha256::digest(FLAKE_LOCK)); assert!(SOURCE_LOCK.starts_with( - "schema = \"radroots.service.source-lock.v2\"\ncontract_version = 2\nservice = \"myc\"\n" + "schema = \"radroots.service.source-lock.v3\"\ncontract_version = 3\nservice = \"myc\"\n" )); assert!(SOURCE_LOCK.contains(&format!("cargo_lock_sha256 = \"{digest}\""))); - assert!(SOURCE_LOCK.contains(&format!("flake_lock_sha256 = \"{flake_digest}\""))); - assert!(SOURCE_LOCK.contains("revision = \"053d0c750bf9cd683c6ea37cefe7e79617ba629f\"")); + assert!(SOURCE_LOCK.contains(&format!("sha256 = \"{flake_digest}\""))); + assert!(SOURCE_LOCK.contains("revision = \"055096853fca95e15d0f813d33a14aca13be3881\"")); assert!(SOURCE_LOCK.contains( - "[nix]\nmaterial = \"deferred\"\nlib_revision = \"b44119fbac5985be8127ad1bf56d2950e6399427\"\n" - )); - assert!(!SOURCE_LOCK.contains( - "[nix]\nmaterial = \"deferred\"\nlib_revision = \"053d0c750bf9cd683c6ea37cefe7e79617ba629f\"\n" + "[nix]\nmaterial = \"qualified\"\nlib_revision = \"055096853fca95e15d0f813d33a14aca13be3881\"\nsupported_systems = [\"aarch64-darwin\", \"x86_64-linux\"]\n" )); assert!(SOURCE_LOCK.contains( "workspace_catalog_sha256 = \"deca0c080deae187ff8186c0708903e42f41ea57f77c5f91581e23aa561164a4\"" )); assert!(SOURCE_LOCK.contains( - "source_archive_sha256 = \"4c0769a6105cf7547b85544a249178fc7384161e759e9e712994419eaf168e9c\"" + "source_archive_sha256 = \"89b8ace3f61167df43aca89917405d58b2aaf2ddea8fadfb21d351d76f184e68\"" )); assert!(SOURCE_LOCK.ends_with( "[contract_versions]\nconfig = 1\nstate = 12\nadmin = 1\nstatus = 1\nprovider = 1\n" diff --git a/tests/services_hardening_local_signer_transport.rs b/tests/services_hardening_local_signer_transport.rs @@ -84,7 +84,7 @@ fn machine_contract_freezes_the_complete_local_signer_transport() { #[test] fn implementation_uses_only_the_hardened_fixed_unix_admin_boundary() { for required in [ - "radroots_service_host = { git = \"https://github.com/radrootslabs/lib\", rev = \"053d0c750bf9cd683c6ea37cefe7e79617ba629f\"", + "radroots_service_host = { git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\"", "const MYC_LOCAL_SIGNER_ENDPOINT: &str = \"/v1/provider/operation\"", "radroots_service_host::AdminClient", ".mutate::<_, LocalSignerResponse>(", diff --git a/tests/services_hardening_native_release.rs b/tests/services_hardening_native_release.rs @@ -5,6 +5,8 @@ use std::collections::BTreeSet; use serde_json::json; const CONTRACT: &str = include_str!("../contracts/services_hardening/native_release.v2.json"); +const ACTIVE_CONTRACT: &str = + include_str!("../contracts/services_hardening/native_release.v3.json"); const MANIFEST: &str = include_str!("../Cargo.toml"); const LOCK: &str = include_str!("../Cargo.lock"); const FLAKE: &str = include_str!("../flake.nix"); @@ -12,8 +14,7 @@ const FLAKE_LOCK: &str = include_str!("../flake.lock"); const CARGO_CONFIG: &str = include_str!("../.cargo/config.toml"); const SYSTEMD_UNIT: &str = include_str!("../packaging/systemd/myc@.service"); -const LIB_REVISION: &str = "053d0c750bf9cd683c6ea37cefe7e79617ba629f"; -const DEFERRED_NIX_LIB_REVISION: &str = "b44119fbac5985be8127ad1bf56d2950e6399427"; +const LIB_REVISION: &str = "055096853fca95e15d0f813d33a14aca13be3881"; const LIB_REPOSITORY: &str = "https://github.com/radrootslabs/lib"; #[test] @@ -157,7 +158,7 @@ fn native_release_contract_and_manifest_metadata_are_exact() { toml::Value::Table(toml::toml! { service = "myc" host_feature_profile = "service-host" - nix_material = "deferred" + nix_material = "qualified" config_contract_version = 1 state_contract_version = 12 admin_contract_version = 1 @@ -248,9 +249,9 @@ fn every_radroots_dependency_is_exactly_source_locked() { assert!(source.contains(&format!("?rev={LIB_REVISION}#{LIB_REVISION}"))); for required in [ - "lib = {", - "github:radrootslabs/lib/b44119fbac5985be8127ad1bf56d2950e6399427", - "flake = false;", + "inputs.lib.url = \"github:radrootslabs/lib/055096853fca95e15d0f813d33a14aca13be3881\";", + "systems = lib.lib.supportedSystems;", + "nixosModules.default", ] { assert!( FLAKE.contains(required), @@ -265,18 +266,25 @@ fn every_radroots_dependency_is_exactly_source_locked() { assert_eq!( flake_lock["nodes"]["lib"], json!({ + "inputs": { + "crane": "crane", + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay", + "treefmt-nix": "treefmt-nix" + }, "locked": { - "lastModified": 1787301679_u64, - "narHash": "sha256-WOcgJuKhM9aP55yTuTM63uBf+/IroeBu26zy+lMkvpE=", + "lastModified": 1788739124_u64, + "narHash": "sha256-Aw8qbU1DrtxSYJKg0js6kexnKgVGFCjR34bgq+ZVAVo=", "owner": "radrootslabs", "repo": "lib", - "rev": DEFERRED_NIX_LIB_REVISION, + "rev": LIB_REVISION, "type": "github" }, "original": { "owner": "radrootslabs", "repo": "lib", - "rev": DEFERRED_NIX_LIB_REVISION, + "rev": LIB_REVISION, "type": "github" } }) @@ -288,7 +296,8 @@ fn native_release_surfaces_remain_generated_outside_the_source_tree() { let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")); assert!(!root.join("radroots.lib.source-lock.v1.toml").exists()); assert!(!root.join("radroots.service.source-lock.v1.toml").exists()); - assert!(root.join("radroots.service.source-lock.v2.toml").is_file()); + assert!(!root.join("radroots.service.source-lock.v2.toml").exists()); + assert!(root.join("radroots.service.source-lock.v3.toml").is_file()); assert!( !root .join("contracts/services_hardening/native_release.v1.json") @@ -298,6 +307,10 @@ fn native_release_surfaces_remain_generated_outside_the_source_tree() { root.join("contracts/services_hardening/native_release.v2.json") .is_file() ); + assert!( + root.join("contracts/services_hardening/native_release.v3.json") + .is_file() + ); for forbidden in [ ".github", "target", @@ -317,4 +330,16 @@ fn native_release_surfaces_remain_generated_outside_the_source_tree() { assert!(!CONTRACT.contains("production_ready")); assert!(!CONTRACT.contains("oci-image")); assert!(!CONTRACT.contains("nixos-module")); + let active: serde_json::Value = + serde_json::from_str(ACTIVE_CONTRACT).expect("active release contract"); + assert_eq!(active["schema_version"], 3); + assert_eq!(active["contract_version"], 3); + assert_eq!(active["predecessor"]["filename"], "native_release.v2.json"); + assert_eq!( + active["source_lock"]["filename"], + "radroots.service.source-lock.v3.toml" + ); + assert_eq!(active["source_lock"]["nix_material"], "qualified"); + assert_eq!(active["nix_outputs"]["bundled_sqlite"], true); + assert_eq!(active["nix_outputs"]["native_linkage_count"], 1); } diff --git a/tests/services_hardening_runtime_context.rs b/tests/services_hardening_runtime_context.rs @@ -288,7 +288,7 @@ fn unsupported_profile_platform_and_diagnostics_fail_safely() { #[test] fn shared_runtime_paths_are_the_only_path_policy_and_identity_authority() { assert!(MANIFEST.contains( - "radroots_runtime_paths = { git = \"https://github.com/radrootslabs/lib\", rev = \"053d0c750bf9cd683c6ea37cefe7e79617ba629f\", version = \"=0.1.0-alpha\" }" + "radroots_runtime_paths = { git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\", version = \"=0.1.0-alpha\" }" )); assert!(LIB_SOURCE.contains("mod runtime_context;")); assert!(!LIB_SOURCE.contains("pub mod runtime_context;")); diff --git a/tests/services_hardening_state_catalog.rs b/tests/services_hardening_state_catalog.rs @@ -469,7 +469,7 @@ fn catalog_errors_are_stable_source_free_and_redacted() { #[test] fn catalog_source_is_pure_pinned_and_uses_only_the_shared_authority() { assert!(MANIFEST.contains( - "radroots_service_sqlite = { git = \"https://github.com/radrootslabs/lib\", rev = \"053d0c750bf9cd683c6ea37cefe7e79617ba629f\", version = \"=0.1.0-alpha\" }" + "radroots_service_sqlite = { git = \"https://github.com/radrootslabs/lib\", rev = \"055096853fca95e15d0f813d33a14aca13be3881\", version = \"=0.1.0-alpha\" }" )); assert!(LIB_SOURCE.contains("mod state_catalog;")); assert!(!LIB_SOURCE.contains("pub mod state_catalog;")); diff --git a/tools/xtask/src/main.rs b/tools/xtask/src/main.rs @@ -19,7 +19,7 @@ const VERSION: &str = "0.1.0"; const REPOSITORY: &str = "https://github.com/radrootslabs/myc"; const RUST_VERSION: &str = "1.97.1"; const HOST_FEATURE_PROFILE: &str = "service-host"; -const SOURCE_LOCK: &str = "radroots.service.source-lock.v2.toml"; +const SOURCE_LOCK: &str = "radroots.service.source-lock.v3.toml"; const CONFIG_EXAMPLE: &str = "contracts/services_hardening/config.v1.example.toml"; const CONFIG_SCHEMA: &str = "contracts/services_hardening/config.v1.schema.json"; const SYSTEMD_UNIT: &str = "packaging/systemd/myc@.service"; @@ -161,10 +161,13 @@ struct SourceLock { workspace_catalog_sha256: String, version: String, source_archive_sha256: String, + source_archive_contract: SourceArchiveContract, cargo_lock_sha256: String, rust_version: String, host_feature_profile: String, nix: NixEvidence, + artifact_contract: ArtifactContract, + sqlite: SqliteContract, contract_versions: ContractVersions, } @@ -172,8 +175,68 @@ struct SourceLock { #[serde(deny_unknown_fields)] struct NixEvidence { material: String, - lib_revision: Option<String>, - flake_lock_sha256: Option<String>, + lib_revision: String, + public_input_lock: PublicInputLock, + parent_result: ParentResult, + supported_systems: Vec<String>, +} + +#[derive(Clone, Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct PublicInputLock { + path: String, + sha256: String, + binding: String, + mutable_reference: String, + lib_input: String, +} + +#[derive(Clone, Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct ParentResult { + embedded_in_public_input_lock: bool, + embedded_in_source_lock: bool, + storage: String, +} + +#[derive(Clone, Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct SourceArchiveContract { + binding: String, + format: String, + compression: String, + compression_timestamp: String, + entry_order: String, + path_prefix: String, + file_mode: String, + uid: u32, + gid: u32, + uname: String, + gname: String, + mtime: String, + pax_headers: String, + directory_entries: String, + symlinks: String, + hardlinks: String, + submodules: String, + trailer: String, +} + +#[derive(Clone, Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct ArtifactContract { + path: String, + sha256: String, + binding: String, +} + +#[derive(Clone, Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct SqliteContract { + high_level_authority: String, + second_pool_connection_query_transaction_migration_authority: String, + incremental_backup_adapter: String, + native_linkage_count: u32, } #[derive(Clone, Debug, Deserialize, Serialize)] @@ -465,7 +528,7 @@ fn native_release(root: &Path, args: &NativeReleaseArgs) -> Result<(), ReleaseEr host_feature_profile: HOST_FEATURE_PROFILE, contract_versions: source_lock.contract_versions.clone(), protected_material_included: false, - nix_qualified: false, + nix_qualified: true, oci_included: false, artifacts: payload, }; @@ -624,9 +687,14 @@ fn read_source_lock(root: &Path) -> Result<SourceLock, ReleaseError> { let text = std::str::from_utf8(&bytes).map_err(|_| ReleaseError::InvalidSourceLock)?; let lock: SourceLock = toml::from_str(text).map_err(|_| ReleaseError::InvalidSourceLock)?; let cargo_lock = hash_regular(&root.join("Cargo.lock"), MAX_DOCUMENT_BYTES)?; + let flake_lock = hash_regular(&root.join("flake.lock"), MAX_DOCUMENT_BYTES)?; + let artifact_contract = hash_regular( + &root.join("contracts/release/myc-artifact-contract.v3.json"), + MAX_DOCUMENT_BYTES, + )?; let revisions = cargo_dependency_revisions(root)?; - if lock.schema != "radroots.service.source-lock.v2" - || lock.contract_version != 2 + if lock.schema != "radroots.service.source-lock.v3" + || lock.contract_version != 3 || lock.service != SERVICE || lock.repository != "https://github.com/radrootslabs/lib" || !lower_hex(&lock.revision, 40) @@ -637,17 +705,46 @@ fn read_source_lock(root: &Path) -> Result<SourceLock, ReleaseError> { || lock.cargo_lock_sha256 != cargo_lock.sha256 || lock.rust_version != RUST_VERSION || lock.host_feature_profile != HOST_FEATURE_PROFILE - || lock.nix.material != "deferred" - || lock - .nix - .lib_revision - .as_deref() - .is_none_or(|revision| !lower_hex(revision, 40)) + || lock.source_archive_contract.binding + != "sha256_of_canonical_exact_lib_revision_tree_archive" + || lock.source_archive_contract.format != "ustar" + || lock.source_archive_contract.compression != "none" + || lock.source_archive_contract.compression_timestamp != "not_applicable" + || lock.source_archive_contract.entry_order != "bytewise_git_path" + || lock.source_archive_contract.path_prefix != "none" + || lock.source_archive_contract.file_mode != "git_index_100644_or_100755" + || lock.source_archive_contract.uid != 0 + || lock.source_archive_contract.gid != 0 + || !lock.source_archive_contract.uname.is_empty() + || !lock.source_archive_contract.gname.is_empty() + || lock.source_archive_contract.mtime != "lib_revision_commit_timestamp" + || lock.source_archive_contract.pax_headers != "forbidden" + || lock.source_archive_contract.directory_entries != "omitted" + || lock.source_archive_contract.symlinks != "forbidden" + || lock.source_archive_contract.hardlinks != "forbidden" + || lock.source_archive_contract.submodules != "forbidden" + || lock.source_archive_contract.trailer != "two_zero_blocks" + || lock.nix.material != "qualified" + || lock.nix.lib_revision != lock.revision + || lock.nix.supported_systems != ["aarch64-darwin", "x86_64-linux"] + || lock.nix.public_input_lock.path != "flake.lock" + || lock.nix.public_input_lock.sha256 != flake_lock.sha256 + || lock.nix.public_input_lock.binding != "exact_regular_file_bytes" + || lock.nix.public_input_lock.mutable_reference != "forbidden" + || lock.nix.public_input_lock.lib_input != "lib" + || lock.nix.parent_result.embedded_in_public_input_lock + || lock.nix.parent_result.embedded_in_source_lock + || lock.nix.parent_result.storage != "separate_generation_scoped_evidence" + || lock.artifact_contract.path != "contracts/release/myc-artifact-contract.v3.json" + || lock.artifact_contract.sha256 != artifact_contract.sha256 + || lock.artifact_contract.binding != "exact_regular_file_bytes_in_same_source_revision" + || lock.sqlite.high_level_authority != "sqlx_only" || lock - .nix - .flake_lock_sha256 - .as_deref() - .is_none_or(|digest| !lower_hex(digest, 64)) + .sqlite + .second_pool_connection_query_transaction_migration_authority + != "forbidden" + || lock.sqlite.incremental_backup_adapter != "sealed_native_sqlx_owned_locked_handle_only" + || lock.sqlite.native_linkage_count != 1 || revisions != BTreeSet::from([lock.revision.clone()]) || [ lock.contract_versions.config,