2026-06-26 23:57:59 +02:00
|
|
|
|
---
|
|
|
|
|
|
id: ATLAS-WP-0004
|
|
|
|
|
|
type: workplan
|
|
|
|
|
|
title: "Effective-config explain and graph"
|
|
|
|
|
|
domain: infotech
|
|
|
|
|
|
repo: config-atlas
|
2026-06-27 00:16:58 +02:00
|
|
|
|
status: finished
|
2026-06-26 23:57:59 +02:00
|
|
|
|
owner: codex
|
|
|
|
|
|
topic_slug: custodian
|
|
|
|
|
|
created: "2026-06-26"
|
2026-06-27 00:05:01 +02:00
|
|
|
|
updated: "2026-06-27"
|
2026-06-26 23:58:30 +02:00
|
|
|
|
state_hub_workstream_id: "fbfdbf2b-ca6b-450e-a654-a61c5939f068"
|
2026-06-26 23:57:59 +02:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
# 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
|
2026-06-27 00:05:01 +02:00
|
|
|
|
status: done
|
2026-06-26 23:57:59 +02:00
|
|
|
|
priority: high
|
2026-06-26 23:58:30 +02:00
|
|
|
|
state_hub_task_id: "cee293aa-b407-4b97-a462-b67d7aa0f170"
|
2026-06-26 23:57:59 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-27 00:05:01 +02:00
|
|
|
|
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).
|
|
|
|
|
|
|
2026-06-26 23:57:59 +02:00
|
|
|
|
Implement a static resolver that, from a surface's `sources[]` (with layer `role`),
|
|
|
|
|
|
the L0–L9 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
|
2026-06-27 00:05:01 +02:00
|
|
|
|
status: done
|
2026-06-26 23:57:59 +02:00
|
|
|
|
priority: high
|
2026-06-26 23:58:30 +02:00
|
|
|
|
state_hub_task_id: "5d66a8c1-74bd-4c6f-9ea6-839e884ad103"
|
2026-06-26 23:57:59 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-27 00:05:01 +02:00
|
|
|
|
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`.
|
|
|
|
|
|
|
2026-06-26 23:57:59 +02:00
|
|
|
|
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
|
2026-06-27 00:16:58 +02:00
|
|
|
|
status: done
|
2026-06-26 23:57:59 +02:00
|
|
|
|
priority: medium
|
2026-06-26 23:58:30 +02:00
|
|
|
|
state_hub_task_id: "7b16eaa0-f5e1-4ff3-809d-729b312fd154"
|
2026-06-26 23:57:59 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-27 00:16:58 +02:00
|
|
|
|
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`.
|
|
|
|
|
|
|
2026-06-26 23:57:59 +02:00
|
|
|
|
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
|
2026-06-27 00:16:58 +02:00
|
|
|
|
status: done
|
2026-06-26 23:57:59 +02:00
|
|
|
|
priority: medium
|
2026-06-26 23:58:30 +02:00
|
|
|
|
state_hub_task_id: "57e085c7-25e8-4e2d-bb3e-43b82e351aa9"
|
2026-06-26 23:57:59 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-27 00:16:58 +02:00
|
|
|
|
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.
|
|
|
|
|
|
|
2026-06-26 23:57:59 +02:00
|
|
|
|
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
|
2026-06-27 00:16:58 +02:00
|
|
|
|
status: done
|
2026-06-26 23:57:59 +02:00
|
|
|
|
priority: medium
|
2026-06-26 23:58:30 +02:00
|
|
|
|
state_hub_task_id: "77b19d5f-f55c-48bb-8129-ba1478e47223"
|
2026-06-26 23:57:59 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-27 00:16:58 +02:00
|
|
|
|
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`).
|
|
|
|
|
|
|
2026-06-26 23:57:59 +02:00
|
|
|
|
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>
|