From 1e10c188ab68a3121a2094cc49172a265b2e78b7 Mon Sep 17 00:00:00 2001 From: forkwright Date: Fri, 21 Aug 2026 10:56:59 -0500 Subject: [PATCH] refactor(koinon): split the shared crate into stoicheion and tekmerion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `koinon` crate collided by name with the standalone fleet repo of the same name, and the collision was not incidental: the crate held two unrelated things under one "common types" label. Splitting it resolves the collision and the conflation in the same move. `stoicheion` carries the workspace vocabulary — the identifiers, units, and value types every crate speaks in. `tekmerion` carries evidence: callers, effect receipts, and the tamper log that attests to them. The dependency runs one way, tekmerion on stoicheion, because evidence is stated in the vocabulary while the vocabulary knows nothing about being attested. The tamper-log domain separators keep their original `koinon/...` strings. They are keyed-hash inputs rather than names, so changing one re-roots every existing chain and makes logs already on disk verify as broken — which is indistinguishable from the tampering they exist to detect. `tamper_log_seal.rs` carries that constraint at the constants themselves. --- Cargo.lock | 67 ++++++++++++------- crates/akroasis/Cargo.toml | 3 +- crates/akroasis/src/caller.rs | 13 ++-- crates/akroasis/src/caller_tests.rs | 2 +- crates/akroasis/src/radio/export.rs | 2 +- crates/akroasis/src/radio/import.rs | 2 +- crates/akroasis/src/radio/program.rs | 2 +- crates/akroasis/src/radio/read.rs | 2 +- crates/akroasis/src/radio/serial_hardware.rs | 2 +- crates/akroasis/tests/caller_architecture.rs | 10 +-- crates/akroasis/tests/caller_contract.rs | 9 +-- crates/akroasis/tests/caller_receipt_wire.rs | 6 +- crates/akroasis/tests/caller_recovery.rs | 9 +-- crates/kerykeion/Cargo.toml | 2 +- crates/kerykeion/src/collector.rs | 7 +- crates/kerykeion/src/discovery.rs | 2 +- crates/kerykeion/src/processor.rs | 4 +- crates/kerykeion/src/signals.rs | 6 +- crates/kryphos/Cargo.toml | 2 +- crates/kryphos/src/error.rs | 2 +- crates/kryphos/src/key.rs | 22 +++--- crates/kryphos/src/storage.rs | 28 ++++---- crates/kryphos/tests/tamper_log_signing.rs | 2 +- crates/kryphos/tests/vault_tamper_audit.rs | 8 +-- crates/semaino/Cargo.toml | 2 +- crates/semaino/src/aggregator.rs | 14 ++-- crates/semaino/src/alert.rs | 16 ++--- crates/semaino/src/convergence.rs | 4 +- crates/semaino/src/pipeline.rs | 27 ++++---- crates/semaino/tests/smoke.rs | 4 +- .../{koinon => stoicheion}/.kanon-lint-ignore | 0 crates/stoicheion/Cargo.toml | 23 +++++++ crates/{koinon => stoicheion}/src/baseline.rs | 0 .../src/baseline_tests.rs | 0 .../{koinon => stoicheion}/src/coordinates.rs | 0 crates/{koinon => stoicheion}/src/entity.rs | 0 .../{koinon => stoicheion}/src/frequency.rs | 0 crates/{koinon => stoicheion}/src/hardware.rs | 0 .../src/hardware_tests.rs | 0 crates/{koinon => stoicheion}/src/id.rs | 0 crates/stoicheion/src/lib.rs | 35 ++++++++++ crates/{koinon => stoicheion}/src/power.rs | 0 crates/{koinon => stoicheion}/src/signal.rs | 0 .../src/signal_tests.rs | 0 .../{koinon => stoicheion}/src/timestamp.rs | 0 crates/{koinon => stoicheion}/tests/smoke.rs | 2 +- crates/syntonia/Cargo.toml | 2 +- crates/syntonia/src/baofeng/codec.rs | 2 +- crates/syntonia/src/channel.rs | 2 +- crates/syntonia/src/export/csv.rs | 2 +- crates/syntonia/src/hardware/detect.rs | 2 +- crates/syntonia/src/hardware/warnings.rs | 4 +- crates/syntonia/src/import/csv.rs | 2 +- crates/syntonia/src/import/img.rs | 2 +- crates/syntonia/src/plan.rs | 2 +- crates/syntonia/src/types.rs | 2 +- crates/syntonia/src/validate.rs | 2 +- crates/syntonia/src/yaesu/codec.rs | 2 +- crates/syntonia/src/yaesu/variant.rs | 2 +- crates/{koinon => tekmerion}/Cargo.toml | 18 ++--- crates/{koinon => tekmerion}/src/caller.rs | 2 +- .../{koinon => tekmerion}/src/caller_error.rs | 0 .../{koinon => tekmerion}/src/caller_ref.rs | 0 .../src/effect_receipt.rs | 2 +- .../src/effect_receipt_state.rs | 2 +- crates/{koinon => tekmerion}/src/lib.rs | 38 +++++------ .../{koinon => tekmerion}/src/tamper_log.rs | 0 .../src/tamper_log_codec_tests.rs | 0 .../src/tamper_log_entry.rs | 2 +- .../src/tamper_log_lock.rs | 0 .../src/tamper_log_recovery_tests.rs | 0 .../src/tamper_log_rotation.rs | 0 .../src/tamper_log_seal.rs | 11 +++ .../src/tamper_log_segments.rs | 0 .../src/tamper_log_tests.rs | 2 +- .../src/tamper_log_verify.rs | 0 76 files changed, 264 insertions(+), 182 deletions(-) rename crates/{koinon => stoicheion}/.kanon-lint-ignore (100%) create mode 100644 crates/stoicheion/Cargo.toml rename crates/{koinon => stoicheion}/src/baseline.rs (100%) rename crates/{koinon => stoicheion}/src/baseline_tests.rs (100%) rename crates/{koinon => stoicheion}/src/coordinates.rs (100%) rename crates/{koinon => stoicheion}/src/entity.rs (100%) rename crates/{koinon => stoicheion}/src/frequency.rs (100%) rename crates/{koinon => stoicheion}/src/hardware.rs (100%) rename crates/{koinon => stoicheion}/src/hardware_tests.rs (100%) rename crates/{koinon => stoicheion}/src/id.rs (100%) create mode 100644 crates/stoicheion/src/lib.rs rename crates/{koinon => stoicheion}/src/power.rs (100%) rename crates/{koinon => stoicheion}/src/signal.rs (100%) rename crates/{koinon => stoicheion}/src/signal_tests.rs (100%) rename crates/{koinon => stoicheion}/src/timestamp.rs (100%) rename crates/{koinon => stoicheion}/tests/smoke.rs (93%) rename crates/{koinon => tekmerion}/Cargo.toml (75%) rename crates/{koinon => tekmerion}/src/caller.rs (99%) rename crates/{koinon => tekmerion}/src/caller_error.rs (100%) rename crates/{koinon => tekmerion}/src/caller_ref.rs (100%) rename crates/{koinon => tekmerion}/src/effect_receipt.rs (99%) rename crates/{koinon => tekmerion}/src/effect_receipt_state.rs (99%) rename crates/{koinon => tekmerion}/src/lib.rs (60%) rename crates/{koinon => tekmerion}/src/tamper_log.rs (100%) rename crates/{koinon => tekmerion}/src/tamper_log_codec_tests.rs (100%) rename crates/{koinon => tekmerion}/src/tamper_log_entry.rs (99%) rename crates/{koinon => tekmerion}/src/tamper_log_lock.rs (100%) rename crates/{koinon => tekmerion}/src/tamper_log_recovery_tests.rs (100%) rename crates/{koinon => tekmerion}/src/tamper_log_rotation.rs (100%) rename crates/{koinon => tekmerion}/src/tamper_log_seal.rs (98%) rename crates/{koinon => tekmerion}/src/tamper_log_segments.rs (100%) rename crates/{koinon => tekmerion}/src/tamper_log_tests.rs (99%) rename crates/{koinon => tekmerion}/src/tamper_log_verify.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 7b86440..5c89114 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,14 +44,15 @@ dependencies = [ "indicatif", "jiff", "kerykeion", - "koinon", "kryphos", "rpassword", "serde", "serde_json", "snafu", + "stoicheion", "syn 3.0.3", "syntonia", + "tekmerion", "tempfile", "tokio", "tracing", @@ -1401,7 +1402,6 @@ dependencies = [ "ctr", "futures", "jiff", - "koinon", "petgraph", "proptest", "prost", @@ -1410,6 +1410,7 @@ dependencies = [ "serde", "serde_json", "snafu", + "stoicheion", "tokio", "tokio-serial", "tokio-util", @@ -1417,27 +1418,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "koinon" -version = "0.6.0" -dependencies = [ - "blake3", - "ciborium", - "compact_str", - "fs2", - "jiff", - "proptest", - "serde", - "serde_json", - "snafu", - "subtle", - "tempfile", - "toml 1.1.4+spec-1.1.0", - "tracing", - "ulid", - "zeroize", -] - [[package]] name = "kryphos" version = "0.6.0" @@ -1451,12 +1431,12 @@ dependencies = [ "fjall", "fs2", "jiff", - "koinon", "rand_core 0.6.4", "serde", "serde_json", "snafu", "subtle", + "tekmerion", "tempfile", "zeroize", ] @@ -2169,9 +2149,9 @@ name = "semaino" version = "0.6.0" dependencies = [ "jiff", - "koinon", "serde", "snafu", + "stoicheion", "tokio", "toml 1.1.4+spec-1.1.0", "tracing", @@ -2417,6 +2397,20 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "stoicheion" +version = "0.6.0" +dependencies = [ + "compact_str", + "jiff", + "proptest", + "serde", + "serde_json", + "snafu", + "tracing", + "ulid", +] + [[package]] name = "strsim" version = "0.11.1" @@ -2463,16 +2457,37 @@ version = "0.6.0" dependencies = [ "compact_str", "csv", - "koinon", "proptest", "rusb", "serde", "serde_json", "serialport", "snafu", + "stoicheion", + "tempfile", + "toml 1.1.4+spec-1.1.0", + "tracing", +] + +[[package]] +name = "tekmerion" +version = "0.6.0" +dependencies = [ + "blake3", + "ciborium", + "compact_str", + "fs2", + "jiff", + "serde", + "serde_json", + "snafu", + "stoicheion", + "subtle", "tempfile", "toml 1.1.4+spec-1.1.0", "tracing", + "ulid", + "zeroize", ] [[package]] diff --git a/crates/akroasis/Cargo.toml b/crates/akroasis/Cargo.toml index 62d21ef..8886dcd 100644 --- a/crates/akroasis/Cargo.toml +++ b/crates/akroasis/Cargo.toml @@ -29,7 +29,8 @@ figment = { workspace = true } indicatif = "0.17" jiff = { workspace = true } kerykeion = { path = "../kerykeion" } -koinon = { path = "../koinon" } +stoicheion = { path = "../stoicheion" } +tekmerion = { path = "../tekmerion" } kryphos = { path = "../kryphos" } rpassword = { workspace = true } serde = { workspace = true } diff --git a/crates/akroasis/src/caller.rs b/crates/akroasis/src/caller.rs index 94c47ac..ebed9a0 100644 --- a/crates/akroasis/src/caller.rs +++ b/crates/akroasis/src/caller.rs @@ -6,14 +6,15 @@ use std::fmt; -use koinon::{ +use snafu::{ResultExt, Snafu}; +use stoicheion::Timestamp; +use tekmerion::{ AuthorizationDenial, AuthorizationRequirement, CALLER_RESOLVER_VERSION, CallerAuthority, CallerContractError, CallerRef, CallerResolver, EffectDescriptor, EffectOutcome, EffectReceipt, EffectReceiptError, EffectReceiptSink, EvidenceDigest, LocalPeerCredentials, PersistedIntent, PersistedOutcome, ReceiptDigest, RecoveryAuthorization, RecoveryTicket, RevocationState, - Timestamp, ValidatedCaller, authorize_caller, + ValidatedCaller, authorize_caller, }; -use snafu::{ResultExt, Snafu}; use tokio::net::UnixStream; /// Version of accepted service-identity evidence. @@ -423,19 +424,19 @@ where const fn outcome_needs_recovery( outcome: EffectOutcome, - recovery: koinon::RecoveryRelation, + recovery: tekmerion::RecoveryRelation, ) -> bool { matches!( (outcome, recovery), ( EffectOutcome::Partial | EffectOutcome::RecoveryRequired, - koinon::RecoveryRelation::RequiredFor(_) + tekmerion::RecoveryRelation::RequiredFor(_) ) | ( EffectOutcome::Failed | EffectOutcome::Cancelled | EffectOutcome::Backpressured | EffectOutcome::AuthorizationDenied, - koinon::RecoveryRelation::RecoveryOf(_) + tekmerion::RecoveryRelation::RecoveryOf(_) ) ) } diff --git a/crates/akroasis/src/caller_tests.rs b/crates/akroasis/src/caller_tests.rs index 57275f0..be0ef0c 100644 --- a/crates/akroasis/src/caller_tests.rs +++ b/crates/akroasis/src/caller_tests.rs @@ -8,7 +8,7 @@ use std::cell::Cell; use std::rc::Rc; -use koinon::{ +use tekmerion::{ AuthorityClaims, AuthorityDecision, AuthorityGrant, AuthorizationDenial, AuthorizationRequirement, CALLER_CONTEXT_VERSION, CallerContractError, CapabilityRef, PersonaRef, PolicyEpoch, PrincipalSource, ScopeRef, authorize_caller, diff --git a/crates/akroasis/src/radio/export.rs b/crates/akroasis/src/radio/export.rs index 3d0b90b..b6ba497 100644 --- a/crates/akroasis/src/radio/export.rs +++ b/crates/akroasis/src/radio/export.rs @@ -278,7 +278,7 @@ fn csv_escape(s: &str) -> String { reason = "test code: panics and unwraps acceptable in assertions" )] mod tests { - use koinon::Frequency; + use stoicheion::Frequency; use syntonia::tone::CtcssTone; use syntonia::types::FrequencyOffset; diff --git a/crates/akroasis/src/radio/import.rs b/crates/akroasis/src/radio/import.rs index 521ec4a..bc3f342 100644 --- a/crates/akroasis/src/radio/import.rs +++ b/crates/akroasis/src/radio/import.rs @@ -3,9 +3,9 @@ use std::io::Write; use std::path::Path; -use koinon::Frequency; use serde::Serialize; use snafu::ResultExt; +use stoicheion::Frequency; use syntonia::{Bandwidth, Channel, FrequencyPlan, PowerLevel, ScanMode, ToneMode}; use super::errors::{IoSnafu, JsonReportSnafu, RadioError, ReadFileSnafu, SyntoniaSnafu}; diff --git a/crates/akroasis/src/radio/program.rs b/crates/akroasis/src/radio/program.rs index 388a88f..928d7dc 100644 --- a/crates/akroasis/src/radio/program.rs +++ b/crates/akroasis/src/radio/program.rs @@ -128,7 +128,7 @@ pub(crate) fn load_plan(path: &Path) -> Result { reason = "test code: panics and unwraps acceptable in assertions" )] mod tests { - use koinon::Frequency; + use stoicheion::Frequency; use syntonia::{Bandwidth, Channel, PowerLevel, ScanMode, ToneMode, types::FrequencyOffset}; use super::*; diff --git a/crates/akroasis/src/radio/read.rs b/crates/akroasis/src/radio/read.rs index 29f3e7d..2bcd754 100644 --- a/crates/akroasis/src/radio/read.rs +++ b/crates/akroasis/src/radio/read.rs @@ -129,7 +129,7 @@ const fn format_scan(scan: ScanMode) -> &'static str { reason = "test code: panics and unwraps acceptable in assertions" )] mod tests { - use koinon::Frequency; + use stoicheion::Frequency; use syntonia::tone::CtcssTone; use syntonia::types::FrequencyOffset; diff --git a/crates/akroasis/src/radio/serial_hardware.rs b/crates/akroasis/src/radio/serial_hardware.rs index 8566284..39e1758 100644 --- a/crates/akroasis/src/radio/serial_hardware.rs +++ b/crates/akroasis/src/radio/serial_hardware.rs @@ -1,6 +1,6 @@ //! Feature-gated live serial radio detection and protocol session backend. -use koinon::RadioKind; +use stoicheion::RadioKind; use syntonia::baofeng::{ codec::{CodecError, decode_all_channels, encode_all_channels}, image::MemoryImage, diff --git a/crates/akroasis/tests/caller_architecture.rs b/crates/akroasis/tests/caller_architecture.rs index 7c4bb01..2616350 100644 --- a/crates/akroasis/tests/caller_architecture.rs +++ b/crates/akroasis/tests/caller_architecture.rs @@ -90,11 +90,7 @@ fn restricted_identifiers(source: &str) -> BTreeSet { #[test] fn caller_construction_aliases_are_detected() { let source = r" - use koinon::{ - AuthorityClaimsBuilder as Claims, - CallerAuthority as Authority, - CallerResolver as Resolver, - }; + use tekmerion::{AuthorityClaimsBuilder as Claims, CallerAuthority as Authority, CallerResolver as Resolver}; fn bypass(authority: A) { let _claims = Claims::new(); @@ -166,8 +162,8 @@ fn is_allowed(path: &Path) -> bool { || path == Path::new("crates/akroasis/tests/caller_contract.rs") || path == Path::new("crates/akroasis/tests/caller_recovery.rs") || path == Path::new("crates/akroasis/tests/caller_receipt_wire.rs") - || path == Path::new("crates/koinon/src/caller.rs") - || path == Path::new("crates/koinon/src/lib.rs") + || path == Path::new("crates/tekmerion/src/caller.rs") + || path == Path::new("crates/tekmerion/src/lib.rs") } fn collect_rust_files(path: &Path, files: &mut Vec) { diff --git a/crates/akroasis/tests/caller_contract.rs b/crates/akroasis/tests/caller_contract.rs index 0bdccdb..a6d2430 100644 --- a/crates/akroasis/tests/caller_contract.rs +++ b/crates/akroasis/tests/caller_contract.rs @@ -13,14 +13,15 @@ use akroasis_lib::caller::{ AdmissionDecision, ApplicationCallerError, ApplicationCallerResolver, EffectExecution, EffectGateError, EffectRequest, TrustedClock, execute_effect, }; -use koinon::{ +use snafu::Snafu; +use stoicheion::Timestamp; +use tekmerion::{ AuthorityClaims, AuthorityDecision, AuthorityGrant, AuthorizationDenial, AuthorizationRequirement, CALLER_CONTEXT_VERSION, CALLER_RESOLVER_VERSION, CallerAuthority, CallerContractError, CallerRef, CapabilityRef, EffectDescriptor, EffectOutcome, EffectReceipt, EffectReceiptError, EffectReceiptSink, EffectRef, LocalPeerCredentials, PersonaRef, - PolicyEpoch, ReceiptDigest, ReceiptEvent, SchemaEpoch, ScopeRef, Timestamp, + PolicyEpoch, ReceiptDigest, ReceiptEvent, SchemaEpoch, ScopeRef, }; -use snafu::Snafu; use tokio::net::UnixStream; #[derive(Debug, Clone, Copy)] @@ -296,7 +297,7 @@ fn standard_grant() -> AuthorityGrant { ) } -fn valid_caller() -> koinon::ValidatedCaller { +fn valid_caller() -> tekmerion::ValidatedCaller { let authority = FakeAuthority::granted(standard_grant(), policy_epoch(7)); let resolver = ApplicationCallerResolver::current(authority).expect("current resolver"); let (client, _server) = UnixStream::pair().expect("Unix socket pair"); diff --git a/crates/akroasis/tests/caller_receipt_wire.rs b/crates/akroasis/tests/caller_receipt_wire.rs index cdbba64..ede009f 100644 --- a/crates/akroasis/tests/caller_receipt_wire.rs +++ b/crates/akroasis/tests/caller_receipt_wire.rs @@ -11,14 +11,14 @@ use akroasis_lib::caller::{ AdmissionDecision, ApplicationCallerResolver, EffectExecution, EffectRequest, TrustedClock, execute_effect, }; -use koinon::{ +use snafu::Snafu; +use stoicheion::Timestamp; +use tekmerion::{ AuthorityClaims, AuthorityDecision, AuthorityGrant, AuthorizationRequirement, CALLER_CONTEXT_VERSION, CallerAuthority, CallerRef, CapabilityRef, EffectDescriptor, EffectReceipt, EffectReceiptError, EffectReceiptSink, EffectRef, EvidenceDigest, LocalPeerCredentials, PolicyEpoch, ReceiptDigest, RecoveryRelation, SchemaEpoch, ScopeRef, - Timestamp, }; -use snafu::Snafu; use tokio::net::UnixStream; #[derive(Debug, Clone, Copy)] diff --git a/crates/akroasis/tests/caller_recovery.rs b/crates/akroasis/tests/caller_recovery.rs index 6a46eb6..040faa8 100644 --- a/crates/akroasis/tests/caller_recovery.rs +++ b/crates/akroasis/tests/caller_recovery.rs @@ -12,14 +12,15 @@ use akroasis_lib::caller::{ AdmissionDecision, ApplicationCallerResolver, EffectExecution, EffectGateError, EffectRequest, TrustedClock, execute_effect, }; -use koinon::{ +use snafu::Snafu; +use stoicheion::Timestamp; +use tekmerion::{ AuthorityClaims, AuthorityDecision, AuthorityGrant, AuthorizationRequirement, CALLER_CONTEXT_VERSION, CallerAuthority, CallerRef, CapabilityRef, EFFECT_RECEIPT_VERSION, EffectDescriptor, EffectOutcome, EffectReceipt, EffectReceiptError, EffectReceiptSink, EffectRef, LocalPeerCredentials, PersistedIntent, PersistedOutcome, PolicyEpoch, ReceiptDigest, - ReceiptEvent, RecoveryAuthorization, RecoveryRelation, SchemaEpoch, ScopeRef, Timestamp, + ReceiptEvent, RecoveryAuthorization, RecoveryRelation, SchemaEpoch, ScopeRef, }; -use snafu::Snafu; use tokio::net::UnixStream; #[derive(Debug, Clone, Copy)] @@ -255,7 +256,7 @@ fn grant() -> AuthorityGrant { ) } -fn caller() -> koinon::ValidatedCaller { +fn caller() -> tekmerion::ValidatedCaller { let resolver = ApplicationCallerResolver::current(RecoveryAuthority { grant: grant() }) .expect("current caller resolver"); let (client, _server) = UnixStream::pair().expect("Unix socket pair"); diff --git a/crates/kerykeion/Cargo.toml b/crates/kerykeion/Cargo.toml index 582cdc8..3a6fddc 100644 --- a/crates/kerykeion/Cargo.toml +++ b/crates/kerykeion/Cargo.toml @@ -7,7 +7,7 @@ license.workspace = true description = "Meshtastic mesh networking integration for Akroasis" [dependencies] -koinon = { path = "../koinon" } +stoicheion = { path = "../stoicheion" } serde = { workspace = true } serde_json = { workspace = true } snafu = { workspace = true } diff --git a/crates/kerykeion/src/collector.rs b/crates/kerykeion/src/collector.rs index b5ba288..13f3973 100644 --- a/crates/kerykeion/src/collector.rs +++ b/crates/kerykeion/src/collector.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use std::time::Duration; -use koinon::GeoSignal; +use stoicheion::GeoSignal; use tokio::sync::{Mutex, broadcast}; use tokio::task::JoinSet; use tokio_util::sync::CancellationToken; @@ -37,7 +37,10 @@ use crate::types::ClaimedNodeNum; /// Trait for Akroasis data collectors. /// /// Defines the minimal lifecycle interface shared across all collector crates. -/// This is a local definition pending the addition of `koinon::Collector`. +/// This is a local definition pending a shared one. Which crate it belongs in +/// is genuinely open: a collector produces signals, which is `stoicheion`'s +/// layer, but it is a pipeline role rather than an element, so it may belong +/// in neither. Left local until something forces the choice. pub trait Collector: Send + Sync { /// Returns the canonical name of this collector. fn name(&self) -> &'static str; diff --git a/crates/kerykeion/src/discovery.rs b/crates/kerykeion/src/discovery.rs index b14d8aa..de2e6c8 100644 --- a/crates/kerykeion/src/discovery.rs +++ b/crates/kerykeion/src/discovery.rs @@ -2,7 +2,7 @@ use std::time::Duration; -use koinon::GeoSignal; +use stoicheion::GeoSignal; use tokio::sync::broadcast; use tokio_util::sync::CancellationToken; use tracing::instrument; diff --git a/crates/kerykeion/src/processor.rs b/crates/kerykeion/src/processor.rs index bbc9448..a72fcdf 100644 --- a/crates/kerykeion/src/processor.rs +++ b/crates/kerykeion/src/processor.rs @@ -1,7 +1,7 @@ //! Central packet dispatch for incoming `FromRadio` messages after handshake. -use koinon::GeoSignal; use prost::Message as _; +use stoicheion::GeoSignal; use tokio::sync::broadcast; use crate::delivery::{DeliveryFailure, DeliveryTracker}; @@ -301,7 +301,7 @@ impl PacketProcessor { // unchecked. `Coordinates::new` already owns this rule for the whole // fleet, so it is reused rather than restated; it also rejects NaN, // which a bare range comparison would silently admit. - if let Err(error) = koinon::Coordinates::new(lat, lon, None) { + if let Err(error) = stoicheion::Coordinates::new(lat, lon, None) { tracing::warn!( from = from.0, %error, diff --git a/crates/kerykeion/src/signals.rs b/crates/kerykeion/src/signals.rs index 7e4ff63..dac93a1 100644 --- a/crates/kerykeion/src/signals.rs +++ b/crates/kerykeion/src/signals.rs @@ -1,7 +1,7 @@ -//! Mesh event types and conversion to [`koinon::GeoSignal`] for the broadcast channel. +//! Mesh event types and conversion to [`stoicheion::GeoSignal`] for the broadcast channel. -use koinon::signal::MeshDetail; -use koinon::{Confidence, Coordinates, GeoSignal, SignalKind, Timestamp}; +use stoicheion::signal::MeshDetail; +use stoicheion::{Confidence, Coordinates, GeoSignal, SignalKind, Timestamp}; use crate::node_db::NodePosition; use crate::types::NodeNum; diff --git a/crates/kryphos/Cargo.toml b/crates/kryphos/Cargo.toml index 6f92f4c..9d332ca 100644 --- a/crates/kryphos/Cargo.toml +++ b/crates/kryphos/Cargo.toml @@ -23,7 +23,7 @@ compact_str.workspace = true figment.workspace = true fjall.workspace = true fs2.workspace = true -koinon = { path = "../koinon" } +tekmerion = { path = "../tekmerion" } [dev-dependencies] serde_json.workspace = true diff --git a/crates/kryphos/src/error.rs b/crates/kryphos/src/error.rs index 570e5b6..bcefc89 100644 --- a/crates/kryphos/src/error.rs +++ b/crates/kryphos/src/error.rs @@ -138,7 +138,7 @@ pub enum VaultError { #[snafu(display("tamper log error: {source}"))] TamperLog { /// Underlying tamper-log failure. - source: koinon::TamperLogError, + source: tekmerion::TamperLogError, }, /// A field passed to [`crate::crypto::entry_aad`] is too long to encode diff --git a/crates/kryphos/src/key.rs b/crates/kryphos/src/key.rs index 5064664..0481267 100644 --- a/crates/kryphos/src/key.rs +++ b/crates/kryphos/src/key.rs @@ -184,34 +184,34 @@ impl fmt::Display for VerifyingKey { const KEY_ID_DOMAIN: &[u8] = b"kryphos/installation/key-id/v1"; /// Computes the stable short identifier for a verifying key. -fn installation_key_id(verifying: &VerifyingKey) -> [u8; koinon::KEY_ID_LEN] { +fn installation_key_id(verifying: &VerifyingKey) -> [u8; tekmerion::KEY_ID_LEN] { let digest = blake3::keyed_hash(&blake3::hash(KEY_ID_DOMAIN).into(), verifying.as_bytes()); - let mut id = [0u8; koinon::KEY_ID_LEN]; + let mut id = [0u8; tekmerion::KEY_ID_LEN]; id.copy_from_slice( digest .as_bytes() - .get(..koinon::KEY_ID_LEN) - .unwrap_or(&[0u8; koinon::KEY_ID_LEN]), + .get(..tekmerion::KEY_ID_LEN) + .unwrap_or(&[0u8; tekmerion::KEY_ID_LEN]), ); id } -impl koinon::TipSigner for InstallationIdentity { - fn key_id(&self) -> [u8; koinon::KEY_ID_LEN] { +impl tekmerion::TipSigner for InstallationIdentity { + fn key_id(&self) -> [u8; tekmerion::KEY_ID_LEN] { installation_key_id(self.verifying_key()) } - fn sign_tip(&self, payload: &[u8]) -> [u8; koinon::TIP_SIGNATURE_LEN] { + fn sign_tip(&self, payload: &[u8]) -> [u8; tekmerion::TIP_SIGNATURE_LEN] { self.sign(payload).to_bytes() } } -impl koinon::TipVerifier for VerifyingKey { - fn key_id(&self) -> [u8; koinon::KEY_ID_LEN] { +impl tekmerion::TipVerifier for VerifyingKey { + fn key_id(&self) -> [u8; tekmerion::KEY_ID_LEN] { installation_key_id(self) } - fn verify_tip(&self, payload: &[u8], signature: &[u8; koinon::TIP_SIGNATURE_LEN]) -> bool { + fn verify_tip(&self, payload: &[u8], signature: &[u8; tekmerion::TIP_SIGNATURE_LEN]) -> bool { let signature = ed25519_dalek::Signature::from_bytes(signature); self.verify(payload, &signature).is_ok() } @@ -282,7 +282,7 @@ impl InstallationIdentity { /// Signs a tamper log entry hash, proving this installation produced it. /// - /// `entry_hash` is the 32-byte BLAKE3 hash from `koinon::tamper_log::encode_entry`. + /// `entry_hash` is the 32-byte BLAKE3 hash from `tekmerion::tamper_log::encode_entry`. #[must_use] pub fn sign_entry(&self, entry_hash: &[u8; 32]) -> ed25519_dalek::Signature { self.signing.sign(entry_hash) diff --git a/crates/kryphos/src/storage.rs b/crates/kryphos/src/storage.rs index 5869ea0..1123749 100644 --- a/crates/kryphos/src/storage.rs +++ b/crates/kryphos/src/storage.rs @@ -7,9 +7,9 @@ use std::path::{Path, PathBuf}; use compact_str::CompactString; use fs2::FileExt; use jiff::Timestamp; -use koinon::{ChainKey, LogEntryKind, TamperLog, VerificationResult}; use serde::{Deserialize, Serialize}; use snafu::ResultExt; +use tekmerion::{ChainKey, LogEntryKind, TamperLog, VerificationResult}; use zeroize::Zeroizing; use crate::crypto::{self, ENTRY_ENVELOPE_VERSION, decrypt, encrypt, entry_aad}; @@ -76,17 +76,17 @@ const AUDIT_REF_DOMAIN: &[u8] = b"kryphos/vault/audit-ref/v1"; /// question "which installation produced this log" still has an answer when the /// asking vault has no identity of its own, and it is not always "none". A log /// that carries provenance under a vault with no recorded key is reported as -/// [`koinon::TipStatus::ForeignInstallation`] — the log names someone this +/// [`tekmerion::TipStatus::ForeignInstallation`] — the log names someone this /// vault has no record of, which is worth surfacing rather than flattening into /// "unsigned". struct NoInstallation; -impl koinon::TipVerifier for NoInstallation { - fn key_id(&self) -> [u8; koinon::KEY_ID_LEN] { - [0u8; koinon::KEY_ID_LEN] +impl tekmerion::TipVerifier for NoInstallation { + fn key_id(&self) -> [u8; tekmerion::KEY_ID_LEN] { + [0u8; tekmerion::KEY_ID_LEN] } - fn verify_tip(&self, _payload: &[u8], _signature: &[u8; koinon::TIP_SIGNATURE_LEN]) -> bool { + fn verify_tip(&self, _payload: &[u8], _signature: &[u8; tekmerion::TIP_SIGNATURE_LEN]) -> bool { false } } @@ -1003,20 +1003,20 @@ impl Vault { /// /// Returns [`VaultError::TamperLog`] if the log file cannot be read. pub fn verify_tamper_log(&self) -> Result { - koinon::verify_chain(self.tamper_log_path(), &self.chain_key()).context(TamperLogSnafu) + tekmerion::verify_chain(self.tamper_log_path(), &self.chain_key()).context(TamperLogSnafu) } /// Reports which installation produced this vault's audit log. /// /// WHY the vault answers this rather than the caller reaching for - /// `koinon::verify_tip_provenance` directly: the vault is what knows + /// `tekmerion::verify_tip_provenance` directly: the vault is what knows /// whether an identity is *expected*. koinon can report that a log is /// unsigned; only the header says whether that is a vault which never had /// an identity or one whose signing has been stripped. /// /// That distinction is the migration rule (forkwright/akroasis#284). An /// unsigned log under a vault with no recorded identity is the ordinary - /// pre-provenance state and reports [`koinon::TipStatus::Unsigned`]. An + /// pre-provenance state and reports [`tekmerion::TipStatus::Unsigned`]. An /// unsigned log under a vault that *has* an identity is a downgrade with no /// innocent cause, and is refused as [`VaultError::InvalidHeader`] rather /// than reported as merely unsigned — the same asymmetry the tamper log's @@ -1027,10 +1027,10 @@ impl Vault { /// /// Returns [`VaultError::TamperLog`] if the log cannot be read, and the /// header errors of [`Self::installation_identity`]. - pub fn verify_tamper_log_provenance(&self) -> Result { + pub fn verify_tamper_log_provenance(&self) -> Result { let Some(identity) = self.installation_identity()? else { // No identity to check against; koinon reports the log's own state. - return koinon::verify_tip_provenance( + return tekmerion::verify_tip_provenance( self.tamper_log_path(), &self.chain_key(), &NoInstallation, @@ -1039,14 +1039,14 @@ impl Vault { }; let verifying = identity.verifying_key(); - let status = koinon::verify_tip_provenance( + let status = tekmerion::verify_tip_provenance( self.tamper_log_path(), &self.chain_key(), - verifying as &dyn koinon::TipVerifier, + verifying as &dyn tekmerion::TipVerifier, ) .context(TamperLogSnafu)?; - if status == koinon::TipStatus::Unsigned { + if status == tekmerion::TipStatus::Unsigned { return Err(VaultError::InvalidHeader { reason: String::from( "vault has an installation identity but its audit log tip is unsigned", diff --git a/crates/kryphos/tests/tamper_log_signing.rs b/crates/kryphos/tests/tamper_log_signing.rs index 4490c5c..24eeaaf 100644 --- a/crates/kryphos/tests/tamper_log_signing.rs +++ b/crates/kryphos/tests/tamper_log_signing.rs @@ -13,8 +13,8 @@ reason = "integration test — panics are the correct failure mode" )] -use koinon::TipStatus; use kryphos::{CredentialType, Vault}; +use tekmerion::TipStatus; const TEST_PASSPHRASE: &[u8] = b"correct horse battery staple"; diff --git a/crates/kryphos/tests/vault_tamper_audit.rs b/crates/kryphos/tests/vault_tamper_audit.rs index 6e3a5bb..7e0d322 100644 --- a/crates/kryphos/tests/vault_tamper_audit.rs +++ b/crates/kryphos/tests/vault_tamper_audit.rs @@ -7,14 +7,14 @@ reason = "integration test — panics are the correct failure mode" )] -use koinon::{ChainStatus, LogEntryKind}; use kryphos::{CredentialType, Vault, VaultError}; +use tekmerion::{ChainStatus, LogEntryKind}; const TEST_PASSPHRASE: &[u8] = b"correct horse battery staple"; /// Walks wire-format bytes and returns the byte offset of entry `target_idx`. /// -/// Mirrors `koinon::tamper_log`'s own private test helper — kryphos has no +/// Mirrors `tekmerion::tamper_log`'s own private test helper — kryphos has no /// access to it, and the wire format (`[4-byte LE len][cbor][32-byte hash]`) /// is part of the documented on-disk contract, not an implementation detail. fn entry_offset(data: &[u8], target_idx: usize) -> usize { @@ -64,7 +64,7 @@ fn vault_mutations_append_intact_tamper_log() { ]; for (idx, (name, operation)) in expected.into_iter().enumerate() { let offset = entry_offset(&data, idx); - let (entry, _hash) = koinon::tamper_log::decode_entry(&data[offset..]).unwrap(); + let (entry, _hash) = tekmerion::tamper_log::decode_entry(&data[offset..]).unwrap(); match entry.kind { LogEntryKind::VaultMutation { credential_ref, @@ -99,7 +99,7 @@ fn vault_mutations_append_intact_tamper_log() { let refs: Vec = (0..5) .map(|idx| { let offset = entry_offset(&data, idx); - let (entry, _) = koinon::tamper_log::decode_entry(&data[offset..]).unwrap(); + let (entry, _) = tekmerion::tamper_log::decode_entry(&data[offset..]).unwrap(); match entry.kind { LogEntryKind::VaultMutation { credential_ref, .. } => credential_ref.to_string(), other => panic!("entry {idx}: expected VaultMutation, got {other:?}"), diff --git a/crates/semaino/Cargo.toml b/crates/semaino/Cargo.toml index 0ed2112..40d34cf 100644 --- a/crates/semaino/Cargo.toml +++ b/crates/semaino/Cargo.toml @@ -6,7 +6,7 @@ rust-version.workspace = true license.workspace = true [dependencies] -koinon = { path = "../koinon" } +stoicheion = { path = "../stoicheion" } serde = { workspace = true } tokio = { workspace = true } snafu = { workspace = true } diff --git a/crates/semaino/src/aggregator.rs b/crates/semaino/src/aggregator.rs index 3f442d6..a5955ca 100644 --- a/crates/semaino/src/aggregator.rs +++ b/crates/semaino/src/aggregator.rs @@ -7,11 +7,11 @@ use std::collections::HashMap; -use koinon::{ +use snafu::Snafu; +use stoicheion::{ AnomalyScore, GeoSignal, TemporalBucketedBaseline, signal::{EnvironmentalDetail, GpsDetail, MeshDetail, ProximityDetail, RfDetail, SignalKind}, }; -use snafu::Snafu; use tokio::sync::mpsc; // --------------------------------------------------------------------------- @@ -224,11 +224,11 @@ impl SignalAggregator { } } -/// Extract (`day_of_week`, `hour`) from a [`koinon::Timestamp`]. +/// Extract (`day_of_week`, `hour`) from a [`stoicheion::Timestamp`]. /// /// Returns (0, 0) — Monday 00:00 — on any conversion failure so the caller /// always gets a valid bucket index. -pub(crate) fn day_hour_from_timestamp(ts: &koinon::Timestamp) -> (u8, u8) { +pub(crate) fn day_hour_from_timestamp(ts: &stoicheion::Timestamp) -> (u8, u8) { use jiff::civil::Weekday; let millis = ts.as_unix_millis(); @@ -266,7 +266,7 @@ pub(crate) fn day_hour_from_timestamp(ts: &koinon::Timestamp) -> (u8, u8) { reason = "test code: panics and unwraps acceptable in assertions" )] mod tests { - use koinon::{ + use stoicheion::{ Coordinates, Frequency, Power, Timestamp, signal::{ EnvironmentalDetail, GpsDetail, MeshDetail, NetworkDetail, OsintDetail, @@ -491,7 +491,7 @@ mod tests { #[test] fn extract_feature_returns_none_for_tracker() { - use koinon::signal::TrackerKind; + use stoicheion::signal::TrackerKind; let sig = GeoSignal::new( SignalKind::Proximity(ProximityDetail::Tracker { @@ -564,7 +564,7 @@ mod tests { fn day_hour_from_timestamp_maps_known_instants() { // NOTE: the (0, 0) conversion fallback documented on // day_hour_from_timestamp is unreachable through any public path — - // `koinon::Timestamp` only ever holds an already-valid jiff timestamp + // `stoicheion::Timestamp` only ever holds an already-valid jiff timestamp // (`now()`, the validating `from_unix_millis`, or a Deserialize impl // that delegates to jiff's own), so neither `from_millisecond` nor // `in_tz("UTC")` can fail on a value obtained from one. It is diff --git a/crates/semaino/src/alert.rs b/crates/semaino/src/alert.rs index 579dc45..c5b7750 100644 --- a/crates/semaino/src/alert.rs +++ b/crates/semaino/src/alert.rs @@ -18,7 +18,7 @@ use std::collections::HashMap; -use koinon::{ +use stoicheion::{ AnomalyScore, SignalId, Timestamp, signal::{AlertSeverity, SignalKind}, }; @@ -377,7 +377,7 @@ fn build_summary( reason = "test code: panics and unwraps acceptable in assertions" )] mod tests { - use koinon::{ + use stoicheion::{ AnomalyScore, Coordinates, Frequency, Power, Timestamp, signal::{EnvironmentalDetail, RfDetail}, }; @@ -387,11 +387,11 @@ mod tests { // ── helper builders ─────────────────────────────────────────────────────── fn rf_aggregated(score: AnomalyScore) -> AggregatedSignal { - use koinon::GeoSignal; + use stoicheion::GeoSignal; AggregatedSignal { signal: GeoSignal::new( - koinon::signal::SignalKind::Rf(RfDetail::Transmission { + stoicheion::signal::SignalKind::Rf(RfDetail::Transmission { frequency: Frequency::mhz(146), power: Power::dbm(-30.0), modulation: "FM".into(), @@ -407,11 +407,11 @@ mod tests { } fn rf_aggregated_at(score: AnomalyScore, location: Coordinates) -> AggregatedSignal { - use koinon::GeoSignal; + use stoicheion::GeoSignal; AggregatedSignal { signal: GeoSignal::new( - koinon::signal::SignalKind::Rf(RfDetail::Transmission { + stoicheion::signal::SignalKind::Rf(RfDetail::Transmission { frequency: Frequency::mhz(146), power: Power::dbm(-30.0), modulation: "FM".into(), @@ -688,11 +688,11 @@ mod tests { #[test] fn classify_environmental_elevated_alone_is_low() { - use koinon::GeoSignal; + use stoicheion::GeoSignal; let agg = AggregatedSignal { signal: GeoSignal::new( - koinon::signal::SignalKind::Environmental(EnvironmentalDetail::Temperature { + stoicheion::signal::SignalKind::Environmental(EnvironmentalDetail::Temperature { celsius: 99.0, }), Timestamp::now(), diff --git a/crates/semaino/src/convergence.rs b/crates/semaino/src/convergence.rs index 044ccc9..277b824 100644 --- a/crates/semaino/src/convergence.rs +++ b/crates/semaino/src/convergence.rs @@ -11,7 +11,7 @@ use std::collections::HashMap; -use koinon::{Coordinates, GeoSignal, Timestamp, signal::SignalKind}; +use stoicheion::{Coordinates, GeoSignal, Timestamp, signal::SignalKind}; // --------------------------------------------------------------------------- // GridCell @@ -345,7 +345,7 @@ fn cell_center(cell: GridCell, resolution: u32) -> Coordinates { reason = "test code: panics and unwraps acceptable in assertions" )] mod tests { - use koinon::{ + use stoicheion::{ Frequency, Power, Timestamp, signal::{ EnvironmentalDetail, GpsDetail, MeshDetail, NetworkDetail, OsintDetail, diff --git a/crates/semaino/src/pipeline.rs b/crates/semaino/src/pipeline.rs index fb1cd1a..51121a9 100644 --- a/crates/semaino/src/pipeline.rs +++ b/crates/semaino/src/pipeline.rs @@ -5,8 +5,8 @@ use std::time::Duration; -use koinon::GeoSignal; use serde::{Deserialize, Serialize}; +use stoicheion::GeoSignal; use tokio::sync::{broadcast, mpsc}; use tracing::Instrument as _; @@ -213,9 +213,9 @@ impl SemainoPipeline { clippy::cast_possible_truncation, reason = "Duration::as_millis() returns u128; cast to i64 is safe because i64::MAX ms is larger than any realistic eviction window" )] - let evict_before_ms = koinon::Timestamp::now().as_unix_millis() + let evict_before_ms = stoicheion::Timestamp::now().as_unix_millis() - self.time_window.as_millis() as i64; // SAFETY: Duration::as_millis() returns u128 but time_window is config-bounded; fits i64 - if let Ok(ts) = koinon::Timestamp::from_unix_millis(evict_before_ms) { + if let Ok(ts) = stoicheion::Timestamp::from_unix_millis(evict_before_ms) { self.grid.evict(ts); } @@ -290,7 +290,7 @@ impl SemainoPipeline { fn handle_aggregated(&mut self, aggregated: &AggregatedSignal) { self.grid.ingest(&aggregated.signal); - let now = koinon::Timestamp::now(); + let now = stoicheion::Timestamp::now(); // WHY(#223): this read the whole grid and then took `.first()`, under a // comment claiming it was "the cell matching the signal". A HashMap has // no first, so with more than one converged cell the alert was attributed @@ -328,7 +328,7 @@ impl SemainoPipeline { mod tests { use std::sync::{Arc, Mutex}; - use koinon::{ + use stoicheion::{ AnomalyScore, Coordinates, Frequency, GeoSignal, Power, Timestamp, signal::{GpsDetail, MeshDetail, RfDetail, SignalKind}, }; @@ -401,7 +401,7 @@ mod tests { }; assert_eq!( severities, - vec![koinon::signal::AlertSeverity::High], + vec![stoicheion::signal::AlertSeverity::High], "exactly one alert, from the outlier: an empty list means it was \ dropped crossing a saturated channel (#232), and more than one \ means the flat burst itself scored" @@ -490,7 +490,7 @@ mod tests { }; assert_eq!( severities, - vec![koinon::signal::AlertSeverity::Critical], + vec![stoicheion::signal::AlertSeverity::Critical], "one alert, Critical: three domains converged at the anomaly's own \ cell. High would mean the mesh and GPS signals were not yet in the \ grid when the anomaly was evaluated (#224)" @@ -547,7 +547,8 @@ mod tests { assert!( matches!( severity, - koinon::signal::AlertSeverity::High | koinon::signal::AlertSeverity::Critical + stoicheion::signal::AlertSeverity::High + | stoicheion::signal::AlertSeverity::Critical ), "outlier signal should produce High or Critical alert, got {severity:?}", ); @@ -606,7 +607,7 @@ mod tests { #[tokio::test] async fn pipeline_ignores_osint_no_alert() { - use koinon::signal::{OsintDetail, SignalKind}; + use stoicheion::signal::{OsintDetail, SignalKind}; let (tx, rx) = broadcast::channel::(64); let mut pipeline = SemainoPipeline::new(&SemainoConfig::default()); @@ -659,7 +660,7 @@ mod tests { // calling handle_aggregated directly against a grid that has NOT // yet seen the RF trigger signal, only a co-located Mesh signal that // arrived through the ordinary path. - use koinon::signal::MeshDetail; + use stoicheion::signal::MeshDetail; let loc = Coordinates::new(51.5, -0.1, None).expect("valid coordinates"); @@ -715,7 +716,7 @@ mod tests { ); assert_eq!( first_severity, - Some(koinon::signal::AlertSeverity::Medium), + Some(stoicheion::signal::AlertSeverity::Medium), "an Elevated score with 2-domain convergence classifies as \ Medium; a Low severity here means the RF trigger's own signal \ was missing from the grid at detection time (#224)" @@ -732,7 +733,7 @@ mod tests { /// location. #[test] fn a_convergence_in_another_cell_does_not_escalate_this_signal() { - use koinon::signal::MeshDetail; + use stoicheion::signal::MeshDetail; let elsewhere = Coordinates::new(51.5, -0.1, None).expect("valid coordinates"); let trigger_loc = Coordinates::new(48.85, 2.35, None).expect("valid coordinates"); @@ -791,7 +792,7 @@ mod tests { }; assert_eq!( first_severity, - Some(koinon::signal::AlertSeverity::Low), + Some(stoicheion::signal::AlertSeverity::Low), "the trigger's own cell holds one domain, so this must classify \ Low; Medium means an unrelated cell's convergence was used" ); diff --git a/crates/semaino/tests/smoke.rs b/crates/semaino/tests/smoke.rs index 55001d6..d6afe6d 100644 --- a/crates/semaino/tests/smoke.rs +++ b/crates/semaino/tests/smoke.rs @@ -4,9 +4,9 @@ //! that the library exposes a public test binary (required by //! TESTING/no-tests). -use koinon::signal::{RfDetail, SignalKind}; -use koinon::{GeoSignal, Power, Timestamp}; use semaino::{ConvergenceGrid, SemainoConfig, SignalAggregator}; +use stoicheion::signal::{RfDetail, SignalKind}; +use stoicheion::{GeoSignal, Power, Timestamp}; #[test] fn default_config_has_sensible_values() { diff --git a/crates/koinon/.kanon-lint-ignore b/crates/stoicheion/.kanon-lint-ignore similarity index 100% rename from crates/koinon/.kanon-lint-ignore rename to crates/stoicheion/.kanon-lint-ignore diff --git a/crates/stoicheion/Cargo.toml b/crates/stoicheion/Cargo.toml new file mode 100644 index 0000000..56910df --- /dev/null +++ b/crates/stoicheion/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "stoicheion" +description = "στοιχεῖον — the elements the Akroasis workspace is composed from" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +compact_str.workspace = true +jiff.workspace = true +serde.workspace = true +serde_json.workspace = true +snafu.workspace = true +tracing.workspace = true +ulid.workspace = true + +[dev-dependencies] +proptest = "1" + +[lints] +workspace = true diff --git a/crates/koinon/src/baseline.rs b/crates/stoicheion/src/baseline.rs similarity index 100% rename from crates/koinon/src/baseline.rs rename to crates/stoicheion/src/baseline.rs diff --git a/crates/koinon/src/baseline_tests.rs b/crates/stoicheion/src/baseline_tests.rs similarity index 100% rename from crates/koinon/src/baseline_tests.rs rename to crates/stoicheion/src/baseline_tests.rs diff --git a/crates/koinon/src/coordinates.rs b/crates/stoicheion/src/coordinates.rs similarity index 100% rename from crates/koinon/src/coordinates.rs rename to crates/stoicheion/src/coordinates.rs diff --git a/crates/koinon/src/entity.rs b/crates/stoicheion/src/entity.rs similarity index 100% rename from crates/koinon/src/entity.rs rename to crates/stoicheion/src/entity.rs diff --git a/crates/koinon/src/frequency.rs b/crates/stoicheion/src/frequency.rs similarity index 100% rename from crates/koinon/src/frequency.rs rename to crates/stoicheion/src/frequency.rs diff --git a/crates/koinon/src/hardware.rs b/crates/stoicheion/src/hardware.rs similarity index 100% rename from crates/koinon/src/hardware.rs rename to crates/stoicheion/src/hardware.rs diff --git a/crates/koinon/src/hardware_tests.rs b/crates/stoicheion/src/hardware_tests.rs similarity index 100% rename from crates/koinon/src/hardware_tests.rs rename to crates/stoicheion/src/hardware_tests.rs diff --git a/crates/koinon/src/id.rs b/crates/stoicheion/src/id.rs similarity index 100% rename from crates/koinon/src/id.rs rename to crates/stoicheion/src/id.rs diff --git a/crates/stoicheion/src/lib.rs b/crates/stoicheion/src/lib.rs new file mode 100644 index 0000000..0c4b47e --- /dev/null +++ b/crates/stoicheion/src/lib.rs @@ -0,0 +1,35 @@ +//! στοιχεῖον — the elements the Akroasis workspace is composed from. +//! +//! A stoicheion is a primary constituent, and also a letter of the alphabet: +//! the units that combine into everything written above them. This crate holds +//! that layer — what a signal, a frequency, a coordinate, a piece of hardware +//! and a moment in time *are* — and nothing that reasons about them. +//! +//! Evidence about those things (the tamper-evident log, caller authority, +//! effect receipts) lives in `tekmerion`, which depends on this crate and not +//! the reverse. + +#![deny(missing_docs)] + +pub mod baseline; +pub mod coordinates; +pub mod entity; +pub mod frequency; +pub mod hardware; +pub mod id; +pub mod power; +pub mod signal; +pub mod timestamp; + +pub use baseline::{AnomalyScore, Baseline, ScoringConfig, TemporalBucketedBaseline}; +pub use coordinates::{Coordinates, CoordinatesError, Datum}; +pub use entity::{Entity, EntityKind}; +pub use frequency::Frequency; +pub use hardware::{ + AssetRegistry, AssetStatus, ConnectionType, HardwareAsset, HardwareKind, KNOWN_USB_DEVICES, + KnownUsbDevice, MeshNodeKind, RadioKind, RegistryError, SdrKind, UsbId, lookup_usb_device, +}; +pub use id::{DeviceId, EntityId, FrequencyId, SignalId}; +pub use power::Power; +pub use signal::{Confidence, GeoSignal, SignalKind}; +pub use timestamp::{Timestamp, TimestampError}; diff --git a/crates/koinon/src/power.rs b/crates/stoicheion/src/power.rs similarity index 100% rename from crates/koinon/src/power.rs rename to crates/stoicheion/src/power.rs diff --git a/crates/koinon/src/signal.rs b/crates/stoicheion/src/signal.rs similarity index 100% rename from crates/koinon/src/signal.rs rename to crates/stoicheion/src/signal.rs diff --git a/crates/koinon/src/signal_tests.rs b/crates/stoicheion/src/signal_tests.rs similarity index 100% rename from crates/koinon/src/signal_tests.rs rename to crates/stoicheion/src/signal_tests.rs diff --git a/crates/koinon/src/timestamp.rs b/crates/stoicheion/src/timestamp.rs similarity index 100% rename from crates/koinon/src/timestamp.rs rename to crates/stoicheion/src/timestamp.rs diff --git a/crates/koinon/tests/smoke.rs b/crates/stoicheion/tests/smoke.rs similarity index 93% rename from crates/koinon/tests/smoke.rs rename to crates/stoicheion/tests/smoke.rs index 61219f3..da681b6 100644 --- a/crates/koinon/tests/smoke.rs +++ b/crates/stoicheion/tests/smoke.rs @@ -9,7 +9,7 @@ reason = "test code: panics and unwraps acceptable in assertions" )] -use koinon::{Coordinates, Frequency, Power, Timestamp}; +use stoicheion::{Coordinates, Frequency, Power, Timestamp}; #[test] fn frequency_roundtrip_mhz() { diff --git a/crates/syntonia/Cargo.toml b/crates/syntonia/Cargo.toml index 1596879..49ec9be 100644 --- a/crates/syntonia/Cargo.toml +++ b/crates/syntonia/Cargo.toml @@ -11,7 +11,7 @@ license.workspace = true hardware-serial = ["dep:serialport"] [dependencies] -koinon = { path = "../koinon" } +stoicheion = { path = "../stoicheion" } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } toml = { workspace = true } diff --git a/crates/syntonia/src/baofeng/codec.rs b/crates/syntonia/src/baofeng/codec.rs index 183c195..850521c 100644 --- a/crates/syntonia/src/baofeng/codec.rs +++ b/crates/syntonia/src/baofeng/codec.rs @@ -1,7 +1,7 @@ //! Channel encode/decode between raw EEPROM bytes and the Channel model. -use koinon::Frequency; use snafu::Snafu; +use stoicheion::Frequency; use crate::baofeng::bcd::{self, BcdError}; use crate::baofeng::image::MemoryImage; diff --git a/crates/syntonia/src/channel.rs b/crates/syntonia/src/channel.rs index b7a25e9..616e1a1 100644 --- a/crates/syntonia/src/channel.rs +++ b/crates/syntonia/src/channel.rs @@ -1,7 +1,7 @@ //! Radio channel data model. -use koinon::Frequency; use serde::{Deserialize, Serialize}; +use stoicheion::Frequency; use crate::tone::ToneMode; use crate::types::{Bandwidth, FrequencyOffset, PowerLevel, ScanMode}; diff --git a/crates/syntonia/src/export/csv.rs b/crates/syntonia/src/export/csv.rs index 8192e31..ec96061 100644 --- a/crates/syntonia/src/export/csv.rs +++ b/crates/syntonia/src/export/csv.rs @@ -171,7 +171,7 @@ fn channel_to_record(ch: &Channel) -> [String; 19] { reason = "test code: panics and unwraps acceptable in assertions" )] mod tests { - use koinon::Frequency; + use stoicheion::Frequency; use super::*; use crate::import::csv::import_chirp_csv_reader; diff --git a/crates/syntonia/src/hardware/detect.rs b/crates/syntonia/src/hardware/detect.rs index e204524..800b0ba 100644 --- a/crates/syntonia/src/hardware/detect.rs +++ b/crates/syntonia/src/hardware/detect.rs @@ -3,8 +3,8 @@ use std::io::{self, Read, Write}; use std::time::Duration; -use koinon::RadioKind; use snafu::{ResultExt, Snafu}; +use stoicheion::RadioKind; use crate::baofeng::variant::{ BF_F8HP_PREFIXES, MAGIC_UV5R_PROBE, UV5R_PREFIXES, UV5RM_PLUS_PREFIXES, diff --git a/crates/syntonia/src/hardware/warnings.rs b/crates/syntonia/src/hardware/warnings.rs index fd0c9ea..800bf8c 100644 --- a/crates/syntonia/src/hardware/warnings.rs +++ b/crates/syntonia/src/hardware/warnings.rs @@ -204,7 +204,7 @@ mod tests { #[test] fn multiple_radios_generates_warning() { - use koinon::RadioKind; + use stoicheion::RadioKind; use crate::hardware::detect::{RadioIdent, VariantConfig}; @@ -244,7 +244,7 @@ mod tests { #[test] fn single_radio_generates_no_detection_warning() { - use koinon::RadioKind; + use stoicheion::RadioKind; use crate::hardware::detect::{RadioIdent, VariantConfig}; diff --git a/crates/syntonia/src/import/csv.rs b/crates/syntonia/src/import/csv.rs index 601ba39..937b52f 100644 --- a/crates/syntonia/src/import/csv.rs +++ b/crates/syntonia/src/import/csv.rs @@ -3,8 +3,8 @@ use std::io::Read; use std::path::Path; -use koinon::Frequency; use snafu::{ResultExt, Snafu}; +use stoicheion::Frequency; use crate::channel::Channel; use crate::plan::FrequencyPlan; diff --git a/crates/syntonia/src/import/img.rs b/crates/syntonia/src/import/img.rs index b70ae06..57d16d1 100644 --- a/crates/syntonia/src/import/img.rs +++ b/crates/syntonia/src/import/img.rs @@ -109,7 +109,7 @@ pub fn import_img_bytes(data: &[u8]) -> Result { reason = "test code: panics and unwraps acceptable in assertions" )] mod tests { - use koinon::Frequency; + use stoicheion::Frequency; use super::*; use crate::baofeng::codec; diff --git a/crates/syntonia/src/plan.rs b/crates/syntonia/src/plan.rs index 4d37758..bd115b6 100644 --- a/crates/syntonia/src/plan.rs +++ b/crates/syntonia/src/plan.rs @@ -80,7 +80,7 @@ impl FrequencyPlan { reason = "test code: panics and unwraps acceptable in assertions" )] mod tests { - use koinon::Frequency; + use stoicheion::Frequency; use super::*; use crate::tone::ToneMode; diff --git a/crates/syntonia/src/types.rs b/crates/syntonia/src/types.rs index f052aa4..d26315c 100644 --- a/crates/syntonia/src/types.rs +++ b/crates/syntonia/src/types.rs @@ -1,7 +1,7 @@ //! Supporting types for channel configuration. -use koinon::Frequency; use serde::{Deserialize, Serialize}; +use stoicheion::Frequency; /// Frequency offset configuration for repeater operation. #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] diff --git a/crates/syntonia/src/validate.rs b/crates/syntonia/src/validate.rs index ba6fde4..67d7b67 100644 --- a/crates/syntonia/src/validate.rs +++ b/crates/syntonia/src/validate.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; -use koinon::Frequency; +use stoicheion::Frequency; use crate::channel::Channel; use crate::plan::FrequencyPlan; diff --git a/crates/syntonia/src/yaesu/codec.rs b/crates/syntonia/src/yaesu/codec.rs index 83dcbc9..87ff2c1 100644 --- a/crates/syntonia/src/yaesu/codec.rs +++ b/crates/syntonia/src/yaesu/codec.rs @@ -107,7 +107,7 @@ mod tests { let channel = Channel { index: 0, name: String::new(), - rx_freq: koinon::Frequency::mhz(146), + rx_freq: stoicheion::Frequency::mhz(146), tx_freq: None, offset: crate::types::FrequencyOffset::None, tone: crate::tone::ToneMode::None, diff --git a/crates/syntonia/src/yaesu/variant.rs b/crates/syntonia/src/yaesu/variant.rs index 6349d26..2e3c2a9 100644 --- a/crates/syntonia/src/yaesu/variant.rs +++ b/crates/syntonia/src/yaesu/variant.rs @@ -4,7 +4,7 @@ //! — see this module's parent (`super`) for the derivation's licence and //! upstream. The clone-mode protocol itself is not yet documented. -use koinon::Frequency; +use stoicheion::Frequency; use crate::validate::RadioConstraints; diff --git a/crates/koinon/Cargo.toml b/crates/tekmerion/Cargo.toml similarity index 75% rename from crates/koinon/Cargo.toml rename to crates/tekmerion/Cargo.toml index aad6e6a..e86bf31 100644 --- a/crates/koinon/Cargo.toml +++ b/crates/tekmerion/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "koinon" -description = "κοινόν — common/shared types for the Akroasis workspace" +name = "tekmerion" +description = "τεκμήριον — conclusive evidence: tamper-evident log, caller authority, effect receipts" version.workspace = true edition.workspace = true rust-version.workspace = true @@ -8,23 +8,23 @@ license.workspace = true repository.workspace = true [dependencies] -ulid.workspace = true +blake3.workspace = true +ciborium.workspace = true +compact_str.workspace = true +fs2.workspace = true jiff.workspace = true serde.workspace = true serde_json.workspace = true snafu.workspace = true +stoicheion = { path = "../stoicheion" } +subtle.workspace = true tracing.workspace = true -compact_str.workspace = true -blake3.workspace = true -ciborium.workspace = true zeroize.workspace = true -subtle.workspace = true -fs2.workspace = true [dev-dependencies] tempfile.workspace = true -proptest = "1" toml.workspace = true +ulid.workspace = true [lints] workspace = true diff --git a/crates/koinon/src/caller.rs b/crates/tekmerion/src/caller.rs similarity index 99% rename from crates/koinon/src/caller.rs rename to crates/tekmerion/src/caller.rs index 4ee923f..3ac8a2a 100644 --- a/crates/koinon/src/caller.rs +++ b/crates/tekmerion/src/caller.rs @@ -10,7 +10,6 @@ use std::fmt; use serde::{Deserialize, Serialize}; use snafu::{OptionExt, ensure}; -use crate::Timestamp; pub use crate::caller_error::CallerContractError; use crate::caller_error::{ AuthorityUnavailableSnafu, ExpiredSnafu, IdentityReferenceMismatchSnafu, @@ -23,6 +22,7 @@ pub use crate::caller_ref::{ CallerRef, CapabilityRef, EffectRef, EvidenceDigest, PersonaRef, PolicyEpoch, ReceiptDigest, SchemaEpoch, ScopeRef, }; +use stoicheion::Timestamp; /// Caller-context schema version understood by this crate. pub const CALLER_CONTEXT_VERSION: u16 = 1; diff --git a/crates/koinon/src/caller_error.rs b/crates/tekmerion/src/caller_error.rs similarity index 100% rename from crates/koinon/src/caller_error.rs rename to crates/tekmerion/src/caller_error.rs diff --git a/crates/koinon/src/caller_ref.rs b/crates/tekmerion/src/caller_ref.rs similarity index 100% rename from crates/koinon/src/caller_ref.rs rename to crates/tekmerion/src/caller_ref.rs diff --git a/crates/koinon/src/effect_receipt.rs b/crates/tekmerion/src/effect_receipt.rs similarity index 99% rename from crates/koinon/src/effect_receipt.rs rename to crates/tekmerion/src/effect_receipt.rs index b793ab9..22cd5e3 100644 --- a/crates/koinon/src/effect_receipt.rs +++ b/crates/tekmerion/src/effect_receipt.rs @@ -7,12 +7,12 @@ use serde::{Deserialize, Deserializer, Serialize}; use snafu::Snafu; -use crate::Timestamp; use crate::caller::{ AuthorizedCaller, CallerRef, CapabilityRef, EffectRef, EvidenceDigest, PolicyEpoch, ReceiptDigest, SchemaEpoch, }; use crate::effect_receipt_state::{PendingIntent, RecoveryAuthorization}; +use stoicheion::Timestamp; /// Current serialized effect-receipt schema version. pub const EFFECT_RECEIPT_VERSION: u16 = 1; diff --git a/crates/koinon/src/effect_receipt_state.rs b/crates/tekmerion/src/effect_receipt_state.rs similarity index 99% rename from crates/koinon/src/effect_receipt_state.rs rename to crates/tekmerion/src/effect_receipt_state.rs index 2f5163e..5ac0d85 100644 --- a/crates/koinon/src/effect_receipt_state.rs +++ b/crates/tekmerion/src/effect_receipt_state.rs @@ -2,12 +2,12 @@ use snafu::Snafu; -use crate::Timestamp; use crate::caller::{EffectRef, EvidenceDigest, ReceiptDigest, SchemaEpoch}; use crate::effect_receipt::{ EffectDescriptor, EffectOutcome, EffectReceipt, EffectReceiptError, ReceiptEvent, RecoveryRelation, }; +use stoicheion::Timestamp; /// Append-only application ledger for minimized effect receipts. /// diff --git a/crates/koinon/src/lib.rs b/crates/tekmerion/src/lib.rs similarity index 60% rename from crates/koinon/src/lib.rs rename to crates/tekmerion/src/lib.rs index 582ee05..987d28f 100644 --- a/crates/koinon/src/lib.rs +++ b/crates/tekmerion/src/lib.rs @@ -1,24 +1,29 @@ -//! κοινόν — shared foundational types for the Akroasis workspace. +//! τεκμήριον — conclusive evidence about what the system observed and did. +//! +//! Aristotle separates a *semeion*, a sign that suggests, from a *tekmerion*, +//! a proof that settles. This crate holds the second kind: the tamper-evident +//! log and its keyed hash chain, the authority a caller actually carries, and +//! the receipts an effect leaves behind. Each of them answers "can this be +//! shown?" rather than "what is this?". +//! +//! The distinction is load-bearing rather than decorative. `semaino` produces +//! signals — indications, which may be wrong. Everything here produces records +//! that can be checked against a key, and refuses to report a claim it cannot +//! substantiate. +//! +//! Built on `stoicheion`, which supplies the vocabulary these records are +//! written in. The dependency runs one way: evidence knows what a timestamp +//! and an entity are; the elements know nothing of evidence. #![deny(missing_docs)] -pub mod baseline; pub mod caller; mod caller_error; mod caller_ref; -pub mod coordinates; pub mod effect_receipt; mod effect_receipt_state; -pub mod entity; -pub mod frequency; -pub mod hardware; -pub mod id; -pub mod power; -pub mod signal; pub mod tamper_log; -pub mod timestamp; -pub use baseline::{AnomalyScore, Baseline, ScoringConfig, TemporalBucketedBaseline}; pub use caller::{ AuthorityClaims, AuthorityClaimsBuilder, AuthorityDecision, AuthorityGrant, AuthorizationDenial, AuthorizationRequirement, AuthorizedCaller, CALLER_CONTEXT_VERSION, @@ -27,7 +32,6 @@ pub use caller::{ PrincipalSource, ReceiptDigest, RevocationState, SchemaEpoch, ScopeRef, TrustState, ValidatedCaller, authorize_caller, }; -pub use coordinates::{Coordinates, CoordinatesError, Datum}; pub use effect_receipt::{ EFFECT_RECEIPT_VERSION, EffectDescriptor, EffectOutcome, EffectReceipt, EffectReceiptError, ReceiptContext, ReceiptEvent, RecoveryRelation, ValidatedReceiptLink, @@ -36,19 +40,9 @@ pub use effect_receipt_state::{ EffectReceiptSink, OutcomeAppendError, PendingIntent, PendingOutcome, PersistedIntent, PersistedOutcome, ReceiptTransitionError, RecoveryAuthorization, RecoveryTicket, }; -pub use entity::{Entity, EntityKind}; -pub use frequency::Frequency; -pub use hardware::{ - AssetRegistry, AssetStatus, ConnectionType, HardwareAsset, HardwareKind, KNOWN_USB_DEVICES, - KnownUsbDevice, MeshNodeKind, RadioKind, RegistryError, SdrKind, UsbId, lookup_usb_device, -}; -pub use id::{DeviceId, EntityId, FrequencyId, SignalId}; -pub use power::Power; -pub use signal::{Confidence, GeoSignal, SignalKind}; pub use tamper_log::{ CHAIN_KEY_LEN, ChainKey, ChainStatus, DEFAULT_MAX_FILE_BYTES, KEY_ID_LEN, LogEntry, LogEntryKind, MAX_ENTRY_BYTES, SegmentChainStatus, TIP_SIGNATURE_LEN, TamperLog, TamperLogConfig, TamperLogError, TipProvenance, TipSigner, TipStatus, TipVerifier, VerificationResult, verify_chain, verify_segment_chain, verify_tip_provenance, }; -pub use timestamp::{Timestamp, TimestampError}; diff --git a/crates/koinon/src/tamper_log.rs b/crates/tekmerion/src/tamper_log.rs similarity index 100% rename from crates/koinon/src/tamper_log.rs rename to crates/tekmerion/src/tamper_log.rs diff --git a/crates/koinon/src/tamper_log_codec_tests.rs b/crates/tekmerion/src/tamper_log_codec_tests.rs similarity index 100% rename from crates/koinon/src/tamper_log_codec_tests.rs rename to crates/tekmerion/src/tamper_log_codec_tests.rs diff --git a/crates/koinon/src/tamper_log_entry.rs b/crates/tekmerion/src/tamper_log_entry.rs similarity index 99% rename from crates/koinon/src/tamper_log_entry.rs rename to crates/tekmerion/src/tamper_log_entry.rs index 1b93f23..8f85a0f 100644 --- a/crates/koinon/src/tamper_log_entry.rs +++ b/crates/tekmerion/src/tamper_log_entry.rs @@ -3,7 +3,7 @@ use compact_str::CompactString; use serde::{Deserialize, Serialize}; -use crate::{EntityId, SignalId}; +use stoicheion::{EntityId, SignalId}; /// The kind of event recorded in a [`crate::tamper_log::LogEntry`]. #[non_exhaustive] diff --git a/crates/koinon/src/tamper_log_lock.rs b/crates/tekmerion/src/tamper_log_lock.rs similarity index 100% rename from crates/koinon/src/tamper_log_lock.rs rename to crates/tekmerion/src/tamper_log_lock.rs diff --git a/crates/koinon/src/tamper_log_recovery_tests.rs b/crates/tekmerion/src/tamper_log_recovery_tests.rs similarity index 100% rename from crates/koinon/src/tamper_log_recovery_tests.rs rename to crates/tekmerion/src/tamper_log_recovery_tests.rs diff --git a/crates/koinon/src/tamper_log_rotation.rs b/crates/tekmerion/src/tamper_log_rotation.rs similarity index 100% rename from crates/koinon/src/tamper_log_rotation.rs rename to crates/tekmerion/src/tamper_log_rotation.rs diff --git a/crates/koinon/src/tamper_log_seal.rs b/crates/tekmerion/src/tamper_log_seal.rs similarity index 98% rename from crates/koinon/src/tamper_log_seal.rs rename to crates/tekmerion/src/tamper_log_seal.rs index 1d88882..9446f7f 100644 --- a/crates/koinon/src/tamper_log_seal.rs +++ b/crates/tekmerion/src/tamper_log_seal.rs @@ -41,6 +41,17 @@ use super::{IoSnafu, TamperLogError}; pub const CHAIN_KEY_LEN: usize = 32; /// Domain-separation tag for the keyed genesis root. +// WARNING: the four domain separators below still read `koinon/...` after this +// crate was renamed to `tekmerion`, and they must. They are not names — they +// are keyed-hash inputs. `GENESIS_DOMAIN` seeds every chain's root hash and the +// seal domains key every MAC, so changing one byte re-roots the chain and +// invalidates every tamper log already on disk: existing logs would verify as +// broken, which is indistinguishable from the tampering the log exists to +// detect. +// +// A rename that "finishes the job" here is a silent, unrecoverable break. If a +// domain ever must change, it changes as a versioned migration with a reader +// that accepts both, never as a search-and-replace. const GENESIS_DOMAIN: &[u8] = b"koinon/tamper-log/genesis/v1"; /// Domain-separation tag for the seal MAC. diff --git a/crates/koinon/src/tamper_log_segments.rs b/crates/tekmerion/src/tamper_log_segments.rs similarity index 100% rename from crates/koinon/src/tamper_log_segments.rs rename to crates/tekmerion/src/tamper_log_segments.rs diff --git a/crates/koinon/src/tamper_log_tests.rs b/crates/tekmerion/src/tamper_log_tests.rs similarity index 99% rename from crates/koinon/src/tamper_log_tests.rs rename to crates/tekmerion/src/tamper_log_tests.rs index d3357bb..a887752 100644 --- a/crates/koinon/src/tamper_log_tests.rs +++ b/crates/tekmerion/src/tamper_log_tests.rs @@ -5,7 +5,7 @@ use compact_str::CompactString; use ulid::Ulid; use super::*; -use crate::{EntityId, SignalId}; +use stoicheion::{EntityId, SignalId}; fn test_key() -> ChainKey { ChainKey::from_bytes([0x5A; CHAIN_KEY_LEN]) diff --git a/crates/koinon/src/tamper_log_verify.rs b/crates/tekmerion/src/tamper_log_verify.rs similarity index 100% rename from crates/koinon/src/tamper_log_verify.rs rename to crates/tekmerion/src/tamper_log_verify.rs