0d2cbdb423
Genericize forge-detection code: gitea→forge/generic_forge, GITEA_ACTOR→FORGE_ACTOR. Drop .gitea byte-identity test assertions (keep GitHub-side + contract conformance). Add test_no_forge_mentions.py guard test (REQ-230). Delete completed migration docs (NOVA_MIGRATION.md, NOVA_AWS_MIGRATION.md). Move NO_HUMANS_THESIS.md to .ciagent/ (internal artifact). Strip ciagent-internal provenance from synced docs (REQ-/D-/P-/CAP- IDs, milestone headers, .ciagent/PROJECT.md citations). Trim README.md (reusable deploy section, local key rotation paragraph). Fix version-tag drift (@v1.13→@v1.19, acdl/→nova/). ---ci--- project: acdl phase: 1 milestone: v1.20 status: execute requirements: [REQ-230, REQ-231, REQ-232] ---/ci---
241 lines
10 KiB
Markdown
241 lines
10 KiB
Markdown
# Architecture
|
|
|
|
> **Status:** v1.0 (current). All design decisions are resolved. This is the
|
|
> source of truth for *how* the platform works; the [Vision](vision) is the
|
|
> source of truth for *why*.
|
|
|
|
## 0. Purpose
|
|
|
|
This document encodes the architectural commitments that realize the
|
|
[vision](vision). Every commitment is grounded in a vision tenet.
|
|
|
|
The platform is **four layers + six cross-cutting concerns**, bound by the
|
|
vision's "Two Consumer Surfaces, One Platform" tenet: both surfaces converge
|
|
on the same contract schema, the same policy envelope, and the same evidence
|
|
stream.
|
|
|
|
## 1. Architectural Overview
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
A["Consumer surfaces"] --> B["Contract schema"]
|
|
B --> C["Central pipeline"]
|
|
C --> D["Modules + primitives"]
|
|
C --> E["Angine adapter"]
|
|
C --> F["Confidence signal"]
|
|
C --> G["Evidence stream"]
|
|
D --> E
|
|
E --> H["Infrastructure"]
|
|
F --> G
|
|
```
|
|
|
|
The four layers:
|
|
|
|
1. **Primitives** — single-purpose, engine-agnostic modules representing
|
|
the smallest reusable infrastructure pieces (a VPC, an S3 bucket, an ECS
|
|
cluster). A primitive does not reference other primitives; it takes its
|
|
environment as input.
|
|
2. **Modules** — patterns that combine primitives into deployable
|
|
infrastructure shapes (an ECS Fargate microservice, a static-assets site).
|
|
A module references registered primitives (max depth 5).
|
|
3. **Developer surface** — the developer-owned workflow file + contract. The
|
|
developer references the central pipeline via a versioned tag and owns
|
|
their workflow file (no platform auto-sync).
|
|
4. **Agentic surface** — a hybrid runtime where a consumer declares intent
|
|
in natural language and an agent resolves it to a contract submission.
|
|
Trust model: trust and always verify on the platform side. Stateless
|
|
agents; all state lives in the platform.
|
|
|
|
The developer and agentic surfaces are parallel paths, not a progression.
|
|
Both end in a contract submission that enters the same pipeline.
|
|
|
|
## 2. Primitives
|
|
|
|
Single-purpose, engine-agnostic modules. Locked commitments:
|
|
|
|
- No inter-primitive references. A primitive may call engine data sources.
|
|
- Semver with three triggers: interface → MAJOR, behavior → MINOR,
|
|
lifecycle → PATCH.
|
|
- Immutability on publication.
|
|
- 12-month deprecation window.
|
|
- AI refinement is a flag, triggered by a joint operational condition
|
|
(N ≥ 50 consecutive zero-rollback changes, no primitive/module incident in
|
|
6 months, Infra & Ops unilateral override).
|
|
- A primitive's interface is defined against the Target Stack (engine-
|
|
agnostic), not against any engine's variable block directly.
|
|
|
|
## 3. Modules
|
|
|
|
Patterns that combine primitives into deployable shapes. Locked commitments:
|
|
|
|
- One codebase maps to one canonical module (default); `multiStack: true`
|
|
is permitted only for (a) a DR-region mirror, (b) a time-boxed
|
|
experimental stack (TTL ≤ 30 days), or (c) explicit Infra & Ops approval
|
|
with a documented justification.
|
|
- A module references registered primitives only (max depth 5).
|
|
- Pipeline quality checks: secrets-in-plaintext, public ingress, IAM
|
|
wildcard, KMS key reference, tag compliance, naming convention.
|
|
- Restricted from module patterns: IAM principal creation, network boundary
|
|
creation, key/secret creation, external data transfer.
|
|
- Auto-promote after 3 observed usages.
|
|
- A module's pattern tree wires field is defined against the stack's
|
|
relationship type, not against any engine's module block. The stack →
|
|
engine translation is the engine adapter's job (§12). The pattern
|
|
pipeline itself is engine-agnostic.
|
|
|
|
## 4. Developer Surface
|
|
|
|
- Tag-based reference to the central pipeline template.
|
|
- Developer-owned workflow file, no platform auto-sync.
|
|
- Tag mutability for production-bound references: tag for dev/qa, SHA for
|
|
prod. The platform provides a CLI command that resolves the current tag
|
|
to its SHA for prod-bound workflows.
|
|
|
|
## 5. Agentic Surface
|
|
|
|
- Hybrid runtime: skill as markdown, agent as executor.
|
|
- Trust model: trust and always verify on the platform side.
|
|
- Skill envelope (4 dimensions).
|
|
- Stateless agents; all state in the platform.
|
|
- Initial skill catalog: web API, worker, scheduled job, static asset,
|
|
basic observability bootstrap. Addition criteria: (a) reviewable for
|
|
sensitive data, (b) expressible as a single contract submission,
|
|
(c) documented use case.
|
|
- `profile: agentic` unlocks agentic-specific fields
|
|
(`naturalLanguageIntent`, `confidenceAtSubmission`, `agentTrace`).
|
|
|
|
## 6. Cross-Cutting — Central Pipeline Template
|
|
|
|
- JSON Schema (draft 2020-12) with a thin domain-specific wrapper.
|
|
- Central repo + generated client libraries.
|
|
- Multi-stage validation pipeline: schema → policy → NFR → confidence.
|
|
- Distributed enrichment.
|
|
- GitOps reconciler + engine execution layer.
|
|
- The pipeline emits a `PolicyCheckResult` record per policy rule evaluated;
|
|
the confidence signal consumes these as one normalized input (§8).
|
|
|
|
## 7. Cross-Cutting — Contract Schema
|
|
|
|
- Central repo + generated client libraries.
|
|
- Strict fail-fast at the schema stage with reason codes from a published
|
|
vocabulary.
|
|
- Per-environment mandatory fields: dev requires stack + environment; qa
|
|
adds `validation.e2eSuite` + `validation.loadTest`; prod adds runbook +
|
|
dashboard + oncall; dr adds `drDrillRef`. `inputs` is always optional.
|
|
`profile: agentic` fields are optional everywhere (`naturalLanguageIntent`
|
|
required when profile is agentic).
|
|
|
|
## 8. Cross-Cutting — Confidence Signal
|
|
|
|
- Six canonical inputs: policy, validation, freshness, source, history, NFRs.
|
|
- Weighted sum with per-input breakdown.
|
|
- Per-environment thresholds: dev ≥ 0.50, qa ≥ 0.75, prod ≥ 0.90, dr ≥ 0.95.
|
|
- Structured output: `{ score, band, perInput, reasonCodes }`.
|
|
- 1-year storage; no algorithm retraining in v1.
|
|
- Halt with explicit reason on missing input.
|
|
- Severity → score penalty: critical → hard override to mandatory block,
|
|
high → -0.2, medium → -0.05, low → -0.01, info → 0.0. One critical finding
|
|
hard-overrides the score regardless of all other inputs.
|
|
- Thresholds frozen for v1; tuning begins post-v1 with quarterly FP/FN
|
|
tracking per environment. Override authority = Infra & Ops + SRE joint
|
|
sign-off; any override is itself a confidence-event in the audit stream.
|
|
|
|
## 9. Cross-Cutting — Audit and Evidence Stream
|
|
|
|
- Every delivery action produces an immutable, hash-chained evidence event.
|
|
- The audit stream is the platform's certified record of what happened, when,
|
|
and why.
|
|
- Events are written to a DynamoDB outbox and rendered on an evidence
|
|
timeline.
|
|
|
|
## 10. Cross-Cutting — HITL Matrix
|
|
|
|
Human-in-the-loop gates for higher environments:
|
|
|
|
| Environment | Autonomy | Attester | Gate |
|
|
|---|---|---|---|
|
|
| dev | Full autonomy (no HITL) | — | Confidence ≥ 0.50, all six inputs present |
|
|
| qa | Held for attestation | QA | Platform-runner deployment approval + full QA matrix |
|
|
| prod | Held for attestation | SRE | Platform-runner deployment approval + full SRE matrix |
|
|
| dr | Held for attestation | SRE | Platform-runner deployment approval + dr-drill evidence |
|
|
|
|
Staging does not exist. Dev is the only autonomous environment and absorbs
|
|
integration, contract, security smoke, and performance smoke validation.
|
|
|
|
- Pre-execution gate model. 1 business day = warn + escalate; 2 business
|
|
days = auto-freeze + re-submit. Rejection extends the audit chain; no
|
|
partial deploy to roll back.
|
|
- Separation of duties: the platform-internal identity record in the
|
|
DynamoDB outbox enforces `qaApprover ≠ prodApprover` for the same contract.
|
|
|
|
## 11. Cross-Cutting — Separation of Duties
|
|
|
|
- CODEOWNERS routes the right reviewer to the right environment.
|
|
- The DynamoDB outbox enforces identity distinctness across environment
|
|
approvers.
|
|
|
|
## 12. Cross-Cutting — Angine Execution
|
|
|
|
The technical execution layer. Primitives and modules are engine-agnostic
|
|
in shape; engine adapters are the only engine-specific component.
|
|
|
|
The architecture defines a **Target Stack** — a engine-neutral
|
|
description of:
|
|
|
|
- The resources to create (typed against the stack schema).
|
|
- Their relationships (the module's pattern tree).
|
|
- Their inputs (wired from the contract).
|
|
- Policy hooks (the points in the pattern where policy checks attach).
|
|
|
|
The registry, the module pattern tree, the contract schema, and the
|
|
`PolicyCheckResult` schema are all defined against the stack schema. None is
|
|
defined against any specific engine.
|
|
|
|
**v1 implementation reality:** the stack is shaped to round-trip cleanly to
|
|
Terraform because there is no other adapter to differentiate from. As
|
|
additional adapters appear, the stack gets more expressive and the adapters
|
|
gain translation logic, but the primitive content, the module pattern tree,
|
|
and the contract schema do not change. This is the design that prevents a
|
|
polyglot mess.
|
|
|
|
The engine adapter:
|
|
|
|
- Translates the stack-typed module pattern tree to a engine root module
|
|
that calls the primitive modules.
|
|
- Is a thin layer. It does not own primitive/module content; it only
|
|
translates.
|
|
- Is the only engine-specific code in the platform.
|
|
|
|
Policy checks run on the engine plan output. Results are normalized to
|
|
`PolicyCheckResult` records by a policy adapter. The confidence signal
|
|
consumes the union of all `PolicyCheckResult` records, regardless of engine
|
|
— engine-agnostic over its inputs, matching the module model's
|
|
engine-agnosticism over its outputs.
|
|
|
|
## 13. Cross-Cutting — Platform Runners
|
|
|
|
The platform runs on platform-managed runners (GitHub Actions in
|
|
production). Runner-specific code = workflow YAML, OIDC trust, CODEOWNERS,
|
|
environments. The contract schema, stack, `PolicyCheckResult`, confidence
|
|
signal, and audit stream are portable (runner-agnostic); a second runner
|
|
platform needs a runner adapter + workflow-template translator, with no
|
|
change to the modules/stack/confidence/audit.
|
|
|
|
## 14. Versioning
|
|
|
|
- Primitives and modules use semver: interface → MAJOR, behavior → MINOR,
|
|
lifecycle → PATCH.
|
|
- A module pins primitives by `name@semver`; the resolver picks the highest
|
|
compatible.
|
|
- A MAJOR bump requires a new registry entry (immutable publication); the
|
|
old entry enters a 12-month deprecation window.
|
|
- The central deploy pipeline is referenced by a floating MAJOR + MINOR tag
|
|
(e.g. `@v1.19`); patch fixes flow within the tag, breaking changes land
|
|
under the next MINOR tag.
|
|
|
|
See [Versioning](pipeline/versioning) for the consumer-facing details.
|
|
|
|
## 15. OpenTofu
|
|
|
|
Not in v1. The engine abstraction (§12) makes OpenTofu a future adapter,
|
|
not an architecture change. Revisit when an OpenTofu adapter is requested. |