generated from coulomb/repo-seed
T04: add docs/canon-mapping.md mapping config-atlas concepts to InfoTechCanon (itc-gov/data/devsecops/land/org/access/sec/tag) and sibling repos with consume/reference/align/own ownership, plus gaps, validation hooks, and extension candidates. Resolves the (planned) refs in PRD and ecosystem-boundaries. T01: add schemas/surface-entry.schema.json (Draft 2020-12, additionalProperties false to forbid inline values/secrets), docs/configuration-surface-schema.md (fields, kind taxonomy, L0-L9 ordering, explicit merge rules), a validating seed entry (surface.infotech.state-hub.api-config), and expand registry/README.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
95 lines
4.4 KiB
Markdown
95 lines
4.4 KiB
Markdown
# Configuration Surface Schema
|
||
|
||
**Status:** draft
|
||
**Updated:** 2026-06-26
|
||
**Repo:** config-atlas
|
||
**Schema:** [`../schemas/surface-entry.schema.json`](../schemas/surface-entry.schema.json)
|
||
**Related:** [`canon-mapping.md`](canon-mapping.md), [`../specs/ProductRequirementsDocument.md`](../specs/ProductRequirementsDocument.md) §7/§10,
|
||
[`../specs/ArchitectureBlueprint.md`](../specs/ArchitectureBlueprint.md) §3
|
||
|
||
A **configuration surface** is a bounded, named place where configuration is
|
||
defined, read, or overridden. Each surface is one markdown file in
|
||
`registry/surfaces/` whose **YAML frontmatter** validates against
|
||
`schemas/surface-entry.schema.json`; the markdown body holds prose (meaning,
|
||
precedence notes, gotchas).
|
||
|
||
The atlas stores the **map**: where a surface lives, who owns it, its kind, scope,
|
||
and source links. It **never** stores live configuration values and **never** stores
|
||
secret values (PRD NFR-2, NFR-4). `additionalProperties: false` throughout the schema
|
||
prevents an entry from sneaking a `value` field anywhere.
|
||
|
||
## Fields
|
||
|
||
| Field | Required | Meaning |
|
||
|-------|----------|---------|
|
||
| `id` | yes | Stable id `surface.<domain>.<system>.<name>` (lowercase, dashes). |
|
||
| `name` | yes | Human-readable name. |
|
||
| `kind` | yes | Closed taxonomy (below). Drives kind-separation. |
|
||
| `summary` | yes | One-line description. |
|
||
| `owner` | yes | Team/agent identity, resolved against `domain-tree`. Not a person. |
|
||
| `status` | yes | `draft` \| `active` \| `deprecated`. |
|
||
| `scope` | yes | `allowed_layers` (subset of the layer ordering) + `default_layer`. |
|
||
| `mutability` | yes | Delivery stage / blast radius (below). |
|
||
| `security_class` | yes | `operational` \| `sensitive` \| `secret-ref` \| `policy`. |
|
||
| `schema` | no | The **contract** (type/default/min/max/validator) — metadata, not a live value. |
|
||
| `sources` | yes | Canonical sources by reference, each with a layer `role`. Never inlines a value. |
|
||
| `relations` | no | `consumed_by`, `overrides`, `depends_on_secret` (refs only), `related_to`. |
|
||
| `evidence` | no | `last_seen`, `discovery_method`, `change_log_ref`. |
|
||
|
||
### `kind` taxonomy
|
||
`app-config`, `deploy-config`, `secret-ref`, `feature-flag`, `policy`,
|
||
`tenant-config`, `infra-state`, `runtime-override`. Secrets, flags, and infra-state
|
||
are never treated as ordinary config. A `feature-flag` surface links to a
|
||
`feature-control` key (via a `sources[].role: feature-control-key`) and contains no
|
||
evaluation logic. A `secret-ref` surface references a secret by id/path only.
|
||
|
||
### `mutability` classes
|
||
`build-time`, `deploy-time`, `startup-time`, `hot-reloadable`, `per-request`,
|
||
`emergency`. Prevents treating structural config like a harmless flag.
|
||
|
||
## Scope / layer ordering (L0–L9)
|
||
|
||
`allowed_layers` and `default_layer` draw from the **shared scope vocabulary** — an
|
||
ordering, not a new set of names (aligned to ITC-LAND/ITC-ORG and `feature-control`
|
||
`EvaluationScope`; see `canon-mapping.md`):
|
||
|
||
```text
|
||
L0 product-default L5 installation
|
||
L1 company L6 tenant
|
||
L2 platform L7 group
|
||
L3 environment L8 user / agent
|
||
L4 region L9 emergency
|
||
```
|
||
|
||
"More specific wins" by default; higher layers may declare **non-overridable
|
||
guardrails**. A surface declares which layers may set it, e.g.
|
||
`allowed_layers: [company, environment, tenant]`.
|
||
|
||
## Merge rules (explicit — no hidden last-writer-wins)
|
||
|
||
```text
|
||
scalar more specific layer replaces earlier value
|
||
object/map deep merge by key
|
||
array/list replace by default; keyed merge only if declared
|
||
null not deletion unless tombstone semantics are defined
|
||
secret never merged into normal config
|
||
policy restrictive rule wins unless explicitly delegated
|
||
```
|
||
|
||
Resolution of the *effective value* is out of scope (delegated downstream). The
|
||
atlas renders only the **effective-config path** — the ordered override path with
|
||
owner and validating-schema references (PRD FR-5).
|
||
|
||
## Authoring
|
||
|
||
1. Copy the example below into `registry/surfaces/surface.<domain>.<system>.<name>.md`.
|
||
2. Fill frontmatter; link `sources[]` to canonical files (no values, no secrets).
|
||
3. Add the row to `registry/indexes/surfaces.yaml` (ATLAS-WP-0002-T03).
|
||
4. Validate (ATLAS-WP-0002-T06): frontmatter against the schema, plus
|
||
`reuse-surface validate --root .` and `git diff --check`.
|
||
|
||
## Example
|
||
|
||
See [`../registry/surfaces/surface.infotech.state-hub.api-config.md`](../registry/surfaces/surface.infotech.state-hub.api-config.md)
|
||
— a real, validating entry for the State Hub API configuration surface.
|