031887ec56
Contract surface redesign: - New top-level fields: id (3-6 char acronym → stack.name), name (full → stack.title), infrastructure (map keyed by module name, replaces module:) - Drop uses: field (dead reference; version pin lives in CI workflow uses: line) - Drop top-level module/inputs (now nested under infrastructure map) - Per-module optional version (defaults to latest published from registry) - Multi-module contracts: one file deploys N modules in one pipeline run, resource IDs namespaced with module name to avoid collisions - stack.schema.json: add optional title field for display name Rename: - pipelines/deploy.yaml → pipelines/contract.yml (declarative spec, not a pipeline) - pipelines/ci.yaml → pipelines/ci.yml - All 44 .yaml files → .yml repo-wide (contracts, module examples, kyverno policies) - .acdl/contract.yaml → .acdl/contract.yml Resolver (core/contract_resolver.py): - Rewrite resolve() to loop infrastructure map, default version to latest, merge module fragments into one stack with namespaced resource IDs - _latest_version() picks highest non-deprecated from registry - _namespace_resources() prefixes IDs + rewrites ref: expressions for multi-module - Single-module path: unprefixed IDs (backward compatible) Verification: - 494 tests pass (0 contract-shape failures) - Local E2E passes (contract → resolver → adapter → local ECS HTTP 200 → outbox) ---ci--- project: acdl phase: 57 milestone: v1.10.2 status: execute ---/ci---
58 lines
4.5 KiB
Markdown
58 lines
4.5 KiB
Markdown
# ACDL Schemas
|
|
|
|
## Overview
|
|
|
|
ACDL uses JSON Schema draft 2020-12 for all declarative contracts. Schemas are the single source of truth for validation. Every contract, stack instance, pipeline, and policy result in the platform is validated against a schema in this directory before it is consumed by any downstream code path. The resolver, the pipeline runner, the CI workflows, and the test suite all load these schemas directly.
|
|
|
|
## Existing Schemas
|
|
|
|
| Schema | File | Purpose | Where Validated |
|
|
| --- | --- | --- | --- |
|
|
| ACDL Consumer Contract | `contract.schema.json` | Consumer contract validation (id, name, environment, infrastructure map with module versions + inputs) | `core/contract_resolver.py`, `scripts/run_platform.sh` Step 1, CI `schema-validation` job |
|
|
| ACDL Target Stack | `stack.schema.json` | Target Stack instance validation (resources, relationships, composition tree, NFRs) | `core/contract_resolver.py` (post-resolution), `tests/conftest.py` |
|
|
| ACDL Central Pipeline Contract | `pipeline.schema.json` | Central CI pipeline contract (stages, commands, triggers, runner) | `tests/test_pipeline_contract.py` |
|
|
| ACDL Central Deployment Pipeline Contract | `deploy-pipeline.schema.json` | Central deploy pipeline contract (validate → resolve → plan → checkov → confidence → apply → publish → uptime → comment) | `tests/test_pipeline_contract.py` |
|
|
| ACDL PolicyCheckResult | `policy_check_result.schema.json` | Normalized policy check result schema (the contract between policy engines and the confidence signal) | `tests/conftest.py`, all adapter tests |
|
|
| ACDL Tagging Standard | `tagging-standard.json` | Required tag set for all taggable AWS resources | `adapters/terraform/policy/custom_rules/acdl_tagging.py` |
|
|
|
|
## How to Write a Schema
|
|
|
|
1. Use JSON Schema draft 2020-12: `"$schema": "https://json-schema.org/draft/2020-12/schema"`.
|
|
2. Set `$id` to `https://acdl.cloudinit.dev/schemas/<name>.schema.json`.
|
|
3. Include `title` and `description` at the document root.
|
|
4. Set `type: object` at the document root.
|
|
5. Declare a `required` array listing the mandatory top-level property names.
|
|
6. Define `properties` with explicit `type`, `pattern`, `enum`, and `description` for every field.
|
|
7. Use `$defs` for reusable sub-schemas (e.g. resource definitions, input maps) and `$ref` them from the main document.
|
|
|
|
## How to Wire a Schema into the Platform
|
|
|
|
- **Contract validation** — load the schema in `core/contract_resolver.py` and in `scripts/run_platform.sh` Step 1 (`validate-contract`).
|
|
- **Stack validation** — load the schema in `core/contract_resolver.py` after the contract is resolved to a stack instance.
|
|
- **Pipeline validation** — load the schema in `tests/test_pipeline_contract.py`, which validates `pipelines/ci.yml` and `pipelines/contract.yml`.
|
|
- **Module interface validation** — structural checks in `.github/workflows/platform-test.yml` (`schema-validation` job) that validate each module's `interface.json` / `composition.json`.
|
|
- **Policy result validation** — the schema is loaded as a fixture in `tests/conftest.py` and reused by every adapter test to validate emitted `PolicyCheckResult` records.
|
|
|
|
## Dependencies
|
|
|
|
- `jsonschema` (Python) — installed via `requirements-test.txt`.
|
|
- `pyyaml` — for YAML contract loading (`core/contract_resolver.py`, `scripts/run_platform.sh`, tests).
|
|
|
|
## How to Test Schemas in CI
|
|
|
|
- `tests/test_pipeline_contract.py` — validates the pipeline schemas and asserts workflow conformance (byte-identical Gitea/GitHub workflows, same stages/commands/triggers).
|
|
- `tests/conftest.py` — provides `stack_schema` and `policy_check_result_schema` fixtures for reuse across the test suite.
|
|
- `.github/workflows/platform-test.yml` `schema-validation` job — self-validates every schema in `schemas/` (each schema is loaded and meta-validated), validates module interfaces, and validates example contracts.
|
|
|
|
## Where to Write Tests
|
|
|
|
- `tests/test_<schema_name>.py` for schema-specific tests (e.g. `tests/test_contract_schema.py`).
|
|
- Extend `tests/test_pipeline_contract.py` for pipeline-schema changes.
|
|
- Module interface validation lives in the CI workflow (`.github/workflows/platform-test.yml`).
|
|
|
|
## Adding a New Schema
|
|
|
|
1. Create `schemas/<name>.schema.json` using the draft 2020-12 conventions above.
|
|
2. Add it to the CI validation glob in `.github/workflows/platform-test.yml` (`schema-validation` job).
|
|
3. Write a test in `tests/test_<name>.py` that loads the schema and validates representative valid/invalid documents.
|
|
4. Wire it into the consuming code path (resolver, script, or test) so it is enforced at runtime. |