Files
config-atlas/workplans/ATLAS-WP-0004-explain-and-graph.md
tegwick 4620244f39
Some checks failed
validate-registry / validate (push) Has been cancelled
feat(explain): complete ATLAS-WP-0004 — graph edges, blast-radius, determinism tests
T05: tests/test_effective_config.py (6 tests) — order-independence, most-specific
winner, no value/secret leak; wired into make validate + CI.
T04: tools/blast_radius.py + make blast-radius — consumers, transitive dependents
(cycle-safe), secret refs, fan-out risk band.
T03: tools/config_graph.py + make graph/graph-query — emit config-typed edges to
registry/indexes/graph.yaml (queryable by surface id); staleness check in the gate.

WP-0004 finished (5/5). Read-first control-plane MVP complete: explain, graph,
and blast-radius over the seeded surfaces.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 00:16:58 +02:00

166 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: ATLAS-WP-0004
type: workplan
title: "Effective-config explain and graph"
domain: infotech
repo: config-atlas
status: finished
owner: codex
topic_slug: custodian
created: "2026-06-26"
updated: "2026-06-27"
state_hub_workstream_id: "fbfdbf2b-ca6b-450e-a654-a61c5939f068"
---
# Effective-config explain and graph
Turn the registry into the **read-first control-plane MVP**: given a key, show its
layer path, what overrides what, its owner, its consumers, and its blast radius —
**statically, from source links, without reading any live value**.
This is **Phase 3** of [`specs/ArchitectureBlueprint.md`](../specs/ArchitectureBlueprint.md)
§6 and realizes PRD FR-5 and FR-7
([`specs/ProductRequirementsDocument.md`](../specs/ProductRequirementsDocument.md)).
The configuration knowledge graph reuses the **State Hub** relationship store rather
than building a new graph database ([`docs/ecosystem-boundaries.md`](../docs/ecosystem-boundaries.md)
§2.5; [`research/configuration-control-plane.md`](../research/configuration-control-plane.md) §5).
**Depends on:** ATLAS-WP-0002 (entries carry `sources[].role` and `relations`).
Benefits from, but does not require, ATLAS-WP-0003 (connectors enrich coverage).
**Hard boundary:** this renders the effective-config *path* only. Resolving the
actual effective *value* is out of scope (delegated downstream); `feature-flag`
surfaces link to feature-control and are never re-resolved here.
**Exit condition:** `config explain <surface-id>` emits an ordered override path
with winning layer, what it overrode, validating schema, and owner; config-typed
edges are expressible to the State Hub graph; a blast-radius view lists affected
consumers.
**Sequencing:** T01 (resolver) → T02 (CLI) and T05 (tests); T03 (graph edges) →
T04 (blast-radius). T01 and T03 may start in parallel.
## Effective-config path resolver (static)
```task
id: ATLAS-WP-0004-T01
status: done
priority: high
state_hub_task_id: "cee293aa-b407-4b97-a462-b67d7aa0f170"
```
Result 2026-06-27: Added `tools/effective_config.py` — a pure, deterministic
resolver that orders a surface's `sources[]` by canonical L0-L9 layer rank and
emits the override path (contributing layers, winning layer, what each overrode,
validator, owner). Renders the PATH only, never a value; non-layer roles
(feature-control-key) are listed as linked authority. Verified order-independent
(8x shuffle -> identical path).
Implement a static resolver that, from a surface's `sources[]` (with layer `role`),
the L0L9 ordering, and the explicit merge rules, produces the **override path**:
ordered contributing layers, the winning layer, what each overrode, the validating
schema, and the owner — never a live value. Honors non-overridable guardrails. See
the `config explain` shape in [`wiki/ConfigLayering.md`](../wiki/ConfigLayering.md).
- **Acceptance:** given a surface with ordered sources, the resolver returns a
deterministic, order-independent override path with owner + validator refs and no
resolved value.
## `config explain` tool
```task
id: ATLAS-WP-0004-T02
status: done
priority: high
state_hub_task_id: "5d66a8c1-74bd-4c6f-9ea6-839e884ad103"
```
Result 2026-06-27: Added `tools/config_explain.py` and `make explain
SURFACE=...`. Renders the resolver output (layer path, overrides, winning layer,
validator, owner, consumers, secret refs) for any `surface.*` id. Verified on all
4 seeded surfaces; no values or secret values appear in output. Documented in
`.claude/rules/stack-and-commands.md`.
Add a `tools/` command (e.g. `config_explain.py`) that takes a `surface.*` id and
renders the resolver output as the human/agent-readable `config explain` view.
Reuse the existing `tools/` + Makefile pattern (`make explain SURFACE=...`).
- **Acceptance:** `config explain surface.infotech.state-hub.api-config` prints the
ordered layer path, overrides, validator, owner, and consumers.
## Config knowledge graph edges to State Hub
```task
id: ATLAS-WP-0004-T03
status: done
priority: medium
state_hub_task_id: "7b16eaa0-f5e1-4ff3-809d-729b312fd154"
```
Result 2026-06-27: Added `tools/config_graph.py` + `make graph`/`graph-query`.
Emits config-typed edges (consumed_by/overrides/depends_on_secret/related_to) to
`registry/indexes/graph.yaml` (10 nodes, 10 edges) — queryable by surface id in
both directions. config-atlas owns edge semantics; the State Hub owns storage
(artifact is hub-ingestible). A `--check` staleness gate runs in `make validate`.
Emit config-typed edges (`consumed_by`, `overrides`, `depends_on_secret`,
`related_to`) from surface entries to the **State Hub** relationship/graph model,
contributing the config semantics of each edge while the hub stores topology
(PRD FR-7; ecosystem-boundaries §2.5). Do not build a separate graph store.
- **Acceptance:** declared edges from the seed surfaces are expressed to the State
Hub without duplicating its store; edges are queryable by surface id.
## Blast-radius / dependency view
```task
id: ATLAS-WP-0004-T04
status: done
priority: medium
state_hub_task_id: "57e085c7-25e8-4e2d-bb3e-43b82e351aa9"
```
Result 2026-06-27: Added `tools/blast_radius.py` + `make blast-radius`. For a
surface it lists direct consumers, transitively-dependent surfaces (cycle-safe),
referenced secrets, owner, and a fan-out risk band. Verified: state-hub config is
high risk (fan-out 4); leaf surfaces lower.
Build a view that, for a given surface, traverses the graph to list affected
consumers, dependent surfaces, and referenced secrets — the
`config key → service → tenant → feature → secret → owner` chain from
research §5. Supports change-risk reasoning before a change.
- **Acceptance:** for a surface, the view lists downstream consumers and dependent
surfaces; a change to a high-fan-out surface is visibly higher risk.
## Resolver determinism tests
```task
id: ATLAS-WP-0004-T05
status: done
priority: medium
state_hub_task_id: "77b19d5f-f55c-48bb-8129-ba1478e47223"
```
Result 2026-06-27: Added `tests/test_effective_config.py` (6 tests) proving the
override path is order-independent (16x shuffle), the winner is the most-specific
layer, and no schema default / live / secret value leaks into explain output.
Wired into `make validate` and CI (`validate-tests`).
Add tests proving the override path is deterministic and order-independent
(consistent with the merge-rule and CUE-unification rationale,
research §3.3), and that no live or secret value ever appears in explain output.
Wire into the CI gate (`make validate`).
- **Acceptance:** tests pass in CI; an explain output containing a literal value or
secret fails the test.
---
After workplan or registry file updates, sync from `~/state-hub`:
```bash
make fix-consistency REPO=config-atlas
```
</content>