root 9cc0ceb894
Some checks failed
lakehouse/auditor 1 blocking issue: cloud: claim not backed — "journal event verified live (total_events_created 0→1 after probe)."
P42-002: wire truth gate into queryd /sql + /paged SQL paths
The scrum master flagged crates/queryd/src/service.rs across iters 3-5
with the same finding: "raw SQL forwarded to DataFusion without schema
or policy gate; violates PRD §42-002 truth enforcement." Confidence
79-95%, gradient tier auto/dry_run. Applier couldn't touch it — the fix
is larger than 6 lines and crosses crate boundaries.

Hand-fix lands the missing enforcement point:

  - truth: new RuleCondition::FieldContainsAny { field, needles } with
    case-insensitive substring matching. 4 new unit tests cover the
    positive, negative, missing-field, and empty-needles paths.
  - truth: sql_query_guard_store() helper returns a baseline store that
    rejects destructive verbs (DROP/TRUNCATE/DELETE FROM) and empty SQL.
  - queryd: QueryState grows an Arc<TruthStore>; default router() loads
    sql_query_guard_store; new router_with_truth(engine, store) lets
    tests inject a custom store.
  - queryd: sql_policy_check() runs truth.evaluate("sql_query", ctx)
    before hitting DataFusion. Reject/Block actions on matched
    conditions short-circuit to HTTP 403 with the rule's message.
    Both /sql and /paged gated.
  - queryd: 7 new tests cover block/allow/case-insensitive/false-
    positive scenarios. "SELECT deleted_at FROM t" must NOT be rejected
    (substring match is narrow: "delete from", not "delete").

Total: 28 truth tests green (was 24), 7 new queryd policy tests green.
Workspace baseline warnings unchanged at 11.

This is a signal-driven fix the mechanical pipeline couldn't produce
but the scrum master kept asking for. Closes one of four LOOPING files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 04:38:52 -05:00

24 lines
609 B
TOML

[package]
name = "queryd"
version = "0.1.0"
edition = "2024"
[dependencies]
shared = { path = "../shared" }
catalogd = { path = "../catalogd" }
storaged = { path = "../storaged" }
truth = { path = "../truth" }
tokio = { workspace = true }
axum = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
tracing = { workspace = true }
datafusion = { workspace = true }
object_store = { workspace = true }
arrow = { workspace = true }
parquet = { workspace = true }
bytes = { workspace = true }
futures = { workspace = true }
url = { workspace = true }
chrono = { workspace = true }