lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

commit 94da71c063f25f47c73d128c072215eaa72f57fd
parent ff0bb738e138003a8c49dda4d34f673be6290c4b
Author: triesap <tyson@radroots.org>
Date:   Mon, 10 Aug 2026 21:16:06 +0000

contracts: reserve service host decisions

- Freeze Unix-admin envelopes and common route semantics.
- Fix process exit and doctor contracts.
- Define platform peer authorization and systemd readiness posture.
- Bind bare-Rust native prerequisites and clean-image proof.

Diffstat:
MAGENTS.md | 6++++++
Acontracts/architecture/decisions/services_hardening_host.v1.json | 139+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atools/xtask/tests/services_hardening_host_decision.rs | 239+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 384 insertions(+), 0 deletions(-)

diff --git a/AGENTS.md b/AGENTS.md @@ -27,6 +27,12 @@ This file exists for compatibility with tools that look for AGENTS.md. Service-event source, registry, generated, and consumer work must implement that exact kind, tag, cardinality, query, and supersession contract; it may not reinterpret the reservation from current prototype wire behavior. +- The pre-implementation local-admin, process-exit, doctor, readiness, + peer-credential, systemd, and bare-Rust host decisions are reserved by + `contracts/architecture/decisions/services_hardening_host.v1.json`. + Service-host and service-owned operator contracts must implement or narrow + that boundary without adding a second transport, exit map, or readiness + authority. - Source-lock consumer identities include `sdk`, `mobile`, `studio`, `myc`, and `rhi`. Only the first three are generated-artifact product identities; accepting a service consumer marker must not expose an artifact route. diff --git a/contracts/architecture/decisions/services_hardening_host.v1.json b/contracts/architecture/decisions/services_hardening_host.v1.json @@ -0,0 +1,139 @@ +{ + "schema": "radroots.services-hardening.host-decisions.v1", + "contract_version": 1, + "decision_state": "reserved_preimplementation", + "local_admin": { + "transport": "http_1_1_over_unix_domain_socket", + "base_path": "/v1", + "tcp_admin": false, + "cors": false, + "browser_authentication": false, + "mutation_request_envelope": { + "required_fields": ["contract_version", "operation_id", "request"], + "optional_fields": ["correlation_id"], + "contract_version": 1, + "operation_id_semantics": "caller_stable_idempotency_identity", + "correlation_id_semantics": "caller_safe_trace_identity_or_daemon_generated_when_absent", + "identical_operation_id_reuse": "return_original_committed_result", + "different_request_operation_id_reuse": { + "admin_error_code": "operation_id_conflict", + "cli_exit": 5 + } + }, + "success_response_envelope": { + "required_fields": ["contract_version", "ok", "correlation_id", "result"], + "contract_version": 1, + "ok": true + }, + "failure_response_envelope": { + "required_fields": ["contract_version", "ok", "correlation_id", "error"], + "error_required_fields": ["code", "message"], + "contract_version": 1, + "ok": false + }, + "output_safety": { + "request_body_max_utf8_bytes": 65536, + "response_body_max_utf8_bytes": 1048576, + "operation_id_max_utf8_bytes": 128, + "correlation_id_max_utf8_bytes": 128, + "error_code_max_utf8_bytes": 64, + "error_message_max_utf8_bytes": 256, + "redaction_required": true, + "forbidden_material": ["secret_or_credential_material", "private_identity_material", "decrypted_payload", "raw_absolute_or_resolved_path", "raw_sql_or_database_error", "raw_provider_error", "raw_relay_or_network_error", "source_error_chain"] + }, + "common_route_suffixes": [ + { "method": "GET", "path": "/status", "operation_suffix": "status.get", "request_model": "empty", "response_model": "service_status_v1" }, + { "method": "GET", "path": "/config/effective", "operation_suffix": "config.effective.get", "request_model": "empty", "response_model": "effective_config_v1" }, + { "method": "GET", "path": "/identity/status", "operation_suffix": "identity.status.get", "request_model": "identity_status_query_v1", "response_model": "identity_status_v1" }, + { "method": "POST", "path": "/identity/rekey", "operation_suffix": "identity.rekey", "request_model": "identity_rekey_request_v1", "response_model": "identity_mutation_receipt_v1" }, + { "method": "POST", "path": "/identity/replace", "operation_suffix": "identity.replace", "request_model": "identity_replace_request_v1", "response_model": "identity_mutation_receipt_v1" }, + { "method": "GET", "path": "/state/status", "operation_suffix": "state.status.get", "request_model": "empty", "response_model": "state_status_v1" }, + { "method": "POST", "path": "/state/backup", "operation_suffix": "state.backup.create", "request_model": "state_backup_request_v1", "response_model": "state_backup_receipt_v1" }, + { "method": "GET", "path": "/metrics/snapshot", "operation_suffix": "metrics.snapshot.get", "request_model": "empty", "response_model": "metrics_snapshot_v1" } + ], + "unknown_major_version": "unsupported_contract_version", + "unknown_route": "route_not_found", + "duplicate_json_fields_rejected": true, + "unknown_json_fields_rejected": true + }, + "peer_authorization": { + "linux_service_host": { + "credential_api": "SO_PEERCRED", + "required": true, + "allow": ["peer_uid_equals_daemon_euid", "peer_primary_gid_equals_configured_admin_gid"], + "credential_unavailable": "deny", + "parent_mode_without_admin_gid": "0700", + "socket_mode_without_admin_gid": "0600", + "parent_mode_with_admin_gid": "0750", + "socket_mode_with_admin_gid": "0660" + }, + "macos_interactive": { + "credential_api": "none_v1", + "required": false, + "authority": "filesystem_owner_permissions_only", + "parent_mode": "0700", + "socket_mode": "0600", + "peer_credential_equivalence_claim": false + }, + "other_platforms": { "admin_support": "unsupported_v1" } + }, + "tcp_operations": { + "routes": [ + { "method": "GET", "path": "/livez", "source": "cached_supervisor_state" }, + { "method": "GET", "path": "/readyz", "source": "cached_readiness_state" }, + { "method": "GET", "path": "/metrics", "source": "cached_bounded_metrics_snapshot" } + ], + "active_probe_per_request": false, + "additional_routes": false + }, + "doctor": { + "schema": "radroots.service.doctor.v1", + "contract_version": 1, + "required_fields": ["contract_version", "service", "instance", "status", "checks"], + "check_required_fields": ["id", "status", "required", "deadline_ms", "summary", "remediation_code"], + "statuses": ["pass", "fail", "timeout", "skipped"], + "required_skipped": "forbidden", + "aggregate_statuses": ["pass", "degraded", "fail"], + "aggregation": { + "required_fail_or_timeout": "fail", + "optional_fail_timeout_or_skipped": "degraded", + "otherwise": "pass" + }, + "optional_nonpass_exit": 0, + "summary_max_utf8_bytes": 256, + "raw_error_or_path_allowed": false, + "required_fail_or_timeout_exit": 6 + }, + "exit_codes": [ + { "code": 0, "name": "success", "meaning": "successful command or completed graceful first-signal shutdown" }, + { "code": 1, "name": "unexpected_internal", "meaning": "unexpected invariant, critical task, or internal failure" }, + { "code": 2, "name": "input_or_configuration", "meaning": "CLI, config, validation, or unsupported contract input" }, + { "code": 3, "name": "service_or_dependency_unavailable", "meaning": "daemon, required provider, relay, source, or local dependency unavailable" }, + { "code": 4, "name": "state_or_identity_unavailable", "meaning": "state, schema, lock, credential, or identity unavailable" }, + { "code": 5, "name": "operation_rejected_or_conflict", "meaning": "authorization rejection, idempotency conflict, stale generation, or domain conflict" }, + { "code": 6, "name": "doctor_required_check_failed", "meaning": "one or more required doctor checks failed or timed out" } + ], + "forced_signal_exit": "operating_system_128_plus_signal_not_remapped", + "systemd": { + "sd_notify_v1": false, + "service_type": "simple", + "readiness_authority": "cached_http_readyz", + "process_running_does_not_imply_ready": true + }, + "bare_rust_linux": { + "qualification_base": "debian_bookworm_slim_digest_pinned_per_receipt", + "architectures": ["x86_64", "aarch64"], + "rust_install": "rustup_profile_minimal_exact_repository_toolchain", + "apt_packages": ["build-essential", "ca-certificates", "git"], + "not_required_by_final_graph": ["clang", "libclang-dev", "libsodium-dev", "libsqlite3-dev", "libssl-dev", "pkg-config"], + "sqlite": "bundled", + "tls": "rustls", + "proof": [ + "fresh_digest_pinned_base_for_each_architecture", + "install_only_declared_apt_packages_and_exact_rust_toolchain", + "locked_format_check_test_clippy_rustdoc_release_build", + "repeat_with_network_disabled_from_governed_vendor_bundle", + "fail_if_undeclared_native_package_is_installed_or_linked" + ] + } +} diff --git a/tools/xtask/tests/services_hardening_host_decision.rs b/tools/xtask/tests/services_hardening_host_decision.rs @@ -0,0 +1,239 @@ +#![forbid(unsafe_code)] + +use serde_json::Value; + +const HOST_DECISION: &str = + include_str!("../../../contracts/architecture/decisions/services_hardening_host.v1.json"); + +fn decision() -> Value { + serde_json::from_str(HOST_DECISION).expect("host decision must be valid JSON") +} + +#[test] +fn admin_routes_envelopes_and_exit_codes_are_unique_and_exact() { + let value = decision(); + assert_eq!( + value["schema"], + "radroots.services-hardening.host-decisions.v1" + ); + assert_eq!(value["decision_state"], "reserved_preimplementation"); + assert_eq!( + value["local_admin"]["transport"], + "http_1_1_over_unix_domain_socket" + ); + assert_eq!(value["local_admin"]["base_path"], "/v1"); + assert_eq!(value["local_admin"]["tcp_admin"], false); + + assert_eq!( + value["local_admin"]["mutation_request_envelope"], + serde_json::json!({ + "required_fields": ["contract_version", "operation_id", "request"], + "optional_fields": ["correlation_id"], + "contract_version": 1, + "operation_id_semantics": "caller_stable_idempotency_identity", + "correlation_id_semantics": "caller_safe_trace_identity_or_daemon_generated_when_absent", + "identical_operation_id_reuse": "return_original_committed_result", + "different_request_operation_id_reuse": { + "admin_error_code": "operation_id_conflict", + "cli_exit": 5 + } + }) + ); + assert_eq!(value["local_admin"]["cors"], false); + assert_eq!(value["local_admin"]["browser_authentication"], false); + assert_eq!( + value["local_admin"]["unknown_major_version"], + "unsupported_contract_version" + ); + assert_eq!(value["local_admin"]["unknown_route"], "route_not_found"); + assert_eq!(value["local_admin"]["duplicate_json_fields_rejected"], true); + assert_eq!(value["local_admin"]["unknown_json_fields_rejected"], true); + assert_eq!( + value["local_admin"]["success_response_envelope"], + serde_json::json!({ + "required_fields": ["contract_version", "ok", "correlation_id", "result"], + "contract_version": 1, + "ok": true + }) + ); + assert_eq!( + value["local_admin"]["failure_response_envelope"], + serde_json::json!({ + "required_fields": ["contract_version", "ok", "correlation_id", "error"], + "error_required_fields": ["code", "message"], + "contract_version": 1, + "ok": false + }) + ); + assert_eq!( + value["local_admin"]["output_safety"], + serde_json::json!({ + "request_body_max_utf8_bytes": 65_536, + "response_body_max_utf8_bytes": 1_048_576, + "operation_id_max_utf8_bytes": 128, + "correlation_id_max_utf8_bytes": 128, + "error_code_max_utf8_bytes": 64, + "error_message_max_utf8_bytes": 256, + "redaction_required": true, + "forbidden_material": [ + "secret_or_credential_material", + "private_identity_material", + "decrypted_payload", + "raw_absolute_or_resolved_path", + "raw_sql_or_database_error", + "raw_provider_error", + "raw_relay_or_network_error", + "source_error_chain" + ] + }) + ); + + let routes = value["local_admin"]["common_route_suffixes"] + .as_array() + .expect("common routes"); + assert_eq!( + routes, + serde_json::json!([ + { "method": "GET", "path": "/status", "operation_suffix": "status.get", "request_model": "empty", "response_model": "service_status_v1" }, + { "method": "GET", "path": "/config/effective", "operation_suffix": "config.effective.get", "request_model": "empty", "response_model": "effective_config_v1" }, + { "method": "GET", "path": "/identity/status", "operation_suffix": "identity.status.get", "request_model": "identity_status_query_v1", "response_model": "identity_status_v1" }, + { "method": "POST", "path": "/identity/rekey", "operation_suffix": "identity.rekey", "request_model": "identity_rekey_request_v1", "response_model": "identity_mutation_receipt_v1" }, + { "method": "POST", "path": "/identity/replace", "operation_suffix": "identity.replace", "request_model": "identity_replace_request_v1", "response_model": "identity_mutation_receipt_v1" }, + { "method": "GET", "path": "/state/status", "operation_suffix": "state.status.get", "request_model": "empty", "response_model": "state_status_v1" }, + { "method": "POST", "path": "/state/backup", "operation_suffix": "state.backup.create", "request_model": "state_backup_request_v1", "response_model": "state_backup_receipt_v1" }, + { "method": "GET", "path": "/metrics/snapshot", "operation_suffix": "metrics.snapshot.get", "request_model": "empty", "response_model": "metrics_snapshot_v1" } + ]) + .as_array() + .unwrap() + ); + + assert_eq!( + value["exit_codes"], + serde_json::json!([ + { "code": 0, "name": "success", "meaning": "successful command or completed graceful first-signal shutdown" }, + { "code": 1, "name": "unexpected_internal", "meaning": "unexpected invariant, critical task, or internal failure" }, + { "code": 2, "name": "input_or_configuration", "meaning": "CLI, config, validation, or unsupported contract input" }, + { "code": 3, "name": "service_or_dependency_unavailable", "meaning": "daemon, required provider, relay, source, or local dependency unavailable" }, + { "code": 4, "name": "state_or_identity_unavailable", "meaning": "state, schema, lock, credential, or identity unavailable" }, + { "code": 5, "name": "operation_rejected_or_conflict", "meaning": "authorization rejection, idempotency conflict, stale generation, or domain conflict" }, + { "code": 6, "name": "doctor_required_check_failed", "meaning": "one or more required doctor checks failed or timed out" } + ]) + ); +} + +#[test] +fn readiness_peer_authorization_and_native_support_fail_closed() { + let value = decision(); + assert_eq!( + value["tcp_operations"]["routes"], + serde_json::json!([ + { "method": "GET", "path": "/livez", "source": "cached_supervisor_state" }, + { "method": "GET", "path": "/readyz", "source": "cached_readiness_state" }, + { "method": "GET", "path": "/metrics", "source": "cached_bounded_metrics_snapshot" } + ]) + ); + assert_eq!(value["tcp_operations"]["active_probe_per_request"], false); + assert_eq!(value["tcp_operations"]["additional_routes"], false); + assert_eq!(value["systemd"]["sd_notify_v1"], false); + assert_eq!(value["systemd"]["service_type"], "simple"); + assert_eq!( + value["systemd"]["readiness_authority"], + "cached_http_readyz" + ); + assert_eq!( + value["systemd"]["process_running_does_not_imply_ready"], + true + ); + assert_eq!( + value["peer_authorization"]["linux_service_host"], + serde_json::json!({ + "credential_api": "SO_PEERCRED", + "required": true, + "allow": ["peer_uid_equals_daemon_euid", "peer_primary_gid_equals_configured_admin_gid"], + "credential_unavailable": "deny", + "parent_mode_without_admin_gid": "0700", + "socket_mode_without_admin_gid": "0600", + "parent_mode_with_admin_gid": "0750", + "socket_mode_with_admin_gid": "0660" + }) + ); + assert_eq!( + value["peer_authorization"]["macos_interactive"], + serde_json::json!({ + "credential_api": "none_v1", + "required": false, + "authority": "filesystem_owner_permissions_only", + "parent_mode": "0700", + "socket_mode": "0600", + "peer_credential_equivalence_claim": false + }) + ); + assert_eq!( + value["peer_authorization"]["other_platforms"], + serde_json::json!({ "admin_support": "unsupported_v1" }) + ); + assert_eq!( + value["doctor"], + serde_json::json!({ + "schema": "radroots.service.doctor.v1", + "contract_version": 1, + "required_fields": ["contract_version", "service", "instance", "status", "checks"], + "check_required_fields": ["id", "status", "required", "deadline_ms", "summary", "remediation_code"], + "statuses": ["pass", "fail", "timeout", "skipped"], + "required_skipped": "forbidden", + "aggregate_statuses": ["pass", "degraded", "fail"], + "aggregation": { + "required_fail_or_timeout": "fail", + "optional_fail_timeout_or_skipped": "degraded", + "otherwise": "pass" + }, + "optional_nonpass_exit": 0, + "summary_max_utf8_bytes": 256, + "raw_error_or_path_allowed": false, + "required_fail_or_timeout_exit": 6 + }) + ); + assert_eq!( + value["forced_signal_exit"], + "operating_system_128_plus_signal_not_remapped" + ); + assert_eq!( + value["bare_rust_linux"]["qualification_base"], + "debian_bookworm_slim_digest_pinned_per_receipt" + ); + assert_eq!( + value["bare_rust_linux"]["architectures"], + serde_json::json!(["x86_64", "aarch64"]) + ); + assert_eq!( + value["bare_rust_linux"]["rust_install"], + "rustup_profile_minimal_exact_repository_toolchain" + ); + assert_eq!( + value["bare_rust_linux"]["apt_packages"], + serde_json::json!(["build-essential", "ca-certificates", "git"]) + ); + assert_eq!( + value["bare_rust_linux"]["not_required_by_final_graph"], + serde_json::json!([ + "clang", + "libclang-dev", + "libsodium-dev", + "libsqlite3-dev", + "libssl-dev", + "pkg-config" + ]) + ); + assert_eq!(value["bare_rust_linux"]["sqlite"], "bundled"); + assert_eq!(value["bare_rust_linux"]["tls"], "rustls"); + assert_eq!( + value["bare_rust_linux"]["proof"], + serde_json::json!([ + "fresh_digest_pinned_base_for_each_architecture", + "install_only_declared_apt_packages_and_exact_rust_toolchain", + "locked_format_check_test_clippy_rustdoc_release_build", + "repeat_with_network_disabled_from_governed_vendor_bundle", + "fail_if_undeclared_native_package_is_installed_or_linked" + ]) + ); +}