Skip to main content

ADR-0009: Analyst — typed plan over an allowlisted semantic schema

Status: Accepted · 2026-07-14

Decision

Pipeline: question → intent parse → TypedQueryPlan (Zod) → server validation → authorization injection → cost/row/depth bounds → read-only compile → execute → answer composed only from returned rows.
  • The semantic schema exposes named entities (asset, container, finding, reviewCandidate, action, domainPosture) with allowlisted fields, filters, group-bys, and measures — never tables or SQL.
  • Two planners behind one interface: DeterministicPlanner (pattern-based, covers the canonical questions, used in tests) and AiPlanner (gateway task with Zod-validated output). Both produce the same TypedQueryPlan; the server treats plans from either source as untrusted and re-validates identically.
  • Tenant + domain-scope predicates are injected server-side from the authenticated session; the plan cannot set or widen them. Display values resolve to scoped internal IDs server-side.
  • Scanned content passed to any AI planner/summarizer is delimited as untrusted data; the model has no tools that mutate or fetch arbitrarily. Action drafting is a separate, explicitly-invoked tool that creates Draft actions only.
  • Every run audits question, plan, executed query descriptors, result-set IDs, template/model version, and answer reference.

Consequences

  • Answers cite evidence/assertion/result IDs, coverage, and freshness watermarks and are reproducible.
  • Injection tests: hostile content in fixtures attempts scope-widening, tool escape, and cross-domain reads; all must fail closed.