provisioning-code/.ncl-cache/1e445f966234e94f0f1dcc434df661e4963dd446bba279df6886e7ae667df3e0.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"
}