Wires the AuditPipeline's flush() path to QM's QuartermasterNotary gRPC service. Previously flush() only updated local notarized=true flags; now it batches pending leaf hashes into a CreateAnchorRequest and persists the returned anchor_id + leaf_index back on each event row. Lazy-retry semantics match guildhouse-spire-plugins pkg/governance (F.1): the gRPC channel is established on first successful flush and cached in Arc<Mutex<Option<QuartermasterNotaryClient<Channel>>>>. If QM is unreachable, bascule logs a warning, re-queues the leaves into the pending buffer, and retries on the next flush interval. Local audit rows are still written with notarized=true; only anchor_id stays NULL until an anchor successfully lands. This is the same pattern that unblocks the bascule-deploys-before-QM ordering problem without crashing bascule. Schema: bascule.audit_events already had anchor_id uuid + leaf_index integer columns (migrations.rs, pre-existing). This commit populates them for the first time. Config: - New `cluster_id` field on BasculeConfig, sourced from BASCULE_CLUSTER_ID env. Empty string disables QM submission (local storage only). In F.4, bascule gets the UUID from QM's clusters table (generated at QM genesis). - Existing `qm_endpoint` field now actually used (was scaffolded in pre-F.4 code but never read). Backwards-compat: - submit(&self, event: &AuditEvent, notarize: bool) signature preserved. - should_notarize(classification, fidelity) public fn preserved. - Internal leaf_data hashing simplified to an event-field digest (event_id + session_id + operator + command + classification + exec_result + timestamp); bypasses serde_json_canonicalizer dependency that the prior version required. Verify path still works against QM's merkle tree because QM hashes whatever bytes bascule submits — QM doesn't re-compute; it trusts the leaf payload bascule submitted is the leaf. Signed-off-by: Tyler J King <tking@guildhouse.dev>
75 lines
1.9 KiB
TOML
75 lines
1.9 KiB
TOML
[package]
|
|
name = "bascule-gateway"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
description = "Bascule governance gateway — cluster-side API gateway for governed access"
|
|
license = "Apache-2.0"
|
|
repository = "https://git.guildhouse.dev/guildhouse/bascule"
|
|
|
|
[[bin]]
|
|
name = "bascule-gateway"
|
|
path = "src/main.rs"
|
|
|
|
[dependencies]
|
|
bascule-core = { workspace = true }
|
|
bascule-proto = { workspace = true }
|
|
|
|
# Cross-workspace path deps — Guildhouse governance/ceremony primitives.
|
|
# Future: extract to standalone crates.
|
|
accord-core = { path = "../../guildhouse/services/accord-core" }
|
|
accord-opa = { path = "../../guildhouse/services/accord-opa" }
|
|
qm-core = { path = "../../guildhouse/services/qm-core" }
|
|
guildhouse-proto = { path = "../../guildhouse/services/guildhouse-proto" }
|
|
|
|
# Cross-workspace path dep — substrate governance types (for PostureLevel).
|
|
governance-types = { path = "../../substrate/crates/governance-types" }
|
|
|
|
# Kubernetes
|
|
kube = { workspace = true }
|
|
k8s-openapi = { workspace = true }
|
|
|
|
# gRPC
|
|
tonic = { workspace = true }
|
|
prost = { workspace = true }
|
|
prost-types = { workspace = true }
|
|
|
|
# Auth
|
|
jsonwebtoken = { workspace = true }
|
|
reqwest = { workspace = true }
|
|
|
|
# Database
|
|
sqlx = { workspace = true }
|
|
|
|
# Session cache
|
|
dashmap = { workspace = true }
|
|
|
|
# Async
|
|
tokio = { workspace = true }
|
|
async-trait = { workspace = true }
|
|
|
|
# Serialization
|
|
serde = { workspace = true }
|
|
serde_json = { workspace = true }
|
|
serde_json_canonicalizer = { workspace = true }
|
|
hex = { workspace = true }
|
|
sha2 = { workspace = true }
|
|
|
|
# Observability
|
|
tracing = { workspace = true }
|
|
tracing-subscriber = { workspace = true }
|
|
|
|
# HTTP (ceremony approval endpoints)
|
|
axum = { workspace = true }
|
|
tower-http = { workspace = true }
|
|
|
|
# Common
|
|
uuid = { workspace = true }
|
|
chrono = { workspace = true }
|
|
thiserror = { workspace = true }
|
|
anyhow = { workspace = true }
|
|
config = { workspace = true }
|
|
rustls = { workspace = true }
|
|
tokio-stream = "0.1"
|
|
|
|
[dev-dependencies]
|
|
tower = "0.5"
|