105 lines
6 KiB
JSON
105 lines
6 KiB
JSON
{
|
|
"alternatives_considered": [
|
|
{
|
|
"option": "Generic LLM without schema grounding (GitHub Copilot style)",
|
|
"why_rejected": "Generates syntactically valid but semantically wrong configs — wrong enum values, missing required fields, invalid option combinations. Schema validation must happen after generation and frequently fails."
|
|
},
|
|
{
|
|
"option": "Fine-tuned model on project schemas",
|
|
"why_rejected": "Fine-tuning is expensive, requires retraining on every schema change, and does not generalize across projects. RAG is dynamic and always reflects the current schema state."
|
|
}
|
|
],
|
|
"consequences": {
|
|
"negative": [
|
|
"RAG index must be kept current as schemas and docs evolve — stale index degrades answer quality",
|
|
"ai-service adds a service dependency for all AI-assisted operations",
|
|
"Cost tracking required: rate limiting at 60 req/min, 1M tokens/day, $100/day"
|
|
],
|
|
"positive": [
|
|
"AI cannot generate configs that fail Nickel schema validation — structural correctness enforced",
|
|
"Cedar prevents AI from accessing secrets or deploying without human approval",
|
|
"RAG over project artifacts reduces hallucination on project-specific options",
|
|
"MCP tool calling (nickel_validate, schema_query) enables LLM agents to self-correct"
|
|
]
|
|
},
|
|
"constraints": [
|
|
{
|
|
"check": {
|
|
"must_be_empty": false,
|
|
"paths": [
|
|
"platform/"
|
|
],
|
|
"pattern": "ai-service.*Secret|Secret.*ai-service",
|
|
"tag": "Grep"
|
|
},
|
|
"claim": "ai-service must have a Cedar policy explicitly forbidding access to any Secret resource",
|
|
"id": "ai-cannot-access-secrets",
|
|
"rationale": "AI agents with secret access create unaudited credential exposure. The constraint must be at the authorization layer, not in the LLM prompt.",
|
|
"scope": "platform/crates/control-center/src/policies/",
|
|
"severity": "Hard"
|
|
},
|
|
{
|
|
"check": {
|
|
"must_be_empty": false,
|
|
"paths": [
|
|
"platform/"
|
|
],
|
|
"pattern": "human_approved",
|
|
"tag": "Grep"
|
|
},
|
|
"claim": "Any deployment action triggered by ai-service must have context.human_approved == true in the Cedar evaluation context",
|
|
"id": "ai-deployment-requires-human-approval",
|
|
"rationale": "Autonomous deployment without human review is an unacceptable risk for production infrastructure. The approval gate is enforced by Cedar, not by AI self-restraint.",
|
|
"scope": "platform/crates/orchestrator/src/",
|
|
"severity": "Hard"
|
|
},
|
|
{
|
|
"check": {
|
|
"must_be_empty": false,
|
|
"paths": [
|
|
"platform/crates/ai-service/"
|
|
],
|
|
"pattern": "nickel.*export|nickel_validate",
|
|
"tag": "Grep"
|
|
},
|
|
"claim": "All AI-generated Nickel configs must be validated via nickel export before being presented to the user or submitted to the orchestrator",
|
|
"id": "ai-generation-validates-against-schema",
|
|
"rationale": "Post-generation validation closes the loop — if the LLM generates an invalid config despite schema grounding, the user sees a validation error, not a deployment failure.",
|
|
"scope": "platform/crates/ai-service/src/",
|
|
"severity": "Hard"
|
|
}
|
|
],
|
|
"context": "Infrastructure configuration generation via LLM is unreliable without grounding: generic AI produces plausible but structurally invalid configs (wrong field names, invalid enum values, incompatible option combinations). Two risks: (1) hallucination — AI generates configs that fail schema validation; (2) security — AI agents with unrestricted access to secrets and deployment operations create unaudited paths. The platform has Nickel schemas for all configuration surfaces and Cedar for authorization — both can be used to constrain AI behavior.",
|
|
"date": "2026-01-08",
|
|
"decision": "AI config generation is constrained by Nickel schemas at generation time and by Cedar policies at authorization time. The ai-service is the HTTP entry point for all AI operations. RAG indexes Nickel schemas, documentation, and past deployments as retrieval context — AI generates WITH schema context, making hallucination structurally harder. Cedar policy forbids ai-service from accessing any secret and requires `context.human_approved == true` before any deployment operation. The mcp-server exposes tool calling (nickel_validate, schema_query, best_practices) to LLM agents.",
|
|
"id": "adr-019",
|
|
"ontology_check": {
|
|
"decision_string": "AI config generation is constrained by Nickel schemas (RAG grounding) and Cedar policies (secret isolation, human approval gate)",
|
|
"invariants_at_risk": [
|
|
"solid-boundaries",
|
|
"type-safety-nickel"
|
|
],
|
|
"verdict": "Safe"
|
|
},
|
|
"rationale": [
|
|
{
|
|
"claim": "Schema-constrained generation eliminates invalid config hallucination",
|
|
"detail": "Generic LLMs generate `engine = 'postgresql'` when the contract says `engine | [| 'postgres, 'mysql |]`. Providing the schema as RAG context gives the model the exact valid values. Post-generation nickel export validates the output against the same contract."
|
|
},
|
|
{
|
|
"claim": "Cedar is the enforcement layer — not prompt engineering",
|
|
"detail": "Prompting AI to 'not access secrets' is not a security boundary. Cedar policy `forbid(principal == Service::\"ai-service\", action == Action::\"read\", resource in Secret::\"*\")` is enforced at the platform layer regardless of what the LLM requests."
|
|
},
|
|
{
|
|
"claim": "RAG over project artifacts is more accurate than generic LLM for project-specific configs",
|
|
"detail": "Indexing `schemas/`, `docs/`, and past successful deployments means AI answers are grounded in actual project patterns — not generic infrastructure knowledge that may conflict with project constraints."
|
|
}
|
|
],
|
|
"related_adrs": [
|
|
"adr-014-solid-enforcement",
|
|
"adr-017-typedialog-web-ui",
|
|
"adr-018-secretumvault-integration"
|
|
],
|
|
"status": "Accepted",
|
|
"title": "Schema-Aware AI and RAG — Nickel Contracts Constrain AI Config Generation"
|
|
}
|