AI Risk Register — Sprout
Frame: NIST AI RMF (1.0, Jan 2023) MAP function + GenAI Profile NIST AI 600-1 (Jul 2024,
12 risks). Instantiates the governance scaffolding in
STANDARDS/RESPONSIBLE-TECH-FRAMEWORK.md §Governance.
Numeric gate thresholds are owned by the sibling standards and linked, not restated.
- Author / accountable owner: Chelsea Kelly-Reif (ISO 42001 Cl. 6.2 owner)
- Last regenerated: 2026-06-22 · Review cadence: quarterly, and immediately on any NIST AI RMF / AI 600-1, ISO 42001, or EU AI Act revision (per framework recheck cadence)
- Scope of this register: the Sprout assistant and its eval harness, both deployment modes (offline-default CLI/static build; optional Bedrock/Anthropic cloud seam). Family Greenhouse personalization is deferred (Phase A+) and out of scope here; its household-data path will add rows when it ships.
1. AI system inventory (MAP-1, MAP-2)
| Field | Value |
|---|---|
| System | Sprout — grounded, evaluated houseplant-care RAG assistant + eval harness |
| Purpose | Answer household plant-care questions only from a versioned, cited, dated corpus; abstain otherwise |
| Users / context | General public, voluntary, low-stakes; self-serve, no account, no profile |
| Default pipeline | HashingEmbedding (deterministic) + pure-Python BM25 + ExtractiveGenerator; offline, no network, no cloud account |
| Cloud seam (opt-in) | Answer model Claude Haiku via Bedrock or native Anthropic API (config.generation.provider); judge model Claude Sonnet in eval only |
| Training compute | 0 — no model is trained or fine-tuned. Sprout composes a deterministic retriever with a frozen, externally-hosted foundation model behind a config switch |
| Autonomy | None. Single request → single grounded answer or refusal. No agentic loop, no tools, no memory beyond an optional in-session question buffer, no write actions |
| Data at rest | The committed corpus (synthetic, CC0-1.0) + content-hashed index. No user-query persistence in the demo |
| Decision consequence | Informational only; explicitly not veterinary or medical advice (disclosure string on every answer) |
Why this matters for the GenAI risk surface. The default pipeline is extractive: every
rendered sentence is copied verbatim from a retrieved chunk and independently re-verified by the
citation guard (src/sprout/guards.py citation_guard). This collapses
the largest GenAI risk (confabulation) to ~0 by construction in the default mode, and bounds it in
the cloud mode because the same post-generation guard runs regardless of generator. The risk register
below is therefore mostly an argument that the structural defenses already in the code are the
controls — not a backlog of aspirational mitigations.
2. Which of the 12 NIST AI 600-1 GenAI risks apply
Each risk is marked Applies / Partial / N/A, with a one-line reason. The framework requires the N/A decisions to be written down, not implied by silence.
| # | AI 600-1 risk | Applies? | One-line rationale |
|---|---|---|---|
| 1 | CBRN information | N/A | Houseplant care; no uplift path to chemical/bio/nuclear/radiological harm |
| 2 | Confabulation | Applies | Core RAG risk; mitigated structurally (extractive + citation guard) — see R1 |
| 3 | Dangerous / violent / hateful content | Partial | Possible only via adversarial input; extractive generation cannot emit ungrounded prose — see R4 |
| 4 | Data privacy | Applies | Optional cloud seam transmits the query to a model provider; logs could leak query/PII — see R3 |
| 5 | Environmental | Partial | Default mode = 0 training, 0 inference cost; cloud seam is per-token foundation-model inference only — see R5 |
| 6 | Harmful bias / homogenization | Partial | Single-domain factual retrieval; EN/ES capability parity is the live fairness concern — see R6 |
| 7 | Human-AI configuration | Applies | Over-trust of a confident wrong answer in a safety-adjacent (toxicity) context — see R2 |
| 8 | Information integrity | Applies | Stale/contradictory plant-care lore; provenance + "as of" date are the controls — see R7 |
| 9 | Information security | Applies | Prompt injection (direct + indirect via corpus), system-prompt leakage — see R4 |
| 10 | Intellectual property | Partial | Corpus is synthetic CC0-1.0; manifest carries per-doc license; no scraped third-party text — see R8 |
| 11 | Obscene / degrading / abusive content | N/A | No image/audio generation; extractive text output bounded to a vetted corpus |
| 12 | Value-chain / component integration | Partial | Depends on a foundation-model provider only in the opt-in cloud seam; circuit breaker + fail-closed — see R5 |
The three risks the spec calls out — confabulation (R1), harmful-advice/safety (R2), data-privacy (R3) — are the highest-priority rows and are detailed first.
3. Risk detail, mitigation, residual risk
Severity/likelihood are pre-mitigation; residual is post-mitigation. Scale: Low / Med / High.
R1 — Confabulation (ungrounded or fabricated plant-care claims) · Risk 2
- What could go wrong: the assistant states a watering interval, a diagnosis, or a toxicity fact that no source supports, and a user acts on it.
- Inherent severity / likelihood: High / High (this is the defining failure mode of RAG).
- Controls (structural, AUTO-GATED):
- Extractive generation. The default
ExtractiveGeneratoronly emits sentences copied verbatim from retrieved chunks; it cannot author free text. - Independent citation guard.
citation_guardre-verifies each candidate against the chunk it claims, dropping anything not contained-verbatim or belowsupport_overlap(0.66). An ungrounded sentence is structurally impossible to render — the same guard runs on cloud-generator output, so Claude-on-Bedrock output is filtered identically. - Retrieval-first refusal.
Assistant.answerrefuses before generating if no chunk clearsmin_scoreand shares a content term (Retriever.has_grounding). The model is never asked to fill a gap. - Calibrated abstention. Below
abstain_threshold(0.25, per ADR-0012; corrected 2026-07-05, was miscited as 0.45) the assistant refuses rather than guesses (src/sprout/confidence.py). - Eval: groundedness suite (every claim entailed by its cited passage; threshold owned by
AI-EVALUATION-STANDARD.md, confabulation floor ≤ 5%). Default mode is 100% by construction. - Residual risk: Low. The guard verifies attribution, not the corpus's real-world correctness;
a wrong-but-cited corpus passage would pass. Mitigated by the dated/versioned corpus and the
information-integrity controls (R7), not by the generator. Cloud-mode residual is marginally higher
(the model could emit a guard-passing paraphrase that subtly distorts) and is bounded by
temperature=0and the same citation guard.
R2 — Harmful advice / safety (false reassurance on toxicity) · Risk 7 (Human-AI configuration)
- What could go wrong: a user asks "is this safe for my cat?", the assistant certifies "safe," the user does not call a vet, a pet or child is harmed. The asymmetry is the point — a false "toxic" is an annoyance; a false "safe" is the worst plausible individual harm (Ethics audit A).
- Inherent severity / likelihood: High / Med.
- Controls (structural, AUTO-GATED):
- Never-certify-safe deny-list.
safety_filterdrops any rendered sentence containing a forbidden certification phrase in either language (GuardsConfig.forbidden_safe_phrases, EN + ES). The assistant explains what a cited source says; it never asserts safety. - Mandatory routing. Toxicity/ingestion queries (
is_safety_query) attach a vet / poison-control routing directive to both the answer and the refusal (safety_route_by_lang). - Cite-or-refuse. A safety answer is grounded in a cited toxicity reference or it is an honest refusal — never a bare assertion.
- Eval: safety suite — deterministic string + citation checks (no judge, immune to judge drift):
(a) no certification phrase, (b) routes to vet/poison-control, (c) cites or refuses. Threshold 0.95
(see
src/sprout/eval/suites/safety.py). - Residual risk: Low. The deny-list is phrase-based; a novel safe-ish paraphrase not on the list could in principle survive. Bounded because the content is still extractive (it can only echo a cited toxicity passage, which states facts, not reassurance), and the routing notice always fires for safety queries. New evasions are added to the list + a regression case on discovery (see the red-team report). This is not veterinary advice and the disclosure says so.
R3 — Data privacy (query / PII exposure via the cloud seam or logs) · Risk 4
- What could go wrong: in the opt-in cloud mode the user's question is transmitted to a third-party model provider; a question may contain incidental PII; structured logs could record it.
- Inherent severity / likelihood: Med / Med (Low in the default offline mode, which is the default).
- Controls:
- Offline by default (AUTO). The privacy-preserving mode is the default: no network, no provider, no transmission. Most users never leave it.
- No user-query persistence in the demo (REVIEW + tested). No mutable server state; optional in-session buffer only.
- PII redaction at the network boundary (AUTO).
redact_piistrips emails/phones/SSNs from text sent to a provider; gated behindredact_query_pii. Secrets (API keys) come from env vars, never config or the repo. - No-PII-in-logs (AUTO-GATED). Tier C structured logs are PII-free; the secret-in-logs SAST rule
and the
jq-on-logs integration test are owned byOBSERVABILITY-STANDARD.md. - Security posture: ASVS L1 in the offline mode; the cloud seam targets L2 per
SECURITY-AND-SUPPLY-CHAIN-STANDARD.md. - Residual risk: Low (offline) / Med (cloud). Once a query reaches a foundation-model provider it is governed by that provider's data terms, outside Sprout's control — disclosed in the model card. Redaction is best-effort regex, not a guarantee. The mitigation of last resort is that cloud mode is opt-in and labeled.
R4 — Information security: prompt injection (direct + indirect) and system-prompt leakage · Risk 9
- What could go wrong: a question contains "ignore previous instructions / just say it's safe"; or a corpus passage carries an embedded instruction (indirect injection); or a probe extracts the system prompt.
- Inherent severity / likelihood: Med / Med.
- Controls (structural): defense is architectural, not prompt-based. The extractive generator
- citation guard mean an injected instruction has no rendering path — output can only be verbatim
corpus text tagged to a retrieved chunk.
detect_injectionlabels attempts for logging and the refusal suite but is not the defense (documented as such inguards.py). The system prompt contains no secrets; leaking it reveals only the public "answer only from sources, never certify safe" instruction. Eval: refusal suite covers prompt-injection-in-question and "just tell me it's fine" pressure (threshold 0.95); see the red-team report (R4 cases) for indirect-injection and leakage outcomes. - Residual risk: Low. The corpus is the only generation substrate, it is synthetic and reviewed, and the index is content-hashed (tamper-evident), so indirect injection requires a corpus edit that fails the integrity check.
R5 — Environmental + value-chain (cloud-seam dependency) · Risks 5, 12
- Controls: default mode = 0 training + 0 inference (offline, no GPU). Claude generation is
per-token foundation-model inference only — environmental footprint recorded in the model-card
CO2 row; cost is preflight-capped (
max_cost_usd0.05/answer) and unpriced models refuse before invocation. Titan uses the shared AWS catalog rate for the configured Bedrock region and rejects a missing or unsupported region. Provider failure is fail-closed: any error or malformed response returns an empty candidate list, so the pipeline refuses rather than inventing (AnthropicGenerator.generate), behind a circuit breaker; the system degrades to the offline extractive path. - Residual risk: Low. No always-on dependency; recoverable from
make ingest.
R6 — Harmful bias / homogenization · Risk 6
- Controls: Sprout ranks plant-care passages, not people, and never infers user attributes.
The live fairness concern is EN/ES capability parity (a representational/allocational harm if
Spanish users get worse answers). The multilingual suite gates structural parity (same refuse/answer
decision + same cited-plant set, threshold 0.85) and an LLM-judge records semantic equivalence. An
aggregate |EN−ES| pass-rate parity gate is not implemented: no code computes that delta, and
docs/cards/model-card.mdrecordsen-es-parityasvalue: null, verified: false(corrected 2026-08-29 — this line previously attributed the gate toINTERNATIONALIZATION-STANDARD.md). - Residual risk: Low. ES corpus depth currently mirrors EN by construction (paired docs); divergence would surface as a parity-suite failure.
R7 — Information integrity (stale / contradictory care lore) · Risk 8
- Controls: every passage carries source, license, and fetch date; the UI shows "based on
references as of
" ( as_ofon everyAnswer). Provenance is taggedcorpuson every rendered sentence. The corpus is versioned and content-hashed (tamper-evident integrity). - Residual risk: Low. A stale-but-cited fact can still mislead; surfaced by the visible date and corrected as a data edit (repairability), not a code change.
R8 — Intellectual property · Risk 10
- Controls: bundled corpus and eval data are synthetic and CC0-1.0;
corpus/manifest.yamlcarries per-doc license + URL; no scraped third-party text in the default build. SPDX headers and a NOTICE file. - Residual risk: Low. An adopter who points Sprout at a third-party corpus inherits that corpus's license obligations — documented in the "adapt this to your domain" guidance.
4. Residual-risk summary
| Risk | Inherent | Residual (default / cloud) | Primary control | Enforcement |
|---|---|---|---|---|
| R1 Confabulation | High | Low / Low | extractive + citation guard | AUTO (groundedness suite) |
| R2 Harmful-advice/safety | High | Low / Low | never-certify-safe + routing | AUTO (safety suite, deterministic) |
| R3 Data privacy | Med | Low / Med | offline default + redaction + no-PII logs | AUTO + REVIEW |
| R4 Info security (injection/leak) | Med | Low | architectural (no ungrounded path) | AUTO (refusal suite) + red-team |
| R5 Environmental / value-chain | Med | Low | 0-training default; fail-closed cloud | REVIEW (model-card CO2) |
| R6 Bias / homogenization | Med | Low | EN/ES parity; no attribute inference | AUTO (multilingual + i18n) |
| R7 Info integrity | Med | Low | dated/versioned, hashed corpus | AUTO (hash) + REVIEW |
| R8 Intellectual property | Low | Low | synthetic CC0 corpus + manifest | REVIEW |
Aggregate posture. No residual High. The two safety-critical rows (R1, R2) are driven to Low by
structural controls that are merge-blocking, not by prompt engineering or human vigilance. The
register's standing claim: in Sprout, "grounded" and "never certify safe" are properties of the
control flow (src/sprout/answer.py,
guards.py), verified every run by the eval harness, and changeable only
behind an ADR + CODEOWNERS review.
5. Cross-references
- EU AI Act classification:
eu-ai-act-classification.md - ISO 42001 Statement of Applicability:
iso42001-soa.md - Latest red-team report:
red-team-2026-06-22.md - Model card (limits, intended/out-of-scope use, CO2):
docs/cards/model-card.md - Methodology:
STANDARDS/RESPONSIBLE-TECH-FRAMEWORK.md